improve speed of installing from smb, nfs, sftp

This commit is contained in:
Chee Yee
2024-04-28 13:49:06 -07:00
parent 232a6233ca
commit f041172768
17 changed files with 541 additions and 159 deletions
+2 -1
View File
@@ -62,11 +62,12 @@ add_executable(ezremote_client
source/windows.cpp
source/zip_util.cpp
source/split_file.cpp
source/mem_file.cpp
)
add_self(ezremote_client)
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.23" 32 0)
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.24" 32 0)
target_link_libraries(ezremote_client
c
+17
View File
@@ -345,3 +345,20 @@ std::string BaseClient::UnEscape(const std::string &url)
}
return "";
}
void *BaseClient::Open(const std::string &path, int flags)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return nullptr;
}
int BaseClient::Read(void **fp, void *buf, uint64_t size)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return -1;
}
void BaseClient::Close(void **fp)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
}
+3
View File
@@ -33,6 +33,9 @@ public:
std::vector<DirEntry> ListDir(const std::string &path);
std::string GetPath(std::string path1, std::string path2);
std::string GetFullPath(std::string path1);
void *Open(const std::string &path, int flags);
int Read(void **fp, void *buf, uint64_t size);
void Close(void **fp);
bool IsConnected();
bool Ping();
const char *LastResponse();
+16 -2
View File
@@ -1744,7 +1744,7 @@ ClientType FtpClient::clientType()
uint32_t FtpClient::SupportedActions()
{
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE;
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE ^ REMOTE_ACTION_RAW_READ;
}
std::string FtpClient::GetPath(std::string ppath1, std::string ppath2)
@@ -1783,4 +1783,18 @@ int FtpClient::Head(const std::string &path, void *buffer, uint64_t len)
if (l != len)
return 0;
return 1;
}
}
void *FtpClient::Open(const std::string &path, int flags)
{
return nullptr;
}
int FtpClient::Read(void **fp, void *buf, uint64_t size)
{
return -1;
}
void FtpClient::Close(void **fp)
{
}
+3
View File
@@ -87,6 +87,9 @@ public:
int Copy(const std::string &from, const std::string &to);
int Move(const std::string &from, const std::string &to);
int Head(const std::string &path, void *buffer, uint64_t len);
void *Open(const std::string &path, int flags);
int Read(void **fp, void *buf, uint64_t size);
void Close(void **fp);
std::vector<DirEntry> ListDir(const std::string &path);
void SetCallbackXferFunction(FtpCallbackXfer pointer);
void SetCallbackArg(void *arg);
+19 -2
View File
@@ -887,7 +887,7 @@ ClientType GDriveClient::clientType()
uint32_t GDriveClient::SupportedActions()
{
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE;
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE ^ REMOTE_ACTION_RAW_READ;
}
void *GDriveClient::RefreshTokenThread(void *argp)
@@ -941,4 +941,21 @@ void GDriveClient::SetAccessToken(const std::string &token)
{
if (this->client != nullptr)
this->client->set_bearer_token_auth(token);
}
}
void *GDriveClient::Open(const std::string &path, int flags)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return nullptr;
}
int GDriveClient::Read(void **fp, void *buf, uint64_t size)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return -1;
}
void GDriveClient::Close(void **fp)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
}
+3
View File
@@ -32,6 +32,9 @@ public:
bool FileExists(const std::string &path);
void SetAccessToken(const std::string &token);
std::vector<DirEntry> ListDir(const std::string &path);
void *Open(const std::string &path, int flags);
int Read(void **fp, void *buf, uint64_t size);
void Close(void **fp);
static void *RefreshTokenThread(void *argp);
static void StartRefreshToken();
static void StopRefreshToken();
+17
View File
@@ -553,6 +553,23 @@ int NfsClient::Head(const std::string &ppath, void *buffer, uint64_t len)
return 1;
}
void *NfsClient::Open(const std::string &path, int flags)
{
struct nfsfh *nfsfh = nullptr;
nfs_open(nfs, path.c_str(), 0400, &nfsfh);;
return nfsfh;
}
int NfsClient::Read(void **fp, void *buf, uint64_t size)
{
return nfs_read(nfs, (struct nfsfh*)*fp, size, buf);
}
void NfsClient::Close(void **fp)
{
nfs_close(nfs, (struct nfsfh*)*fp);
}
ClientType NfsClient::clientType()
{
return CLIENT_TYPE_NFS;
+3
View File
@@ -32,6 +32,9 @@ public:
int Copy(const std::string &from, const std::string &to);
int Move(const std::string &from, const std::string &to);
std::vector<DirEntry> ListDir(const std::string &path);
void *Open(const std::string &path, int flags);
int Read(void **fp, void *buf, uint64_t size);
void Close(void **fp);
bool IsConnected();
bool Ping();
const char *LastResponse();
+5 -1
View File
@@ -21,7 +21,8 @@ enum RemoteActions
REMOTE_ACTION_EDIT = 512,
REMOTE_ACTION_NEW_FILE = 1024,
REMOTE_ACTION_EXTRACT = 2048,
REMOTE_ACTION_ALL = 4095
REMOTE_ACTION_RAW_READ = 4096,
REMOTE_ACTION_ALL = 8191
};
enum ClientType
@@ -58,6 +59,9 @@ public:
virtual int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset) = 0;
virtual bool FileExists(const std::string &path) = 0;
virtual std::vector<DirEntry> ListDir(const std::string &path) = 0;
virtual void *Open(const std::string &path, int flags) = 0;
virtual int Read(void **fp, void *buf, uint64_t size) = 0;
virtual void Close(void **fp) = 0;
virtual std::string GetPath(std::string path1, std::string path2) = 0;
virtual bool IsConnected() = 0;
virtual bool Ping() = 0;
+17
View File
@@ -642,6 +642,23 @@ int SFTPClient::Quit()
return 1;
}
void *SFTPClient::Open(const std::string &path, int flags)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return nullptr;
}
int SFTPClient::Read(void **fp, void *buf, uint64_t size)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return -1;
}
void SFTPClient::Close(void **fp)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
}
ClientType SFTPClient::clientType()
{
return CLIENT_TYPE_SFTP;
+3
View File
@@ -30,6 +30,9 @@ public:
int Head(const std::string &path, void *buffer, uint64_t len);
bool FileExists(const std::string &path);
std::vector<DirEntry> ListDir(const std::string &path);
void *Open(const std::string &path, int flags);
int Read(void **fp, void *buf, uint64_t size);
void Close(void **fp);
std::string GetPath(std::string path1, std::string path2);
bool IsConnected();
bool Ping();
+16
View File
@@ -567,6 +567,22 @@ int SmbClient::Head(const std::string &ppath, void *buffer, uint64_t len)
return 1;
}
void *SmbClient::Open(const std::string &path, int flags)
{
struct smb2fh* in = smb2_open(smb2, path.c_str(), flags);
return in;
}
int SmbClient::Read(void **fp, void *buf, uint64_t size)
{
return smb2_read(smb2, (struct smb2fh*) *fp, (uint8_t*)buf, size);
}
void SmbClient::Close(void **fp)
{
smb2_close(smb2, (struct smb2fh*)*fp);
}
ClientType SmbClient::clientType()
{
return CLIENT_TYPE_SMB;
+3
View File
@@ -34,6 +34,9 @@ public:
int Move(const std::string &from, const std::string &to);
int CopyToSocket(const std::string &path, int socket_fd);
std::vector<DirEntry> ListDir(const std::string &path);
void *Open(const std::string &path, int flags);
int Read(void **fp, void *buf, uint64_t size);
void Close(void **fp);
bool IsConnected();
bool Ping();
const char *LastResponse();
+197
View File
@@ -0,0 +1,197 @@
#include <stdio.h>
#include <stdio.h>
#include <string>
#include "common.h"
#include "mem_file.h"
MemFile::MemFile(const std::string &path, size_t block_size)
{
this->block_size = block_size;
this->complete = false;
sem_init(&this->block_ready, 0, 0);
}
MemFile::~MemFile()
{
for (int i = 0; i < this->mem_blocks.size(); i++)
{
if (this->mem_blocks[i] != nullptr && this->mem_blocks[i]->status != MEM_BLOCK_STATUS_DELETED)
{
if (this->mem_blocks[i]->buf != nullptr)
{
free(this->mem_blocks[i]->buf);
this->mem_blocks[i]->buf = nullptr;
}
free(this->mem_blocks[i]);
}
}
sem_destroy(&this->block_ready);
};
int MemFile::Open()
{
this->block_in_progress = NewBlock();
this->block_in_progress->buf = malloc(block_size);
return (block_in_progress->buf == nullptr);
}
size_t MemFile::Read(char *buf, size_t buf_size, size_t offset)
{
int first_block_num, block_num;
size_t block_offset;
size_t remaining;
size_t bytes_read;
size_t total_bytes_read;
MemBlock *block;
char *p;
first_block_num= offset / this->block_size;
block_num = first_block_num;
block_offset = offset % this->block_size;
while ((block_num >= this->mem_blocks.size() && !this->complete) ||
(block_num < this->mem_blocks.size() && this->mem_blocks[block_num]->status == MEM_BLOCK_STATUS_NOT_EXISTS))
{
sem_wait(&this->block_ready);
}
block = this->mem_blocks[block_num];
if (block->status == MEM_BLOCK_STATUS_DELETED)
{
return -1;
}
if (block_offset > block->size - 1 && this->complete)
{
// requested offset is pass the end of split file
return 0;
}
remaining = buf_size;
bool eof = false;
total_bytes_read = 0;
p = buf;
while (remaining > 0 && !eof)
{
uint8_t *src = (uint8_t*)block->buf;
src += block_offset;
bytes_read = block_size - block_offset;
memcpy(p, src, bytes_read);
if (bytes_read == remaining)
{
p += bytes_read;
total_bytes_read += bytes_read;
}
else
{
p += bytes_read;
total_bytes_read += bytes_read;
if (block->is_last)
{
eof = true;
continue;
}
}
remaining -= bytes_read;
if (remaining == 0)
continue;
block_num++;
block_offset = 0;
while ((block_num > this->mem_blocks.size() - 1 && !this->complete) ||
this->mem_blocks[block_num]->status == MEM_BLOCK_STATUS_NOT_EXISTS)
{
sem_wait(&this->block_ready);
}
block = this->mem_blocks[block_num];
}
// delete blocks before the first read offset block. Assumuption, that reads are always
// forward and won't read previously already read blocks. For safety, keeping only current block and 2 previous blocks
for (int j=0; j < first_block_num - 2; j++)
{
if (this->mem_blocks[j]->status == MEM_BLOCK_STATUS_CREATED)
{
if (this->mem_blocks[j]->buf != nullptr)
{
free(this->mem_blocks[j]->buf);
this->mem_blocks[j]->buf = nullptr;
}
this->mem_blocks[j]->status = MEM_BLOCK_STATUS_DELETED;
}
}
return total_bytes_read;
}
size_t MemFile::Write(char *buf, size_t buf_size)
{
size_t bytes_written;
size_t block_space_remaining;
size_t bytes_to_write;
char *p = buf;
size_t total_bytes_written = 0;
size_t remaining_to_write = buf_size;
while (remaining_to_write > 0)
{
block_space_remaining = this->block_size - block_in_progress->size;
bytes_to_write = MIN(remaining_to_write, block_space_remaining);
memcpy(block_in_progress->buf, p, bytes_to_write);
bytes_written = bytes_to_write;
block_in_progress->size += bytes_written;
total_bytes_written += bytes_written;
remaining_to_write -= bytes_written;
block_space_remaining -= bytes_written;
p += bytes_written;
// error if bytes_to_write != bytes_written
if (bytes_written != bytes_to_write)
{
break;
}
if (block_space_remaining == 0)
{
block_in_progress->status = MEM_BLOCK_STATUS_CREATED;
this->mem_blocks.push_back(block_in_progress);
sem_post(&this->block_ready);
block_in_progress = NewBlock();
}
}
return total_bytes_written;
}
int MemFile::Close()
{
block_in_progress->status = MEM_BLOCK_STATUS_CREATED;
block_in_progress->is_last = true;
this->mem_blocks.push_back(block_in_progress);
this->complete = true;
sem_post(&this->block_ready);
return 0;
}
MemBlock *MemFile::NewBlock()
{
MemBlock *block = (MemBlock *)malloc(sizeof(MemBlock));
memset(block, 0, sizeof(MemBlock));
block->is_last = false;
block->size = 0;
block->buf = malloc(block_size);
return block;
}
+46
View File
@@ -0,0 +1,46 @@
#ifndef MEM_FILE_H
#define MEM_FILE_H
#include <string>
#include <vector>
#include <mutex>
#include <pthread.h>
enum MemBlockStatus
{
MEM_BLOCK_STATUS_NOT_EXISTS,
MEM_BLOCK_STATUS_CREATED,
MEM_BLOCK_STATUS_DELETED
};
typedef struct
{
size_t size;
void* buf;
bool is_last;
MemBlockStatus status;
} MemBlock;
class MemFile
{
public:
MemFile(const std::string& path, size_t block_size);
~MemFile();
size_t Read(char* buf, size_t buf_size, size_t offset);
size_t Write(char* buf, size_t buf_size);
int Open();
int Close();
private:
std::vector<MemBlock*> mem_blocks;
size_t write_offset;
size_t block_size;
int write_error;
bool complete;
MemBlock *block_in_progress;
sem_t block_ready;
MemBlock *NewBlock();
};
#endif
+171 -153
View File
@@ -8,6 +8,12 @@
#include "clients/smbclient.h"
#include "clients/ftpclient.h"
#include "clients/nfsclient.h"
#include "clients/webdav.h"
#include "clients/apache.h"
#include "clients/iis.h"
#include "clients/nginx.h"
#include "clients/npxserve.h"
#include "clients/rclone.h"
#include "filehost/filehost.h"
#include "config.h"
#include "fs.h"
@@ -27,6 +33,14 @@
using namespace httplib;
struct RemoteDownloadData
{
RemoteClient *client = nullptr;
std::map<std::string, void **> fp_handles;
};
static RemoteDownloadData remote_data[100];
Server *svr;
int http_server_port = 8080;
char compressed_file_path[1024];
@@ -91,22 +105,22 @@ namespace HttpServer
return s;
}
void failed(Response & res, int status, const std::string &msg)
void failed(Response &res, int status, const std::string &msg)
{
res.status = status;
char response_msg[msg.length()+strlen(FAILURE_MSG)+2];
char response_msg[msg.length() + strlen(FAILURE_MSG) + 2];
snprintf(response_msg, sizeof(response_msg), "{ \"result\": { \"success\": false, \"error\": \"%s\" } }", msg.c_str());
res.set_content(response_msg, strlen(response_msg), "application/json");
return;
}
void bad_request(Response & res, const std::string &msg)
void bad_request(Response &res, const std::string &msg)
{
failed(res, 200, msg);
return;
}
void success(Response & res)
void success(Response &res)
{
res.status = 200;
res.set_content(SUCCESS_MSG, SUCCESS_MSG_LEN, "application/json");
@@ -182,15 +196,77 @@ namespace HttpServer
return 1;
}
static RemoteClient *GetRemoteClient(int site_idx, bool new_client)
{
RemoteClient *tmp_client;
RemoteSettings *tmp_settings = &site_settings[sites[site_idx]];
if (!new_client)
{
tmp_client = remote_data[site_idx].client;
if (tmp_client != nullptr)
return tmp_client;
}
if (tmp_settings->type == CLIENT_TYPE_SFTP)
{
tmp_client = new SFTPClient();
}
else if (tmp_settings->type == CLIENT_TYPE_SMB)
{
tmp_client = new SmbClient();
}
else if (tmp_settings->type == CLIENT_TYPE_FTP)
{
tmp_client = new FtpClient();
}
else if (tmp_settings->type == CLIENT_TYPE_NFS)
{
tmp_client = new NfsClient();
}
else if (tmp_settings->type == CLIENT_TYPE_WEBDAV)
{
tmp_client = new WebDAVClient();
}
else if (tmp_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();
}
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
if (!new_client && tmp_client->clientType() != CLIENT_TYPE_FTP)
{
remote_data[site_idx].client = tmp_client;
}
return tmp_client;
}
static void DeleteRemoteClient(RemoteClient *tmp_client, int site_idx)
{
if (tmp_client != nullptr)
{
tmp_client->Quit();
delete tmp_client;
}
}
void *ServerThread(void *argp)
{
svr->Get("/", [&](const Request & req, Response & res)
{
res.set_redirect("/index.html");
});
svr->Get("/", [&](const Request &req, Response &res)
{ res.set_redirect("/index.html"); });
svr->Get("/index.html", [&](const Request & req, Response & res)
{
svr->Get("/index.html", [&](const Request &req, Response &res)
{
FILE *in = FS::OpenRead("/mnt/sandbox/pfsmnt/RMTC00001-app0/assets/index.html");
size_t size = FS::GetSize("/mnt/sandbox/pfsmnt/RMTC00001-app0/assets/index.html");
res.set_content_provider(
@@ -206,11 +282,10 @@ namespace HttpServer
},
[in](bool success) {
FS::Close(in);
});
});
}); });
svr->Get("/favicon.ico", [&](const Request & req, Response & res)
{
svr->Get("/favicon.ico", [&](const Request &req, Response &res)
{
FILE *in = FS::OpenRead("/mnt/sandbox/pfsmnt/RMTC00001-app0/assets/favicon.ico");
size_t size = FS::GetSize("/mnt/sandbox/pfsmnt/RMTC00001-app0/assets/favicon.ico");
res.set_content_provider(
@@ -226,11 +301,10 @@ namespace HttpServer
},
[in](bool success) {
FS::Close(in);
});
});
}); });
svr->Post("/__local__/list", [&](const Request & req, Response & res)
{
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());
@@ -276,11 +350,10 @@ namespace HttpServer
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");
});
res.set_content(results_str, strlen(results_str), "application/json"); });
svr->Post("/__local__/rename", [&](const Request & req, Response & res)
{
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());
@@ -302,11 +375,10 @@ namespace HttpServer
FS::Rename(item, newItemPath);
success(res);
return;
});
return; });
svr->Post("/__local__/move", [&](const Request & req, Response & res)
{
svr->Post("/__local__/move", [&](const Request &req, Response &res)
{
const json_object *items;
const char *newPath;
json_object *jobj = json_tokener_parse(req.body.c_str());
@@ -357,11 +429,10 @@ namespace HttpServer
failed(res, 200, error_msg);
}
else
success(res);
});
success(res); });
svr->Post("/__local__/copy", [&](const Request & req, Response & res)
{
svr->Post("/__local__/copy", [&](const Request &req, Response &res)
{
const json_object *items;
const char *newPath;
const char *singleFilename;
@@ -432,11 +503,10 @@ namespace HttpServer
failed(res, 200, error_msg);
}
else
success(res);
});
success(res); });
svr->Post("/__local__/remove", [&](const Request & req, Response & res)
{
svr->Post("/__local__/remove", [&](const Request &req, Response &res)
{
json_object *items;
json_object *jobj = json_tokener_parse(req.body.c_str());
if (jobj != nullptr)
@@ -472,11 +542,10 @@ namespace HttpServer
failed(res, 200, error_msg);
}
else
success(res);
});
success(res); });
svr->Post("/__local__/install", [&](const Request & req, Response & res)
{
svr->Post("/__local__/install", [&](const Request &req, Response &res)
{
json_object *items;
json_object *jobj = json_tokener_parse(req.body.c_str());
if (jobj != nullptr)
@@ -509,11 +578,10 @@ namespace HttpServer
failed(res, 200, error_msg);
}
else
success(res);
});
success(res); });
svr->Post("/__local__/edit", [&](const Request & req, Response & res)
{
svr->Post("/__local__/edit", [&](const Request &req, Response &res)
{
const char *item;
const char *content;
size_t content_len;
@@ -543,11 +611,10 @@ namespace HttpServer
return;
}
success(res);
});
success(res); });
svr->Post("/__local__/getContent", [&](const Request & req, Response & 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)
@@ -570,11 +637,10 @@ namespace HttpServer
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)
{
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)
@@ -593,16 +659,13 @@ namespace HttpServer
}
FS::MkDirs(newPath);
success(res);
});
success(res); });
svr->Post("/__local__/permission", [&](const Request & req, Response & res)
{
failed(res, 200, "Operation not supported");
});
svr->Post("/__local__/permission", [&](const Request &req, Response &res)
{ failed(res, 200, "Operation not supported"); });
svr->Post("/__local__/compress", [&](const Request & req, Response & res)
{
svr->Post("/__local__/compress", [&](const Request &req, Response &res)
{
json_object *items;
const char* destination;
const char* compressedFilename;
@@ -652,11 +715,10 @@ namespace HttpServer
else
{
failed(res, 200, "Failed to create zip");
}
});
} });
svr->Post("/__local__/extract", [&](const Request & req, Response & res)
{
svr->Post("/__local__/extract", [&](const Request &req, Response &res)
{
const char* item;
const char* destination;
const char* folderName;
@@ -692,11 +754,10 @@ namespace HttpServer
else if (ret == -1)
failed(res, 200, "Unsupported compressed file format");
else
success(res);
});
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;
@@ -705,11 +766,10 @@ namespace HttpServer
size = FS::GetSize(file_path);
std::string result_str = "{\"size\":" + std::to_string(size) + "}";
res.status = 200;
res.set_content(result_str.c_str(), result_str.length(), "application/json");
});
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;
@@ -775,12 +835,11 @@ namespace HttpServer
{
FS::Close(out);
}
success(res);
});
success(res); });
// Download multiple files as ZIP
svr->Get("/__local__/downloadMultiple", [&](const Request & req, Response & res)
{
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");
@@ -834,12 +893,11 @@ namespace HttpServer
else
{
failed(res, 200, "Failed to create zip");
}
});
} });
// Download single file
svr->Get("/__local__/downloadFile", [&](const Request & req, Response & res)
{
svr->Get("/__local__/downloadFile", [&](const Request &req, Response &res)
{
std::string path = req.get_param_value("path", 0);
if (path.empty())
{
@@ -869,11 +927,10 @@ namespace HttpServer
},
[in](bool success) {
FS::Close(in);
});
});
}); });
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);
@@ -919,12 +976,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;
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;
std::string path;
@@ -932,33 +988,6 @@ namespace HttpServer
if (site_idx != 98)
{
path = std::string("/") + std::string(req.matches[3]);
tmp_settings = &site_settings[sites[site_idx]];
if (tmp_settings->type == CLIENT_TYPE_SFTP)
{
tmp_client = new SFTPClient();
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
}
else if (tmp_settings->type == CLIENT_TYPE_SMB)
{
tmp_client = new SmbClient();
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
}
else if (tmp_settings->type == CLIENT_TYPE_FTP)
{
tmp_client = new FtpClient();
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
}
else if (tmp_settings->type == CLIENT_TYPE_NFS)
{
tmp_client = new NfsClient();
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
}
else
{
tmp_client = remoteclient;
}
}
else
{
@@ -973,33 +1002,34 @@ namespace HttpServer
tmp_client->Connect(host, "", "");
}
if (tmp_client == nullptr || !tmp_client->IsConnected())
{
res.status = 404;
return;
}
if (req.method == "HEAD")
{
int64_t file_size;
int ret;
if (site_idx != 98)
tmp_client = GetRemoteClient(site_idx, true);
ret = tmp_client->Size(path, &file_size);
if (!ret)
{
res.status = 500;
DeleteRemoteClient(tmp_client, site_idx);
return;
}
res.status = 204;
res.set_header("Content-Length", std::to_string(file_size));
res.set_header("Accept-Ranges", "bytes");
DeleteRemoteClient(tmp_client, site_idx);
return;
}
if (req.ranges.empty())
{
res.status = 200;
if (site_idx != 98)
tmp_client = GetRemoteClient(site_idx, true);
res.set_content_provider(
(1024*128), "application/octet-stream",
[tmp_client, path](size_t offset, size_t length, DataSink &sink) {
@@ -1007,15 +1037,7 @@ namespace HttpServer
return (ret == 1);
},
[tmp_client, path, site_idx](bool success) {
if (tmp_client != nullptr && (tmp_client->clientType() == CLIENT_TYPE_SFTP
|| tmp_client->clientType() == CLIENT_TYPE_SMB
|| tmp_client->clientType() == CLIENT_TYPE_FTP
|| tmp_client->clientType() == CLIENT_TYPE_NFS
|| (tmp_client->clientType() == CLIENT_TYPE_HTTP_SERVER && site_idx == 98)))
{
tmp_client->Quit();
delete tmp_client;
}
DeleteRemoteClient(tmp_client, site_idx);
});
}
else
@@ -1027,6 +1049,11 @@ namespace HttpServer
range_len = 524288ul;
res.set_header("Content-Length", std::to_string(range_len));
res.set_header("Content-Range", std::string("bytes ") + std::to_string(req.ranges[0].first)+"-" + std::to_string(req.ranges[0].first+524288ul-1) + "/"+std::to_string(range_len));
tmp_client = GetRemoteClient(site_idx, true);
}
else
{
tmp_client = GetRemoteClient(site_idx, false);
}
std::pair<ssize_t, ssize_t> range = req.ranges[0];
res.set_content_provider(
@@ -1035,22 +1062,18 @@ namespace HttpServer
int ret = tmp_client->GetRange(path, sink, range_len, range.first);
return (ret == 1);
},
[tmp_client, site_idx, path, range, range_len](bool success) {
if (tmp_client != nullptr && (tmp_client->clientType() == CLIENT_TYPE_SFTP
|| tmp_client->clientType() == CLIENT_TYPE_SMB
|| tmp_client->clientType() == CLIENT_TYPE_FTP
|| tmp_client->clientType() == CLIENT_TYPE_NFS
|| (tmp_client->clientType() == CLIENT_TYPE_HTTP_SERVER && site_idx == 98)))
[tmp_client, path, range, site_idx](bool success) {
if (range.second >= 18000000000000000000ul ||
(tmp_client->clientType() == CLIENT_TYPE_HTTP_SERVER && site_idx == 98) ||
tmp_client->clientType() == CLIENT_TYPE_FTP)
{
tmp_client->Quit();
delete tmp_client;
DeleteRemoteClient(tmp_client, site_idx);
}
});
}
});
} });
svr->Get("/archive_inst/(.*)", [&](const Request & req, Response & res)
{
svr->Get("/archive_inst/(.*)", [&](const Request &req, Response &res)
{
RemoteClient *tmp_client;
RemoteSettings *tmp_settings;
std::string hash = req.matches[1];
@@ -1104,11 +1127,10 @@ namespace HttpServer
[](bool success) {
return true;
});
}
});
} });
svr->Post("/__local__/install_url", [&](const Request & req, Response & res)
{
svr->Post("/__local__/install_url", [&](const Request &req, Response &res)
{
std::string url;
const char *url_param;
bool use_alldebrid = false;
@@ -1231,21 +1253,17 @@ namespace HttpServer
return;
}
}
success(res);
});
success(res); });
svr->Get("/stop", [&](const Request & /*req*/, Response & /*res*/)
{
svr->stop();
});
{ svr->stop(); });
svr->set_error_handler([](const Request & /*req*/, Response &res)
{
{
const char *fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
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)
@@ -1253,11 +1271,11 @@ namespace HttpServer
dbglogger_log("%s", log(req, res).c_str());
});
*/
svr->set_payload_max_length(1024 * 1024 * 12);
svr->set_tcp_nodelay(true);
svr->set_mount_point("/", "/");
if (web_server_enabled)
svr->listen("0.0.0.0", http_server_port);
else