add rclone http server support
This commit is contained in:
@@ -40,6 +40,8 @@ add_executable(ezremote_client
|
||||
source/clients/smbclient.cpp
|
||||
source/clients/webdavclient.cpp
|
||||
source/clients/sftpclient.cpp
|
||||
source/clients/rclone.cpp
|
||||
source/filehost/gdrive_host.cpp
|
||||
source/server/http_server.cpp
|
||||
source/actions.cpp
|
||||
source/config.cpp
|
||||
@@ -65,6 +67,7 @@ add_self(ezremote_client)
|
||||
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.10" 32 0)
|
||||
|
||||
target_link_libraries(ezremote_client
|
||||
dbglogger
|
||||
c
|
||||
c++
|
||||
png
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "clients/npxserve.h"
|
||||
#include "clients/nfsclient.h"
|
||||
#include "clients/iis.h"
|
||||
#include "clients/rclone.h"
|
||||
#include "clients/sftpclient.h"
|
||||
#include "common.h"
|
||||
#include "fs.h"
|
||||
@@ -1133,6 +1134,8 @@ namespace Actions
|
||||
remoteclient = new NginxClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_NPX_SERVE) == 0)
|
||||
remoteclient = new NpxServeClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_RCLONE) == 0)
|
||||
remoteclient = new RCloneClient();
|
||||
}
|
||||
else if (strncmp(remote_settings->server, "webdavs://", 10) == 0 || strncmp(remote_settings->server, "webdav://", 9) == 0)
|
||||
{
|
||||
|
||||
@@ -12,26 +12,6 @@ using httplib::Client;
|
||||
using httplib::Headers;
|
||||
using httplib::Result;
|
||||
|
||||
lxb_dom_node_t *nextChildElement(lxb_dom_element_t *element)
|
||||
{
|
||||
lxb_dom_node_t *node = element->node.first_child;
|
||||
while (node != nullptr && node->type != LXB_DOM_NODE_TYPE_ELEMENT)
|
||||
{
|
||||
node = node->next;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
lxb_dom_node_t *nextElement(lxb_dom_node_t *node)
|
||||
{
|
||||
lxb_dom_node_t *next = node->next;
|
||||
while (next != nullptr && next->type != LXB_DOM_NODE_TYPE_ELEMENT)
|
||||
{
|
||||
next = next->next;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
std::vector<DirEntry> ApacheClient::ListDir(const std::string &path)
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
@@ -101,7 +81,7 @@ std::vector<DirEntry> ApacheClient::ListDir(const std::string &path)
|
||||
memset(&entry, 0, sizeof(DirEntry));
|
||||
|
||||
element = lxb_dom_collection_element(collection, i);
|
||||
node = nextChildElement(element);
|
||||
node = NextChildElement(element);
|
||||
if (node == nullptr) continue;
|
||||
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(node), &value_len);
|
||||
@@ -114,7 +94,7 @@ std::vector<DirEntry> ApacheClient::ListDir(const std::string &path)
|
||||
if (tmp_string.compare("td") == 0)
|
||||
{
|
||||
// get the child img element
|
||||
lxb_dom_node_t *img = nextChildElement(lxb_dom_interface_element(node));
|
||||
lxb_dom_node_t *img = NextChildElement(lxb_dom_interface_element(node));
|
||||
if (img == nullptr) continue;
|
||||
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(img), &value_len);
|
||||
@@ -142,7 +122,7 @@ std::vector<DirEntry> ApacheClient::ListDir(const std::string &path)
|
||||
else continue; // invalid record
|
||||
|
||||
// file/folder name
|
||||
node = nextElement(node);
|
||||
node = NextElement(node);
|
||||
if (node == nullptr) continue;
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(node), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
@@ -165,7 +145,7 @@ std::vector<DirEntry> ApacheClient::ListDir(const std::string &path)
|
||||
else continue; // not valid record
|
||||
|
||||
// datetime
|
||||
node = nextElement(node);
|
||||
node = NextElement(node);
|
||||
if (node == nullptr) continue;
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(node), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
@@ -195,7 +175,7 @@ std::vector<DirEntry> ApacheClient::ListDir(const std::string &path)
|
||||
else continue; // invalid record
|
||||
|
||||
// filesize
|
||||
node = nextElement(node);
|
||||
node = NextElement(node);
|
||||
if (node == nullptr) continue;
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(node), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
|
||||
@@ -319,3 +319,23 @@ std::string BaseClient::DecodeUrl(const std::string &url)
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
lxb_dom_node_t *BaseClient::NextChildElement(lxb_dom_element_t *element)
|
||||
{
|
||||
lxb_dom_node_t *node = element->node.first_child;
|
||||
while (node != nullptr && node->type != LXB_DOM_NODE_TYPE_ELEMENT)
|
||||
{
|
||||
node = node->next;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
lxb_dom_node_t *BaseClient::NextElement(lxb_dom_node_t *node)
|
||||
{
|
||||
lxb_dom_node_t *next = node->next;
|
||||
while (next != nullptr && next->type != LXB_DOM_NODE_TYPE_ELEMENT)
|
||||
{
|
||||
next = next->next;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "http/httplib.h"
|
||||
@@ -38,6 +40,8 @@ public:
|
||||
uint32_t SupportedActions();
|
||||
static std::string EncodeUrl(const std::string &url);
|
||||
static std::string DecodeUrl(const std::string &url);
|
||||
static lxb_dom_node_t *NextChildElement(lxb_dom_element_t *element);
|
||||
static lxb_dom_node_t *NextElement(lxb_dom_node_t *node);
|
||||
|
||||
protected:
|
||||
httplib::Client *client;
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <fstream>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/rclone.h"
|
||||
#include "lang.h"
|
||||
#include "util.h"
|
||||
#include "system.h"
|
||||
#include "windows.h"
|
||||
#include "dbglogger.h"
|
||||
|
||||
using httplib::Client;
|
||||
using httplib::Headers;
|
||||
using httplib::Result;
|
||||
|
||||
std::vector<DirEntry> RCloneClient::ListDir(const std::string &path)
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
DirEntry entry;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
|
||||
std::string encoded_path = httplib::detail::encode_url(GetFullPath(path)+"/");
|
||||
if (auto res = client->Get(encoded_path))
|
||||
{
|
||||
lxb_status_t status;
|
||||
lxb_dom_attr_t *attr;
|
||||
lxb_dom_element_t *tbody_element, *tr_element, *td_element;
|
||||
lxb_html_document_t *document;
|
||||
lxb_dom_collection_t *tbody_collection;
|
||||
lxb_dom_collection_t *tr_collection;
|
||||
lxb_dom_collection_t *td_collection;
|
||||
|
||||
document = lxb_html_document_create();
|
||||
status = lxb_html_document_parse(document, (lxb_char_t *)res->body.c_str(), res->body.length());
|
||||
if (status != LXB_STATUS_OK)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
tbody_collection = lxb_dom_collection_make(&document->dom_document, 1);
|
||||
if (tbody_collection == NULL)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
tr_collection = lxb_dom_collection_make(&document->dom_document, 128);
|
||||
if (tbody_collection == NULL)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
|
||||
tbody_collection, (const lxb_char_t *)"tbody", 5);
|
||||
if (status != LXB_STATUS_OK)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(tbody_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (lxb_dom_collection_length(tbody_collection) < 1)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(tbody_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// Get the first tbody which should only be 1
|
||||
tbody_element = lxb_dom_collection_element(tbody_collection, 0);
|
||||
status = lxb_dom_elements_by_tag_name(tbody_element,
|
||||
tr_collection, (const lxb_char_t *)"tr", 2);
|
||||
if (status != LXB_STATUS_OK)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(tbody_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// skip row 0 , since it has the previous folder header
|
||||
for (size_t i = 1; i < lxb_dom_collection_length(tr_collection); i++)
|
||||
{
|
||||
DirEntry entry;
|
||||
std::string title, aclass;
|
||||
memset(&entry.modified, 0, sizeof(DateTime));
|
||||
const lxb_char_t *value;
|
||||
size_t value_len;
|
||||
std::string tmp_string;
|
||||
|
||||
tr_element = lxb_dom_collection_element(tr_collection, i);
|
||||
|
||||
td_collection = lxb_dom_collection_make(&document->dom_document, 5);
|
||||
status = lxb_dom_elements_by_tag_name(tr_element,
|
||||
td_collection, (const lxb_char_t *)"td", 2);
|
||||
if (status != LXB_STATUS_OK || lxb_dom_collection_length(td_collection) < 0)
|
||||
{
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(tbody_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// td 0 is empty, td 1 is file or folder
|
||||
td_element = lxb_dom_collection_element(td_collection, 1);
|
||||
lxb_dom_node_t *use_node = NextChildElement(lxb_dom_interface_element(NextChildElement(td_element)));
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(use_node), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string.compare("use") != 0)
|
||||
{
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(tbody_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
value = lxb_dom_element_get_attribute(lxb_dom_interface_element(use_node), (const lxb_char_t *)"xlink:href", 10, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string.compare("#folder") == 0)
|
||||
{
|
||||
entry.isDir = true;
|
||||
entry.selectable = true;
|
||||
entry.file_size = 0;
|
||||
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.isDir = false;
|
||||
entry.selectable = true;
|
||||
}
|
||||
|
||||
// <a> element contains the file/folder name
|
||||
lxb_dom_node_t *a_node = NextChildElement(lxb_dom_interface_element(NextElement(NextChildElement(td_element))));
|
||||
value = lxb_dom_element_get_attribute(lxb_dom_interface_element(a_node), (const lxb_char_t *)"href", 4, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string[tmp_string.length()-1] == '/')
|
||||
tmp_string = tmp_string.substr(0, tmp_string.length()-1);
|
||||
tmp_string = BaseClient::DecodeUrl(tmp_string);
|
||||
sprintf(entry.name, "%s", tmp_string.c_str());
|
||||
sprintf(entry.directory, "%s", path.c_str());
|
||||
if (path.length() > 0 && path[path.length() - 1] == '/')
|
||||
{
|
||||
sprintf(entry.path, "%s%s", path.c_str(), entry.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(entry.path, "%s/%s", path.c_str(), entry.name);
|
||||
}
|
||||
|
||||
// td 3 - filesize
|
||||
if (!entry.isDir)
|
||||
{
|
||||
td_element = lxb_dom_collection_element(td_collection, 2);
|
||||
lxb_dom_node_t *size_node = NextChildElement(td_element);
|
||||
value = lxb_dom_node_text_content(size_node->first_child, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
entry.file_size = atoi(tmp_string.c_str());
|
||||
DirEntry::SetDisplaySize(&entry);
|
||||
}
|
||||
|
||||
// td 4 - datetime
|
||||
td_element = lxb_dom_collection_element(td_collection, 3);
|
||||
lxb_dom_node_t *date_node = NextChildElement(td_element);
|
||||
value = lxb_dom_element_get_attribute(lxb_dom_interface_element(date_node), (const lxb_char_t *)"datetime", 8, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
std::vector<std::string> date_time = Util::Split(tmp_string, " ");
|
||||
|
||||
OrbisDateTime gmt;
|
||||
OrbisDateTime lt;
|
||||
|
||||
if (date_time.size() > 1)
|
||||
{
|
||||
std::vector<std::string> adate = Util::Split(date_time[0], "-");
|
||||
if (adate.size() == 3)
|
||||
{
|
||||
gmt.year = atoi(adate[0].c_str());
|
||||
gmt.month = atoi(adate[1].c_str());
|
||||
gmt.day = atoi(adate[2].c_str());
|
||||
}
|
||||
|
||||
std::vector<std::string> atime = Util::Split(date_time[1], ":");
|
||||
if (atime.size() == 3)
|
||||
{
|
||||
gmt.hour = atoi(atime[0].c_str());
|
||||
gmt.minute = atoi(atime[1].c_str());
|
||||
|
||||
std::vector<std::string> sec_msec = Util::Split(atime[2], ".");
|
||||
if (sec_msec.size() > 0)
|
||||
{
|
||||
gmt.second = atoi(sec_msec[0].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
convertUtcToLocalTime(&gmt, <);
|
||||
entry.modified.day = lt.day;
|
||||
entry.modified.month = lt.month;
|
||||
entry.modified.year = lt.year;
|
||||
entry.modified.hours = lt.hour;
|
||||
entry.modified.minutes = lt.minute;
|
||||
entry.modified.seconds = lt.second;
|
||||
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
out.push_back(entry);
|
||||
}
|
||||
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(tbody_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
|
||||
return out;
|
||||
}
|
||||
|
||||
finish:
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef RCLONE_H
|
||||
#define RCLONE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "common.h"
|
||||
|
||||
class RCloneClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
};
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -151,7 +151,7 @@ namespace CONFIG
|
||||
sites = {"Site 1", "Site 2", "Site 3", "Site 4", "Site 5", "Site 6", "Site 7", "Site 8", "Site 9", "Site 10",
|
||||
"Site 11", "Site 12", "Site 13", "Site 14", "Site 15", "Site 16", "Site 17", "Site 18", "Site 19", "Site 20"};
|
||||
|
||||
http_servers = {HTTP_SERVER_APACHE, HTTP_SERVER_MS_IIS, HTTP_SERVER_NGINX, HTTP_SERVER_NPX_SERVE};
|
||||
http_servers = {HTTP_SERVER_APACHE, HTTP_SERVER_MS_IIS, HTTP_SERVER_NGINX, HTTP_SERVER_NPX_SERVE, HTTP_SERVER_RCLONE};
|
||||
text_file_extensions = { ".txt", ".ini", ".log", ".json", ".xml", ".html", ".xhtml", ".conf", ".config" };
|
||||
image_file_extensions = { ".bmp", ".jpg", ".jpeg", ".png", ".webp" };
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
#define HTTP_SERVER_MS_IIS "Microsoft IIS"
|
||||
#define HTTP_SERVER_NGINX "Nginx"
|
||||
#define HTTP_SERVER_NPX_SERVE "Serve"
|
||||
#define HTTP_SERVER_RCLONE "RClone"
|
||||
|
||||
#define MAX_EDIT_FILE_SIZE 32768
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef FILEHOST_H
|
||||
#define FILEHOST_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "openssl/md5.h"
|
||||
|
||||
class FileHost
|
||||
{
|
||||
public:
|
||||
FileHost(const std::string &url) { this->url = url; };
|
||||
virtual ~FileHost(){};
|
||||
virtual bool IsValidUrl() = 0;
|
||||
virtual std::string GetDownloadUrl() = 0;
|
||||
|
||||
std::vector<unsigned char> Hash()
|
||||
{
|
||||
std::vector<unsigned char> res(16);
|
||||
MD5((const unsigned char *)this->url.c_str(), this->url.length(), res.data());
|
||||
return res;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string url;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
#include <regex>
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <http/httplib.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "gdrive_host.h"
|
||||
|
||||
|
||||
#define VALIDATION_REGEX_1 "https:\\/\\/drive\\.google\\.com\\/file\\/d\\/(.*)\\/(edit|view)\\?usp=(.*)"
|
||||
#define VALIDATION_REGEX_2 "https:\\/\\/drive\\.google\\.com\\/uc\\?export=download&id=(.*)"
|
||||
|
||||
GDriveHost::GDriveHost(const std::string &url) : FileHost(url)
|
||||
{
|
||||
}
|
||||
|
||||
bool GDriveHost::IsValidUrl()
|
||||
{
|
||||
std::regex regex_1(VALIDATION_REGEX_1);
|
||||
std::regex regex_2(VALIDATION_REGEX_1);
|
||||
|
||||
if (std::regex_match(url, regex_1) || std::regex_match(url, regex_2))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string GDriveHost::GetDownloadUrl()
|
||||
{
|
||||
std::regex re("https:\\/\\/drive\\.google\\.com");
|
||||
std::string path = std::regex_replace(url, re, "");
|
||||
|
||||
httplib::Client tmp_client("https://drive.google.com");
|
||||
auto res = tmp_client.Head(path);
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
std::string content_type = res->get_header_value("Content-Type");
|
||||
if (content_type == "application/octet-stream")
|
||||
return url;
|
||||
else if (content_type != "text/html")
|
||||
return "";
|
||||
}
|
||||
else
|
||||
return "";
|
||||
|
||||
res = tmp_client.Get(path);
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
lxb_status_t status;
|
||||
lxb_dom_element_t *element;
|
||||
lxb_html_document_t *document;
|
||||
lxb_dom_collection_t *collection;
|
||||
lxb_dom_attr_t *attr;
|
||||
document = lxb_html_document_create();
|
||||
status = lxb_html_document_parse(document, (lxb_char_t *)res->body.c_str(), res->body.length());
|
||||
if (status != LXB_STATUS_OK)
|
||||
return "";
|
||||
collection = lxb_dom_collection_make(&document->dom_document, 128);
|
||||
if (collection == NULL)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
|
||||
collection, (const lxb_char_t *)"form", 4);
|
||||
if (status != LXB_STATUS_OK)
|
||||
return "";
|
||||
std::string download_url;
|
||||
for (size_t i = 0; i < lxb_dom_collection_length(collection); i++)
|
||||
{
|
||||
element = lxb_dom_collection_element(collection, i);
|
||||
std::string form_id((char *)element->attr_id->value->data, element->attr_id->value->length);
|
||||
if (form_id == "download-form")
|
||||
{
|
||||
size_t value_len;
|
||||
const lxb_char_t *value = lxb_dom_element_get_attribute(element, (const lxb_char_t *)"action", 6, &value_len);
|
||||
download_url = std::string((char *)value, value_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lxb_dom_collection_destroy(collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
|
||||
return download_url;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef GDRIVE_HOST_H
|
||||
#define GDRIVE_HOST_H
|
||||
|
||||
#include "filehost.h"
|
||||
|
||||
class GDriveHost : public FileHost
|
||||
{
|
||||
public:
|
||||
GDriveHost(const std::string &url);
|
||||
bool IsValidUrl();
|
||||
std::string GetDownloadUrl();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1900,6 +1900,7 @@ namespace detail {
|
||||
|
||||
std::string encode_query_param(const std::string &value);
|
||||
|
||||
std::string encode_url(const std::string &s);
|
||||
std::string decode_url(const std::string &s, bool convert_plus_to_space);
|
||||
|
||||
void read_file(const std::string &path, std::string &out);
|
||||
|
||||
@@ -125,11 +125,14 @@ namespace INSTALLER
|
||||
else
|
||||
{
|
||||
std::string encoded_path = path;
|
||||
std::string encoded_site_name = remote_settings->site_name;
|
||||
Web::Urn::Path uri(encoded_path);
|
||||
Web::Urn::Path site_name(encoded_site_name);
|
||||
CURL *curl = curl_easy_init();
|
||||
encoded_path = uri.quote(curl);
|
||||
encoded_site_name = site_name.quote(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
std::string full_url = std::string("http://localhost:") + std::to_string(http_server_port) + "/rmt_inst" + encoded_path;
|
||||
std::string full_url = std::string("http://localhost:") + std::to_string(http_server_port) + "/rmt_inst" + encoded_site_name + encoded_path;
|
||||
|
||||
return full_url;
|
||||
}
|
||||
@@ -587,4 +590,4 @@ namespace INSTALLER
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@
|
||||
#include <orbis/Pad.h>
|
||||
#include <orbis/AudioOut.h>
|
||||
#include <orbis/Net.h>
|
||||
// #include <dbglogger.h>
|
||||
#include <dbglogger.h>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "SDL2/SDL.h"
|
||||
@@ -271,8 +271,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);
|
||||
|
||||
@@ -2,9 +2,70 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/uio.h>
|
||||
#include <orbis/libkernel.h>
|
||||
#include <libjbc.h>
|
||||
|
||||
#define SYSCALL(nr, fn) __attribute__((naked)) fn\
|
||||
{\
|
||||
asm volatile("mov $" #nr ", %rax\nmov %rcx, %r10\nsyscall\nret");\
|
||||
}
|
||||
|
||||
SYSCALL(22, static int unmount(const char* path, int flags))
|
||||
SYSCALL(378, static int nmount(struct iovec* iov, unsigned int niov, int flags))
|
||||
|
||||
static void build_iovec(struct iovec** iov, int* iovlen, const char* name, const void* val, size_t len) {
|
||||
int i;
|
||||
|
||||
if (*iovlen < 0)
|
||||
return;
|
||||
|
||||
i = *iovlen;
|
||||
*iov = (struct iovec*)realloc(*iov, sizeof **iov * (i + 2));
|
||||
if (*iov == NULL) {
|
||||
*iovlen = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
(*iov)[i].iov_base = strdup(name);
|
||||
(*iov)[i].iov_len = strlen(name) + 1;
|
||||
++i;
|
||||
|
||||
(*iov)[i].iov_base = (void*)val;
|
||||
if (len == (size_t)-1) {
|
||||
if (val != NULL)
|
||||
len = strlen((const char*)val) + 1;
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
(*iov)[i].iov_len = (int)len;
|
||||
|
||||
*iovlen = ++i;
|
||||
}
|
||||
|
||||
int mount_large_fs(const char* device, const char* mountpoint, const char* fstype, const char* mode, unsigned int flags)
|
||||
{
|
||||
struct iovec* iov = NULL;
|
||||
int iovlen = 0;
|
||||
|
||||
unmount(mountpoint, 0);
|
||||
|
||||
build_iovec(&iov, &iovlen, "fstype", fstype, -1);
|
||||
build_iovec(&iov, &iovlen, "fspath", mountpoint, -1);
|
||||
build_iovec(&iov, &iovlen, "from", device, -1);
|
||||
build_iovec(&iov, &iovlen, "large", "yes", -1);
|
||||
build_iovec(&iov, &iovlen, "timezone", "static", -1);
|
||||
build_iovec(&iov, &iovlen, "async", "", -1);
|
||||
build_iovec(&iov, &iovlen, "ignoreacl", "", -1);
|
||||
|
||||
if (mode) {
|
||||
build_iovec(&iov, &iovlen, "dirmask", mode, -1);
|
||||
build_iovec(&iov, &iovlen, "mask", mode, -1);
|
||||
}
|
||||
|
||||
return nmount(iov, iovlen, flags);
|
||||
}
|
||||
|
||||
// Variables for (un)jailbreaking
|
||||
jbc_cred g_Cred;
|
||||
jbc_cred g_RootCreds;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#ifndef __ORBIS_JBC_H__
|
||||
#define __ORBIS_JBC_H__
|
||||
|
||||
#define MNT_UPDATE 0x0000000000010000ULL
|
||||
|
||||
int initialize_jbc();
|
||||
void terminate_jbc();
|
||||
int mount_large_fs(const char* device, const char* mountpoint, const char* fstype, const char* mode, unsigned int flags);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -920,30 +920,34 @@ namespace HttpServer
|
||||
res.set_content(str.c_str(), "text/plain");
|
||||
});
|
||||
|
||||
svr->Get("/rmt_inst/(.*)", [&](const Request & req, Response & res)
|
||||
svr->Get("/rmt_inst/Site (\\d+)(/)(.*)", [&](const Request & req, Response & res)
|
||||
{
|
||||
RemoteClient *tmp_client;
|
||||
auto path = std::string("/") + std::string(req.matches[1]);
|
||||
RemoteSettings *tmp_settings;
|
||||
auto site_idx = std::stoi(req.matches[1])-1;
|
||||
auto path = std::string("/") + std::string(req.matches[3]);
|
||||
|
||||
if (remote_settings->type == CLIENT_TYPE_SFTP)
|
||||
tmp_settings = &site_settings[sites[site_idx]];
|
||||
|
||||
if (tmp_settings->type == CLIENT_TYPE_SFTP)
|
||||
{
|
||||
tmp_client = new SFTPClient();
|
||||
tmp_client->Connect(remote_settings->server, remote_settings->username, remote_settings->password);
|
||||
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
|
||||
}
|
||||
else if (remote_settings->type == CLIENT_TYPE_SMB)
|
||||
else if (tmp_settings->type == CLIENT_TYPE_SMB)
|
||||
{
|
||||
tmp_client = new SmbClient();
|
||||
tmp_client->Connect(remote_settings->server, remote_settings->username, remote_settings->password);
|
||||
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
|
||||
}
|
||||
else if (remote_settings->type == CLIENT_TYPE_FTP)
|
||||
else if (tmp_settings->type == CLIENT_TYPE_FTP)
|
||||
{
|
||||
tmp_client = new FtpClient();
|
||||
tmp_client->Connect(remote_settings->server, remote_settings->username, remote_settings->password);
|
||||
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
|
||||
}
|
||||
else if (remote_settings->type == CLIENT_TYPE_NFS)
|
||||
else if (tmp_settings->type == CLIENT_TYPE_NFS)
|
||||
{
|
||||
tmp_client = new NfsClient();
|
||||
tmp_client->Connect(remote_settings->server, remote_settings->username, remote_settings->password);
|
||||
tmp_client->Connect(tmp_settings->server, tmp_settings->username, tmp_settings->password);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1072,4 +1076,4 @@ namespace HttpServer
|
||||
if (svr != nullptr)
|
||||
svr->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user