Compare commits

...

18 Commits

Author SHA1 Message Date
Chee Yee 529d88af06 remove old hash from map 2023-08-30 13:37:17 -07:00
Chee Yee d26baf817e update readme 2023-08-30 08:34:22 -07:00
Chee Yee 01f2f44942 add ability to install via alldebrid 2023-08-30 02:30:26 -07:00
Chee Yee e28e562a10 add ability to install shared URL from web interface 2023-08-06 17:53:27 -07:00
Chee Yee 83661c7fcb add rclone http server support 2023-08-01 22:11:05 -07:00
Chee Yee 8aba3939a8 close nfs handle on error 2023-07-26 00:58:11 -07:00
Chee Yee 51eb0760d8 Merge branch 'master' of github.com:cy33hc/ps4-ezremote-client 2023-07-24 16:43:49 -07:00
Chee Yee 8c8d23603c proper closing of handles 2023-07-24 16:43:40 -07:00
cy33hc 338107c951 Merge pull request #11 from rex07/master
Update Arabic.ini
2023-07-24 08:10:07 -07:00
Chee Yee 499dbc1b27 update Arabic language 2023-07-23 21:47:49 -07:00
Rex_sa e02e81acc1 Update Arabic.ini 2023-07-24 04:03:17 +03:00
cy33hc d6c97303b0 Update README.md 2023-07-23 15:48:47 -07:00
Chee Yee d98284a050 fix type 2023-07-21 23:49:08 -07:00
Chee Yee 3dc2054e44 free memory 2023-07-21 23:47:53 -07:00
cy33hc b18f764d27 Update README.md 2023-07-21 20:39:12 -07:00
cy33hc 3354af7f88 Update README.md 2023-07-21 20:37:32 -07:00
Chee Yee 0dac26d98c add ability to install fpkgs directly direct from remote servers 2023-07-21 19:29:06 -07:00
Chee Yee 1f2b27b52a read the current chunk size 2023-07-17 22:04:05 -07:00
57 changed files with 2079 additions and 452 deletions
+9 -1
View File
@@ -40,6 +40,14 @@ add_executable(ezremote_client
source/clients/smbclient.cpp
source/clients/webdavclient.cpp
source/clients/sftpclient.cpp
source/clients/rclone.cpp
source/filehost/alldebrid.cpp
source/filehost/directhost.cpp
source/filehost/gdrive.cpp
source/filehost/filehost.cpp
source/filehost/1fichier.cpp
source/filehost/mediafire.cpp
source/filehost/pixeldrain.cpp
source/server/http_server.cpp
source/actions.cpp
source/config.cpp
@@ -62,7 +70,7 @@ add_executable(ezremote_client
add_self(ezremote_client)
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.08" 32 0)
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.10" 32 0)
target_link_libraries(ezremote_client
c
+7 -2
View File
@@ -1,9 +1,13 @@
# ezRemote Client
ezRemote Client is an application that allows you to connect the PS4 to remote FTP/SFTP, SMB, NFS, WebDAV, HTTP servers and Google Drive to transfer files. The interface is inspired by Filezilla client which provides a commander like GUI.
![Preview](/screenshot.jpg)
**New:** As of version 1.0.8, ezRemote Client has a Web Interface that can be access from any modern browser to manage the PS4 files.
**New:** As of version 1.0.9. Remote Package Installation does not require you to host an external Http Server. The embedded Web Server built into ezRemote Client acts as a Proxy Server between the PS4 and remote server (FTP, SFTP, SMB, NFS, WebDav, HttpServer(IIS/Nginx/Apache/Serve) and GoogleDrive). There's no data written to the PS4 hard drive in the process, rather everything is streamed via embedded Web Server directly to the PS4 installer.
![Preview](/screenshot.jpg)
![Preview](/ezremote_client_web.png)
## Usage
@@ -83,7 +87,7 @@ Tested with following WebDAV server:
- drivehq.com
## Remote Package Installer Feature
Remote Package Installation only works if the WebDAV server allow anonymous access. It's a limitation of the PS4 Installer not able to access protected links. As suggested, use the [Dufs](https://github.com/sigoden/dufs) app for WebDAV.
Remote Package Installation with all Remote Server, even if they are password protected.
## Features Native Application##
- Transfer files back and forth between PS4 and FTP/SMB/NFS/WebDAV server
@@ -110,6 +114,7 @@ Remote Package Installation only works if the WebDAV server allow anonymous acce
- Upload files to the PS4
- Download files from the PS4
- Install packages on the PS4
- Install packages from shared links from mediafire, google and pixeldrain. For other filehost, they can installed via AllDebrid (See AllDebrid website for supported filehost).
## How to access the Web Interface ##
You need to launch the "ezRemote Client" app on the PS4. Then on any device(laptop, tablet, phone etc..) with web browser goto to http://<ip_address_of_ps4>:8080 . That's all.
+1
View File
@@ -41,6 +41,7 @@
permissionsUrl: '/__local__/permission',
installUrl: '/__local__/install',
uploadResumeSizeUrl: '__local__/uploadResumeSize',
installUrlUrl: '/__local__/install_url',
multipleDownloadFileName: 'ezremote-client.zip',
isExtractableFilePattern: /\.(7z|rar|zip)$/i,
pickCallback: function (item) {
+113 -36
View File
@@ -1,75 +1,152 @@
STR_CONNECTION_SETTINGS=إعداد الاتصال
STR_CONNECTION_SETTINGS=إعدادات الإتصال
STR_SITE=الموقع
STR_LOCAL=محلي
STR_REMOTE=بعيد
STR_MESSAGES=الرسائل
STR_UPDATE_SOFTWARE=تحديث التطبيق
STR_CONNECT=توصيل
STR_UPDATE_SOFTWARE=تحديث البرنامج
STR_CONNECT=اتصال
STR_DISCONNECT=قطع الاتصال
STR_SEARCH=بحث
STR_REFRESH=تحديث
STR_REFRESH=تنشيط
STR_SERVER=الخادم
STR_USERNAME=اسم المستخدم
STR_PASSWORD=كلمة المرور
STR_PORT=المنفذ
STR_PASV=متجاوز
STR_DIRECTORY=المسار
STR_FILTER=الفلتر
STR_FILTER=المرشح
STR_YES=نعم
STR_NO=لا
STR_CANCEL=إلغاء
STR_CANCEL=الغاء
STR_CONTINUE=استمرار
STR_CLOSE=اغلاق
STR_FOLDER=المجلد
STR_FILE=الملف
STR_FOLDER=مجلد
STR_FILE=ملف
STR_TYPE=النوع
STR_NAME=الاسم
STR_SIZE=الحجم
STR_DATE=التاريخ
STR_NEW_FOLDER=مجلد جديد
STR_RENAME=أعادة تسمية
STR_RENAME=اعادة تسمية
STR_DELETE=حذف
STR_UPLOAD=رفع
STR_DOWNLOAD=تحميل
STR_DOWNLOAD=تنزيل
STR_SELECT_ALL=تحديد الكل
STR_CLEAR_ALL=تجاهل الكل
STR_CLEAR_ALL=الغاء الكل
STR_UPLOADING=قيد الرفع
STR_DOWNLOADING=قيد التحميل
STR_OVERWRITE=الكتابة فوق
STR_DOWNLOADING=قيد التنزيل
STR_OVERWRITE=كتابة فوق
STR_DONT_OVERWRITE=لاتكتب فوق
STR_ASK_FOR_CONFIRM=أسال لتأكيد
STR_DONT_ASK_CONFIRM=لاتسأل لتأكيد
STR_ALLWAYS_USE_OPTION=استخدم هذا الاختيار بشكل دائم ولاتسأل مجددا
STR_ACTIONS=الإجراءات
STR_ASK_FOR_CONFIRM=اطلب التاكيد
STR_DONT_ASK_CONFIRM=لاتطلب التاكيد
STR_ALLWAYS_USE_OPTION=استخدم دائما هذا الخيار ولاتسال مجددا
STR_ACTIONS=الاجرءات
STR_CONFIRM=تأكيد
STR_OVERWRITE_OPTIONS=خيارات الاستبدال او الكتابة فوق
STR_PROPERTIES=الخصائص
STR_OVERWRITE_OPTIONS=خيارات الكتابة فوف
STR_PROPERTIES=الخيارات
STR_PROGRESS=التقدم
STR_UPDATES=التحديثات
STR_DEL_CONFIRM_MSG=هل انت متأكد من اجراء حذف حذف الملف او المجلد?
STR_CANCEL_ACTION_MSG=قيد الإلغاء. بأنتظار الاتصال الاخير ليتم إلغائه
STR_DEL_CONFIRM_MSG=هل أنت متأكد أنك تريد حذف هذا الملف (الملفات) / المجلد (المجلدات)؟
STR_CANCEL_ACTION_MSG=قيدالإلغاء. في انتظار اكتمال الإجراء الأخير
STR_FAIL_UPLOAD_MSG=فشل في رفع الملف
STR_FAIL_DOWNLOAD_MSG=فشل في تحميل الملف
STR_FAIL_READ_LOCAL_DIR_MSG=فشل في قراءة محتويات المسار او المجلد غير متوفر.
STR_CONNECTION_CLOSE_ERR_MSG=٤٢٦ أغلق الاتصال.
STR_REMOTE_TERM_CONN_MSG=٤٢٦ الخادم البعيد قطع الإتصال.
STR_FAIL_LOGIN_MSG=٣٠٠ فشل تسجيل الدخول. الرجاء التاكد من اسم المستخدم وكلمة المرور.
STR_FAIL_TIMEOUT_MSG=٤٢٦ فشل. انتهى الاتصال.
STR_FAIL_DOWNLOAD_MSG=فشل في تنزيل الملف
STR_FAIL_READ_LOCAL_DIR_MSG=فشل في قراءة محتويات المسار أو المجلد غير موجود.
STR_CONNECTION_CLOSE_ERR_MSG=426 اتصال مغلق.
STR_REMOTE_TERM_CONN_MSG=426 أنهى الخادم البعيد الاتصال.
STR_FAIL_LOGIN_MSG=300 فشل تسجيل الدخول. يرجى التحقق من اسم المستخدم أو كلمة المرور الخاصة بك.
STR_FAIL_TIMEOUT_MSG=فشل 426. انتهى وقت محاولة الاتصال.
STR_FAIL_DEL_DIR_MSG=فشل في حذف المسار
STR_DELETING=قيد الحذف
STR_FAIL_DEL_FILE_MSG=فشل في حذف الملف
STR_DELETED=تم الحذف
STR_LINK=ربط
STR_LINK=رابط
STR_SHARE=مشاركة
STR_FAILED=٣١٠ فشل
STR_FAIL_CREATE_LOCAL_FILE_MSG= فشل في انشاء الملف في المحلي ٣١٠
STR_FAILED=310 فشل
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 فشل إنشاء ملف على المستوى المحلي
STR_INSTALL=تثبيت
STR_INSTALLING=يقوم بالتثبيت
STR_INSTALLING=قيد التثبيت
STR_INSTALL_SUCCESS=تم بنجاح
STR_INSTALL_FAILED=فشل
STR_INSTALL_SKIPPED=تم التخطي
STR_CHECK_HTTP_MSG=فحص الإتصال بخادم HTTP البعيد
STR_FAILED_HTTP_CHECK=فشل الإتصال بخادم HTTP
STR_INSTALL_SKIPPED=تم تخطيه
STR_CHECK_HTTP_MSG=التحقق من الاتصال بخادم HTTP البعيد
STR_FAILED_HTTP_CHECK=فشل الاتصال بخادم HTTP
STR_REMOTE_NOT_HTTP=البعيد ليس خادم HTTP
STR_INSTALL_FROM_DATA_MSG=الحزمة غير متوفرة في /data او /mnt/usbX مجلد
STR_ALREADY_INSTALLED_MSG=الحزمة مثبتة مسبقا
STR_INSTALL_FROM_DATA_MSG=الحزمة ليست في المجلد / data أو / mnt / usbX
STR_ALREADY_INSTALLED_MSG=الحزمة مثبتة بالفعل
STR_INSTALL_FROM_URL=التثبيت من الرابط
STR_CANNOT_READ_PKG_HDR_MSG=تعذرت قراءة معلومات رأس الحزمة
STR_FAVORITE_URLS=عناوين المواقع المفضلة
STR_SLOT=فتحة
STR_EDIT=تعديل
STR_ONETIME_URL=رابط لمرة واحدة
STR_NOT_A_VALID_PACKAGE=ليست حزمة صالحة
STR_WAIT_FOR_INSTALL_MSG=في انتظار انتهاء تثبيت الحزمة
STR_FAIL_INSTALL_TMP_PKG_MSG=فشل تثبيت ملف pkg. يرجى حذف tmp pkg يدويًا
STR_FAIL_TO_OBTAIN_GG_DL_MSG=فشل الحصول على رابط تحميل قوقل
STR_AUTO_DELETE_TMP_PKG=الحذف التلقائي لملف pkg الذي تم تنزيله مؤقتًا بعد التثبيت
STR_PROTOCOL_NOT_SUPPORTED=البروتكول غير مدعوم
STR_COULD_NOT_RESOLVE_HOST=لم يتم التوصل الى اسم المضيف
STR_EXTRACT=استخراج
STR_EXTRACTING=قيد الاستخراج
STR_FAILED_TO_EXTRACT=فشل في الاستخراج
STR_EXTRACT_LOCATION=مسار الاستخراج
STR_COMPRESS=ضغط
STR_ZIP_FILE_PATH=اسم الملف المضغوط
STR_COMPRESSING=قيد الضغط
STR_ERROR_CREATE_ZIP=حدث خطأ أثناء إنشاء الرمز البريدي
STR_UNSUPPORTED_FILE_FORMAT=تنسيق ملف مضغوط غير مدعوم
STR_CUT=قص
STR_COPY=نسخ
STR_PASTE=لصق
STR_MOVING=نقل
STR_COPYING=نسخ
STR_FAIL_MOVE_MSG=فشل نقل الملف
STR_FAIL_COPY_MSG=فشل نسخ الملف
STR_CANT_MOVE_TO_SUBDIR_MSG=لا يمكن نقل الدليل الأصل إلى دليل فرعي
STR_CANT_COPY_TO_SUBDIR_MSG=لا يمكن نسخ الدليل الأصل إلى دليل فرعي
STR_UNSUPPORTED_OPERATION_MSG=العملية غير مدعومة
STR_HTTP_PORT=منفذ Http
STR_REINSTALL_CONFIRM_MSG=تم بالفعل تثبيت المحتوى. هل تريد متابعة التثبيت
STR_REMOTE_NOT_SUPPORT_MSG=تثبيت الحزمة عن بعد غير مدعوم للخوادم المحمية.
STR_CANNOT_CONNECT_REMOTE_MSG=لا يمكن الوصول إلى خادم HTTP البعيد.
STR_DOWNLOAD_INSTALL_MSG=تثبيت الحزمة عن بعد غير ممكن. هل ترغب في تنزيل الحزمة وتثبيتها بدلاً من ذلك؟
STR_CHECKING_REMOTE_SERVER_MSG=التحقق من الخادم البعيد لتثبيت الحزمة عن بعد.
STR_ENABLE_RPI=RPI
STR_ENABLE_RPI_FTP_SMB_MSG=يتيح هذا الخيار تثبيت الحزمة عن بُعد عبر خادم الويب المضمن.
STR_ENABLE_RPI_WEBDAV_MSG==يتيح هذا الخيار تثبيت الحزمة عن بُعد عبر خادم الويب المضمن.
STR_FILES=الملفات
STR_EDITOR=المحرر
STR_SAVE=حفظ
STR_MAX_EDIT_FILE_SIZE_MSG=لا يمكن تحرير ملفات أكبر من
STR_DELETE_LINE=حذف الخط المحدد
STR_INSERT_LINE=ادخال تحت الخط المخصص
STR_MODIFIED=معدل
STR_FAIL_GET_TOKEN_MSG=فشل الحصول على رمز وصول من
STR_GET_TOKEN_SUCCESS_MSG=النجاح في تسجيل الدخول. يمكنك إغلاق المتصفح والعودة إلى التطبيق
STR_PERM_DRIVE=يمكنك الاطلاع على جميع ملفات Google Drive وتعديلها وإنشاؤها وحذفها
STR_PERM_DRIVE_APPDATA=مشاهدة وإنشاء وحذف بيانات التكوين الخاصة به في Google Drive الخاص بك
STR_PERM_DRIVE_FILE=يمكنك مشاهدة ملفات Google Drive المحددة التي تستخدمها مع هذا التطبيق وتعديلها وإنشاؤها وحذفها فقط
STR_PERM_DRIVE_METADATA=عرض وإدارة البيانات الوصفية للملفات في Google Drive
STR_PERM_DRIVE_METADATA_RO=اطلع على معلومات حول ملفات Google Drive الخاصة بك
STR_GOOGLE_LOGIN_FAIL_MSG=فشل تسجيل الدخول إلى Google
STR_GOOGLE_LOGIN_TIMEOUT_MSG=انتهت مهلة تسجيل الدخول إلى Google
STR_NEW_FILE=ملف جديد
STR_SETTINGS=الاعدادات
STR_CLIENT_ID=معرف العميل
STR_CLIENT_SECRET=اسرار الخادم
STR_GLOBAL=عالمي
STR_GOOGLE=قوقل
STR_COPY_LINE=نسخ النص المحدد
STR_PASTE_LINE=لصق في الخط المخصص
STR_SHOW_HIDDEN_FILES=اضهار الملفات المخفيه
STR_SET_DEFAULT_DIRECTORY=تعيين المجلد الافتراضي
STR_SET_DEFAULT_DIRECTORY_MSG=تم تعيينه كمسار افتراضي
STR_VIEW_IMAGE=عرض الصور
STR_VIEW_PKG_INFO=معلومات الحزمة
STR_NFS_EXP_PATH_MISSING_MSG=مسار تصدير NFS مفقود في URL
STR_FAIL_INIT_NFS_CONTEXT=فشل في تهيئة سياق NFS
STR_FAIL_MOUNT_NFS_MSG=فشل تحميل مشاركة NFS
STR_WEB_SERVER=خادم الويب
STR_ENABLE=تمكين
STR_COMPRESSED_FILE_PATH=مسار الملف المظغوط
STR_COMPRESSED_FILE_PATH_MSG=المسار حيث يتم تخزين الملفات المضغوطة على خادم الويب
+9 -3
View File
@@ -82,7 +82,7 @@ STR_ONETIME_URL=One Time Url
STR_NOT_A_VALID_PACKAGE=Not a valid Package
STR_WAIT_FOR_INSTALL_MSG=Waiting for Package to finish installing
STR_FAIL_INSTALL_TMP_PKG_MSG=Failed to install pkg file. Please delete the tmp pkg manually
STR_FAIL_TO_OBTAIN_GG_DL_MSG=Failed to obtain google download URL
STR_FAIL_TO_OBTAIN_GG_DL_MSG=Failed to obtain download URL
STR_AUTO_DELETE_TMP_PKG=Auto delete temporary downloaded pkg file after install
STR_PROTOCOL_NOT_SUPPORTED=Protocol not supported
STR_COULD_NOT_RESOLVE_HOST=Could not resolve hostname
@@ -112,8 +112,8 @@ STR_CANNOT_CONNECT_REMOTE_MSG=Remote HTTP Server not reachable.
STR_DOWNLOAD_INSTALL_MSG=Remote Package Install not possible. Would you like to download package and install instead?
STR_CHECKING_REMOTE_SERVER_MSG=Checking remote server for Remote Package Install.
STR_ENABLE_RPI=RPI
STR_ENABLE_RPI_FTP_SMB_MSG=This option enables Remote Package Installation. This requires a HTTP Server setup on the same host sharing the same folder with anonymous access.
STR_ENABLE_RPI_WEBDAV_MSG=This option enables Remote Package Installation. This requires the Server with anonymous access that does not need username/password.
STR_ENABLE_RPI_FTP_SMB_MSG=This option enables Remote Package Installation via embedded Web Server.
STR_ENABLE_RPI_WEBDAV_MSG==This option enables Remote Package Installation via embedded Web Server.
STR_FILES=Files
STR_EDITOR=Editor
STR_SAVE=Save
@@ -150,3 +150,9 @@ STR_WEB_SERVER=Web Server
STR_ENABLE=Enable
STR_COMPRESSED_FILE_PATH=Compressed Files Location
STR_COMPRESSED_FILE_PATH_MSG=Location of where compressed files are stored on the web server
STR_ALLDEBRID=AllDebrid
STR_API_KEY=API Key
STR_CANT_EXTRACT_URL_MSG=Couldn't extract download url
STR_FAIL_INSTALL_FROM_URL_MSG=Failed to install from URL
STR_INVALID_URL=InValid URL
STR_ALLDEBRID_API_KEY_MISSING_MSG=To use this function, an API Key needs to be configured in the ezRemote Client settings
+2 -2
View File
@@ -112,8 +112,8 @@ STR_CANNOT_CONNECT_REMOTE_MSG=Servidor HTTP remoto não esta acessível.
STR_DOWNLOAD_INSTALL_MSG=A instalação remota do pacote não é possível. Você gostaria de baixar o pacote e instalar?
STR_CHECKING_REMOTE_SERVER_MSG=Verificando servidor remoto para instalação de pacote remoto.
STR_ENABLE_RPI=RPI
STR_ENABLE_RPI_FTP_SMB_MSG=Esta opção permite a instalação remota de pacotes. Isso requer uma configuração de servidor HTTP no mesmo Host compartilhando a mesma pasta com acesso anônimo.
STR_ENABLE_RPI_WEBDAV_MSG=Esta opção permite a instalação remota de pacotes. Isso requer o servidor com acesso anônimo que não precisa de nome de usuário/senha.
STR_ENABLE_RPI_FTP_SMB_MSG=Esta opção permite a instalação remota de pacotes.
STR_ENABLE_RPI_WEBDAV_MSG=Esta opção permite a instalação remota de pacotes.
STR_FILES=Arquivos
STR_EDITOR=Editar
STR_SAVE=Salvar
File diff suppressed because one or more lines are too long
+20 -84
View File
@@ -4,6 +4,7 @@
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <minizip/unzip.h>
#include <orbis/SystemService.h>
#include "clients/gdrive.h"
#include "clients/ftpclient.h"
#include "clients/smbclient.h"
@@ -13,7 +14,9 @@
#include "clients/npxserve.h"
#include "clients/nfsclient.h"
#include "clients/iis.h"
#include "clients/rclone.h"
#include "clients/sftpclient.h"
#include "filehost/filehost.h"
#include "common.h"
#include "fs.h"
#include "config.h"
@@ -365,6 +368,7 @@ namespace Actions
return remoteclient->Put(src, dest);
}
sceSystemServicePowerTick();
return 1;
}
@@ -516,6 +520,7 @@ namespace Actions
return remoteclient->Get(dest, src);
}
sceSystemServicePowerTick();
return 1;
}
@@ -672,6 +677,7 @@ namespace Actions
{
download_and_install = true;
}
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
if (stop_activity)
@@ -702,7 +708,8 @@ namespace Actions
}
else
{
if (INSTALLER::InstallRemotePkg(it->path, &header) == 0)
std::string url = INSTALLER::getRemoteUrl(it->path, true);
if (INSTALLER::InstallRemotePkg(url, &header, true) == 0)
failed++;
else
success++;
@@ -914,87 +921,6 @@ namespace Actions
}
}
std::string GetGoogleDownloadUrl(std::string &url)
{
size_t scheme_pos = url.find_first_of("://");
size_t path_pos = url.find_first_of("/", scheme_pos + 3);
std::string host = url.substr(0, path_pos);
std::string path = url.substr(path_pos);
std::string first_download_path;
size_t file_id_start_pos = path.find("/file/d/");
if (file_id_start_pos != std::string::npos)
{
file_id_start_pos = file_id_start_pos + 8;
std::string file_id = path.substr(file_id_start_pos);
size_t file_id_end_pos = file_id.find_first_of("/");
file_id = file_id.substr(0, file_id_end_pos);
first_download_path = "/uc?export=download&id=" + file_id;
}
else if (path.find("/uc?export=download") != std::string::npos)
{
first_download_path = path;
}
else
{
return "";
}
WebDAV::WebDavClient tmp_client;
tmp_client.Connect(host.c_str(), "", "", false);
WebDAV::dict_t headers;
tmp_client.GetHeaders(first_download_path.c_str(), &headers);
std::string content_type = WebDAV::get(headers, "content-type");
if (content_type.find("application/octet-stream") != std::string::npos)
{
return first_download_path;
}
else if (content_type.find("text/html") == std::string::npos)
{
return "";
}
char *buffer_ptr = nullptr;
unsigned long long buffer_size = 0;
tmp_client.GetClient()->download_to(first_download_path, buffer_ptr, buffer_size);
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 *)buffer_ptr, buffer_size);
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;
}
void *InstallUrlPkgThread(void *argp)
{
bytes_transfered = 0;
@@ -1008,8 +934,16 @@ namespace Actions
sprintf(filename, "%s/%lu.pkg", DATA_PATH, tick.mytick);
std::string full_url = std::string(install_pkg_url.url);
if (full_url.find("https://drive.google.com") != std::string::npos)
full_url = GetGoogleDownloadUrl(full_url);
FileHost *filehost = FileHost::getFileHost(full_url);
if (!filehost->IsValidUrl())
{
sprintf(status_message, "%s", lang_strings[STR_FAIL_TO_OBTAIN_GG_DL_MSG]);
activity_inprogess = false;
Windows::SetModalMode(false);
return NULL;
}
full_url = filehost->GetDownloadUrl();
delete(filehost);
if (full_url.empty())
{
@@ -1129,6 +1063,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)
{
+6 -2
View File
@@ -6,7 +6,7 @@
class Base64
{
public:
static int Encode(const std::string &input, std::string &out)
static int Encode(unsigned char *input, size_t in_len, std::string &out)
{
static constexpr char sEncodingTable[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
@@ -18,7 +18,6 @@ public:
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
size_t in_len = input.size();
size_t out_len = 4 * ((in_len + 2) / 3);
out.resize(out_len);
size_t i;
@@ -50,6 +49,11 @@ public:
return 1;
}
static int Encode(const std::string &input, std::string &out)
{
return Encode((unsigned char*)input.data(), input.size(), out);
}
static int Decode(const std::string &input, std::string &out)
{
static constexpr unsigned char kDecodingTable[] = {
+5 -25
View File
@@ -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);
+23 -2
View File
@@ -1,5 +1,3 @@
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include <curl/curl.h>
#include "common.h"
@@ -94,6 +92,29 @@ int BaseClient::Get(const std::string &outputfile, const std::string &path, uint
return 0;
}
int BaseClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
{
char range_header[64];
sprintf(range_header, "bytes=%lu-%lu", offset, offset+size-1);
Headers headers = {{"Range", range_header}};
size_t bytes_read = 0;
if (auto res = client->Get(GetFullPath(path), headers,
[&](const char *data, size_t data_length)
{
bytes_read += data_length;
bool ok = sink.write(data, data_length);
return ok;
}))
{
return bytes_read == size;
}
else
{
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
}
return 0;
}
int BaseClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
{
char range_header[64];
+4
View File
@@ -3,8 +3,11 @@
#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"
#include "common.h"
class BaseClient : public RemoteClient
@@ -18,6 +21,7 @@ public:
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset);
int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
+39
View File
@@ -1266,6 +1266,45 @@ int FtpClient::Get(const std::string &outputfile, const std::string &path, uint6
return FtpXfer(outputfile, path, mp_ftphandle, FtpClient::filereadappend, FtpClient::transfermode::image);
}
int FtpClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
{
ftphandle *nData;
mp_ftphandle->offset = offset;
if (!FtpAccess(path, FtpClient::fileread, FtpClient::transfermode::image, mp_ftphandle, &nData))
{
return 0;
}
char buf[FTP_CLIENT_BUFSIZ];
int count = 0;
size_t bytes_remaining = size;
do
{
size_t bytes_to_read = std::min<size_t>(FTP_CLIENT_BUFSIZ, bytes_remaining);
count = FtpRead(buf, bytes_to_read, nData);
if (count > 0)
{
bytes_remaining -= count;
bool ok = sink.write((char*)buf, count);
if (!ok)
{
FtpClose(nData);
mp_ftphandle->offset = 0;
return 0;
}
}
else
{
break;
}
} while (1);
FtpClose(nData);
mp_ftphandle->offset = 0;
return 1;
}
int FtpClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
{
ftphandle *nData;
+2
View File
@@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include "clients/remote_client.h"
#include "http/httplib.h"
#define FTP_CLIENT_MAX_FILENAME_LEN 128
@@ -79,6 +80,7 @@ public:
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset = 0);
int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset);
int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset = 0);
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
+29
View File
@@ -331,6 +331,35 @@ int GDriveClient::Get(const std::string &outputfile, const std::string &path, ui
return 0;
}
int GDriveClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
{
size_t bytes_read = 0;
std::string id = GetValue(path_id_map, path);
std::string drive_id = GetDriveId(path);
std::string url = std::string("/drive/v3/files/") + BaseClient::EncodeUrl(id) + "?alt=media";
if (!drive_id.empty())
url += "&supportsAllDrives=true";
Headers headers;
headers.insert(std::make_pair("Range", "bytes=" + std::to_string(offset) + "-" + std::to_string(offset + size - 1)));
if (auto res = client->Get(url, headers,
[&](const char *data, size_t data_length)
{
bytes_read += data_length;
bool ok = sink.write(data, data_length);
return ok;
}))
{
return bytes_read == size;
}
else
{
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
}
return 0;
}
int GDriveClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
{
size_t bytes_read = 0;
+2
View File
@@ -6,6 +6,7 @@
#include "http/httplib.h"
#include "clients/remote_client.h"
#include "clients/baseclient.h"
#include "http/httplib.h"
#include "common.h"
static pthread_t refresh_token_thid;
@@ -20,6 +21,7 @@ public:
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 GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset);
int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
int Head(const std::string &path, void *buffer, uint64_t len);
int Update(const std::string &inputfile, const std::string &path);
+46 -1
View File
@@ -17,7 +17,7 @@
#include "util.h"
#include "system.h"
#define BUF_SIZE 64*1024
#define BUF_SIZE 256*1024
NfsClient::NfsClient()
{
@@ -233,6 +233,51 @@ int NfsClient::Get(const std::string &outputfile, const std::string &ppath, uint
return 1;
}
int NfsClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
{
struct nfsfh *nfsfh = nullptr;
int ret = nfs_open(nfs, path.c_str(), 0400, &nfsfh);
if (ret != 0)
{
return 0;
}
ret = nfs_lseek(nfs, nfsfh, offset, SEEK_SET, NULL);
if (ret != 0)
{
return 0;
}
void *buff = malloc(BUF_SIZE);
int count = 0;
size_t bytes_remaining = size;
do
{
size_t bytes_to_read = std::min<size_t>(BUF_SIZE, bytes_remaining);
count = nfs_read(nfs, nfsfh, bytes_to_read, buff);
if (count > 0)
{
bytes_remaining -= count;
bool ok = sink.write((char*)buff, count);
if (!ok)
{
free((void *)buff);
nfs_close(nfs, nfsfh);
return 0;
}
}
else
{
break;
}
} while (1);
free((void *)buff);
nfs_close(nfs, nfsfh);
return 1;
}
int NfsClient::GetRange(const std::string &ppath, void *buffer, uint64_t size, uint64_t offset)
{
if (!FileExists(ppath))
+2
View File
@@ -10,6 +10,7 @@
#include "nfsc/libnfs-raw.h"
#include "nfsc/libnfs-raw-mount.h"
#include "clients/remote_client.h"
#include "http/httplib.h"
#include "common.h"
class NfsClient : public RemoteClient
@@ -23,6 +24,7 @@ public:
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset);
int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
+225
View File
@@ -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, &lt);
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;
}
+17
View File
@@ -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
+5
View File
@@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include "common.h"
#include "http/httplib.h"
enum RemoteActions
{
@@ -25,6 +26,7 @@ enum RemoteActions
enum ClientType
{
CLIENT_TYPE_FTP,
CLIENT_TYPE_SFTP,
CLIENT_TYPE_SMB,
CLIENT_TYPE_WEBDAV,
CLIENT_TYPE_HTTP_SERVER,
@@ -33,6 +35,8 @@ enum ClientType
CLINET_TYPE_UNKNOWN
};
using namespace httplib;
class RemoteClient
{
public:
@@ -50,6 +54,7 @@ public:
virtual int Move(const std::string &from, const std::string &to) = 0;
virtual int Head(const std::string &path, void *buffer, uint64_t len) = 0;
virtual int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset) = 0;
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 std::string GetPath(std::string path1, std::string path2) = 0;
+44 -1
View File
@@ -255,6 +255,7 @@ int SFTPClient::Size(const std::string &path, int64_t *size)
{
return 0;
}
*size = attrs.filesize;
return 1;
}
@@ -296,12 +297,54 @@ int SFTPClient::Get(const std::string &outputfile, const std::string &path, uint
break;
}
} while (1);
free((char *)buff);
FS::Close(out);
libssh2_sftp_close(sftp_handle);
return 1;
}
int SFTPClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
{
LIBSSH2_SFTP_HANDLE *sftp_handle = libssh2_sftp_open(sftp_session, path.c_str(), LIBSSH2_FXF_READ, 0);
if (!sftp_handle)
{
sprintf(response, "Unable to open file with SFTP: %ld", libssh2_sftp_last_error(sftp_session));
return 0;
}
libssh2_sftp_seek64(sftp_handle, offset);
char *buff = (char *)malloc(FTP_CLIENT_BUFSIZ);
int rc, count = 0;
size_t bytes_remaining = size;
do
{
size_t bytes_to_read = std::min<size_t>(FTP_CLIENT_BUFSIZ, bytes_remaining);
rc = libssh2_sftp_read(sftp_handle, buff, bytes_to_read);
if (rc > 0)
{
bytes_remaining -= rc;
bool ok = sink.write(buff, rc);
if (!ok)
{
free((char *)buff);
libssh2_sftp_close(sftp_handle);
return 0;
}
}
else
{
break;
}
} while (1);
free((char *)buff);
libssh2_sftp_close(sftp_handle);
return 1;
}
int SFTPClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
{
int64_t filesize;
@@ -601,7 +644,7 @@ int SFTPClient::Quit()
ClientType SFTPClient::clientType()
{
return CLIENT_TYPE_FTP;
return CLIENT_TYPE_SFTP;
}
uint32_t SFTPClient::SupportedActions()
+2
View File
@@ -6,6 +6,7 @@
#include <string>
#include <vector>
#include "clients/remote_client.h"
#include "http/httplib.h"
#include "common.h"
class SFTPClient : public RemoteClient
@@ -20,6 +21,7 @@ public:
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset);
int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
+42
View File
@@ -226,6 +226,48 @@ int SmbClient::Get(const std::string &outputfile, const std::string &ppath, uint
return 1;
}
int SmbClient::GetRange(const std::string &ppath, DataSink &sink, uint64_t size, uint64_t offset)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
struct smb2fh* in = smb2_open(smb2, path.c_str(), O_RDONLY);
if (in == NULL)
{
return 0;
}
smb2_lseek(smb2, in, offset, SEEK_SET, NULL);
uint8_t *buff = (uint8_t*)malloc(max_read_size);
int count = 0;
size_t bytes_remaining = size;
do
{
size_t bytes_to_read = std::min<size_t>(max_read_size, bytes_remaining);
count = smb2_read(smb2, in, buff, bytes_to_read);
if (count > 0)
{
bytes_remaining -= count;
bool ok = sink.write((char*)buff, count);
if (!ok)
{
free((uint8_t *)buff);
smb2_close(smb2, in);
return 0;
}
}
else
{
break;
}
} while (1);
free((char *)buff);
smb2_close(smb2, in);
return 1;
}
int SmbClient::GetRange(const std::string &ppath, void *buffer, uint64_t size, uint64_t offset)
{
std::string path = std::string(ppath);
+2
View File
@@ -8,6 +8,7 @@
#include <vector>
#include <smb2/smb2.h>
#include <smb2/libsmb2.h>
#include "http/httplib.h"
#include "clients/remote_client.h"
#include "common.h"
@@ -24,6 +25,7 @@ public:
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset);
int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
+5
View File
@@ -215,6 +215,11 @@ namespace WebDAV
return 1;
}
int WebDavClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
{
return client->download_range_to(path, sink, offset, offset+size-1);
}
/*
* Put - issue a PUT command and send data from input
*
+4
View File
@@ -5,10 +5,13 @@
#include <string>
#include <vector>
#include <regex>
#include "http/httplib.h"
#include "webdav/client.hpp"
#include "clients/remote_client.h"
#include "common.h"
using namespace httplib;
namespace WebDAV
{
inline std::string GetHttpUrl(std::string url)
@@ -29,6 +32,7 @@ namespace WebDAV
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset);
int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
+42
View File
@@ -4,6 +4,8 @@
#include <string>
#include <vector>
#include <string.h>
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#define HTTP_SUCCESS(x) (x >= 200 && x < 300)
#define MIN(a,b) (((a)<(b))?(a):(b))
@@ -86,4 +88,44 @@ struct DirEntry
}
};
static 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;
}
static 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;
}
static lxb_dom_node_t *NextChildTextNode(lxb_dom_element_t *element)
{
lxb_dom_node_t *node = element->node.first_child;
while (node != nullptr && node->type != LXB_DOM_NODE_TYPE_TEXT)
{
node = node->next;
}
return node;
}
static lxb_dom_node_t *NextTextNode(lxb_dom_node_t *node)
{
lxb_dom_node_t *next = node->next;
while (next != nullptr && next->type != LXB_DOM_NODE_TYPE_TEXT)
{
next = next->next;
}
return next;
}
#endif
+32 -7
View File
@@ -37,6 +37,7 @@ bool auto_delete_tmp_pkg;
int max_edit_file_size;
GoogleAppInfo gg_app;
bool show_hidden_files;
char alldebrid_api_key[32];
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'};
@@ -82,10 +83,14 @@ namespace CONFIG
{
setting->type = CLIENT_TYPE_SMB;
}
else if (strncmp(setting->server, "ftp://", 6) == 0 || strncmp(setting->server, "sftp://", 7) == 0)
else if (strncmp(setting->server, "ftp://", 6) == 0)
{
setting->type = CLIENT_TYPE_FTP;
}
else if (strncmp(setting->server, "sftp://", 7) == 0)
{
setting->type = CLIENT_TYPE_SFTP;
}
else if (strncmp(setting->server, "webdav://", 9) == 0 || strncmp(setting->server, "webdavs://", 10) == 0)
{
setting->type = CLIENT_TYPE_WEBDAV;
@@ -147,7 +152,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" };
@@ -177,6 +182,22 @@ namespace CONFIG
show_hidden_files = ReadBool(CONFIG_GLOBAL, CONFIG_SHOW_HIDDEN_FILES, false);
WriteBool(CONFIG_GLOBAL, CONFIG_SHOW_HIDDEN_FILES, show_hidden_files);
// alldebrid api key
char tmp_api_key[512];
sprintf(tmp_api_key, "%s", ReadString(CONFIG_GLOBAL, CONFIG_ALLDEBRID_API_KEY, ""));
std::string encrypted_api_key;
if (strlen(tmp_api_key) > 0)
{
std::string decrypted__api_key;
int ret = Decrypt(tmp_api_key, decrypted__api_key);
if (ret == 0)
sprintf(alldebrid_api_key, "%s", tmp_api_key);
else
sprintf(alldebrid_api_key, "%s", decrypted__api_key.c_str());
Encrypt(alldebrid_api_key, encrypted_api_key);
}
WriteString(CONFIG_GLOBAL, CONFIG_ALLDEBRID_API_KEY, encrypted_api_key.c_str());
// Load Google Account Info
sprintf(gg_app.client_id, "%s", ReadString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_ID, ""));
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_ID, gg_app.client_id);
@@ -244,10 +265,7 @@ namespace CONFIG
}
WriteString(sites[i].c_str(), CONFIG_REMOTE_SERVER_PASSWORD, encrypted_password.c_str());
setting.http_port = ReadInt(sites[i].c_str(), CONFIG_REMOTE_SERVER_HTTP_PORT, 80);
WriteInt(sites[i].c_str(), CONFIG_REMOTE_SERVER_HTTP_PORT, setting.http_port);
setting.enable_rpi = ReadBool(sites[i].c_str(), CONFIG_ENABLE_RPI, false);
setting.enable_rpi = ReadBool(sites[i].c_str(), CONFIG_ENABLE_RPI, true);
WriteBool(sites[i].c_str(), CONFIG_ENABLE_RPI, setting.enable_rpi);
sprintf(setting.http_server_type, "%s", ReadString(sites[i].c_str(), CONFIG_REMOTE_HTTP_SERVER_TYPE, HTTP_SERVER_APACHE));
@@ -322,7 +340,6 @@ namespace CONFIG
WriteString(last_site, CONFIG_REMOTE_SERVER_URL, remote_settings->server);
WriteString(last_site, CONFIG_REMOTE_SERVER_USER, remote_settings->username);
WriteString(last_site, CONFIG_REMOTE_SERVER_PASSWORD, encrypted_text.c_str());
WriteInt(last_site, CONFIG_REMOTE_SERVER_HTTP_PORT, remote_settings->http_port);
WriteBool(last_site, CONFIG_ENABLE_RPI, remote_settings->enable_rpi);
WriteString(last_site, CONFIG_REMOTE_HTTP_SERVER_TYPE, remote_settings->http_server_type);
WriteString(last_site, CONFIG_REMOTE_DEFAULT_DIRECTORY, remote_settings->default_directory);
@@ -355,9 +372,17 @@ namespace CONFIG
Encrypt(gg_app.client_secret, encrypted_secret);
else
encrypted_secret = std::string(gg_app.client_secret);
std::string encrypted_api_key;
if (strlen(alldebrid_api_key) > 0)
Encrypt(alldebrid_api_key, encrypted_api_key);
else
encrypted_api_key = std::string(alldebrid_api_key);
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_SECRET, encrypted_secret.c_str());
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_ID, gg_app.client_id);
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_PERMISSIONS, gg_app.permissions);
WriteString(CONFIG_GLOBAL, CONFIG_ALLDEBRID_API_KEY, encrypted_api_key.c_str());
WriteBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, auto_delete_tmp_pkg);
WriteBool(CONFIG_GLOBAL, CONFIG_SHOW_HIDDEN_FILES, show_hidden_files);
WriteInt(CONFIG_HTTP_SERVER, CONFIG_HTTP_SERVER_PORT, http_server_port);
+4 -1
View File
@@ -57,6 +57,8 @@
#define CONFIG_REMOTE_HTTP_SERVER_TYPE "remote_server_http_server_type"
#define CONFIG_REMOTE_DEFAULT_DIRECTORY "remote_server_default_directory"
#define CONFIG_ALLDEBRID_API_KEY "alldebrid_api_key"
#define CONFIG_VERSION "config_version"
#define CONFIG_VERSION_NUM 1
@@ -75,6 +77,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
@@ -98,7 +101,6 @@ struct RemoteSettings
char server[256];
char username[33];
char password[128];
int http_port;
ClientType type;
bool enable_rpi;
uint32_t supported_actions;
@@ -135,6 +137,7 @@ extern unsigned char cipher_key[32];
extern unsigned char cipher_iv[16];
extern GoogleAppInfo gg_app;
extern bool show_hidden_files;
extern char alldebrid_api_key[32];
namespace CONFIG
{
+142
View File
@@ -0,0 +1,142 @@
#include <regex>
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <http/httplib.h>
#include "common.h"
#include "1fichier.h"
#define VALIDATION_REGEX "https:\\/\\/1fichier\\.com\\/(.*)"
FichierHost::FichierHost(const std::string &url) : FileHost(url)
{
}
bool FichierHost::IsValidUrl()
{
std::regex regex(VALIDATION_REGEX);
if (std::regex_match(url, regex))
return true;
return false;
}
std::string FichierHost::GetDownloadUrl()
{
std::regex re("https:\\/\\/1fichier\\.com");
std::string path = std::regex_replace(url, re, "");
httplib::Client tmp_client("https://1fichier.com");
tmp_client.set_keep_alive(true);
tmp_client.set_follow_location(true);
tmp_client.set_connection_timeout(30);
tmp_client.set_read_timeout(30);
tmp_client.enable_server_certificate_verification(false);
auto res = tmp_client.Get(path);
if (HTTP_SUCCESS(res->status))
{
lxb_status_t status;
lxb_dom_element_t *element;
lxb_dom_node_t *node;
lxb_html_document_t *document;
lxb_dom_collection_t *collection;
lxb_dom_attr_t *attr;
const lxb_char_t *value;
size_t value_len;
std::string download_url = "";
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)
{
lxb_html_document_destroy(document);
return "";
}
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
collection, (const lxb_char_t *)"input", 5);
if (status != LXB_STATUS_OK)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
return "";
}
std::string post_data;
for (size_t i = 0; i < lxb_dom_collection_length(collection); i++)
{
element = lxb_dom_collection_element(collection, i);
value = lxb_dom_element_get_attribute(element, (const lxb_char_t *)"name", 4, &value_len);
if (value != nullptr)
{
std::string name_attr((char *)value, value_len);
if (name_attr == "adz")
{
value = lxb_dom_element_get_attribute(element, (const lxb_char_t *)"value", 5, &value_len);
std::string adz_value((char *)value, value_len);
post_data = std::string("adz=") + adz_value + "&did=0&dl_no_ssl=off&dlinline=on";
break;
}
}
}
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
if (auto res = tmp_client.Post(path, post_data.c_str(), post_data.length(), "application/x-www-form-urlencoded"))
{
if (HTTP_SUCCESS(res->status))
{
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)
{
lxb_html_document_destroy(document);
return "";
}
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
collection, (const lxb_char_t *)"a", 1);
if (status != LXB_STATUS_OK)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
return "";
}
for (size_t i = 0; i < lxb_dom_collection_length(collection); i++)
{
element = lxb_dom_collection_element(collection, i);
value = lxb_dom_element_get_attribute(element, (const lxb_char_t *)"class", 5, &value_len);
if (value != nullptr)
{
std::string class_value((char*) value, value_len);
if (class_value == "ok btn-general btn-orange")
{
value = lxb_dom_element_get_attribute(element, (const lxb_char_t *)"href", 4, &value_len);
if (value != nullptr)
{
download_url = std::string((char*) value, value_len);
break;
}
}
}
}
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
}
}
return download_url;
}
return "";
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef FICHIER_HOST_H
#define FICHIER_HOST_H
#include "filehost.h"
class FichierHost : public FileHost
{
public:
FichierHost(const std::string &url);
bool IsValidUrl();
std::string GetDownloadUrl();
};
#endif
+64
View File
@@ -0,0 +1,64 @@
#include <http/httplib.h>
#include <json-c/json.h>
#include "config.h"
#include "common.h"
#include "alldebrid.h"
AllDebridHost::AllDebridHost(const std::string &url) : FileHost(url)
{
}
bool AllDebridHost::IsValidUrl()
{
httplib::Client tmp_client("https://api.alldebrid.com");
tmp_client.set_keep_alive(true);
tmp_client.set_follow_location(true);
tmp_client.set_connection_timeout(30);
tmp_client.set_read_timeout(30);
tmp_client.enable_server_certificate_verification(false);
std::string path = std::string("/v4/link/unlock?agent=ezRemoteClient&apikey=") + alldebrid_api_key + "&link=" + httplib::detail::encode_url(url);
auto res = tmp_client.Get(path);
if (HTTP_SUCCESS(res->status))
{
json_object *jobj = json_tokener_parse(res->body.c_str());
const char *status = json_object_get_string(json_object_object_get(jobj, "status"));
if (strcmp(status, "success") == 0)
return true;
}
return false;
}
std::string AllDebridHost::GetDownloadUrl()
{
httplib::Client tmp_client("https://api.alldebrid.com");
tmp_client.set_keep_alive(true);
tmp_client.set_follow_location(true);
tmp_client.set_connection_timeout(30);
tmp_client.set_read_timeout(30);
tmp_client.enable_server_certificate_verification(false);
std::string path = std::string("/v4/link/unlock?agent=ezRemoteClient&apikey=") + alldebrid_api_key + "&link=" + httplib::detail::encode_url(url);
auto res = tmp_client.Get(path);
if (HTTP_SUCCESS(res->status))
{
json_object *jobj = json_tokener_parse(res->body.c_str());
const char *status = json_object_get_string(json_object_object_get(jobj, "status"));
if (status != nullptr && strcmp(status, "success") == 0)
{
json_object *data = json_object_object_get(jobj, "data");
const char *link = json_object_get_string(json_object_object_get(data, "link"));
return std::string(link);
}
else
{
return "";
}
}
return "";
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef ALLDEBRID_HOST_H
#define ALLDEBRID_HOST_H
#include "filehost.h"
class AllDebridHost : public FileHost
{
public:
AllDebridHost(const std::string &url);
bool IsValidUrl();
std::string GetDownloadUrl();
};
#endif
+28
View File
@@ -0,0 +1,28 @@
#include <regex>
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <http/httplib.h>
#include "common.h"
#include "directhost.h"
#define VALIDATION_REGEX "(.*)"
DirectHost::DirectHost(const std::string &url) : FileHost(url)
{
}
bool DirectHost::IsValidUrl()
{
std::regex regex_1(VALIDATION_REGEX);
if (std::regex_match(url, regex_1))
return true;
return false;
}
std::string DirectHost::GetDownloadUrl()
{
return url;
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef DIRECT_HOST_H
#define DIRECT_HOST_H
#include "filehost.h"
class DirectHost : public FileHost
{
public:
DirectHost(const std::string &url);
bool IsValidUrl();
std::string GetDownloadUrl();
};
#endif
+67
View File
@@ -0,0 +1,67 @@
#include <regex>
#include <string>
#include <vector>
#include <map>
#include "openssl/md5.h"
#include "filehost.h"
#include "1fichier.h"
#include "filehost/alldebrid.h"
#include "filehost/directhost.h"
#include "filehost/gdrive.h"
#include "filehost/mediafire.h"
#include "filehost/pixeldrain.h"
#include "config.h"
#include "base64.h"
#include "util.h"
#define GDRIVE_REGEX "https:\\/\\/drive\\.google\\.com\\/(.*)"
#define MEDIAFIRE_REGEX "https:\\/\\/www\\.mediafire\\.com\\/(.*)"
#define PIXELDRAIN_REGEX "https:\\/\\/pixeldrain\\.com\\/(.*)"
#define FICHIER_REGEX "https:\\/\\/1fichier\\.com\\/(.*)"
static std::map<std::string, std::string> cache_downloal_urls;
std::string FileHost::Hash()
{
std::vector<unsigned char> res(16);
MD5((const unsigned char *)this->url.c_str(), this->url.length(), res.data());
std::string out;
Base64::Encode(res.data(), res.size(), out);
Util::ReplaceAll(out, "=", "_");
Util::ReplaceAll(out, "+", "_");
out = out + ".pkg";
return out;
}
FileHost *FileHost::getFileHost(const std::string &url, bool use_alldebrid)
{
std::regex google_re(GDRIVE_REGEX);
std::regex mediafire_re(MEDIAFIRE_REGEX);
std::regex pixeldrain_re(PIXELDRAIN_REGEX);
std::regex fichier_re(FICHIER_REGEX);
if (use_alldebrid)
return new AllDebridHost(url);
else if (std::regex_match(url, google_re))
return new GDriveHost(url);
else if (std::regex_match(url, mediafire_re))
return new MediaFireHost(url);
else if (std::regex_match(url, pixeldrain_re))
return new PixelDrainHost(url);
else
return new DirectHost(url);
}
std::string FileHost::GetCachedDownloadUrl(std::string &hash)
{
return cache_downloal_urls[hash];
}
void FileHost::AddCacheDownloadUrl(std::string &hash, std::string &url)
{
std::pair<std::string, std::string> pair = std::make_pair(hash, url);
cache_downloal_urls.erase(hash);
cache_downloal_urls.insert(pair);
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef FILEHOST_H
#define FILEHOST_H
#include <string>
#include <vector>
class FileHost
{
public:
FileHost(const std::string &url) { this->url = url; };
virtual ~FileHost(){};
virtual bool IsValidUrl() = 0;
virtual std::string GetDownloadUrl() = 0;
std::string Hash();
static FileHost *getFileHost(const std::string &url, bool use_alldebrid = false);
static std::string GetCachedDownloadUrl(std::string &hash);
static void AddCacheDownloadUrl(std::string &hash, std::string &url);
protected:
std::string url;
};
#endif
+118
View File
@@ -0,0 +1,118 @@
#include <regex>
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <http/httplib.h>
#include "common.h"
#include "gdrive.h"
#define VALIDATION_REGEX_1 "https:\\/\\/drive\\.google\\.com\\/file\\/d\\/(.*)\\/(edit|view)\\?usp=(.*)"
#define VALIDATION_REGEX_2 "https:\\/\\/drive\\.google\\.com\\/(.*)uc\\?(id=|export=)(.*)&(id=|export=)(.*)"
GDriveHost::GDriveHost(const std::string &url) : FileHost(url)
{
}
bool GDriveHost::IsValidUrl()
{
std::regex regex_1(VALIDATION_REGEX_1);
std::regex regex_2(VALIDATION_REGEX_2);
if (std::regex_match(url, regex_1) || std::regex_match(url, regex_2))
return true;
return false;
}
std::string GDriveHost::GetDownloadUrl()
{
std::regex regex_1(VALIDATION_REGEX_1);
std::smatch matches;
std::string path;
if(std::regex_search(url, matches, regex_1))
{
path = std::string("/uc?export=download&id=") + matches[1].str();
}
else
{
std::regex re("https:\\/\\/drive\\.google\\.com");
path = std::regex_replace(url, re, "");
}
httplib::Client tmp_client("https://drive.google.com");
tmp_client.set_keep_alive(true);
tmp_client.set_follow_location(true);
tmp_client.set_connection_timeout(30);
tmp_client.set_read_timeout(30);
tmp_client.enable_server_certificate_verification(false);
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.find("text/html") == std::string::npos)
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)
{
lxb_html_document_destroy(document);
return "";
}
collection = lxb_dom_collection_make(&document->dom_document, 128);
if (collection == NULL)
{
lxb_html_document_destroy(document);
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)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
return "";
}
std::string download_url;
for (size_t i = 0; i < lxb_dom_collection_length(collection); i++)
{
element = lxb_dom_collection_element(collection, i);
if (element->attr_id != nullptr)
{
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 "";
}
+14
View File
@@ -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
+89
View File
@@ -0,0 +1,89 @@
#include <regex>
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <http/httplib.h>
#include "common.h"
#include "mediafire.h"
#define VALIDATION_REGEX "https:\\/\\/www\\.mediafire\\.com\\/file\\/(.*)\\/(.*)\\/file"
MediaFireHost::MediaFireHost(const std::string &url) : FileHost(url)
{
}
bool MediaFireHost::IsValidUrl()
{
std::regex regex(VALIDATION_REGEX);
if (std::regex_match(url, regex))
return true;
return false;
}
std::string MediaFireHost::GetDownloadUrl()
{
std::regex re("https:\\/\\/www\\.mediafire\\.com");
std::string path = std::regex_replace(url, re, "");
httplib::Client tmp_client("https://www.mediafire.com");
tmp_client.set_keep_alive(true);
tmp_client.set_follow_location(true);
tmp_client.set_connection_timeout(30);
tmp_client.set_read_timeout(30);
tmp_client.enable_server_certificate_verification(false);
auto 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)
{
lxb_html_document_destroy(document);
return "";
}
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
collection, (const lxb_char_t *)"a", 1);
if (status != LXB_STATUS_OK)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
return "";
}
std::string download_url;
for (size_t i = 0; i < lxb_dom_collection_length(collection); i++)
{
element = lxb_dom_collection_element(collection, i);
if (element->attr_id != nullptr)
{
std::string a_id((char *)element->attr_id->value->data, element->attr_id->value->length);
if (a_id == "downloadButton")
{
size_t value_len;
const lxb_char_t *value = lxb_dom_element_get_attribute(element, (const lxb_char_t *)"href", 4, &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 "";
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef MEDIAFIRE_HOST_H
#define MEDIAFIRE_HOST_H
#include "filehost.h"
class MediaFireHost : public FileHost
{
public:
MediaFireHost(const std::string &url);
bool IsValidUrl();
std::string GetDownloadUrl();
};
#endif
+38
View File
@@ -0,0 +1,38 @@
#include <regex>
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <http/httplib.h>
#include "common.h"
#include "pixeldrain.h"
#define VALIDATION_REGEX "https:\\/\\/pixeldrain\\.com\\/u\\/(.*)"
PixelDrainHost::PixelDrainHost(const std::string &url) : FileHost(url)
{
}
bool PixelDrainHost::IsValidUrl()
{
std::regex re(VALIDATION_REGEX);
if (std::regex_match(url, re))
return true;
return false;
}
std::string PixelDrainHost::GetDownloadUrl()
{
std::regex re(VALIDATION_REGEX);
std::smatch matches;
if(std::regex_search(url, matches, re))
{
if (matches.size() > 1)
{
return std::string("https://pixeldrain.com/api/file/") + matches[1].str() + "?download=";
}
}
return "";
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef PIXELDRAIN_HOST_H
#define PIXELDRAIN_HOST_H
#include "filehost.h"
class PixelDrainHost : public FileHost
{
public:
PixelDrainHost(const std::string &url);
bool IsValidUrl();
std::string GetDownloadUrl();
};
#endif
+2 -1
View File
@@ -353,7 +353,7 @@ private:
} // namespace detail
using Headers = std::multimap<std::string, std::string, detail::ci>;
using Headers = std::map<std::string, std::string, detail::ci>;
using Params = std::multimap<std::string, std::string>;
using Match = std::smatch;
@@ -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);
+93 -96
View File
@@ -9,9 +9,11 @@
#include <orbis/Bgft.h>
#include <orbis/AppInstUtil.h>
#include <orbis/UserService.h>
#include <orbis/SystemService.h>
#include <curl/curl.h>
#include <web/request.hpp>
#include <web/urn.hpp>
#include "server/http_server.h"
#include "installer.h"
#include "util.h"
#include "config.h"
@@ -97,11 +99,12 @@ namespace INSTALLER
s_bgft_initialized = false;
}
std::string getRemoteUrl(const std::string filename, bool encodeUrl)
std::string getRemoteUrl(const std::string path, bool encodeUrl)
{
if (remoteclient->clientType() == CLIENT_TYPE_WEBDAV || remoteclient->clientType() == CLIENT_TYPE_HTTP_SERVER)
if (strlen(remote_settings->username) == 0 && strlen(remote_settings->password) == 0 &&
(remoteclient->clientType() == CLIENT_TYPE_WEBDAV || remoteclient->clientType() == CLIENT_TYPE_HTTP_SERVER))
{
std::string full_url = WebDAV::GetHttpUrl(remote_settings->server + filename);
std::string full_url = WebDAV::GetHttpUrl(remote_settings->server + path);
size_t scheme_pos = full_url.find("://");
if (scheme_pos == std::string::npos)
return "";
@@ -121,24 +124,17 @@ namespace INSTALLER
}
else
{
std::string full_url = std::string(remote_settings->server);
size_t scheme_pos = full_url.find("://");
if (scheme_pos == std::string::npos)
return "";
size_t root_pos = full_url.find("/", scheme_pos + 3);
std::string host = full_url.substr(scheme_pos + 3, (root_pos - (scheme_pos + 3)));
size_t port_pos = host.find(":");
if (port_pos != std::string::npos)
host = host.substr(0, port_pos);
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_site_name + encoded_path;
std::string path = std::string(filename);
if (encodeUrl)
{
Web::Urn::Path uri(path);
CURL *curl = curl_easy_init();
path = uri.quote(curl);
}
return "http://" + host + ":" + std::to_string(remote_settings->http_port) + path;
return full_url;
}
return "";
@@ -146,41 +142,11 @@ namespace INSTALLER
bool canInstallRemotePkg(const std::string &url)
{
if (remoteclient->clientType() == CLIENT_TYPE_WEBDAV)
{
if (strlen(remote_settings->username) > 0)
{
sprintf(confirm_message, "%s %s", lang_strings[STR_REMOTE_NOT_SUPPORT_MSG], lang_strings[STR_DOWNLOAD_INSTALL_MSG]);
return false;
}
else
return true;
}
else
{
size_t scheme_pos = url.find_first_of("://");
size_t path_pos = url.find_first_of("/", scheme_pos + 3);
std::string host = url.substr(0, path_pos);
std::string path = url.substr(path_pos);
WebDAV::WebDavClient tmp_client;
tmp_client.Connect(host.c_str(), "", "", false);
WebDAV::dict_t response_headers{};
int ret = tmp_client.GetHeaders(path.c_str(), &response_headers);
if (!ret)
{
sprintf(confirm_message, "%s %s", lang_strings[STR_CANNOT_CONNECT_REMOTE_MSG], lang_strings[STR_DOWNLOAD_INSTALL_MSG]);
return false;
}
return true;
}
return false;
return true;
}
int InstallRemotePkg(const std::string &filename, pkg_header *header)
int InstallRemotePkg(const std::string &url, pkg_header *header, bool prompt)
{
std::string url = getRemoteUrl(filename, true);
if (url.empty())
return 0;
@@ -222,6 +188,7 @@ namespace INSTALLER
is_patch = true;
}
OrbisBgftTaskProgress progress_info;
OrbisBgftDownloadParam params;
memset(&params, 0, sizeof(params));
{
@@ -246,18 +213,28 @@ namespace INSTALLER
ret = sceBgftServiceIntDebugDownloadRegisterPkg(&params, &task_id);
if (ret == 0x80990088 || ret == 0x80990015)
{
sprintf(confirm_message, "%s - %s?", filename.c_str(), lang_strings[STR_REINSTALL_CONFIRM_MSG]);
confirm_state = CONFIRM_WAIT;
action_to_take = selected_action;
activity_inprogess = false;
while (confirm_state == CONFIRM_WAIT)
if (prompt)
{
sceKernelUsleep(100000);
}
activity_inprogess = true;
selected_action = action_to_take;
sprintf(confirm_message, "%s - %s?", cid.c_str(), lang_strings[STR_REINSTALL_CONFIRM_MSG]);
confirm_state = CONFIRM_WAIT;
action_to_take = selected_action;
activity_inprogess = false;
while (confirm_state == CONFIRM_WAIT)
{
sceKernelUsleep(100000);
}
activity_inprogess = true;
selected_action = action_to_take;
if (confirm_state == CONFIRM_YES)
if (confirm_state == CONFIRM_YES)
{
ret = sceAppInstUtilAppUnInstall(cid.c_str());
if (ret != 0)
goto err;
goto retry;
}
}
else
{
ret = sceAppInstUtilAppUnInstall(cid.c_str());
if (ret != 0)
@@ -275,46 +252,61 @@ namespace INSTALLER
}
Util::Notify("%s queued", cid.c_str());
return 1;
if (prompt)
{
file_transfering = true;
bytes_to_download = 100;
bytes_transfered = 0;
while (bytes_transfered < 99)
{
memset(&progress_info, 0, sizeof(progress_info));
ret = sceBgftServiceDownloadGetProgress(task_id, &progress_info);
if (ret || (progress_info.transferred > 0 && progress_info.errorResult != 0))
return 0;
bytes_transfered = (uint32_t)(((float)progress_info.transferred / progress_info.length) * 100.f);
sceSystemServicePowerTick();
}
}
return 1;
err:
return 0;
}
int InstallLocalPkg(const std::string &filename)
int InstallLocalPkg(const std::string &path)
{
int ret;
pkg_header header;
memset(&header, 0, sizeof(header));
if (FS::Head(filename.c_str(), (void *)&header, sizeof(header)) == 0)
if (FS::Head(path.c_str(), (void *)&header, sizeof(header)) == 0)
return 0;
if (BE32(header.pkg_magic) != PKG_MAGIC)
return 0;
char filepath[1024];
snprintf(filepath, 1023, "%s", filename.c_str());
if (strncmp(filename.c_str(), "/data/", 6) == 0)
snprintf(filepath, 1023, "/user%s", filename.c_str());
snprintf(filepath, 1023, "%s", path.c_str());
if (strncmp(path.c_str(), "/data/", 6) == 0)
snprintf(filepath, 1023, "/user%s", path.c_str());
char titleId[18];
memset(titleId, 0, sizeof(titleId));
int is_app = -1;
ret = sceAppInstUtilGetTitleIdFromPkg(filename.c_str(), titleId, &is_app);
ret = sceAppInstUtilGetTitleIdFromPkg(path.c_str(), titleId, &is_app);
if (ret)
{
return 0;
}
OrbisBgftTaskProgress progress_info;
int prog = 0;
OrbisBgftDownloadParamEx download_params;
memset(&download_params, 0, sizeof(download_params));
{
download_params.params.entitlementType = 5;
download_params.params.id = (char *)header.pkg_content_id;
download_params.params.contentUrl = filepath;
download_params.params.contentName = (char *)header.pkg_content_id;
download_params.params.contentName = path.c_str();
;
download_params.params.iconPath = "";
download_params.params.playgoScenarioId = "0";
@@ -339,15 +331,19 @@ namespace INSTALLER
if (ret)
return 0;
Util::Notify("%s queued", titleId);
Util::Notify("%s queued", path.c_str());
while (prog < 99)
file_transfering = true;
bytes_to_download = 100;
bytes_transfered = 0;
while (bytes_transfered < 99)
{
memset(&progress_info, 0, sizeof(progress_info));
ret = sceBgftServiceDownloadGetProgress(task_id, &progress_info);
if (ret || (progress_info.transferred > 0 && progress_info.errorResult != 0))
return 0;
prog = (uint32_t)(((float)progress_info.transferred / progress_info.length) * 100.f);
bytes_transfered = (uint32_t)(((float)progress_info.transferred / progress_info.length) * 100.f);
sceSystemServicePowerTick();
}
return 1;
@@ -355,22 +351,23 @@ namespace INSTALLER
return 0;
}
int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install)
int InstallLocalPkg(const std::string &path, pkg_header *header, bool remove_after_install)
{
int ret;
if (strncmp(filename.c_str(), "/data/", 6) != 0 &&
strncmp(filename.c_str(), "/user/data/", 11) != 0 &&
strncmp(filename.c_str(), "/mnt/usb", 8) != 0)
if (strncmp(path.c_str(), "/data/", 6) != 0 &&
strncmp(path.c_str(), "/user/data/", 11) != 0 &&
strncmp(path.c_str(), "/mnt/usb", 8) != 0)
return -1;
std::string filename = path.substr(path.find_last_of("/")+1);
char filepath[1024];
snprintf(filepath, 1023, "%s", filename.c_str());
if (strncmp(filename.c_str(), "/data/", 6) == 0)
snprintf(filepath, 1023, "/user%s", filename.c_str());
snprintf(filepath, 1023, "%s", path.c_str());
if (strncmp(path.c_str(), "/data/", 6) == 0)
snprintf(filepath, 1023, "/user%s", path.c_str());
char titleId[18];
memset(titleId, 0, sizeof(titleId));
int is_app = -1;
ret = sceAppInstUtilGetTitleIdFromPkg(filename.c_str(), titleId, &is_app);
ret = sceAppInstUtilGetTitleIdFromPkg(path.c_str(), titleId, &is_app);
if (ret)
{
return 0;
@@ -384,7 +381,7 @@ namespace INSTALLER
download_params.params.entitlementType = 5;
download_params.params.id = (char *)header->pkg_content_id;
download_params.params.contentUrl = filepath;
download_params.params.contentName = (char *)header->pkg_content_id;
download_params.params.contentName = filename.c_str();
;
download_params.params.iconPath = "";
download_params.params.playgoScenarioId = "0";
@@ -397,7 +394,7 @@ namespace INSTALLER
ret = sceBgftServiceIntDownloadRegisterTaskByStorageEx(&download_params, &task_id);
if (ret == 0x80990088 || ret == 0x80990015)
{
sprintf(confirm_message, "%s - %s?", filename.c_str(), lang_strings[STR_REINSTALL_CONFIRM_MSG]);
sprintf(confirm_message, "%s - %s?", path.c_str(), lang_strings[STR_REINSTALL_CONFIRM_MSG]);
confirm_state = CONFIRM_WAIT;
action_to_take = selected_action;
activity_inprogess = false;
@@ -418,7 +415,7 @@ namespace INSTALLER
else
{
if (auto_delete_tmp_pkg)
FS::Rm(filename);
FS::Rm(path);
}
}
else if (ret > 0)
@@ -432,7 +429,7 @@ namespace INSTALLER
if (!remove_after_install)
{
Util::Notify("%s queued", titleId);
Util::Notify("%s queued", filename.c_str());
return 1;
}
@@ -450,24 +447,24 @@ namespace INSTALLER
bytes_transfered = progress_info.transferred;
}
if (auto_delete_tmp_pkg)
FS::Rm(filename);
FS::Rm(path);
return 1;
err:
return 0;
}
bool ExtractLocalPkg(const std::string &filename, const std::string sfo_path, const std::string icon_path)
bool ExtractLocalPkg(const std::string &path, const std::string sfo_path, const std::string icon_path)
{
pkg_header tmp_hdr;
FS::Head(filename, &tmp_hdr, sizeof(pkg_header));
FS::Head(path, &tmp_hdr, sizeof(pkg_header));
size_t entry_count = BE32(tmp_hdr.pkg_entry_count);
uint32_t entry_table_offset = BE32(tmp_hdr.pkg_table_offset);
uint64_t entry_table_size = entry_count * sizeof(pkg_table_entry);
void *entry_table_data = malloc(entry_table_size);
FILE *fd = FS::OpenRead(filename);
FILE *fd = FS::OpenRead(path);
FS::Seek(fd, entry_table_offset);
FS::Read(fd, entry_table_data, entry_table_size);
@@ -528,10 +525,10 @@ namespace INSTALLER
return true;
}
bool ExtractRemotePkg(const std::string &filename, const std::string sfo_path, const std::string icon_path)
bool ExtractRemotePkg(const std::string &path, const std::string sfo_path, const std::string icon_path)
{
pkg_header tmp_hdr;
if (!remoteclient->Head(filename, &tmp_hdr, sizeof(pkg_header)))
if (!remoteclient->Head(path, &tmp_hdr, sizeof(pkg_header)))
return false;
size_t entry_count = BE32(tmp_hdr.pkg_entry_count);
@@ -539,7 +536,7 @@ namespace INSTALLER
uint64_t entry_table_size = entry_count * sizeof(pkg_table_entry);
void *entry_table_data = malloc(entry_table_size);
if (!remoteclient->GetRange(filename, entry_table_data, entry_table_size, entry_table_offset))
if (!remoteclient->GetRange(path, entry_table_data, entry_table_size, entry_table_offset))
return false;
pkg_table_entry *entries = (pkg_table_entry *)entry_table_data;
@@ -577,7 +574,7 @@ namespace INSTALLER
{
param_sfo_data = malloc(param_sfo_size);
FILE *out = FS::Create(sfo_path);
if (!remoteclient->GetRange(filename, param_sfo_data, param_sfo_size, param_sfo_offset))
if (!remoteclient->GetRange(path, param_sfo_data, param_sfo_size, param_sfo_offset))
{
FS::Close(out);
return false;
@@ -591,7 +588,7 @@ namespace INSTALLER
{
icon0_png_data = malloc(icon0_png_size);
FILE *out = FS::Create(icon_path);
if (!remoteclient->GetRange(filename, icon0_png_data, icon0_png_size, icon0_png_offset))
if (!remoteclient->GetRange(path, icon0_png_data, icon0_png_size, icon0_png_offset))
{
FS::Close(out);
return false;
@@ -603,4 +600,4 @@ namespace INSTALLER
return true;
}
}
}
+6 -6
View File
@@ -120,10 +120,10 @@ namespace INSTALLER
void Exit(void);
bool canInstallRemotePkg(const std::string &url);
std::string getRemoteUrl(const std::string filename, bool encodeUrl = false);
int InstallRemotePkg(const std::string &filename, pkg_header *header);
int InstallLocalPkg(const std::string &filename);
int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install = false);
bool ExtractLocalPkg(const std::string &filename, const std::string sfo_path, const std::string icon_path);
bool ExtractRemotePkg(const std::string &filename, const std::string sfo_path, const std::string icon_path);
std::string getRemoteUrl(const std::string path, bool encodeUrl = false);
int InstallRemotePkg(const std::string &path, pkg_header *header, bool prompt = false);
int InstallLocalPkg(const std::string &path);
int InstallLocalPkg(const std::string &path, pkg_header *header, bool remove_after_install = false);
bool ExtractLocalPkg(const std::string &path, const std::string sfo_path, const std::string icon_path);
bool ExtractRemotePkg(const std::string &path, const std::string sfo_path, const std::string icon_path);
}
+122 -118
View File
@@ -10,124 +10,122 @@ char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE] = {
// This is properly populated so that emulator won't crash if an user launches it without language INI files.
char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
"Connection Settings", // STR_CONNECTION_SETTINGS
"Site", // STR_SITE
"Local", // STR_LOCAL
"Remote", // STR_REMOTE
"Messages", // STR_MESSAGES
"Update Software", // STR_UPDATE_SOFTWARE
"Connect", // STR_CONNECT
"Disconnect", // STR_DISCONNECT
"Search", // STR_SEARCH
"Refresh", // STR_REFRESH
"Server", // STR_SERVER
"Username", // STR_USERNAME
"Password", // STR_PASSWORD
"Port", // STR_PORT
"Pasv", // STR_PASV
"Directory", // STR_DIRECTORY
"Filter", // STR_FILTER
"Yes", // STR_YES
"No", // STR_NO
"Cancel", // STR_CANCEL
"Continue", // STR_CONTINUE
"Close", // STR_CLOSE
"Folder", // STR_FOLDER
"File", // STR_FILE
"Type", // STR_TYPE
"Name", // STR_NAME
"Size", // STR_SIZE
"Date", // STR_DATE
"New Folder", // STR_NEW_FOLDER
"Rename", // STR_RENAME
"Delete", // STR_DELETE
"Upload", // STR_UPLOAD
"Download", // STR_DOWNLOAD
"Select All", // STR_SELECT_ALL
"Clear All", // STR_CLEAR_ALL
"Uploading", // STR_UPLOADING
"Downloading", // STR_DOWNLOADING
"Overwrite", // STR_OVERWRITE
"Don't Overwrite", // STR_DONT_OVERWRITE
"Ask for Confirmation", // STR_ASK_FOR_CONFIRM
"Don't Ask for Confirmation", // STR_DONT_ASK_CONFIRM
"Always use this option and don't ask again", // STR_ALLWAYS_USE_OPTION
"Actions", // STR_ACTIONS
"Confirm", // STR_CONFIRM
"Overwrite Options", // STR_OVERWRITE_OPTIONS
"Properties", // STR_PROPERTIES
"Progress", // STR_PROGRESS
"Updates", // STR_UPDATES
"Are you sure you want to delete this file(s)/folder(s)?", // STR_DEL_CONFIRM_MSG
"Canceling. Waiting for last action to complete", // STR_CANCEL_ACTION_MSG
"Failed to upload file", // STR_FAIL_UPLOAD_MSG
"Failed to download file", // STR_FAIL_DOWNLOAD_MSG
"Failed to read contents of directory or folder does not exist.", // STR_FAIL_READ_LOCAL_DIR_MSG
"426 Connection closed.", // STR_CONNECTION_CLOSE_ERR_MSG
"426 Remote Server has terminated the connection.", // STR_REMOTE_TERM_CONN_MSG
"300 Failed Login. Please check your username or password.", // STR_FAIL_LOGIN_MSG
"426 Failed. Connection timeout.", // STR_FAIL_TIMEOUT_MSG
"Failed to delete directory", // STR_FAIL_DEL_DIR_MSG
"Deleting", // STR_DELETING
"Failed to delete file", // STR_FAIL_DEL_FILE_MSG
"Deleted", // STR_DELETED
"Link", // STR_LINK
"Share", // STR_SHARE
"310 Failed", // STR_FAILED
"310 Failed to create file on local", // STR_FAIL_CREATE_LOCAL_FILE_MSG
"Install", // STR_INSTALL
"Installing", // STR_INSTALLING
"Success", // STR_INSTALL_SUCCESS
"Failed", // STR_INSTALL_FAILED
"Skipped", // STR_INSTALL_SKIPPED
"Checking connection to remote HTTP Server", // STR_CHECK_HTTP_MSG
"Failed connecting to HTTP Server", // STR_FAILED_HTTP_CHECK
"Remote is not a HTTP Server", // STR_REMOTE_NOT_HTTP
"Package not in the /data or /mnt/usbX folder", // STR_INSTALL_FROM_DATA_MSG
"Package is already installed", // STR_ALREADY_INSTALLED_MSG
"Install from URL", // STR_INSTALL_FROM_URL
"Could not read package header info", // STR_CANNOT_READ_PKG_HDR_MSG
"Favorite URLs", // STR_FAVORITE_URLS
"Slot", // STR_SLOT
"Edit", // STR_EDIT
"One Time Url", // STR_ONETIME_URL
"Not a valid Package", // STR_NOT_A_VALID_PACKAGE
"Waiting for Package to finish installing", // STR_WAIT_FOR_INSTALL_MSG
"Failed to install pkg file. Please delete the tmp pkg manually", // STR_FAIL_INSTALL_TMP_PKG_MSG
"Failed to obtain google download URL", // STR_FAIL_TO_OBTAIN_GG_DL_MSG
"Auto delete temporary downloaded pkg file after install", // STR_AUTO_DELETE_TMP_PKG
"Protocol not supported", // STR_PROTOCOL_NOT_SUPPORTED
"Could not resolve hostname", // STR_COULD_NOT_RESOLVE_HOST
"Extract", // STR_EXTRACT
"Extracting", // STR_EXTRACTING
"Failed to extract", // STR_FAILED_TO_EXTRACT
"Extract Location", // STR_EXTRACT_LOCATION
"Compress", // STR_COMPRESS
"Zip Filename", // STR_ZIP_FILE_PATH
"Compressing", // STR_COMPRESSING
"Error occured while creating zip", // STR_ERROR_CREATE_ZIP
"Unsupported compressed file format", // STR_UNSUPPORTED_FILE_FORMAT
"Cut", // STR_CUT
"Copy", // STR_COPY
"Paste", // STR_PASTE
"Moving", // STR_MOVING
"Copying", // STR_COPYING
"Failed to move file", // STR_FAIL_MOVE_MSG
"Failed to copy file", // STR_FAIL_COPY_MSG
"Cannot move parent directory to sub subdirectory", // STR_CANT_MOVE_TO_SUBDIR_MSG
"Cannot copy parent directory to sub subdirectory", // STR_CANT_COPY_TO_SUBDIR_MSG
"Operation not supported", // STR_UNSUPPORTED_OPERATION_MSG
"Http Port", // STR_HTTP_PORT
"The content has already been installed. Do you want to continue installing", // STR_REINSTALL_CONFIRM_MSG
"Remote package installation is not supported for protected servers.", // STR_REMOTE_NOT_SUPPORT_MSG
"Remote HTTP Server not reachable.", // STR_CANNOT_CONNECT_REMOTE_MSG
"Remote Package Install not possible. Would you like to download package and install?", // STR_DOWNLOAD_INSTALL_MSG
"Checking remote server for Remote Package Install.", // STR_CHECKING_REMOTE_SERVER_MSG
"RPI", // STR_ENABLE_RPI
"This option enables Remote Package Installation. "
"This requires a HTTP Server setup on the same host sharing the same folder with anonymous access.", // STR_ENABLE_RPI_FTP_SMB_MSG
"This option enables Remote Package Installation. "
"This requires the Server with anonymous access that does not need username/password.", // STR_ENABLE_RPI_WEBDAV_MSG
"Connection Settings", // STR_CONNECTION_SETTINGS
"Site", // STR_SITE
"Local", // STR_LOCAL
"Remote", // STR_REMOTE
"Messages", // STR_MESSAGES
"Update Software", // STR_UPDATE_SOFTWARE
"Connect", // STR_CONNECT
"Disconnect", // STR_DISCONNECT
"Search", // STR_SEARCH
"Refresh", // STR_REFRESH
"Server", // STR_SERVER
"Username", // STR_USERNAME
"Password", // STR_PASSWORD
"Port", // STR_PORT
"Pasv", // STR_PASV
"Directory", // STR_DIRECTORY
"Filter", // STR_FILTER
"Yes", // STR_YES
"No", // STR_NO
"Cancel", // STR_CANCEL
"Continue", // STR_CONTINUE
"Close", // STR_CLOSE
"Folder", // STR_FOLDER
"File", // STR_FILE
"Type", // STR_TYPE
"Name", // STR_NAME
"Size", // STR_SIZE
"Date", // STR_DATE
"New Folder", // STR_NEW_FOLDER
"Rename", // STR_RENAME
"Delete", // STR_DELETE
"Upload", // STR_UPLOAD
"Download", // STR_DOWNLOAD
"Select All", // STR_SELECT_ALL
"Clear All", // STR_CLEAR_ALL
"Uploading", // STR_UPLOADING
"Downloading", // STR_DOWNLOADING
"Overwrite", // STR_OVERWRITE
"Don't Overwrite", // STR_DONT_OVERWRITE
"Ask for Confirmation", // STR_ASK_FOR_CONFIRM
"Don't Ask for Confirmation", // STR_DONT_ASK_CONFIRM
"Always use this option and don't ask again", // STR_ALLWAYS_USE_OPTION
"Actions", // STR_ACTIONS
"Confirm", // STR_CONFIRM
"Overwrite Options", // STR_OVERWRITE_OPTIONS
"Properties", // STR_PROPERTIES
"Progress", // STR_PROGRESS
"Updates", // STR_UPDATES
"Are you sure you want to delete this file(s)/folder(s)?", // STR_DEL_CONFIRM_MSG
"Canceling. Waiting for last action to complete", // STR_CANCEL_ACTION_MSG
"Failed to upload file", // STR_FAIL_UPLOAD_MSG
"Failed to download file", // STR_FAIL_DOWNLOAD_MSG
"Failed to read contents of directory or folder does not exist.", // STR_FAIL_READ_LOCAL_DIR_MSG
"426 Connection closed.", // STR_CONNECTION_CLOSE_ERR_MSG
"426 Remote Server has terminated the connection.", // STR_REMOTE_TERM_CONN_MSG
"300 Failed Login. Please check your username or password.", // STR_FAIL_LOGIN_MSG
"426 Failed. Connection timeout.", // STR_FAIL_TIMEOUT_MSG
"Failed to delete directory", // STR_FAIL_DEL_DIR_MSG
"Deleting", // STR_DELETING
"Failed to delete file", // STR_FAIL_DEL_FILE_MSG
"Deleted", // STR_DELETED
"Link", // STR_LINK
"Share", // STR_SHARE
"310 Failed", // STR_FAILED
"310 Failed to create file on local", // STR_FAIL_CREATE_LOCAL_FILE_MSG
"Install", // STR_INSTALL
"Installing", // STR_INSTALLING
"Success", // STR_INSTALL_SUCCESS
"Failed", // STR_INSTALL_FAILED
"Skipped", // STR_INSTALL_SKIPPED
"Checking connection to remote HTTP Server", // STR_CHECK_HTTP_MSG
"Failed connecting to HTTP Server", // STR_FAILED_HTTP_CHECK
"Remote is not a HTTP Server", // STR_REMOTE_NOT_HTTP
"Package not in the /data or /mnt/usbX folder", // STR_INSTALL_FROM_DATA_MSG
"Package is already installed", // STR_ALREADY_INSTALLED_MSG
"Install from URL", // STR_INSTALL_FROM_URL
"Could not read package header info", // STR_CANNOT_READ_PKG_HDR_MSG
"Favorite URLs", // STR_FAVORITE_URLS
"Slot", // STR_SLOT
"Edit", // STR_EDIT
"One Time Url", // STR_ONETIME_URL
"Not a valid Package", // STR_NOT_A_VALID_PACKAGE
"Waiting for Package to finish installing", // STR_WAIT_FOR_INSTALL_MSG
"Failed to install pkg file. Please delete the tmp pkg manually", // STR_FAIL_INSTALL_TMP_PKG_MSG
"Failed to obtain download URL", // STR_FAIL_TO_OBTAIN_GG_DL_MSG
"Auto delete temporary downloaded pkg file after install", // STR_AUTO_DELETE_TMP_PKG
"Protocol not supported", // STR_PROTOCOL_NOT_SUPPORTED
"Could not resolve hostname", // STR_COULD_NOT_RESOLVE_HOST
"Extract", // STR_EXTRACT
"Extracting", // STR_EXTRACTING
"Failed to extract", // STR_FAILED_TO_EXTRACT
"Extract Location", // STR_EXTRACT_LOCATION
"Compress", // STR_COMPRESS
"Zip Filename", // STR_ZIP_FILE_PATH
"Compressing", // STR_COMPRESSING
"Error occured while creating zip", // STR_ERROR_CREATE_ZIP
"Unsupported compressed file format", // STR_UNSUPPORTED_FILE_FORMAT
"Cut", // STR_CUT
"Copy", // STR_COPY
"Paste", // STR_PASTE
"Moving", // STR_MOVING
"Copying", // STR_COPYING
"Failed to move file", // STR_FAIL_MOVE_MSG
"Failed to copy file", // STR_FAIL_COPY_MSG
"Cannot move parent directory to sub subdirectory", // STR_CANT_MOVE_TO_SUBDIR_MSG
"Cannot copy parent directory to sub subdirectory", // STR_CANT_COPY_TO_SUBDIR_MSG
"Operation not supported", // STR_UNSUPPORTED_OPERATION_MSG
"Http Port", // STR_HTTP_PORT
"The content has already been installed. Do you want to continue installing", // STR_REINSTALL_CONFIRM_MSG
"Remote package installation is not supported for protected servers.", // STR_REMOTE_NOT_SUPPORT_MSG
"Remote HTTP Server not reachable.", // STR_CANNOT_CONNECT_REMOTE_MSG
"Remote Package Install not possible. Would you like to download package and install?", // STR_DOWNLOAD_INSTALL_MSG
"Checking remote server for Remote Package Install.", // STR_CHECKING_REMOTE_SERVER_MSG
"RPI", // STR_ENABLE_RPI
"This option enables Remote Package Installation.", // STR_ENABLE_RPI_FTP_SMB_MSG
"This option enables Remote Package Installation.", // STR_ENABLE_RPI_WEBDAV_MSG
"Files", // STR_FILES
"Editor", // STR_EDITOR
"Save", // STR_SAVE
@@ -164,6 +162,12 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
"Enable", // STR_ENABLE
"Compressed Files Location", // STR_COMPRESSED_FILE_PATH
"Location of where compressed files are stored on the web server", // STR_COMPRESSED_FILE_PATH_MSG
"AllDebrid", // STR_ALLDEBRID
"API Key", // STR_API_KEY
"Couldn't extract download url", // STR_CANT_EXTRACT_URL_MSG
"Failed to install from URL", // STR_FAIL_INSTALL_FROM_URL_MSG
"InValid URL", // STR_INVALID_URL
"To use this function, an API Key needs to be configured in the ezRemote Client settings", // STR_ALLDEBRID_API_KEY_MISSING_MSG
};
bool needs_extended_font = false;
+9 -3
View File
@@ -153,9 +153,15 @@
FUNC(STR_FAIL_INIT_NFS_CONTEXT) \
FUNC(STR_FAIL_MOUNT_NFS_MSG) \
FUNC(STR_WEB_SERVER) \
FUNC(STR_ENABLE) \
FUNC(STR_ENABLE) \
FUNC(STR_COMPRESSED_FILE_PATH) \
FUNC(STR_COMPRESSED_FILE_PATH_MSG)
FUNC(STR_COMPRESSED_FILE_PATH_MSG) \
FUNC(STR_ALLDEBRID) \
FUNC(STR_API_KEY) \
FUNC(STR_CANT_EXTRACT_URL_MSG) \
FUNC(STR_FAIL_INSTALL_FROM_URL_MSG) \
FUNC(STR_INVALID_URL) \
FUNC(STR_ALLDEBRID_API_KEY_MISSING_MSG)
#define GET_VALUE(x) x,
#define GET_STRING(x) #x,
@@ -165,7 +171,7 @@ enum
FOREACH_STR(GET_VALUE)
};
#define LANG_STRINGS_NUM 152
#define LANG_STRINGS_NUM 158
#define LANG_ID_SIZE 64
#define LANG_STR_SIZE 384
extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE];
+61
View File
@@ -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;
+3
View File
@@ -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
+221 -3
View File
@@ -1,8 +1,14 @@
#include <string>
#include <json-c/json.h>
#include <range_parser/range_parser.hpp>
#include "http/httplib.h"
#include "server/http_server.h"
#include "clients/gdrive.h"
#include "clients/sftpclient.h"
#include "clients/smbclient.h"
#include "clients/ftpclient.h"
#include "clients/nfsclient.h"
#include "filehost/filehost.h"
#include "config.h"
#include "fs.h"
#include "windows.h"
@@ -19,6 +25,7 @@
#define SUCCESS_MSG_LEN 48
using namespace httplib;
Server *svr;
int http_server_port = 8080;
char compressed_file_path[1024];
@@ -382,7 +389,15 @@ namespace HttpServer
{
const char *src = json_object_get_string(json_object_array_get_idx(items, 0));
std::string dest = std::string(newPath) + "/" + singleFilename;
if (dest.compare(src) != 0 && !FS::Copy(src, dest))
std::string temp = std::string(src);
size_t slash_pos = temp.find_last_of("/");
DirEntry entry;
sprintf(entry.name, "%s", temp.substr(slash_pos+1).c_str());
sprintf(entry.path, "%s", src);
entry.isDir = FS::IsFolder(src);
if (entry.isDir)
if (dest.compare(src) != 0 && !CopyOrMove(entry, dest.c_str(), true))
{
failed_items += src;
}
@@ -699,6 +714,7 @@ namespace HttpServer
size_t chunk_size = 0;
size_t chunk_number = -1;
size_t total_size = 0;
size_t currentChunkSize = 0;
FILE *out = nullptr;
std::string new_file;
content_reader(
@@ -742,6 +758,11 @@ namespace HttpServer
std::stringstream ss(items.back().content);
ss >> total_size;
}
else if (items.back().name == "_currentChunkSize")
{
std::stringstream ss(items.back().content);
ss >> currentChunkSize;
}
else
{
if (out != nullptr)
@@ -900,6 +921,203 @@ namespace HttpServer
res.set_content(str.c_str(), "text/plain");
});
svr->Get("/rmt_inst/Site (\\d+)(/)(.*)", [&](const Request & req, Response & res)
{
RemoteClient *tmp_client;
RemoteSettings *tmp_settings;
auto site_idx = std::stoi(req.matches[1])-1;
std::string path;
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
{
std::string hash = std::string(req.matches[3]);
std::string url = FileHost::GetCachedDownloadUrl(hash);
size_t scheme_pos = url.find("://");
size_t root_pos = url.find("/", scheme_pos + 3);
std::string host = url.substr(0, root_pos);
path = url.substr(root_pos);
tmp_client = new BaseClient();
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;
ret = tmp_client->Size(path, &file_size);
if (!ret)
{
res.status = 500;
return;
}
res.status = 204;
res.set_header("Content-Length", std::to_string(file_size));
res.set_header("Accept-Ranges", "bytes");
return;
}
if (req.ranges.empty())
{
res.status = 200;
res.set_content_provider(
(1024*128), "application/octet-stream",
[tmp_client, path](size_t offset, size_t length, DataSink &sink) {
int ret = tmp_client->GetRange(path, sink, length, offset);
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;
}
});
}
else
{
res.status = 206;
size_t range_len = (req.ranges[0].second - req.ranges[0].first) + 1;
if (req.ranges[0].second >= 18000000000000000000ul)
{
range_len = 65536ul - req.ranges[0].first;
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)+"-65535/"+std::to_string(range_len));
}
std::pair<ssize_t, ssize_t> range = req.ranges[0];
res.set_content_provider(
range_len, "application/octet-stream",
[tmp_client, path, range, range_len](size_t offset, size_t length, DataSink &sink) {
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->Quit();
delete tmp_client;
}
});
}
});
svr->Post("/__local__/install_url", [&](const Request & req, Response & res)
{
std::string url;
const char *url_param;
bool use_alldebrid;
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"));
use_alldebrid = json_object_get_boolean(json_object_object_get(jobj, "use_alldebrid"));
if (url_param == nullptr)
{
bad_request(res, "Required url_param, use_alldebrid parameter missing");
return;
}
}
else
{
bad_request(res, "Invalid payload");
return;
}
if (use_alldebrid && strlen(alldebrid_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);
if (!filehost->IsValidUrl())
{
failed(res, 200, lang_strings[STR_INVALID_URL]);
return;
}
std::string hash = filehost->Hash();
std::string download_url = filehost->GetDownloadUrl();
if (download_url.empty())
{
failed(res, 200, lang_strings[STR_CANT_EXTRACT_URL_MSG]);
return;
}
FileHost::AddCacheDownloadUrl(hash, download_url);
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);
pkg_header header;
BaseClient *baseclient = new BaseClient();
baseclient->Connect(host, "", "");
baseclient->Head(path, &header, sizeof(pkg_header));
delete(baseclient);
std::string remote_install_url = std::string("http://localhost:") + std::to_string(http_server_port) + "/rmt_inst/Site%2099/" + hash;
int rc = INSTALLER::InstallRemotePkg(remote_install_url, &header);
if (rc == 0)
{
failed(res, 200, lang_strings[STR_FAIL_INSTALL_FROM_URL_MSG]);
return;
}
success(res);
});
svr->Get("/stop", [&](const Request & /*req*/, Response & /*res*/)
{
svr->stop();
@@ -919,7 +1137,7 @@ 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("/", "/");
@@ -948,4 +1166,4 @@ namespace HttpServer
if (svr != nullptr)
svr->stop();
}
}
}
+11
View File
@@ -23,9 +23,12 @@
#include <algorithm>
#include <fstream>
#include <cstring>
#include "http/httplib.h"
#include "callback.hpp"
using namespace httplib;
namespace Web
{
namespace Callback
@@ -104,6 +107,14 @@ namespace Web
out_stream->write(ptr, write_bytes);
return write_bytes;
}
size_t stream2sink(char* ptr, size_t item_size, size_t item_count, void* sink)
{
auto ostream = reinterpret_cast<DataSink*>(sink);
size_t write_bytes = item_size * item_count;
ostream->write(ptr, write_bytes);
return write_bytes;
}
} // namespace Append
} // namespace Callback
} // namespace Web
+1
View File
@@ -60,6 +60,7 @@ namespace Web
{
size_t stream(char* data, size_t size, size_t count, void* stream);
size_t buffer(char* data, size_t size, size_t count, void* buffer);
size_t stream2sink(char* ptr, size_t item_size, size_t item_count, void* sink);
}
}
} // namespace Web
+64
View File
@@ -29,6 +29,7 @@
#include "web/request.hpp"
#include "web/urn.hpp"
#include "util.h"
#include "http/httplib.h"
#include <algorithm>
#include <thread>
@@ -234,6 +235,57 @@ bool
return true;
}
bool
Client::sync_download_range_to(
const std::string &remote_file,
DataSink &sink,
uint64_t range_from,
uint64_t range_to,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
bool is_existed = this->check(remote_file);
if (!is_existed)
return false;
auto root_urn = Path(this->webdav_root, true);
auto file_urn = root_urn + remote_file;
Request request(this->options());
auto url = this->webdav_hostname + file_urn.quote(request.handle);
struct curl_slist *list = NULL;
char range_header[64];
sprintf(range_header, "Range: bytes=%lu-%lu", range_from, range_to);
list = curl_slist_append(list, range_header);
request.set(CURLOPT_CUSTOMREQUEST, "GET");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_HTTPHEADER, list);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<void*>(&sink));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::stream2sink));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
if (progress != nullptr)
{
request.set(CURLOPT_XFERINFODATA, progress_data);
request.set(CURLOPT_XFERINFOFUNCTION, progress);
request.set(CURLOPT_NOPROGRESS, 0L);
}
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (callback != nullptr)
callback(is_performed);
if (!is_performed)
return false;
return true;
}
bool
Client::sync_download_to(
const std::string &remote_file,
@@ -777,6 +829,18 @@ bool
return this->sync_download_range_to(remote_file, buffer_ptr, buffer_size, range_from, range_to, nullptr, progress_data, std::move(progress));
}
bool
Client::download_range_to(
const std::string &remote_file,
DataSink &sink,
uint64_t range_from,
uint64_t range_to,
progress_data_t progress_data,
progress_t progress)
{
return this->sync_download_range_to(remote_file, sink, range_from, range_to, nullptr, progress_data, std::move(progress));
}
bool
Client::download_to(
const std::string &remote_file,
+31
View File
@@ -29,6 +29,9 @@
#include <string>
#include <vector>
#include <curl/curl.h>
#include "http/httplib.h"
using namespace httplib;
namespace WebDAV
{
@@ -208,6 +211,24 @@ namespace WebDAV
progress_t progress = nullptr
) -> bool;
///
/// Download a remote file to a buffer for specified range
/// \param[in] remote_file
/// \param[out] sink,
/// \param[in] range_from,
/// \param[in] range_to
/// \param[in] progress
/// \snippet client/download.cpp download_to_buffer
///
auto download_range_to(
const std::string &remote_file,
DataSink &sink,
uint64_t range_from,
uint64_t range_to,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
///
/// Download a remote file to a stream
/// \param[in] remote_file
@@ -330,6 +351,16 @@ namespace WebDAV
progress_t progress = nullptr
) -> bool;
auto sync_download_range_to(
const std::string &remote_file,
DataSink &sink,
uint64_t range_from,
uint64_t range_to,
callback_t callback,
progress_data_t progress_data,
progress_t progress
) -> bool;
bool sync_download_to(
const std::string& remote_file,
std::ostream& stream,
+57 -57
View File
@@ -39,7 +39,6 @@ static char *ime_single_field;
static int ime_field_size;
static char txt_http_server_port[6];
static char txt_http_port[6];
bool handle_updates = false;
int64_t bytes_transfered;
@@ -118,7 +117,6 @@ namespace Windows
sprintf(status_message, "");
sprintf(local_filter, "");
sprintf(remote_filter, "");
sprintf(txt_http_port, "%d", remote_settings->http_port);
sprintf(txt_http_server_port, "%d", http_server_port);
dont_prompt_overwrite = false;
confirm_transfer_state = -1;
@@ -320,7 +318,6 @@ namespace Windows
sprintf(display_site, "%s", site_id);
remote_settings = &site_settings[sites[n]];
sprintf(remote_directory, "%s", remote_settings->default_directory);
sprintf(txt_http_port, "%d", remote_settings->http_port);
}
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
@@ -402,66 +399,42 @@ namespace Windows
ImGui::SameLine();
}
if (remote_settings->type != CLIENT_TYPE_GOOGLE)
if (remote_settings->type != CLIENT_TYPE_NFS && remote_settings->type != CLIENT_TYPE_GOOGLE)
{
if (remote_settings->type != CLIENT_TYPE_NFS)
{
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_PASSWORD]);
ImGui::SameLine();
sprintf(id, "%s##password", hidden_password.c_str());
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(100, 0)))
{
ime_single_field = remote_settings->password;
ResetImeCallbacks();
ime_field_size = 127;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_PASSWORD], remote_settings->password, 127, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
}
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_RPI]);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_PASSWORD]);
ImGui::SameLine();
if (ImGui::Checkbox("###enable_rpi", &remote_settings->enable_rpi))
sprintf(id, "%s##password", hidden_password.c_str());
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(100, 0)))
{
CONFIG::SaveConfig();
}
if (ImGui::IsItemHovered())
{
ImGui::SetNextWindowSize(ImVec2(450, 135));
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
ImGui::Text("%s", (remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) ? lang_strings[STR_ENABLE_RPI_FTP_SMB_MSG] : lang_strings[STR_ENABLE_RPI_WEBDAV_MSG]);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
ime_single_field = remote_settings->password;
ResetImeCallbacks();
ime_field_size = 127;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_PASSWORD], remote_settings->password, 127, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
}
}
if ((remote_settings->type == CLIENT_TYPE_NFS || remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) && remote_settings->enable_rpi)
{
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_HTTP_PORT]);
ImGui::SameLine();
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_RPI]);
ImGui::SameLine();
sprintf(id, "%s##http_port", txt_http_port);
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(65, 0)))
{
ime_single_field = txt_http_port;
ResetImeCallbacks();
ime_field_size = 24;
ime_callback = SingleValueImeCallback;
ime_after_update = AfterHttpPortChangeCallback;
Dialog::initImeDialog(lang_strings[STR_PASSWORD], txt_http_port, 24, ORBIS_TYPE_NUMBER, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
}
}
if (ImGui::Checkbox("###enable_rpi", &remote_settings->enable_rpi))
{
CONFIG::SaveConfig();
}
if (ImGui::IsItemHovered())
{
ImGui::SetNextWindowSize(ImVec2(450, 70));
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
ImGui::Text("%s", lang_strings[STR_ENABLE_RPI_FTP_SMB_MSG]);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
ImGui::PopStyleVar();
@@ -1632,7 +1605,7 @@ namespace Windows
ImGui::OpenPopup(lang_strings[STR_SETTINGS]);
ImGui::SetNextWindowPos(ImVec2(1050, 80));
ImGui::SetNextWindowSizeConstraints(ImVec2(850, 80), ImVec2(850, 500), NULL, NULL);
ImGui::SetNextWindowSizeConstraints(ImVec2(850, 80), ImVec2(850, 650), NULL, NULL);
if (ImGui::BeginPopupModal(lang_strings[STR_SETTINGS], NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s", lang_strings[STR_GLOBAL]);
@@ -1701,6 +1674,34 @@ namespace Windows
ImGui::PopStyleVar();
ImGui::Separator();
// Google settings
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s", lang_strings[STR_ALLDEBRID]);
ImGui::Separator();
field_size = ImGui::CalcTextSize(lang_strings[STR_API_KEY]);
width = field_size.x + 45;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 15);
ImGui::Text("%s", lang_strings[STR_API_KEY]);
ImGui::SameLine();
ImGui::SetCursorPosX(width);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 1.0f));
if (strlen(alldebrid_api_key) > 0)
sprintf(id, "%s", "*********************************************##alldebrid_api_key");
else
sprintf(id, "%s", "##client_secret_input");
if (ImGui::Button(id, ImVec2(835-width, 0)))
{
ResetImeCallbacks();
ime_single_field = alldebrid_api_key;
ime_field_size = 31;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_API_KEY], alldebrid_api_key, 31, ORBIS_TYPE_BASIC_LATIN, 1050, 80);
gui_mode = GUI_MODE_IME;
}
ImGui::PopStyleVar();
ImGui::Separator();
// Google settings
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s", lang_strings[STR_GOOGLE]);
ImGui::Separator();
@@ -2399,7 +2400,6 @@ namespace Windows
{
if (ime_result == IME_DIALOG_RESULT_FINISHED)
{
remote_settings->http_port = atoi(txt_http_port);
http_server_port = atoi(txt_http_server_port);
}
}