From a3741a0a6c1ea9f971a1308b8d7b586b0bfa112d Mon Sep 17 00:00:00 2001 From: cy33hc Date: Mon, 18 May 2026 20:03:50 -0700 Subject: [PATCH] initial bg install --- CMakeLists.txt | 3 +- source/actions.cpp | 51 ++++++++ source/actions.h | 5 +- source/clients/archiveorg.cpp | 4 +- source/clients/archiveorg.h | 2 +- source/clients/baseclient.cpp | 8 +- source/clients/baseclient.h | 4 +- source/clients/ftpclient.cpp | 2 +- source/clients/ftpclient.h | 4 +- source/clients/gdrive.cpp | 2 +- source/clients/gdrive.h | 4 +- source/clients/github.cpp | 9 +- source/clients/github.h | 4 +- source/clients/nfsclient.cpp | 2 +- source/clients/nfsclient.h | 4 +- source/clients/remote_client.h | 5 +- source/clients/sftpclient.cpp | 4 +- source/clients/sftpclient.h | 4 +- source/clients/smbclient.cpp | 2 +- source/clients/smbclient.h | 4 +- source/clients/webdav.cpp | 6 +- source/clients/webdav.h | 4 +- source/common.h | 15 ++- source/config.cpp | 11 ++ source/config.h | 8 ++ source/http/httplib.cpp | 4 + source/installer.cpp | 167 ++++++++++++++++++++++++++ source/installer.h | 8 +- source/lang.cpp | 14 ++- source/lang.h | 18 ++- source/main.cpp | 6 +- source/server/http_server.cpp | 207 ++++++++++++++++++++++++++++----- source/server/http_server.h | 3 +- 33 files changed, 523 insertions(+), 75 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9e90a6..2bace7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,9 +70,10 @@ add_executable(ezremote_client add_self(ezremote_client) -add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.39" 32 0) +add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.40" 32 0) target_link_libraries(ezremote_client + dbglogger c c++ png diff --git a/source/actions.cpp b/source/actions.cpp index a733ea3..78f994c 100644 --- a/source/actions.cpp +++ b/source/actions.cpp @@ -1911,4 +1911,55 @@ namespace Actions sprintf(remote_file_to_select, "%s", temp_file.c_str()); } + void RestartServer() + { + StopServer(); + sleep(2); + INSTALLER::StartEzRemoteServer(); + sleep(2); + } + + void StopServer() + { + httplib::Client client = httplib::Client("http://localhost:" + std::to_string(http_int_server_port)); + client.Get("/stop"); + } + + void GetBackgroundDownloadProgress() + { + httplib::Client client = httplib::Client("http://localhost:" + std::to_string(http_int_server_port)); + + if (auto res = client.Get("/get_download_state")) + { + if (HTTP_SUCCESS(res->status)) + { + bg_download_progress.clear(); + + json_object *jobj = json_tokener_parse(res->body.c_str()); + if (jobj != nullptr) + { + struct array_list *progress_list = json_object_get_array(jobj); + + for (size_t idx = 0; idx < progress_list->length; ++idx) + { + DownloadProgress progress; + + json_object *progress_obj = (json_object *)array_list_get_idx(progress_list, idx); + progress.path = json_object_get_string(json_object_object_get(progress_obj, "path")); + progress.bytes_transfered = json_object_get_uint64(json_object_object_get(progress_obj, "bytes_transfered")); + progress.file_size = json_object_get_uint64(json_object_object_get(progress_obj, "file_size")); + progress.state = state_strings[json_object_get_int(json_object_object_get(progress_obj, "state"))]; + progress.timestamp = json_object_get_uint64(json_object_object_get(progress_obj, "timestamp")); + + bg_download_progress.push_back(progress); + } + json_object_put(jobj); + } + } + else + { + snprintf(status_message, 1024, "Failed to get the download progress from ezRemote Server"); + } + } + } } diff --git a/source/actions.h b/source/actions.h index 6c111c0..d15de28 100644 --- a/source/actions.h +++ b/source/actions.h @@ -122,6 +122,9 @@ namespace Actions void CreateRemoteFile(char *filename); void *ExtractArchivePkg(void *argp); void *DownloadSplitPkg(void *argp); + void RestartServer(); + void StopServer(); + void GetBackgroundDownloadProgress(); } -#endif \ No newline at end of file +#endif diff --git a/source/clients/archiveorg.cpp b/source/clients/archiveorg.cpp index db43c2d..83caef6 100644 --- a/source/clients/archiveorg.cpp +++ b/source/clients/archiveorg.cpp @@ -39,7 +39,7 @@ std::string ArchiveOrgClient::GenerateRandomId(const int len) return tmp_s; } -int ArchiveOrgClient::Connect(const std::string &url, const std::string &username, const std::string &password) +int ArchiveOrgClient::Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping) { this->host_url = url; size_t scheme_pos = url.find("://"); @@ -64,6 +64,8 @@ int ArchiveOrgClient::Connect(const std::string &url, const std::string &usernam if (username.length() > 0) return Login(username, password); + else if (!send_ping) + this->connected = true; else if (Ping()) this->connected = true; return 1; diff --git a/source/clients/archiveorg.h b/source/clients/archiveorg.h index 4e47160..09a7871 100644 --- a/source/clients/archiveorg.h +++ b/source/clients/archiveorg.h @@ -11,7 +11,7 @@ class ArchiveOrgClient : public BaseClient { public: - int Connect(const std::string &url, const std::string &username, const std::string &password); + int Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping=false); std::vector ListDir(const std::string &path); private: diff --git a/source/clients/baseclient.cpp b/source/clients/baseclient.cpp index 115a04e..eb0407e 100644 --- a/source/clients/baseclient.cpp +++ b/source/clients/baseclient.cpp @@ -40,7 +40,7 @@ int BaseClient::SetCookies(Headers &headers) return 1; } -int BaseClient::Connect(const std::string &url, const std::string &username, const std::string &password) +int BaseClient::Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping) { this->host_url = url; size_t scheme_pos = url.find("://"); @@ -58,8 +58,12 @@ int BaseClient::Connect(const std::string &url, const std::string &username, con client->set_connection_timeout(30); client->set_read_timeout(30); client->enable_server_certificate_verification(false); - if (Ping()) + + if (!send_ping) this->connected = true; + else if (Ping()) + this->connected = true; + return 1; } diff --git a/source/clients/baseclient.h b/source/clients/baseclient.h index 4dd295b..d3dbb6c 100644 --- a/source/clients/baseclient.h +++ b/source/clients/baseclient.h @@ -16,7 +16,7 @@ class BaseClient : public RemoteClient public: BaseClient(); ~BaseClient(); - int Connect(const std::string &url, const std::string &username, const std::string &password); + int Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping=false); int Connect(const std::string &url, const std::string &api_key); int Mkdir(const std::string &path); int Rmdir(const std::string &path, bool recursive); @@ -59,4 +59,4 @@ protected: std::map cookies; }; -#endif \ No newline at end of file +#endif diff --git a/source/clients/ftpclient.cpp b/source/clients/ftpclient.cpp index fdb8464..b84afd5 100644 --- a/source/clients/ftpclient.cpp +++ b/source/clients/ftpclient.cpp @@ -46,7 +46,7 @@ FtpClient::~FtpClient() free(mp_ftphandle); } -int FtpClient::Connect(const std::string &url, const std::string &user, const std::string &pass) +int FtpClient::Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping) { int port = 21; std::string host = url.substr(6); diff --git a/source/clients/ftpclient.h b/source/clients/ftpclient.h index 58c6b01..1333b82 100644 --- a/source/clients/ftpclient.h +++ b/source/clients/ftpclient.h @@ -67,7 +67,7 @@ public: FtpClient(); ~FtpClient(); - int Connect(const std::string &url, const std::string &user, const std::string &pass); + int Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping=false); void SetConnmode(connmode mode); int Site(const std::string &cmd); int Raw(const std::string &cmd); @@ -137,4 +137,4 @@ private: int ParseMLSDDirEntry(char *line, DirEntry *dirEntry); }; -#endif \ No newline at end of file +#endif diff --git a/source/clients/gdrive.cpp b/source/clients/gdrive.cpp index 860a94f..472c3a1 100644 --- a/source/clients/gdrive.cpp +++ b/source/clients/gdrive.cpp @@ -159,7 +159,7 @@ GDriveClient::GDriveClient() path_id_map.insert(std::make_pair("/" + shared_with_me, shared_with_me)); } -int GDriveClient::Connect(const std::string &url, const std::string &user, const std::string &pass) +int GDriveClient::Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping) { if (strlen(remote_settings->gg_account.refresh_token) > 0) { diff --git a/source/clients/gdrive.h b/source/clients/gdrive.h index 8dbce73..b2f1ad4 100644 --- a/source/clients/gdrive.h +++ b/source/clients/gdrive.h @@ -17,7 +17,7 @@ class GDriveClient : public BaseClient { public: GDriveClient(); - int Connect(const std::string &url, const std::string &user, const std::string &pass); + int Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping=false); int Rename(const std::string &src, const std::string &dst); int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0); int Get(SplitFile *split_file, const std::string &path, uint64_t offset=0); @@ -51,4 +51,4 @@ private: std::map shared_drive_map; }; -#endif \ No newline at end of file +#endif diff --git a/source/clients/github.cpp b/source/clients/github.cpp index 685af01..a865e62 100644 --- a/source/clients/github.cpp +++ b/source/clients/github.cpp @@ -12,7 +12,7 @@ using httplib::Client; using httplib::Headers; using httplib::Result; -int GithubClient::Connect(const std::string &url, const std::string &username, const std::string &password) +int GithubClient::Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping) { if (url.find("https://github.com") == std::string::npos) return 0; @@ -31,8 +31,11 @@ int GithubClient::Connect(const std::string &url, const std::string &username, c client->enable_server_certificate_verification(false); m_client.Connect("https://github.com", username, password); - if (Ping()) + if (!send_ping) this->connected = true; + else if (Ping()) + this->connected = true; + return 1; } @@ -254,4 +257,4 @@ bool GithubClient::ParseReleases() } return 1; -} \ No newline at end of file +} diff --git a/source/clients/github.h b/source/clients/github.h index 362d0e6..0f3bb61 100644 --- a/source/clients/github.h +++ b/source/clients/github.h @@ -11,7 +11,7 @@ class GithubClient : public BaseClient { public: - int Connect(const std::string &url, const std::string &username, const std::string &password); + int Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping=false); std::vector ListDir(const std::string &path); int Size(const std::string &path, int64_t *size); int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0); @@ -43,4 +43,4 @@ private: bool ParseReleases(); }; -#endif \ No newline at end of file +#endif diff --git a/source/clients/nfsclient.cpp b/source/clients/nfsclient.cpp index 76cf475..46610c1 100644 --- a/source/clients/nfsclient.cpp +++ b/source/clients/nfsclient.cpp @@ -27,7 +27,7 @@ NfsClient::~NfsClient() { } -int NfsClient::Connect(const std::string &url, const std::string &user, const std::string &pass) +int NfsClient::Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping) { nfs = nfs_init_context(); if (nfs == nullptr) diff --git a/source/clients/nfsclient.h b/source/clients/nfsclient.h index 0297621..88fd93e 100644 --- a/source/clients/nfsclient.h +++ b/source/clients/nfsclient.h @@ -18,7 +18,7 @@ class NfsClient : public RemoteClient public: NfsClient(); ~NfsClient(); - int Connect(const std::string &url, const std::string &user, const std::string &pass); + int Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping=false); int Mkdir(const std::string &path); int Rmdir(const std::string &path, bool recursive); int Size(const std::string &path, int64_t *size); @@ -53,4 +53,4 @@ private: bool connected = false; }; -#endif \ No newline at end of file +#endif diff --git a/source/clients/remote_client.h b/source/clients/remote_client.h index d663d57..e79c5e3 100644 --- a/source/clients/remote_client.h +++ b/source/clients/remote_client.h @@ -35,6 +35,7 @@ enum ClientType CLIENT_TYPE_HTTP_SERVER, CLIENT_TYPE_GOOGLE, CLIENT_TYPE_NFS, + CLIENT_TYPE_FILEHOST, CLINET_TYPE_UNKNOWN }; @@ -45,7 +46,7 @@ class RemoteClient public: RemoteClient(){}; virtual ~RemoteClient(){}; - virtual int Connect(const std::string &url, const std::string &username, const std::string &password) = 0; + virtual int Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping=false) = 0; virtual int Mkdir(const std::string &path) = 0; virtual int Rmdir(const std::string &path, bool recursive) = 0; virtual int Size(const std::string &path, int64_t *size) = 0; @@ -74,4 +75,4 @@ public: virtual uint32_t SupportedActions() = 0; }; -#endif \ No newline at end of file +#endif diff --git a/source/clients/sftpclient.cpp b/source/clients/sftpclient.cpp index 6dc38f9..3a309c2 100644 --- a/source/clients/sftpclient.cpp +++ b/source/clients/sftpclient.cpp @@ -23,7 +23,7 @@ SFTPClient::SFTPClient() SFTPClient::~SFTPClient(){}; -int SFTPClient::Connect(const std::string &url, const std::string &username, const std::string &password) +int SFTPClient::Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping) { int port = 22; std::string host = url.substr(7); @@ -711,4 +711,4 @@ ClientType SFTPClient::clientType() uint32_t SFTPClient::SupportedActions() { return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE; -} \ No newline at end of file +} diff --git a/source/clients/sftpclient.h b/source/clients/sftpclient.h index f644d05..6544074 100644 --- a/source/clients/sftpclient.h +++ b/source/clients/sftpclient.h @@ -14,7 +14,7 @@ class SFTPClient : public RemoteClient public: SFTPClient(); ~SFTPClient(); - int Connect(const std::string &url, const std::string &username, const std::string &password); + int Connect(const std::string &url, const std::string &username, const std::string &password, bool send_ping=false); int Mkdir(const std::string &path); int Rmdir(const std::string &path, bool recursive); int Rmdir(const std::string &path); @@ -51,4 +51,4 @@ protected: bool connected = false; }; -#endif \ No newline at end of file +#endif diff --git a/source/clients/smbclient.cpp b/source/clients/smbclient.cpp index a55750d..35e466d 100644 --- a/source/clients/smbclient.cpp +++ b/source/clients/smbclient.cpp @@ -24,7 +24,7 @@ SmbClient::~SmbClient() { } -int SmbClient::Connect(const std::string &url, const std::string &user, const std::string &pass) +int SmbClient::Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping) { struct smb2_url *smb_url; diff --git a/source/clients/smbclient.h b/source/clients/smbclient.h index f3f010a..3d86c3c 100644 --- a/source/clients/smbclient.h +++ b/source/clients/smbclient.h @@ -19,7 +19,7 @@ class SmbClient : public RemoteClient public: SmbClient(); ~SmbClient(); - int Connect(const std::string &url, const std::string &user, const std::string &pass); + int Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping=false); int Mkdir(const std::string &path); int Rmdir(const std::string &path, bool recursive); int Size(const std::string &path, int64_t *size); @@ -57,4 +57,4 @@ private: uint32_t max_write_size = 0; }; -#endif \ No newline at end of file +#endif diff --git a/source/clients/webdav.cpp b/source/clients/webdav.cpp index 6da07fe..9ea88be 100644 --- a/source/clients/webdav.cpp +++ b/source/clients/webdav.cpp @@ -24,10 +24,10 @@ std::string WebDAVClient::GetHttpUrl(std::string url) return http_url; } -int WebDAVClient::Connect(const std::string &host, const std::string &user, const std::string &pass) +int WebDAVClient::Connect(const std::string &host, const std::string &user, const std::string &pass, bool send_ping) { std::string url = GetHttpUrl(host); - return BaseClient::Connect(url, user, pass); + return BaseClient::Connect(url, user, pass, send_ping); } Result WebDAVClient::PropFind(const std::string &path, int depth) @@ -321,4 +321,4 @@ ClientType WebDAVClient::clientType() uint32_t WebDAVClient::SupportedActions() { return REMOTE_ACTION_ALL ^ REMOTE_ACTION_RAW_READ; -} \ No newline at end of file +} diff --git a/source/clients/webdav.h b/source/clients/webdav.h index 2da9688..0f73cdb 100644 --- a/source/clients/webdav.h +++ b/source/clients/webdav.h @@ -11,7 +11,7 @@ class WebDAVClient : public BaseClient { public: - int Connect(const std::string &url, const std::string &user, const std::string &pass); + int Connect(const std::string &url, const std::string &user, const std::string &pass, bool send_ping=false); int Mkdir(const std::string &path); int Rmdir(const std::string &path, bool recursive); int Rename(const std::string &src, const std::string &dst); @@ -29,4 +29,4 @@ private: Result PropFind(const std::string &path, int depth); }; -#endif \ No newline at end of file +#endif diff --git a/source/common.h b/source/common.h index 4a9e2e3..bba03ee 100644 --- a/source/common.h +++ b/source/common.h @@ -11,6 +11,10 @@ #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) +enum DownloadState { STATE_PENDING, STATE_DOWNLOADING, STATE_RESUMED, STATE_FAILED, STATE_SUCCESS }; + +static const char* state_strings[] = {"Pending", "Downloading", "Resumed", "Failed", "Success"}; + typedef struct { uint16_t year; @@ -88,6 +92,15 @@ struct DirEntry } }; +struct DownloadProgress +{ + std::string path; + std::string state; + uint64_t bytes_transfered; + uint64_t file_size; + time_t timestamp; +}; + static lxb_dom_node_t *NextChildElement(lxb_dom_element_t *element) { lxb_dom_node_t *node = element->node.first_child; @@ -128,4 +141,4 @@ static lxb_dom_node_t *NextTextNode(lxb_dom_node_t *node) return next; } -#endif \ No newline at end of file +#endif diff --git a/source/config.cpp b/source/config.cpp index d9a8899..a2deb72 100644 --- a/source/config.cpp +++ b/source/config.cpp @@ -41,6 +41,9 @@ bool show_hidden_files; char alldebrid_api_key[64]; char realdebrid_api_key[64]; char temp_folder[256]; +std::string ezremote_server_version; +bool enable_background_download; +uint64_t minimum_backgrond_file_size; unsigned char cipher_key[32] = {'s', '5', 'v', '8', 'y', '/', 'B', '?', 'E', '(', 'H', '+', 'M', 'b', 'Q', 'e', 'T', 'h', 'W', 'm', 'Z', 'q', '4', 't', '7', 'w', '9', 'z', '$', 'C', '&', 'F'}; unsigned char cipher_iv[16] = {'Y', 'p', '3', 's', '6', 'v', '9', 'y', '$', 'B', '&', 'E', ')', 'H', '@', 'M'}; @@ -196,6 +199,12 @@ namespace CONFIG sprintf(temp_folder, ReadString(CONFIG_GLOBAL, CONFIG_TMP_FOLDER_PATH, TMP_FOLDER_PATH)); WriteString(CONFIG_GLOBAL, CONFIG_TMP_FOLDER_PATH, temp_folder); + enable_background_download = ReadBool(CONFIG_GLOBAL, CONFIG_ENABLE_BG_DOWNLOAD, true); + WriteBool(CONFIG_GLOBAL, CONFIG_ENABLE_BG_DOWNLOAD, enable_background_download); + + minimum_backgrond_file_size = ReadLong(CONFIG_GLOBAL, CONFIG_BG_DOWNLOAD_SIZE, 1024*1024*1024); + WriteLong(CONFIG_GLOBAL, CONFIG_BG_DOWNLOAD_SIZE, minimum_backgrond_file_size); + if (!FS::FolderExists(temp_folder)) { FS::MkDirs(temp_folder); @@ -434,6 +443,8 @@ namespace CONFIG WriteInt(CONFIG_HTTP_SERVER, CONFIG_HTTP_SERVER_PORT, http_server_port); WriteString(CONFIG_HTTP_SERVER, CONFIG_HTTP_SERVER_COMPRESSED_FILE_PATH, compressed_file_path); WriteBool(CONFIG_HTTP_SERVER, CONFIG_HTTP_SERVER_ENABLED, web_server_enabled); + WriteBool(CONFIG_GLOBAL, CONFIG_ENABLE_BG_DOWNLOAD, enable_background_download); + WriteLong(CONFIG_GLOBAL, CONFIG_BG_DOWNLOAD_SIZE, minimum_backgrond_file_size); WriteIniFile(CONFIG_INI_FILE); CloseIniFile(); diff --git a/source/config.h b/source/config.h index 4ea4707..e585f33 100644 --- a/source/config.h +++ b/source/config.h @@ -77,6 +77,9 @@ #define CONFIG_LANGUAGE "language" +#define CONFIG_ENABLE_BG_DOWNLOAD "enable_background_download" +#define CONFIG_BG_DOWNLOAD_SIZE "minimum_backgrond_file_size" + #define HTTP_SERVER_APACHE "Apache" #define HTTP_SERVER_MS_IIS "Microsoft IIS" #define HTTP_SERVER_NGINX "Nginx" @@ -86,6 +89,8 @@ #define HTTP_SERVER_MYRIENT "Myrient" #define HTTP_SERVER_GITHUB "Github" +#define EZREMOTE_SERVER_REQUIRED_VERSION "1.00" + #define MAX_EDIT_FILE_SIZE 32768 struct GoogleAccountInfo @@ -153,6 +158,9 @@ extern bool show_hidden_files; extern char alldebrid_api_key[64]; extern char realdebrid_api_key[64]; extern char temp_folder[256]; +extern std::string ezremote_server_version; +extern bool enable_background_download; +extern uint64_t minimum_backgrond_file_size; namespace CONFIG { diff --git a/source/http/httplib.cpp b/source/http/httplib.cpp index 1b5f6d7..6ee5b1b 100644 --- a/source/http/httplib.cpp +++ b/source/http/httplib.cpp @@ -3954,6 +3954,10 @@ bool Server::listen_internal() { #endif } + int const size = 1048576; + setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); + setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); + task_queue->enqueue([this, sock]() { process_and_close_socket(sock); }); } diff --git a/source/installer.cpp b/source/installer.cpp index 4a2b5d4..99433e9 100644 --- a/source/installer.cpp +++ b/source/installer.cpp @@ -12,6 +12,21 @@ #include #include "clients/webdav.h" #include "clients/remote_client.h" +#include "clients/smbclient.h" +#include "clients/sftpclient.h" +#include "clients/ftpclient.h" +#include "clients/nfsclient.h" +#include "clients/webdav.h" +#include "clients/apache.h" +#include "clients/archiveorg.h" +#include "clients/iis.h" +#include "clients/github.h" +#include "clients/myrient.h" +#include "clients/nginx.h" +#include "clients/npxserve.h" +#include "clients/rclone.h" +#include "dbglogger.h" + #include "server/http_server.h" #include "installer.h" #include "util.h" @@ -41,6 +56,11 @@ static std::map split_pkg_install_data_list; namespace INSTALLER { + static int FtpCallback(int64_t xfered, void *arg) + { + return 1; + } + int Init(void) { int ret; @@ -1171,4 +1191,151 @@ namespace INSTALLER Windows::SetModalMode(false); return ret; } + + std::string EzRemoteServerVersion() + { + httplib::Client client = httplib::Client(std::string("http://localhost:") + std::to_string(http_int_server_port)); + + if (auto res = client.Get("/version")) + { + if (HTTP_SUCCESS(res->status)) + { + return res->body; + } + } + + return ""; + } + + int StartEzRemoteServer() + { + /* + char buffer[8192]; + in_addr_t in_addr; + in_addr_t server_addr; + int filefd; + int sockfd; + ssize_t i; + ssize_t read_return; + struct hostent *hostent; + struct sockaddr_in sockaddr_in; + unsigned short server_port = 9021; + + if (!EzRemoteServerVersion().empty()) + return 0; + + filefd = open(SERVER_ELF_PATH, O_RDONLY); + if (filefd == -1) + { + return -1; + } + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) + { + return -1; + } + + hostent = gethostbyname("127.0.0.1"); + if (hostent == NULL) + { + return -1; + } + + in_addr = inet_addr(inet_ntoa(*(struct in_addr *)*(hostent->h_addr_list))); + if (in_addr == (in_addr_t)-1) + { + return -1; + } + + sockaddr_in.sin_addr.s_addr = in_addr; + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); + + if (connect(sockfd, (struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)) == -1) + { + return -1; + } + + while (1) + { + read_return = read(filefd, buffer, 8192); + if (read_return == 0) + break; + if (read_return == -1) + { + return -1; + } + if (write(sockfd, buffer, read_return) == -1) + { + return -1; + } + } + + close(filefd); + close(sockfd); + */ + + return 0; + } + + RemoteClient *GetRemoteClient(int site_idx) + { + RemoteClient *tmp_client = nullptr; + RemoteSettings *tmp_settings = &site_settings[sites[site_idx]]; + + return GetRemoteClient(tmp_settings); + } + + RemoteClient *GetRemoteClient(RemoteSettings *settings) + { + RemoteClient *tmp_client = nullptr; + ; + + if (settings->type == CLIENT_TYPE_HTTP_SERVER) + { + if (strcmp(remote_settings->http_server_type, HTTP_SERVER_APACHE) == 0) + tmp_client = new ApacheClient(); + else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_MS_IIS) == 0) + tmp_client = new IISClient(); + else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_NGINX) == 0) + tmp_client = new NginxClient(); + else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_NPX_SERVE) == 0) + tmp_client = new NpxServeClient(); + else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_RCLONE) == 0) + tmp_client = new RCloneClient(); + else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_ARCHIVEORG) == 0) + tmp_client = new ArchiveOrgClient(); + else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_GITHUB) == 0) + tmp_client = new GithubClient(); + else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_MYRIENT) == 0) + tmp_client = new MyrientClient(); + } + else if (settings->type == CLIENT_TYPE_WEBDAV) + { + tmp_client = new WebDAVClient(); + } + else if (settings->type == CLIENT_TYPE_SMB) + { + tmp_client = new SmbClient(); + } + else if (settings->type == CLIENT_TYPE_SFTP) + { + tmp_client = new SFTPClient(); + } + else if (settings->type == CLIENT_TYPE_FTP) + { + tmp_client = new FtpClient(); + FtpClient *ftp_client = (FtpClient *)tmp_client; + ftp_client->SetCallbackXferFunction(FtpCallback); + } + else if (settings->type == CLIENT_TYPE_NFS) + { + tmp_client = new NfsClient(); + } + + tmp_client->Connect(settings->server, settings->username, settings->password, false); + + return tmp_client; + } } diff --git a/source/installer.h b/source/installer.h index 9040869..df87ac6 100644 --- a/source/installer.h +++ b/source/installer.h @@ -4,6 +4,7 @@ #include "zip_util.h" #include "split_file.h" #include "pthread.h" +#include "config.h" #define SWAP16(x) \ ((uint16_t)((((uint16_t)(x)&UINT16_C(0x00FF)) << 8) | \ @@ -164,4 +165,9 @@ namespace INSTALLER void AddSplitPkgInstallData(const std::string &hash, SplitPkgInstallData *pkg_data); void RemoveSplitPkgInstallData(const std::string &hash); bool InstallSplitPkg(const std::string &path, SplitPkgInstallData* pkg_data, bool bg = false); -} \ No newline at end of file + std::string EzRemoteServerVersion(); + int StartEzRemoteServer(); + std::string StoreBgInstallHostData(RemoteSettings *remote_settings, const std::string &path); + RemoteClient *GetRemoteClient(int site_idx); + RemoteClient *GetRemoteClient(RemoteSettings *settings); +} diff --git a/source/lang.cpp b/source/lang.cpp index 1815224..2b7dc3d 100644 --- a/source/lang.cpp +++ b/source/lang.cpp @@ -177,6 +177,18 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = { "Install Via AllDebrid", // STR_ENABLE_ALLDEBRID_MSG "Install Via RealDebrid", // STR_ENABLE_REALDEBRID_MSG "Enable Disk Cache", // STR_ENABLE_DISKCACHE_DESC + "Cannot perform operation while activity is in progress", // STR_ACTIVITY_IN_PROGRESS_MSG + "ezRemote Direct Package Installer payload is not loaded", // STR_ETAHEN_DPI_ERROR_MSG + "Start/Restart Server", // STR_RESTART_SERVER + "Stop Server", // STR_STOP_SERVER + "Warning", // STR_WARNING + "The version of ezRemote Server payload running does not match the required version needed by ezRemote Client.", // STR_WARNING_MSG_1 + "If you are using an auto payload loader, then update the elf that comes with ezRemoteClient package.", // STR_WARNING_MSG_2 + "You may goto the Global Settings and restart ezRemote Server with the version that came packaged.", // STR_WARNING_MSG_3 + "Enable background download", // STR_ENABLE_BG_DOWNLOAD + "Minimum background file size (bytes)", // STR_BG_DOWNLOAD_MIN_SIZE + "Background Download Progress", // STR_BG_DOWNLOAD_PROGRESS + "Show Background Download Progress", // STR_SHOW_BG_DOWNLOAD_PROGRESS }; bool needs_extended_font = false; @@ -297,4 +309,4 @@ namespace Lang sscanf(last_site, "%[^ ] %d", buf, &num); sprintf(display_site, "%s %d", lang_strings[STR_SITE], num); } -} \ No newline at end of file +} diff --git a/source/lang.h b/source/lang.h index 2408b7c..defd4c6 100644 --- a/source/lang.h +++ b/source/lang.h @@ -170,7 +170,19 @@ FUNC(STR_ENABLE_DISK_CACHE) \ FUNC(STR_ENABLE_ALLDEBRID_MSG) \ FUNC(STR_ENABLE_REALDEBRID_MSG) \ - FUNC(STR_ENABLE_DISKCACHE_DESC) + FUNC(STR_ENABLE_DISKCACHE_DESC) \ + FUNC(STR_ACTIVITY_IN_PROGRESS_MSG) \ + FUNC(STR_DPI_NOT_STARTED_ERROR_MSG) \ + FUNC(STR_RESTART_SERVER) \ + FUNC(STR_STOP_SERVER) \ + FUNC(STR_WARNING) \ + FUNC(STR_WARNING_MSG_1) \ + FUNC(STR_WARNING_MSG_2) \ + FUNC(STR_WARNING_MSG_3) \ + FUNC(STR_ENABLE_BG_DOWNLOAD) \ + FUNC(STR_BG_DOWNLOAD_MIN_SIZE) \ + FUNC(STR_BG_DOWNLOAD_PROGRESS) \ + FUNC(STR_SHOW_BG_DOWNLOAD_PROGRESS) \ #define GET_VALUE(x) x, #define GET_STRING(x) #x, @@ -180,7 +192,7 @@ enum FOREACH_STR(GET_VALUE) }; -#define LANG_STRINGS_NUM 167 +#define LANG_STRINGS_NUM 179 #define LANG_ID_SIZE 64 #define LANG_STR_SIZE 384 extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE]; @@ -192,4 +204,4 @@ namespace Lang void SetTranslation(int32_t lang_idx); } -#endif \ No newline at end of file +#endif diff --git a/source/main.cpp b/source/main.cpp index 7e209b9..0c92f88 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -11,7 +11,7 @@ #include #include #include -// #include +#include #include "imgui.h" #include "SDL2/SDL.h" @@ -273,8 +273,8 @@ static void terminate() int main() { - // dbglogger_init(); - // dbglogger_log("If you see this you've set up dbglogger correctly."); + dbglogger_init(); + dbglogger_log("If you see this you've set up dbglogger correctly."); int rc; // No buffering setvbuf(stdout, NULL, _IONBF, 0); diff --git a/source/server/http_server.cpp b/source/server/http_server.cpp index e3c4ca6..5c36e9b 100644 --- a/source/server/http_server.cpp +++ b/source/server/http_server.cpp @@ -47,6 +47,7 @@ static RemoteDownloadData remote_data[100]; Server *svr; int http_server_port = 8080; +int http_int_server_port = 6701; char compressed_file_path[1024]; bool web_server_enabled = false; @@ -324,7 +325,7 @@ namespace HttpServer }); }); svr->Post("/__local__/list", [&](const Request &req, Response &res) - { + { const char *path; bool onlyFolders = false; json_object *jobj = json_tokener_parse(req.body.c_str()); @@ -369,11 +370,12 @@ namespace HttpServer json_object *results = json_object_new_object(); json_object_object_add(results, "result", json_files); const char *results_str = json_object_to_json_string(results); + res.status = 200; res.set_content(results_str, strlen(results_str), "application/json"); }); svr->Post("/__local__/rename", [&](const Request &req, Response &res) - { + { const char *item; const char *newItemPath; json_object *jobj = json_tokener_parse(req.body.c_str()); @@ -398,7 +400,13 @@ namespace HttpServer return; }); svr->Post("/__local__/move", [&](const Request &req, Response &res) - { + { + if (activity_inprogess) + { + failed(res, 200, lang_strings[STR_ACTIVITY_IN_PROGRESS_MSG]); + return; + } + const json_object *items; const char *newPath; json_object *jobj = json_tokener_parse(req.body.c_str()); @@ -452,7 +460,13 @@ namespace HttpServer success(res); }); svr->Post("/__local__/copy", [&](const Request &req, Response &res) - { + { + if (activity_inprogess) + { + failed(res, 200, lang_strings[STR_ACTIVITY_IN_PROGRESS_MSG]); + return; + } + const json_object *items; const char *newPath; const char *singleFilename; @@ -526,7 +540,13 @@ namespace HttpServer success(res); }); svr->Post("/__local__/remove", [&](const Request &req, Response &res) - { + { + if (activity_inprogess) + { + failed(res, 200, lang_strings[STR_ACTIVITY_IN_PROGRESS_MSG]); + return; + } + json_object *items; json_object *jobj = json_tokener_parse(req.body.c_str()); if (jobj != nullptr) @@ -565,7 +585,13 @@ namespace HttpServer success(res); }); svr->Post("/__local__/install", [&](const Request &req, Response &res) - { + { + if (activity_inprogess) + { + failed(res, 200, lang_strings[STR_ACTIVITY_IN_PROGRESS_MSG]); + return; + } + json_object *items; json_object *jobj = json_tokener_parse(req.body.c_str()); if (jobj != nullptr) @@ -598,10 +624,11 @@ namespace HttpServer failed(res, 200, error_msg); } else - success(res); }); + success(res); + }); svr->Post("/__local__/edit", [&](const Request &req, Response &res) - { + { const char *item; const char *content; size_t content_len; @@ -634,7 +661,7 @@ namespace HttpServer success(res); }); svr->Post("/__local__/getContent", [&](const Request &req, Response &res) - { + { const char *item; json_object *jobj = json_tokener_parse(req.body.c_str()); if (jobj != nullptr) @@ -656,11 +683,13 @@ namespace HttpServer json_object *result = json_object_new_object(); json_object_object_add(result, "result", json_object_new_string(content.data())); const char *result_str = json_object_to_json_string(result); + res.status = 200; - res.set_content(result_str, strlen(result_str), "application/json"); }); + res.set_content(result_str, strlen(result_str), "application/json"); + }); svr->Post("/__local__/createFolder", [&](const Request &req, Response &res) - { + { const char *newPath; json_object *jobj = json_tokener_parse(req.body.c_str()); if (jobj != nullptr) @@ -679,13 +708,22 @@ namespace HttpServer } FS::MkDirs(newPath); - success(res); }); + success(res); + }); svr->Post("/__local__/permission", [&](const Request &req, Response &res) - { failed(res, 200, "Operation not supported"); }); + { + failed(res, 200, "Operation not supported"); + }); svr->Post("/__local__/compress", [&](const Request &req, Response &res) - { + { + if (activity_inprogess) + { + failed(res, 200, lang_strings[STR_ACTIVITY_IN_PROGRESS_MSG]); + return; + } + json_object *items; const char* destination; const char* compressedFilename; @@ -738,7 +776,13 @@ namespace HttpServer } }); svr->Post("/__local__/extract", [&](const Request &req, Response &res) - { + { + if (activity_inprogess) + { + failed(res, 200, lang_strings[STR_ACTIVITY_IN_PROGRESS_MSG]); + return; + } + const char* item; const char* destination; const char* folderName; @@ -777,7 +821,7 @@ namespace HttpServer success(res); }); svr->Get("/__local__/uploadResumeSize", [&](const Request &req, Response &res) - { + { std::string destination = req.get_param_value("destination"); std::string filename = req.get_param_value("filename"); std::string file_path = destination + "/" + filename; @@ -789,7 +833,7 @@ namespace HttpServer res.set_content(result_str.c_str(), result_str.length(), "application/json"); }); svr->Post("/__local__/upload", [&](const Request &req, Response &res, const ContentReader &content_reader) - { + { MultipartFormDataItems items; std::string destination; size_t chunk_size = 0; @@ -859,7 +903,7 @@ namespace HttpServer // Download multiple files as ZIP svr->Get("/__local__/downloadMultiple", [&](const Request &req, Response &res) - { + { if (req.get_param_value_count("items") == 0 || req.get_param_value_count("toFilename") == 0) { failed(res, 200, "Required items and toFilename parameter missing"); @@ -917,7 +961,7 @@ namespace HttpServer // Download single file svr->Get("/__local__/downloadFile", [&](const Request &req, Response &res) - { + { std::string path = req.get_param_value("path", 0); if (path.empty()) { @@ -950,7 +994,7 @@ namespace HttpServer }); }); svr->Get("/google_auth", [](const Request &req, Response &res) - { + { std::string auth_code = req.get_param_value("code"); Client client(GOOGLE_OAUTH_HOST); client.set_follow_location(true); @@ -996,10 +1040,11 @@ namespace HttpServer } login_state = -1; std::string str = std::string(lang_strings[STR_FAIL_GET_TOKEN_MSG]) + " Google"; - res.set_content(str.c_str(), "text/plain"); }); + res.set_content(str.c_str(), "text/plain"); + }); svr->Get("/rmt_inst/Site (\\d+)(/)(.*)", [&](const Request &req, Response &res) - { + { RemoteClient *tmp_client = nullptr; RemoteSettings *tmp_settings; auto site_idx = std::stoi(req.matches[1])-1; @@ -1120,7 +1165,7 @@ namespace HttpServer } }); svr->Get("/archive_inst/(.*)", [&](const Request &req, Response &res) - { + { RemoteClient *tmp_client; RemoteSettings *tmp_settings; std::string hash = req.matches[1]; @@ -1175,7 +1220,8 @@ namespace HttpServer [](bool success) { return true; }); - } }); + } + }); svr->Get("/split_inst/(.*)", [&](const Request &req, Response &res) { @@ -1240,7 +1286,7 @@ namespace HttpServer } }); svr->Post("/__local__/install_url", [&](const Request &req, Response &res) - { + { std::string url; const char *url_param; bool use_alldebrid = false; @@ -1410,17 +1456,120 @@ namespace HttpServer return; } } - success(res); }); + success(res); + + }); + + svr->Post("/__local__/download_url", [&](const Request &req, Response &res) + { + std::string url; + std::string dest; + const char *url_param; + const char *dest_param; + bool use_alldebrid = false; + bool use_realdebrid = false; + + json_object *jobj = json_tokener_parse(req.body.c_str()); + if (jobj != nullptr) + { + url_param = json_object_get_string(json_object_object_get(jobj, "url")); + dest_param = json_object_get_string(json_object_object_get(jobj, "dest")); + use_alldebrid = json_object_get_boolean(json_object_object_get(jobj, "use_alldebrid")); + use_realdebrid = json_object_get_boolean(json_object_object_get(jobj, "use_realdebrid")); + + if (url_param == nullptr || dest_param == nullptr) + { + bad_request(res, "Required url, dest parameter missing"); + return; + } + } + else + { + bad_request(res, "Invalid payload"); + return; + } + + if ((use_alldebrid && strlen(alldebrid_api_key) == 0) || (use_realdebrid && strlen(realdebrid_api_key) == 0)) + { + failed(res, 200, lang_strings[STR_ALLDEBRID_API_KEY_MISSING_MSG]); + return; + } + + url = std::string(url_param); + FileHost *filehost = FileHost::getFileHost(url, use_alldebrid, use_realdebrid); + + if (!filehost->IsValidUrl()) + { + failed(res, 200, lang_strings[STR_INVALID_URL]); + return; + } + + std::string download_url = filehost->GetDownloadUrl(); + if (download_url.empty()) + { + failed(res, 200, lang_strings[STR_CANT_EXTRACT_URL_MSG]); + return; + } + delete(filehost); + + size_t scheme_pos = download_url.find("://"); + size_t root_pos = download_url.find("/", scheme_pos + 3); + std::string host = download_url.substr(0, root_pos); + std::string path = download_url.substr(root_pos); + int64_t file_size; + + RemoteClient *baseclient = new BaseClient(); + baseclient->Connect(host, "", ""); + baseclient->Size(path, &file_size); + delete baseclient; + + OrbisTick tick; + sceRtcGetCurrentTick(&tick); + json_object *params = json_object_new_object(); + json_object_object_add(params, "type", json_object_new_int(CLIENT_TYPE_FILEHOST)); + json_object_object_add(params, "url", json_object_new_string(host.c_str())); + json_object_object_add(params, "username", json_object_new_string("")); + json_object_object_add(params, "password", json_object_new_string("")); + json_object_object_add(params, "src_path", json_object_new_string(path.c_str())); + json_object_object_add(params, "dest_path", json_object_new_string(dest_param)); + json_object_object_add(params, "size", json_object_new_uint64(file_size)); + json_object_object_add(params, "id", json_object_new_uint64(tick.mytick)); + + const char *params_str = json_object_to_json_string(params); + httplib::Client tmp_client = httplib::Client(std::string("http://localhost:") + std::to_string(http_int_server_port)); + + std::string download_req_url = + "/download_url"; + if (auto resp = tmp_client.Post(download_req_url, params_str, strlen(params_str), "application/json")) + { + if (HTTP_SUCCESS(resp->status)) + { + Util::Notify("%s queued for download", path.c_str()); + success(res); + return; + } + else + { + Util::Notify("Failed to queue %s for download in background", path.c_str()); + failed(res, 200, "Failed to download"); + return; + } + } + + failed(res, 200, "Failed to download"); + }); svr->Get("/stop", [&](const Request & /*req*/, Response & /*res*/) - { svr->stop(); }); + { + svr->stop(); + }); svr->set_error_handler([](const Request & /*req*/, Response &res) - { + { const char *fmt = "

Error Status: %d

"; char buf[BUFSIZ]; snprintf(buf, sizeof(buf), fmt, res.status); - res.set_content(buf, "text/html"); }); + res.set_content(buf, "text/html"); + }); /* svr->set_logger([](const Request &req, const Response &res) diff --git a/source/server/http_server.h b/source/server/http_server.h index be47782..4628052 100644 --- a/source/server/http_server.h +++ b/source/server/http_server.h @@ -8,6 +8,7 @@ extern Server *svr; static pthread_t http_server_thid; extern int http_server_port; +extern int http_int_server_port; extern char compressed_file_path[]; extern bool web_server_enabled; @@ -18,4 +19,4 @@ namespace HttpServer void Stop(); } -#endif \ No newline at end of file +#endif