Compare commits

...

53 Commits

Author SHA1 Message Date
Chee Yee 2f7017ad10 update icon 2023-02-21 22:55:12 -08:00
Chee Yee e8f77d94de disable debug 2023-02-21 22:08:44 -08:00
cy33hc 3a08ceee37 Update README.md 2023-02-21 22:00:41 -08:00
cy33hc acb770ca50 Update README.md 2023-02-21 22:00:21 -08:00
Chee Yee 85a5657821 change webdav url scheme to webdav:// and webdavs:// 2023-02-21 21:59:11 -08:00
cy33hc d248e9e3ea Update README.md 2023-02-21 20:48:21 -08:00
Chee Yee d3fd550e90 change label for Serve 2023-02-21 20:38:12 -08:00
cy33hc 8f59465bb9 Update README.md 2023-02-21 20:27:57 -08:00
Chee Yee 6b8289ab8e change label for Microsoft IIS 2023-02-21 20:25:11 -08:00
Chee Yee 75e1283db7 allow url_path in http server path 2023-02-21 20:08:20 -08:00
cy33hc 9ce8c2ef11 Update README.md 2023-02-21 01:36:36 -08:00
Chee Yee 4786c54bd5 update ui to choose http server type 2023-02-21 01:06:05 -08:00
Chee Yee afdc3cd468 support nginx http server 2023-02-21 00:28:02 -08:00
Chee Yee 957e3a0dc0 fix header define 2023-02-20 22:57:54 -08:00
Chee Yee 8f77e62867 support apache httpd server 2023-02-20 22:53:43 -08:00
Chee Yee ec94c22d99 code refactor and add support for iis http server 2023-02-20 20:26:17 -08:00
Chee Yee 0be5c6707c suuport npx serve http server 2023-02-20 16:13:49 -08:00
Chee Yee 43d3ef1c78 http server 2023-02-20 04:56:16 -08:00
Chee Yee 43a9b6063f change ime dialog type for server url 2023-02-19 17:02:45 -08:00
Chee Yee 7e0b2d6661 add httplib library 2023-02-17 01:10:37 -08:00
Chee Yee 3f5ecdd9a3 add some basic http client 2023-02-16 02:47:17 -08:00
Chee Yee 40ac1b95ff prepare for a http client 2023-02-15 20:35:22 -08:00
Chee Yee 2cf692df0c refactor web code 2023-02-15 01:30:36 -08:00
Chee Yee 88859b17f4 add tooltip to paste action to show files being pasted 2023-02-15 01:29:46 -08:00
Chee Yee fe91eaabe3 fix copy of single file with webdav 2023-02-14 00:14:22 -08:00
Chee Yee 52235d7d1c disable site selection while connected 2023-02-13 23:31:25 -08:00
Chee Yee 4a883a6af2 fix rmdir when moving folders 2023-02-13 23:20:58 -08:00
cy33hc 833aede808 Update README.md 2023-02-13 22:39:15 -08:00
cy33hc ae64596cff Update README.md 2023-02-13 22:38:01 -08:00
Chee Yee c315d58d19 option to enable/disable remote package install 2023-02-13 22:25:02 -08:00
Chee Yee 36c4b7dcbb Merge branch 'master' of github.com:cy33hc/ps4-ezremote-client 2023-02-13 21:24:12 -08:00
Chee Yee 0aef91ada2 add option to download and install if remote package install not possible 2023-02-13 21:24:04 -08:00
cy33hc e4449cfc0f Update README.md 2023-02-13 03:13:08 -08:00
Chee Yee 2784994260 disable debug 2023-02-13 02:40:56 -08:00
Chee Yee 44851833a3 add missing message 2023-02-13 02:12:34 -08:00
Chee Yee 864015ba17 add option to reinstall package 2023-02-13 02:05:10 -08:00
Chee Yee cb10992d49 fix message for moving remote files 2023-02-13 00:42:32 -08:00
Chee Yee 83070356d4 add back ability for remote package install for smb/ftp 2023-02-13 00:07:05 -08:00
Chee Yee 2be520d9cf fix some lang issue 2023-02-12 16:10:59 -08:00
cy33hc a9d97f35b4 Update README.md 2023-02-12 00:42:23 -08:00
Chee Yee 24943cca88 fix file progress not updating 2023-02-12 00:23:17 -08:00
Chee Yee 951e3e686e add cut/copy/paste function for webdav server 2023-02-12 00:14:59 -08:00
Chee Yee d5a850dd10 add cut/copy/paste function for local files 2023-02-11 18:52:36 -08:00
Chee Yee 11f7f2eb25 corrected default folder for multiple file 2023-02-10 22:07:13 -08:00
Chee Yee c404a08387 allow actions without need to select item with square first 2023-02-10 21:52:25 -08:00
Chee Yee e2b75307f0 hide/show file extract progress 2023-02-10 01:44:13 -08:00
Chee Yee 58c8b24751 Merge branch 'master' of github.com:cy33hc/ps4-ezremote-client 2023-02-10 01:42:10 -08:00
Chee Yee b240de455b add ability to extract 7zip and rar files 2023-02-10 01:42:03 -08:00
cy33hc 7043453cb4 Update README.md 2023-02-08 21:08:07 -08:00
cy33hc 6292f21bfa Update README.md 2023-02-08 12:27:02 -08:00
cy33hc 259fc496ab Update README.md 2023-02-08 12:22:26 -08:00
cy33hc 7b24c8e53a Update README.md 2023-02-08 12:21:15 -08:00
cy33hc c3bb044d87 Update README.md 2023-02-08 01:10:27 -08:00
62 changed files with 13054 additions and 644 deletions
+17 -7
View File
@@ -5,20 +5,27 @@ project(ezremote_client)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDONT_HAVE_STRUPR")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
add_definitions(-DCPPHTTPLIB_OPENSSL_SUPPORT)
include_directories(
source
source/webdav
source/pugixml
)
add_executable(ezremote_client
source/pugixml/pugixml.cpp
source/webdav/callback.cpp
source/web/callback.cpp
source/web/fsinfo.cpp
source/web/header.cpp
source/web/request.cpp
source/web/urn.cpp
source/webdav/client.cpp
source/webdav/fsinfo.cpp
source/webdav/header.cpp
source/webdav/request.cpp
source/webdav/urn.cpp
source/http/httplib.cpp
source/http/baseclient.cpp
source/http/apache.cpp
source/http/iis.cpp
source/http/nginx.cpp
source/http/npxserve.cpp
source/actions.cpp
source/config.cpp
source/fs.cpp
@@ -46,7 +53,7 @@ add_executable(ezremote_client
add_self(ezremote_client)
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.00" 32 0)
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.01" 32 0)
target_link_libraries(ezremote_client
c
@@ -63,6 +70,8 @@ target_link_libraries(ezremote_client
lexbor
smb2
minizip
un7zip
unrar
kernel
SceShellCoreUtil
SceSysmodule
@@ -78,4 +87,5 @@ target_link_libraries(ezremote_client
SceNet
SceBgft
SceAppInstUtil
SceLncUtil
)
+35 -19
View File
@@ -1,15 +1,15 @@
# ezRemote Client
ezRemote Client is an application that allows you to connect the PS4 to remote FTP, SMB and WebDAV servers to transfer files. The interface is inspired by Filezilla client which provides a commander like GUI.
ezRemote Client is an application that allows you to connect the PS4 to remote FTP, SMB, WebDAV and HTTP servers to transfer files. The interface is inspired by Filezilla client which provides a commander like GUI.
![Preview](/screenshot.jpg)
## Usage
To distinguish between FTP, SMB or WebDAV, the URL mush be prefix with **ftp://**, **smb://**, **http://** and **https://**
To distinguish between FTP, SMB, WebDAV or HTTP, the URL must be prefix with **ftp://**, **smb://**, **webdav://**, **webdavs://**, **http://** and **https://**
- The url format for FTP is
```
ftp://hostname[:port]
- hostname can be the textual hostname or an IP address
- hostname can be the textual hostname or an IP address. hostname is required
- port is optional and defaults to 21 if not provided
```
@@ -17,17 +17,28 @@ To distinguish between FTP, SMB or WebDAV, the URL mush be prefix with **ftp://*
```
smb://hostname[:port]/sharename
- hostname can be the textual hostname or an IP address
- hostname can be the textual hostname or an IP address. hostname is required
- port is optional and defaults to 445 if not provided
- sharename is required
```
- The url format for WebDAV is
```
http://hostname[:port]/url_path
https://hostname[:port]/url_path
webdav://hostname[:port]/[url_path]
webdavs://hostname[:port]/[url_path]
- hostname can be the textual hostname or an IP address
- hostname can be the textual hostname or an IP address. hostname is required
- port is optional and defaults to 80(webdav) and 443(webdavs) if not provided
- url_path is optional based on your WebDAV hosting requiremets
```
- The url format for HTTP Server is
```
http://hostname[:port]/[url_path]
https://hostname[:port]/[url_path]
- hostname can be the textual hostname or an IP address. hostname is required
- port is optional and defaults to 80(http) and 443(https) if not provided
- url_path is optional based on your HTTP Server hosting requiremets
```
Tested with following WebDAV server:
@@ -43,10 +54,15 @@ Remote Package Installation only works if the WebDAV server allow anonymous acce
## Features ##
- Transfer files back and forth between PS4 and FTP/SMB/WebDAV server
- Install packages from connected WebDAV server
- Install packages from PS4 local drive
- Install package from Direct Links. Direct links are links that can be reached without being redirected to a webpage where it requires capthas or timers. Example of direct links are github release artifacts. Google shared links is the only exception since I could indirectly parse the webpage to obtain the direct links.
- Extract/Create Zip files
- Support for connecting to Http Servers like (Apache/Nginx,Microsoft IIS, Serve) with directory listings to download or install pkg.
- Install Remote Packages from connected WebDAV server
- Install Remote Packages for FTP/SMB if HTTP server setup on same host sharing same folder as FTP/SMB
- If Remote Package Install is not possible, optionally the user can choose to download package to PS4 local drive and install
- Install packages from PS4 local drive **/data** folder or usb drive **/mnt/usbX**
- Install package from Direct Links. Direct links are links that can be reached without being redirected to a webpage where it requires capthas or timers. Example of direct links are github release artifacts. Google shared links is the only exception since I could indirectly parse the webpage to obtain the direct links
- Create Zip files on PS4 local drive or usb drive
- Extract from zip, 7zip and rar files
- File management function include cut/copy/paste/rename/delete/new folder for files on PS4 local drive or usb or WebDAV Server.
## Installation
Copy the **ezremote_client.pkg** in to a FAT32 format usb drive then install from package installer
@@ -126,8 +142,7 @@ Download the PS4SDK Toolchain
chmod guo+x /opt/pacbrew/ps4/openorbis/ps4vars.sh
```
Build and install openssl
openssl - https://github.com/cy33hc/ps4-openssl/blob/OpenSSL_1_1_1-ps4/README_PS4.md
Build and install openssl - https://github.com/cy33hc/ps4-openssl/blob/OpenSSL_1_1_1-ps4/README_PS4.md
Build and install libcurl
```
@@ -142,14 +157,15 @@ Build and install libcurl
6. make -C lib install
```
Build and install libsmb2
libsmb2 - https://github.com/cy33hc/libsmb2/blob/ps4/README_PS4.md
Build and install libsmb2 - https://github.com/cy33hc/libsmb2/blob/ps4/README_PS4.md
Build and install lexbor
lexbor - https://github.com/lexbor/lexbor.git
Build and install lexbor - https://github.com/lexbor/lexbor.git
Build libjbc
libjbc - https://github.com/cy33hc/ps4-libjbc/blob/master/README_PS4.md
Build libjbc - https://github.com/cy33hc/ps4-libjbc/blob/master/README_PS4.md
Build libunrar - https://github.com/cy33hc/libunrar-ps3
Build libun7zip - https://github.com/cy33hc/libun7zip
Finally build the app
```
Binary file not shown.
+1 -1
View File
@@ -58,4 +58,4 @@ STR_FAIL_TIMEOUT_MSG=426 Neuspjelo. Konekcijska pauza
STR_FAIL_DEL_DIR_MSG=Neuspješno brisanje mape
STR_DELETING=Brisanje
STR_FAIL_DEL_FILE_MSG=Neuspješno brisanje datoteke
STR_DELETED=Obrisano
STR_DELETED=Obrisano
+61 -61
View File
@@ -1,61 +1,61 @@
STR_CONNECTION_SETTINGS=Verbindingsinstellingen
STR_SITE=Site
STR_LOCAL=Lokaal
STR_REMOTE=Extern
STR_MESSAGES=Berichten
STR_UPDATE_SOFTWARE=Update Software
STR_CONNECT=Verbind met
STR_DISCONNECT=Verbreek verbinding met
STR_SEARCH=Zoek
STR_REFRESH=Vernieuw
STR_SERVER=Server
STR_USERNAME=Gebruikersnaam
STR_PASSWORD=Wachtwoord
STR_PORT=Poort
STR_PASV=Pasv
STR_DIRECTORY=Locatie
STR_FILTER=Filter
STR_YES=Ja
STR_NO=Nee
STR_CANCEL=Annuleren
STR_CONTINUE=Ga door
STR_CLOSE=Sluit
STR_FOLDER=Map
STR_FILE=Bestand
STR_TYPE=Type
STR_NAME=Naam
STR_SIZE=Grootte
STR_DATE=Datum
STR_NEW_FOLDER=Nieuwe Map
STR_RENAME=Hernoemen
STR_DELETE=Verwijderen
STR_UPLOAD=Upload
STR_DOWNLOAD=Download
STR_SELECT_ALL=Alles selecteren
STR_CLEAR_ALL=Alles wissen
STR_UPLOADING=Uploaden
STR_DOWNLOADING=Downloaden
STR_OVERWRITE=Overschrijven
STR_DONT_OVERWRITE=Niet Overschrijven
STR_ASK_FOR_CONFIRM=Vraag om bevestiging
STR_DONT_ASK_CONFIRM=Vraag niet om bevestiging
STR_ALLWAYS_USE_OPTION=Gebruik altijd deze optie en niet opnieuw vragen
STR_ACTIONS=Acties
STR_CONFIRM=Bevestig
STR_OVERWRITE_OPTIONS=Opties Overschrijven
STR_PROPERTIES=Eigenschappen
STR_PROGRESS=Voortgang
STR_UPDATES=Updates
STR_DEL_CONFIRM_MSG=Ben je zeker dat je dit(deze) bestand(en) of map(pen) wilt verwijderen?
STR_CANCEL_ACTION_MSG=Annuleren. Wachten tot de laatste actie voltooid is.
STR_FAIL_UPLOAD_MSG=Uploaden van bestand mislukt
STR_FAIL_DOWNLOAD_MSG=Downloaden van bestand mislukt
STR_FAIL_READ_LOCAL_DIR_MSG=Lezen van inhoud mislukt, map is onbekend
STR_CONNECTION_CLOSE_ERR_MSG=426 Verbinding verbroken.
STR_REMOTE_TERM_CONN_MSG=426 Externe server heeft de verbinding verbroken.
STR_FAIL_LOGIN_MSG=300 Inloggen mislukt. Controleer je gebruikersnaam of wachtwoord.
STR_FAIL_TIMEOUT_MSG=426 Mislukt. Verbinding time-out.
STR_FAIL_DEL_DIR_MSG=Verwijderen van map mislukt.
STR_DELETING=Verwijderen
STR_FAIL_DEL_FILE_MSG=Verwijderen van bestand mislukt.
STR_DELETED=Verwijderd
STR_CONNECTION_SETTINGS=Verbindingsinstellingen
STR_SITE=Site
STR_LOCAL=Lokaal
STR_REMOTE=Extern
STR_MESSAGES=Berichten
STR_UPDATE_SOFTWARE=Update Software
STR_CONNECT=Verbind met
STR_DISCONNECT=Verbreek verbinding met
STR_SEARCH=Zoek
STR_REFRESH=Vernieuw
STR_SERVER=Server
STR_USERNAME=Gebruikersnaam
STR_PASSWORD=Wachtwoord
STR_PORT=Poort
STR_PASV=Pasv
STR_DIRECTORY=Locatie
STR_FILTER=Filter
STR_YES=Ja
STR_NO=Nee
STR_CANCEL=Annuleren
STR_CONTINUE=Ga door
STR_CLOSE=Sluit
STR_FOLDER=Map
STR_FILE=Bestand
STR_TYPE=Type
STR_NAME=Naam
STR_SIZE=Grootte
STR_DATE=Datum
STR_NEW_FOLDER=Nieuwe Map
STR_RENAME=Hernoemen
STR_DELETE=Verwijderen
STR_UPLOAD=Upload
STR_DOWNLOAD=Download
STR_SELECT_ALL=Alles selecteren
STR_CLEAR_ALL=Alles wissen
STR_UPLOADING=Uploaden
STR_DOWNLOADING=Downloaden
STR_OVERWRITE=Overschrijven
STR_DONT_OVERWRITE=Niet Overschrijven
STR_ASK_FOR_CONFIRM=Vraag om bevestiging
STR_DONT_ASK_CONFIRM=Vraag niet om bevestiging
STR_ALLWAYS_USE_OPTION=Gebruik altijd deze optie en niet opnieuw vragen
STR_ACTIONS=Acties
STR_CONFIRM=Bevestig
STR_OVERWRITE_OPTIONS=Opties Overschrijven
STR_PROPERTIES=Eigenschappen
STR_PROGRESS=Voortgang
STR_UPDATES=Updates
STR_DEL_CONFIRM_MSG=Ben je zeker dat je dit(deze) bestand(en) of map(pen) wilt verwijderen?
STR_CANCEL_ACTION_MSG=Annuleren. Wachten tot de laatste actie voltooid is.
STR_FAIL_UPLOAD_MSG=Uploaden van bestand mislukt
STR_FAIL_DOWNLOAD_MSG=Downloaden van bestand mislukt
STR_FAIL_READ_LOCAL_DIR_MSG=Lezen van inhoud mislukt, map is onbekend
STR_CONNECTION_CLOSE_ERR_MSG=426 Verbinding verbroken.
STR_REMOTE_TERM_CONN_MSG=426 Externe server heeft de verbinding verbroken.
STR_FAIL_LOGIN_MSG=300 Inloggen mislukt. Controleer je gebruikersnaam of wachtwoord.
STR_FAIL_TIMEOUT_MSG=426 Mislukt. Verbinding time-out.
STR_FAIL_DEL_DIR_MSG=Verwijderen van map mislukt.
STR_DELETING=Verwijderen
STR_FAIL_DEL_FILE_MSG=Verwijderen van bestand mislukt.
STR_DELETED=Verwijderd
+21
View File
@@ -94,3 +94,24 @@ STR_COMPRESS=Compress
STR_ZIP_FILE_PATH=Zip Filename
STR_COMPRESSING=Compressing
STR_ERROR_CREATE_ZIP=Error occured while creating zip
STR_UNSUPPORTED_FILE_FORMAT=Unsupported compressed file format
STR_CUT=Cut
STR_COPY=Copy
STR_PASTE=Paste
STR_MOVING=Moving
STR_COPYING=Copying
STR_FAIL_MOVE_MSG=Failed to move file
STR_FAIL_COPY_MSG=Failed to copy file
STR_CANT_MOVE_TO_SUBDIR_MSG=Cannot move parent directory to sub subdirectory
STR_CANT_COPY_TO_SUBDIR_MSG=Cannot copy parent directory to sub subdirectory
STR_UNSUPPORTED_OPERATION_MSG=Operation not supported
STR_HTTP_PORT=Http Port
STR_REINSTALL_CONFIRM_MSG=The content has already been installed. Do you want to continue installing
STR_REMOTE_NOT_SUPPORT_MSG=Remote server requires at least a username.
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?
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_FILES=Files
+1 -1
View File
@@ -58,4 +58,4 @@ STR_FAIL_TIMEOUT_MSG=426 Fehler. Verbindung abgelaufen.
STR_FAIL_DEL_DIR_MSG=Verzeichnis konnte nicht gelöscht werden
STR_DELETING=Löschen
STR_FAIL_DEL_FILE_MSG=Datei konnte nicht gelöscht werden
STR_DELETED=Gelöscht
STR_DELETED=Gelöscht
+1 -1
View File
@@ -58,4 +58,4 @@ STR_FAIL_TIMEOUT_MSG=426 실패. 접속시간 초과.
STR_FAIL_DEL_DIR_MSG=디렉토리 삭제에 실패하였습니다.
STR_DELETING=삭제 중
STR_FAIL_DEL_FILE_MSG=파일 삭제에 실패하였습니다.
STR_DELETED=삭제됨
STR_DELETED=삭제됨
+86 -86
View File
@@ -1,86 +1,86 @@
STR_CONNECTION_SETTINGS=Setări de conecțiune
STR_SITE=Site
STR_LOCAL=Local
STR_REMOTE=Distant
STR_MESSAGES=Mesaje
STR_UPDATE_SOFTWARE=Update de aplicație
STR_CONNECT=Conecteazăte
STR_DISCONNECT=Deconecteazăte
STR_SEARCH=Caută
STR_REFRESH=Reîncarca
STR_SERVER=Servere
STR_USERNAME=Nume de utilizator
STR_PASSWORD=Parola
STR_PORT=Portul
STR_PASV=Pasv-ul
STR_DIRECTORY=Directorul
STR_FILTER=Filtru
STR_YES=Da
STR_NO=Nu
STR_CANCEL=Anulează
STR_CONTINUE=Continuă
STR_CLOSE=Închide
STR_FOLDER=Dosar
STR_FILE=Fișier
STR_TYPE=Tip
STR_NAME=Nume
STR_SIZE=Mărime
STR_DATE=Data
STR_NEW_FOLDER=Nou dosar
STR_RENAME=Renumește
STR_DELETE=Șterge
STR_UPLOAD=Încarcă
STR_DOWNLOAD=Descarcă
STR_SELECT_ALL=Selectează tot
STR_CLEAR_ALL=Șterge tot
STR_UPLOADING=Încarcă
STR_DOWNLOADING=Descarcă
STR_OVERWRITE=Suprascrie
STR_DONT_OVERWRITE=Nu suprascrie
STR_ASK_FOR_CONFIRM=Întreabă pentru confirmare
STR_DONT_ASK_CONFIRM=Nu întreba pentru confirmare
STR_ALLWAYS_USE_OPTION=Mereu să folosești această opțiune și să nu mă m-ai întrebi
STR_ACTIONS=Acțiuni
STR_CONFIRM=Confirmă
STR_OVERWRITE_OPTIONS=Suprascrie opțiunile
STR_PROPERTIES=Proprietăți
STR_PROGRESS=Progres
STR_UPDATES=Updateturi
STR_DEL_CONFIRM_MSG=Ești sigur că vrei să ștergi aceast fișier(e)/dosar(e)?
STR_CANCEL_ACTION_MSG=Anulînd. Așteptînd pentru ultima acțiune să fie completată
STR_FAIL_UPLOAD_MSG=Fișierul a eșuat să fie încărcat
STR_FAIL_DOWNLOAD_MSG=Fișierul a eșuat să fie descărcat
STR_FAIL_READ_LOCAL_DIR_MSG=A eșuat să citească conținutul directorului sau dosarului care nu există
STR_CONNECTION_CLOSE_ERR_MSG=426 Conecțiune închisă
STR_REMOTE_TERM_CONN_MSG=426 Servărul distant ți-a terminat conecțiunea.
STR_FAIL_LOGIN_MSG=300 Autentificarea eșuata. Te rog sa verifici numele de utilizator și parola.
STR_FAIL_TIMEOUT_MSG=426 Eșuat. Conecțiune terminată
STR_FAIL_DEL_DIR_MSG=A eșuat sa se ștearga directorul
STR_DELETING=Ștergînd
STR_FAIL_DEL_FILE_MSG=A eșuat ștersul fișierului
STR_DELETED=Șters
STR_LINK=Link
STR_SHARE=Înpărtășește
STR_FAILED=310 Eșuat
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 A eșuat să se creeze fișierul pe local
STR_INSTALL=Instalat
STR_INSTALLING=Instalează
STR_INSTALL_SUCCESS=Succes
STR_INSTALL_FAILED=Eșuat
STR_INSTALL_SKIPPED=Sărit
STR_CHECK_HTTP_MSG=Vericînd conecțiunea la servărul distant HTTP
STR_FAILED_HTTP_CHECK=Eșuat conecțiunea la servărul HTTP
STR_REMOTE_NOT_HTTP=Servărul distant nu este de tip HTTP
STR_INSTALL_FROM_DATA_MSG=Pachetul nu se află in /data sau fișierul /mnt/usbX
STR_ALREADY_INSTALLED_MSG=Pachetul este deja instalat
STR_INSTALL_FROM_URL=Instalează din URL
STR_CANNOT_READ_PKG_HDR_MSG=Nu sa putut citit antetul de info al pachetului
STR_FAVORITE_URLS=URL-urile favorite
STR_SLOT=Slot
STR_EDIT=Editează
STR_ONETIME_URL=Un Url pentru o singură dată
STR_NOT_A_VALID_PACKAGE=Nu este un pachet valid
STR_WAIT_FOR_INSTALL_MSG=Așteptînd pachetul să se termine de instalat
STR_FAIL_INSTALL_TMP_PKG_MSG=A eșuat instalarea fișierului pkg. Te rog șterge pkg temporar manual
STR_FAIL_TO_OBTAIN_GG_DL_MSG=A eșuat obținerea URL-ului de instalare de la google
STR_AUTO_DELETE_TMP_PKG=Auto șterge fișierele temporare pkg instalate dupa instalare
STR_CONNECTION_SETTINGS=Setări de conecțiune
STR_SITE=Site
STR_LOCAL=Local
STR_REMOTE=Distant
STR_MESSAGES=Mesaje
STR_UPDATE_SOFTWARE=Update de aplicație
STR_CONNECT=Conecteazăte
STR_DISCONNECT=Deconecteazăte
STR_SEARCH=Caută
STR_REFRESH=Reîncarca
STR_SERVER=Servere
STR_USERNAME=Nume de utilizator
STR_PASSWORD=Parola
STR_PORT=Portul
STR_PASV=Pasv-ul
STR_DIRECTORY=Directorul
STR_FILTER=Filtru
STR_YES=Da
STR_NO=Nu
STR_CANCEL=Anulează
STR_CONTINUE=Continuă
STR_CLOSE=Închide
STR_FOLDER=Dosar
STR_FILE=Fișier
STR_TYPE=Tip
STR_NAME=Nume
STR_SIZE=Mărime
STR_DATE=Data
STR_NEW_FOLDER=Nou dosar
STR_RENAME=Renumește
STR_DELETE=Șterge
STR_UPLOAD=Încarcă
STR_DOWNLOAD=Descarcă
STR_SELECT_ALL=Selectează tot
STR_CLEAR_ALL=Șterge tot
STR_UPLOADING=Încarcă
STR_DOWNLOADING=Descarcă
STR_OVERWRITE=Suprascrie
STR_DONT_OVERWRITE=Nu suprascrie
STR_ASK_FOR_CONFIRM=Întreabă pentru confirmare
STR_DONT_ASK_CONFIRM=Nu întreba pentru confirmare
STR_ALLWAYS_USE_OPTION=Mereu să folosești această opțiune și să nu mă m-ai întrebi
STR_ACTIONS=Acțiuni
STR_CONFIRM=Confirmă
STR_OVERWRITE_OPTIONS=Suprascrie opțiunile
STR_PROPERTIES=Proprietăți
STR_PROGRESS=Progres
STR_UPDATES=Updateturi
STR_DEL_CONFIRM_MSG=Ești sigur că vrei să ștergi aceast fișier(e)/dosar(e)?
STR_CANCEL_ACTION_MSG=Anulînd. Așteptînd pentru ultima acțiune să fie completată
STR_FAIL_UPLOAD_MSG=Fișierul a eșuat să fie încărcat
STR_FAIL_DOWNLOAD_MSG=Fișierul a eșuat să fie descărcat
STR_FAIL_READ_LOCAL_DIR_MSG=A eșuat să citească conținutul directorului sau dosarului care nu există
STR_CONNECTION_CLOSE_ERR_MSG=426 Conecțiune închisă
STR_REMOTE_TERM_CONN_MSG=426 Servărul distant ți-a terminat conecțiunea.
STR_FAIL_LOGIN_MSG=300 Autentificarea eșuata. Te rog sa verifici numele de utilizator și parola.
STR_FAIL_TIMEOUT_MSG=426 Eșuat. Conecțiune terminată
STR_FAIL_DEL_DIR_MSG=A eșuat sa se ștearga directorul
STR_DELETING=Ștergînd
STR_FAIL_DEL_FILE_MSG=A eșuat ștersul fișierului
STR_DELETED=Șters
STR_LINK=Link
STR_SHARE=Înpărtășește
STR_FAILED=310 Eșuat
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 A eșuat să se creeze fișierul pe local
STR_INSTALL=Instalat
STR_INSTALLING=Instalează
STR_INSTALL_SUCCESS=Succes
STR_INSTALL_FAILED=Eșuat
STR_INSTALL_SKIPPED=Sărit
STR_CHECK_HTTP_MSG=Vericînd conecțiunea la servărul distant HTTP
STR_FAILED_HTTP_CHECK=Eșuat conecțiunea la servărul HTTP
STR_REMOTE_NOT_HTTP=Servărul distant nu este de tip HTTP
STR_INSTALL_FROM_DATA_MSG=Pachetul nu se află in /data sau fișierul /mnt/usbX
STR_ALREADY_INSTALLED_MSG=Pachetul este deja instalat
STR_INSTALL_FROM_URL=Instalează din URL
STR_CANNOT_READ_PKG_HDR_MSG=Nu sa putut citit antetul de info al pachetului
STR_FAVORITE_URLS=URL-urile favorite
STR_SLOT=Slot
STR_EDIT=Editează
STR_ONETIME_URL=Un Url pentru o singură dată
STR_NOT_A_VALID_PACKAGE=Nu este un pachet valid
STR_WAIT_FOR_INSTALL_MSG=Așteptînd pachetul să se termine de instalat
STR_FAIL_INSTALL_TMP_PKG_MSG=A eșuat instalarea fișierului pkg. Te rog șterge pkg temporar manual
STR_FAIL_TO_OBTAIN_GG_DL_MSG=A eșuat obținerea URL-ului de instalare de la google
STR_AUTO_DELETE_TMP_PKG=Auto șterge fișierele temporare pkg instalate dupa instalare
+1 -1
View File
@@ -58,4 +58,4 @@ STR_FAIL_TIMEOUT_MSG=426 Неуспешно. Время соединения в
STR_FAIL_DEL_DIR_MSG=Удаление папки неуспешно
STR_DELETING=Удаляются
STR_FAIL_DEL_FILE_MSG=Удаление файла неуспешно
STR_DELETED=Удалено
STR_DELETED=Удалено
+1 -1
View File
@@ -72,4 +72,4 @@ STR_CHECK_HTTP_MSG=Uzaktan HTTP Sunucusu bağlantısı kontrol ediliyor
STR_FAILED_HTTP_CHECK=HTTP Sunucusuna bağlantı başarısız
STR_REMOTE_NOT_HTTP=Uzaktaki HTTP Sunucusu değil
STR_INSTALL_FROM_DATA_MSG=Paket /data ya da /mnt/usbX dizininde değil
STR_ALREADY_INSTALLED_MSG=Paket zaten kurulu
STR_ALREADY_INSTALLED_MSG=Paket zaten kurulu
Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 88 KiB

File diff suppressed because it is too large Load Diff
+557 -26
View File
@@ -12,12 +12,16 @@
#include "lang.h"
#include "actions.h"
#include "installer.h"
#include "request.hpp"
#include "urn.hpp"
#include "web/request.hpp"
#include "web/urn.hpp"
#include "rtc.h"
#include "ftpclient.h"
#include "smbclient.h"
#include "webdavclient.h"
#include "http/apache.h"
#include "http/nginx.h"
#include "http/npxserve.h"
#include "http/iis.h"
#include "zip_util.h"
namespace Actions
@@ -52,7 +56,7 @@ namespace Actions
{
local_files = FS::ListDir(local_directory, &err);
}
FS::Sort(local_files);
DirEntry::Sort(local_files);
if (err != 0)
sprintf(status_message, "%s", lang_strings[STR_FAIL_READ_LOCAL_DIR_MSG]);
}
@@ -88,7 +92,7 @@ namespace Actions
{
remote_files = remoteclient->ListDir(remote_directory);
}
FS::Sort(remote_files);
DirEntry::Sort(remote_files);
}
void HandleChangeLocalDirectory(const DirEntry entry)
@@ -246,7 +250,13 @@ namespace Actions
void *DeleteSelectedLocalFilesThread(void *argp)
{
for (std::set<DirEntry>::iterator it = multi_selected_local_files.begin(); it != multi_selected_local_files.end(); ++it)
std::vector<DirEntry> files;
if (multi_selected_local_files.size() > 0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(files));
else
files.push_back(selected_local_file);
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
FS::RmRecursive(it->path);
}
@@ -271,7 +281,13 @@ namespace Actions
{
if (remoteclient->Ping())
{
for (std::set<DirEntry>::iterator it = multi_selected_remote_files.begin(); it != multi_selected_remote_files.end(); ++it)
std::vector<DirEntry> files;
if (multi_selected_remote_files.size() > 0)
std::copy(multi_selected_remote_files.begin(), multi_selected_remote_files.end(), std::back_inserter(files));
else
files.push_back(selected_remote_file);
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
if (it->isDir)
remoteclient->Rmdir(it->path, true);
@@ -417,7 +433,13 @@ namespace Actions
void *UploadFilesThread(void *argp)
{
file_transfering = true;
for (std::set<DirEntry>::iterator it = multi_selected_local_files.begin(); it != multi_selected_local_files.end(); ++it)
std::vector<DirEntry> files;
if (multi_selected_local_files.size() > 0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(files));
else
files.push_back(selected_local_file);
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
if (it->isDir)
{
@@ -432,7 +454,6 @@ namespace Actions
}
activity_inprogess = false;
file_transfering = false;
multi_selected_local_files.clear();
Windows::SetModalMode(false);
selected_action = ACTION_REFRESH_REMOTE_FILES;
return NULL;
@@ -560,7 +581,13 @@ namespace Actions
void *DownloadFilesThread(void *argp)
{
file_transfering = true;
for (std::set<DirEntry>::iterator it = multi_selected_remote_files.begin(); it != multi_selected_remote_files.end(); ++it)
std::vector<DirEntry> files;
if (multi_selected_remote_files.size() > 0)
std::copy(multi_selected_remote_files.begin(), multi_selected_remote_files.end(), std::back_inserter(files));
else
files.push_back(selected_remote_file);
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
if (it->isDir)
{
@@ -601,8 +628,45 @@ namespace Actions
int success = 0;
int skipped = 0;
WebDAV::WebDavClient *client = (WebDAV::WebDavClient *)remoteclient;
for (std::set<DirEntry>::iterator it = multi_selected_remote_files.begin(); it != multi_selected_remote_files.end(); ++it)
std::vector<DirEntry> files;
if (multi_selected_remote_files.size() > 0)
std::copy(multi_selected_remote_files.begin(), multi_selected_remote_files.end(), std::back_inserter(files));
else
files.push_back(selected_remote_file);
bool download_and_install = false;
if (remote_settings->enable_rpi)
{
std::string url = INSTALLER::getRemoteUrl(files.begin()->path);
sprintf(activity_message, "%s", lang_strings[STR_CHECKING_REMOTE_SERVER_MSG]);
file_transfering = false;
if (!INSTALLER::canInstallRemotePkg(url))
{
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)
{
download_and_install = true;
}
else
{
goto finish;
}
}
}
else
{
download_and_install = true;
}
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
if (stop_activity)
break;
@@ -617,16 +681,26 @@ namespace Actions
pkg_header header;
memset(&header, 0, sizeof(header));
if (client->Head(it->path, (void *)&header, sizeof(header)) == 0)
if (remoteclient->Head(it->path, (void *)&header, sizeof(header)) == 0)
failed++;
else
{
if (BE32(header.pkg_magic) == PKG_MAGIC)
{
if (INSTALLER::InstallRemotePkg(it->path, &header) == 0)
failed++;
if (download_and_install)
{
if (DownloadAndInstallPkg(it->path, &header) == 0)
failed++;
else
success++;
}
else
success++;
{
if (INSTALLER::InstallRemotePkg(it->path, &header) == 0)
failed++;
else
success++;
}
}
else
skipped++;
@@ -642,6 +716,7 @@ namespace Actions
lang_strings[STR_INSTALL_SUCCESS], success, lang_strings[STR_INSTALL_FAILED], failed,
lang_strings[STR_INSTALL_SKIPPED], skipped);
}
finish:
activity_inprogess = false;
multi_selected_remote_files.clear();
Windows::SetModalMode(false);
@@ -667,7 +742,13 @@ namespace Actions
int skipped = 0;
int ret;
for (std::set<DirEntry>::iterator it = multi_selected_local_files.begin(); it != multi_selected_local_files.end(); ++it)
std::vector<DirEntry> files;
if (multi_selected_local_files.size() > 0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(files));
else
files.push_back(selected_local_file);
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
if (stop_activity)
break;
@@ -739,7 +820,13 @@ namespace Actions
void *ExtractZipThread(void *argp)
{
FS::MkDirs(extract_zip_folder, true);
for (std::set<DirEntry>::iterator it = multi_selected_local_files.begin(); it != multi_selected_local_files.end(); ++it)
std::vector<DirEntry> files;
if (multi_selected_local_files.size() > 0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(files));
else
files.push_back(selected_local_file);
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
if (stop_activity)
break;
@@ -778,15 +865,21 @@ namespace Actions
zipFile zf = zipOpen64(zip_file_path, APPEND_STATUS_CREATE);
if (zf != NULL)
{
for (std::set<DirEntry>::iterator it = multi_selected_local_files.begin(); it != multi_selected_local_files.end(); ++it)
std::vector<DirEntry> files;
if (multi_selected_local_files.size() > 0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(files));
else
files.push_back(selected_local_file);
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
if (stop_activity)
break;
int res = ZipUtil::ZipAddPath(zf, it->path, strlen(it->directory)+1, Z_DEFAULT_COMPRESSION);
int res = ZipUtil::ZipAddPath(zf, it->path, strlen(it->directory) + 1, Z_DEFAULT_COMPRESSION);
if (res <= 0)
{
sprintf(status_message, "%s", lang_strings[STR_ERROR_CREATE_ZIP]);
sceKernelUsleep(2000000);
sceKernelUsleep(1000000);
}
}
zipClose(zf, NULL);
@@ -908,7 +1001,7 @@ namespace Actions
sceRtcGetTick(&now, &tick);
sprintf(filename, "%s/%lu.pkg", DATA_PATH, tick.mytick);
std::string full_url = std::string(install_pkg_url);
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);
@@ -925,7 +1018,7 @@ namespace Actions
std::string path = full_url.substr(path_pos);
WebDAV::WebDavClient tmp_client;
tmp_client.Connect(host.c_str(), "", "0", false);
tmp_client.Connect(host.c_str(), install_pkg_url.username, install_pkg_url.password, false);
sprintf(activity_message, "%s URL to %s", lang_strings[STR_DOWNLOADING], filename);
int s = sizeof(pkg_header);
@@ -1015,6 +1108,17 @@ namespace Actions
{
CONFIG::SaveConfig();
if (strncmp(remote_settings->server, "https://", 8) == 0 || strncmp(remote_settings->server, "http://", 7) == 0)
{
if (strcmp(remote_settings->http_server_type, HTTP_SERVER_APACHE) == 0)
remoteclient = new ApacheClient();
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_MS_IIS) == 0)
remoteclient = new IISClient();
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_NGINX) == 0)
remoteclient = new NginxClient();
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_NPX_SERVE) == 0)
remoteclient = new NpxServeClient();
}
else if (strncmp(remote_settings->server, "webdavs://", 10) == 0 || strncmp(remote_settings->server, "webdav://", 9) == 0)
{
remoteclient = new WebDAV::WebDavClient();
}
@@ -1029,8 +1133,6 @@ namespace Actions
client->SetCallbackBytes(1);
client->SetCallbackXferFunction(FtpCallback);
remoteclient = client;
int res = pthread_create(&ftp_keep_alive_thid, NULL, KeepAliveThread, NULL);
}
else
{
@@ -1042,6 +1144,11 @@ namespace Actions
if (remoteclient->Connect(remote_settings->server, remote_settings->username, remote_settings->password))
{
RefreshRemoteFiles(false);
if (remoteclient->clientType() == CLIENT_TYPE_FTP)
{
int res = pthread_create(&ftp_keep_alive_thid, NULL, KeepAliveThread, NULL);
}
}
else
{
@@ -1093,14 +1200,14 @@ namespace Actions
long idle;
while (remoteclient != nullptr && remoteclient->clientType() == CLIENT_TYPE_FTP && remoteclient->IsConnected())
{
FtpClient *client = (FtpClient*) remoteclient;
FtpClient *client = (FtpClient *)remoteclient;
idle = client->GetIdleTime();
if (idle > 60000000)
{
if (!client->Ping())
{
client->Quit();
sprintf(status_message, lang_strings[STR_REMOTE_TERM_CONN_MSG]);
sprintf(status_message, "%s", lang_strings[STR_REMOTE_TERM_CONN_MSG]);
return NULL;
}
}
@@ -1108,4 +1215,428 @@ namespace Actions
}
return NULL;
}
int CopyOrMoveLocalFile(const char *src, const char *dest, bool isCopy)
{
int ret;
if (overwrite_type == OVERWRITE_PROMPT && FS::FileExists(dest))
{
sprintf(confirm_message, "%s %s?", lang_strings[STR_OVERWRITE], dest);
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;
}
else if (overwrite_type == OVERWRITE_NONE && FS::FileExists(dest))
{
confirm_state = CONFIRM_NO;
}
else
{
confirm_state = CONFIRM_YES;
}
if (confirm_state == CONFIRM_YES)
{
if (isCopy)
return FS::Copy(src, dest);
else
return FS::Move(src, dest);
}
return 1;
}
int CopyOrMove(const DirEntry &src, const char *dest, bool isCopy)
{
if (stop_activity)
return 1;
int ret;
if (src.isDir)
{
int err;
std::vector<DirEntry> entries = FS::ListDir(src.path, &err);
FS::MkDirs(dest, true);
for (int i = 0; i < entries.size(); i++)
{
if (stop_activity)
return 1;
int path_length = strlen(dest) + strlen(entries[i].name) + 2;
char *new_path = (char *)malloc(path_length);
snprintf(new_path, path_length, "%s%s%s", dest, FS::hasEndSlash(dest) ? "" : "/", entries[i].name);
if (entries[i].isDir)
{
if (strcmp(entries[i].name, "..") == 0)
continue;
FS::MkDirs(new_path, true);
ret = CopyOrMove(entries[i], new_path, isCopy);
if (ret <= 0)
{
free(new_path);
return ret;
}
}
else
{
snprintf(activity_message, 1024, "%s %s", isCopy ? lang_strings[STR_COPYING] : lang_strings[STR_MOVING], entries[i].path);
bytes_to_download = entries[i].file_size;
bytes_transfered = 0;
ret = CopyOrMoveLocalFile(entries[i].path, new_path, isCopy);
if (ret <= 0)
{
sprintf(status_message, "%s %s", isCopy ? lang_strings[STR_FAIL_COPY_MSG] : lang_strings[STR_FAIL_MOVE_MSG], entries[i].path);
free(new_path);
return ret;
}
}
free(new_path);
}
}
else
{
int path_length = strlen(dest) + strlen(src.name) + 2;
char *new_path = (char *)malloc(path_length);
snprintf(new_path, path_length, "%s%s%s", dest, FS::hasEndSlash(dest) ? "" : "/", src.name);
snprintf(activity_message, 1024, "%s %s", isCopy ? lang_strings[STR_COPYING] : lang_strings[STR_MOVING], src.name);
bytes_to_download = src.file_size;
ret = CopyOrMoveLocalFile(src.path, new_path, isCopy);
if (ret <= 0)
{
free(new_path);
sprintf(status_message, "%s %s", isCopy ? lang_strings[STR_FAIL_COPY_MSG] : lang_strings[STR_FAIL_MOVE_MSG], src.name);
return 0;
}
free(new_path);
}
return 1;
}
void *MoveLocalFilesThread(void *argp)
{
file_transfering = true;
for (std::vector<DirEntry>::iterator it = local_paste_files.begin(); it != local_paste_files.end(); ++it)
{
if (stop_activity)
break;
if (strcmp(it->directory, local_directory) == 0)
continue;
if (it->isDir)
{
if (strncmp(local_directory, it->path, strlen(it->path)) == 0)
{
sprintf(status_message, "%s", lang_strings[STR_CANT_MOVE_TO_SUBDIR_MSG]);
continue;
}
char new_dir[512];
sprintf(new_dir, "%s%s%s", local_directory, FS::hasEndSlash(local_directory) ? "" : "/", it->name);
CopyOrMove(*it, new_dir, false);
FS::RmRecursive(it->path);
}
else
{
CopyOrMove(*it, local_directory, false);
}
}
activity_inprogess = false;
file_transfering = false;
local_paste_files.clear();
Windows::SetModalMode(false);
selected_action = ACTION_REFRESH_LOCAL_FILES;
return NULL;
}
void MoveLocalFiles()
{
sprintf(status_message, "%s", "");
int res = pthread_create(&bk_activity_thid, NULL, MoveLocalFilesThread, NULL);
if (res != 0)
{
file_transfering = false;
activity_inprogess = false;
local_paste_files.clear();
Windows::SetModalMode(false);
}
}
void *CopyLocalFilesThread(void *argp)
{
file_transfering = true;
for (std::vector<DirEntry>::iterator it = local_paste_files.begin(); it != local_paste_files.end(); ++it)
{
if (stop_activity)
break;
if (strcmp(it->directory, local_directory) == 0)
continue;
if (it->isDir)
{
if (strncmp(local_directory, it->path, strlen(it->path)) == 0)
{
sprintf(status_message, "%s", lang_strings[STR_CANT_COPY_TO_SUBDIR_MSG]);
continue;
}
char new_dir[512];
sprintf(new_dir, "%s%s%s", local_directory, FS::hasEndSlash(local_directory) ? "" : "/", it->name);
CopyOrMove(*it, new_dir, true);
}
else
{
CopyOrMove(*it, local_directory, true);
}
}
activity_inprogess = false;
file_transfering = false;
local_paste_files.clear();
Windows::SetModalMode(false);
selected_action = ACTION_REFRESH_LOCAL_FILES;
return NULL;
}
void CopyLocalFiles()
{
sprintf(status_message, "%s", "");
int res = pthread_create(&bk_activity_thid, NULL, CopyLocalFilesThread, NULL);
if (res != 0)
{
file_transfering = false;
activity_inprogess = false;
local_paste_files.clear();
Windows::SetModalMode(false);
}
}
int CopyOrMoveRemoteFile(const std::string &src, const std::string &dest, bool isCopy)
{
int ret;
if (overwrite_type == OVERWRITE_PROMPT && remoteclient->FileExists(dest))
{
sprintf(confirm_message, "%s %s?", lang_strings[STR_OVERWRITE], dest.c_str());
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;
}
else if (overwrite_type == OVERWRITE_NONE && remoteclient->FileExists(dest))
{
confirm_state = CONFIRM_NO;
}
else
{
confirm_state = CONFIRM_YES;
}
if (confirm_state == CONFIRM_YES)
{
if (isCopy)
return remoteclient->Copy(src, dest);
else
return remoteclient->Move(src, dest);
}
return 1;
}
void *MoveRemoteFilesThread(void *argp)
{
file_transfering = false;
for (std::vector<DirEntry>::iterator it = remote_paste_files.begin(); it != remote_paste_files.end(); ++it)
{
if (stop_activity)
break;
if (strcmp(it->directory, remote_directory) == 0)
continue;
char new_path[1024];
sprintf(new_path, "%s%s%s", remote_directory, FS::hasEndSlash(remote_directory) ? "" : "/", it->name);
if (it->isDir)
{
if (strncmp(remote_directory, it->path, strlen(it->path)) == 0)
{
sprintf(status_message, "%s", lang_strings[STR_CANT_MOVE_TO_SUBDIR_MSG]);
continue;
}
}
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_MOVING], it->path);
int res = CopyOrMoveRemoteFile(it->path, new_path, false);
if (res == 0)
sprintf(status_message, "%s - %s", it->name, lang_strings[STR_FAIL_COPY_MSG]);
}
activity_inprogess = false;
file_transfering = false;
remote_paste_files.clear();
Windows::SetModalMode(false);
selected_action = ACTION_REFRESH_REMOTE_FILES;
return NULL;
}
void MoveRemoteFiles()
{
sprintf(status_message, "%s", "");
int res = pthread_create(&bk_activity_thid, NULL, MoveRemoteFilesThread, NULL);
if (res != 0)
{
file_transfering = false;
activity_inprogess = false;
remote_paste_files.clear();
Windows::SetModalMode(false);
}
}
int CopyRemotePath(const DirEntry &src, const char *dest)
{
if (stop_activity)
return 1;
int ret;
if (src.isDir)
{
int err;
std::vector<DirEntry> entries = remoteclient->ListDir(src.path);
remoteclient->Mkdir(dest);
for (int i = 0; i < entries.size(); i++)
{
if (stop_activity)
return 1;
int path_length = strlen(dest) + strlen(entries[i].name) + 2;
char *new_path = (char *)malloc(path_length);
snprintf(new_path, path_length, "%s%s%s", dest, FS::hasEndSlash(dest) ? "" : "/", entries[i].name);
if (entries[i].isDir)
{
if (strcmp(entries[i].name, "..") == 0)
continue;
FS::MkDirs(new_path, true);
ret = CopyRemotePath(entries[i], new_path);
if (ret <= 0)
{
free(new_path);
return ret;
}
}
else
{
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_COPYING], entries[i].path);
bytes_to_download = entries[i].file_size;
bytes_transfered = 0;
ret = CopyOrMoveRemoteFile(entries[i].path, new_path, true);
if (ret <= 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_COPY_MSG], entries[i].path);
free(new_path);
return ret;
}
}
free(new_path);
}
}
else
{
int path_length = strlen(dest) + strlen(src.name) + 2;
char *new_path = (char *)malloc(path_length);
snprintf(new_path, path_length, "%s%s%s", dest, FS::hasEndSlash(dest) ? "" : "/", src.name);
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_COPYING], src.name);
ret = CopyOrMoveRemoteFile(src.path, new_path, true);
if (ret <= 0)
{
free(new_path);
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_COPY_MSG], src.name);
return 0;
}
free(new_path);
}
return 1;
}
void *CopyRemoteFilesThread(void *argp)
{
file_transfering = false;
for (std::vector<DirEntry>::iterator it = remote_paste_files.begin(); it != remote_paste_files.end(); ++it)
{
if (stop_activity)
break;
if (strcmp(it->directory, remote_directory) == 0)
continue;
char new_path[1024];
sprintf(new_path, "%s%s%s", remote_directory, FS::hasEndSlash(remote_directory) ? "" : "/", it->name);
if (it->isDir)
{
if (strncmp(remote_directory, it->path, strlen(it->path)) == 0)
{
sprintf(status_message, "%s", lang_strings[STR_CANT_COPY_TO_SUBDIR_MSG]);
continue;
}
int res = CopyRemotePath(*it, new_path);
if (res == 0)
sprintf(status_message, "%s - %s", it->name, lang_strings[STR_FAIL_COPY_MSG]);
}
else
{
int res = CopyRemotePath(*it, remote_directory);
if (res == 0)
sprintf(status_message, "%s - %s", it->name, lang_strings[STR_FAIL_COPY_MSG]);
}
}
activity_inprogess = false;
file_transfering = false;
remote_paste_files.clear();
Windows::SetModalMode(false);
selected_action = ACTION_REFRESH_REMOTE_FILES;
return NULL;
}
void CopyRemoteFiles()
{
sprintf(status_message, "%s", "");
int res = pthread_create(&bk_activity_thid, NULL, CopyRemoteFilesThread, NULL);
if (res != 0)
{
file_transfering = false;
activity_inprogess = false;
remote_paste_files.clear();
Windows::SetModalMode(false);
}
}
int DownloadAndInstallPkg(const std::string &filename, pkg_header *header)
{
char local_file[2000];
OrbisDateTime now;
OrbisTick tick;
sceRtcGetCurrentClockLocalTime(&now);
sceRtcGetTick(&now, &tick);
sprintf(local_file, "%s/%lu.pkg", DATA_PATH, tick.mytick);
sprintf(activity_message, "%s %s to %s", lang_strings[STR_DOWNLOADING], filename.c_str(), local_file);
remoteclient->Size(filename, &bytes_to_download);
bytes_transfered = 0;
file_transfering = true;
int ret = remoteclient->Get(local_file, filename);
if (ret == 0)
return 0;
return INSTALLER::InstallLocalPkg(local_file, header, true);
}
}
+17 -1
View File
@@ -2,6 +2,7 @@
#define ACTIONS_H
#include <pthread.h>
#include "installer.h"
#include "common.h"
#define CONFIRM_NONE -1
@@ -39,7 +40,13 @@ enum ACTIONS
ACTION_INSTALL_LOCAL_PKG,
ACTION_INSTALL_URL_PKG,
ACTION_EXTRACT_LOCAL_ZIP,
ACTION_CREATE_LOCAL_ZIP
ACTION_CREATE_LOCAL_ZIP,
ACTION_LOCAL_CUT,
ACTION_LOCAL_COPY,
ACTION_LOCAL_PASTE,
ACTION_REMOTE_CUT,
ACTION_REMOTE_COPY,
ACTION_REMOTE_PASTE
};
enum OverWriteType
@@ -88,6 +95,15 @@ namespace Actions
void ExtractLocalZips();
void *MakeZipThread(void *argp);
void MakeLocalZip();
void *MoveLocalFilesThread(void *argp);
void MoveLocalFiles();
void *CopyLocalFilesThread(void *argp);
void CopyLocalFiles();
void *MoveRemoteFilesThread(void *argp);
void MoveRemoteFiles();
void *CopyRemoteFilesThread(void *argp);
void CopyRemoteFiles();
int DownloadAndInstallPkg(const std::string &filename, pkg_header *header);
}
#endif
+21
View File
@@ -28,6 +28,7 @@ struct DirEntry
bool isDir;
bool isLink;
DateTime modified;
bool selectable;
friend bool operator<(DirEntry const &a, DirEntry const &b)
{
@@ -59,6 +60,26 @@ struct DirEntry
{
qsort(&list[0], list.size(), sizeof(DirEntry), DirEntryComparator);
}
static void SetDisplaySize(DirEntry *entry)
{
if (entry->file_size < 1024)
{
sprintf(entry->display_size, "%ldB", entry->file_size);
}
else if (entry->file_size < 1024 * 1024)
{
sprintf(entry->display_size, "%.2fKB", entry->file_size * 1.0f / 1024);
}
else if (entry->file_size < 1024 * 1024 * 1024)
{
sprintf(entry->display_size, "%.2fMB", entry->file_size * 1.0f / (1024 * 1024));
}
else
{
sprintf(entry->display_size, "%.2fGB", entry->file_size * 1.0f / (1024 * 1024 * 1024));
}
}
};
#endif
+57 -1
View File
@@ -2,6 +2,7 @@
#include <cstring>
#include <map>
#include <vector>
#include <regex>
#include <stdlib.h>
#include "config.h"
#include "fs.h"
@@ -21,8 +22,9 @@ char last_site[32];
char display_site[32];
char language[128];
std::vector<std::string> sites;
std::vector<std::string> http_servers;
std::map<std::string, RemoteSettings> site_settings;
char install_pkg_url[512];
PackageUrlInfo install_pkg_url;
char favorite_urls[MAX_FAVORITE_URLS][512];
bool auto_delete_tmp_pkg;
RemoteClient *remoteclient;
@@ -30,6 +32,30 @@ RemoteClient *remoteclient;
namespace CONFIG
{
void SetClientType(RemoteSettings *setting)
{
if (strncmp(setting->server, "smb://", 6) == 0)
{
setting->type = CLIENT_TYPE_SMB;
}
else if (strncmp(setting->server, "ftp://", 6) == 0)
{
setting->type = CLIENT_TYPE_FTP;
}
else if (strncmp(setting->server, "webdav://", 9) == 0 || strncmp(setting->server, "webdavs://", 10) == 0)
{
setting->type = CLIENT_TYPE_WEBDAV;
}
else if (strncmp(setting->server, "http://", 7) == 0 || strncmp(setting->server, "https://", 8) == 0)
{
setting->type = CLIENT_TYPE_HTTP_SERVER;
}
else
{
setting->type = CLINET_TYPE_UNKNOWN;
}
}
void LoadConfig()
{
if (!FS::FolderExists(DATA_PATH))
@@ -40,8 +66,18 @@ 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};
OpenIniFile(CONFIG_INI_FILE);
int version = ReadInt(CONFIG_GLOBAL, CONFIG_VERSION, 0);
bool conversion_needed = false;
if (version < CONFIG_VERSION_NUM)
{
conversion_needed = true;
}
WriteInt(CONFIG_GLOBAL, CONFIG_VERSION, CONFIG_VERSION_NUM);
// Load global config
sprintf(language, "%s", ReadString(CONFIG_GLOBAL, CONFIG_LANGUAGE, ""));
WriteString(CONFIG_GLOBAL, CONFIG_LANGUAGE, language);
@@ -61,6 +97,13 @@ namespace CONFIG
sprintf(setting.site_name, "%s", sites[i].c_str());
sprintf(setting.server, "%s", ReadString(sites[i].c_str(), CONFIG_REMOTE_SERVER_URL, ""));
if (conversion_needed && strlen(setting.server)>0)
{
std::string tmp = std::string(setting.server);
tmp = std::regex_replace(tmp, std::regex("http://"), "webdav://");
tmp = std::regex_replace(tmp, std::regex("https://"), "webdavs://");
sprintf(setting.server, "%s", tmp.c_str());
}
WriteString(sites[i].c_str(), CONFIG_REMOTE_SERVER_URL, setting.server);
sprintf(setting.username, "%s", ReadString(sites[i].c_str(), CONFIG_REMOTE_SERVER_USER, ""));
@@ -69,6 +112,16 @@ namespace CONFIG
sprintf(setting.password, "%s", ReadString(sites[i].c_str(), CONFIG_REMOTE_SERVER_PASSWORD, ""));
WriteString(sites[i].c_str(), CONFIG_REMOTE_SERVER_PASSWORD, setting.password);
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);
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));
WriteString(sites[i].c_str(), CONFIG_REMOTE_HTTP_SERVER_TYPE, setting.http_server_type);
SetClientType(&setting);
site_settings.insert(std::make_pair(sites[i], setting));
}
@@ -95,6 +148,9 @@ 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, remote_settings->password);
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(CONFIG_GLOBAL, CONFIG_LAST_SITE, last_site);
WriteBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, auto_delete_tmp_pkg);
WriteIniFile(CONFIG_INI_FILE);
+26 -1
View File
@@ -19,6 +19,12 @@
#define CONFIG_REMOTE_SERVER_URL "remote_server_url"
#define CONFIG_REMOTE_SERVER_USER "remote_server_user"
#define CONFIG_REMOTE_SERVER_PASSWORD "remote_server_password"
#define CONFIG_REMOTE_SERVER_HTTP_PORT "remote_server_http_port"
#define CONFIG_ENABLE_RPI "remote_server_enable_rpi"
#define CONFIG_REMOTE_HTTP_SERVER_TYPE "remote_server_http_server_type"
#define CONFIG_VERSION "config_version"
#define CONFIG_VERSION_NUM 1
#define CONFIG_FAVORITE_URLS "favorite_urls"
#define MAX_FAVORITE_URLS 30
@@ -31,15 +37,33 @@
#define CONFIG_LANGUAGE "language"
#define HTTP_SERVER_APACHE "Apache"
#define HTTP_SERVER_MS_IIS "Microsoft IIS"
#define HTTP_SERVER_NGINX "Nginx"
#define HTTP_SERVER_NPX_SERVE "Serve"
struct RemoteSettings
{
char site_name[32];
char server[256];
char username[33];
char password[25];
int http_port;
ClientType type;
bool enable_rpi;
uint32_t supported_actions;
char http_server_type[24];
};
struct PackageUrlInfo
{
char url[512];
char username[33];
char password[25];
};
extern std::vector<std::string> sites;
extern std::vector<std::string> http_servers;
extern std::map<std::string, RemoteSettings> site_settings;
extern char local_directory[255];
extern char remote_directory[255];
@@ -49,7 +73,7 @@ extern char display_site[32];
extern char language[128];
extern RemoteSettings *remote_settings;
extern RemoteClient *remoteclient;
extern char install_pkg_url[512];
extern PackageUrlInfo install_pkg_url;
extern char favorite_urls[MAX_FAVORITE_URLS][512];
extern bool auto_delete_tmp_pkg;
@@ -58,6 +82,7 @@ namespace CONFIG
void LoadConfig();
void SaveConfig();
void SaveFavoriteUrl(int index, char *url);
void SetClientType(RemoteSettings *settings);
void RemoveFromMultiValues(std::vector<std::string> &multi_values, std::string value);
void ParseMultiValueString(const char *prefix_list, std::vector<std::string> &prefixes, bool toLower);
std::string GetMultiValueString(std::vector<std::string> &multi_values);
+78 -30
View File
@@ -7,6 +7,7 @@
#include <filesystem>
#include <stdio.h>
#include <unistd.h>
#include <vector>
#include "util.h"
#include "lang.h"
@@ -176,10 +177,11 @@ namespace FS
memset(&entry, 0, sizeof(DirEntry));
sprintf(entry.directory, "%s", path.c_str());
sprintf(entry.name, "..");
sprintf(entry.display_size, "%s",lang_strings[STR_FOLDER]);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
sprintf(entry.path, "%s", path.c_str());
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
DIR *fd = opendir(path.c_str());
@@ -209,6 +211,7 @@ namespace FS
snprintf(entry.directory, 512, "%s", path.c_str());
snprintf(entry.name, 256, "%s", dirent->d_name);
entry.selectable = true;
if (hasEndSlash(path.c_str()))
{
@@ -246,7 +249,7 @@ namespace FS
{
entry.isDir = true;
entry.file_size = 0;
sprintf(entry.display_size, "%s",lang_strings[STR_FOLDER]);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
}
else
{
@@ -320,7 +323,7 @@ namespace FS
{
if (stop_activity)
return 1;
DIR *dfd = opendir(path.c_str());
if (dfd != NULL)
{
@@ -386,32 +389,6 @@ namespace FS
return 1;
}
int DirEntryComparator(const void *v1, const void *v2)
{
const DirEntry *p1 = (DirEntry *)v1;
const DirEntry *p2 = (DirEntry *)v2;
if (strcasecmp(p1->name, "..") == 0)
return -1;
if (strcasecmp(p2->name, "..") == 0)
return 1;
if (p1->isDir && !p2->isDir)
{
return -1;
}
else if (!p1->isDir && p2->isDir)
{
return 1;
}
return strcasecmp(p1->name, p2->name);
}
void Sort(std::vector<DirEntry> &list)
{
qsort(&list[0], list.size(), sizeof(DirEntry), DirEntryComparator);
}
std::string GetPath(const std::string &ppath1, const std::string &ppath2)
{
std::string path1 = ppath1;
@@ -420,9 +397,11 @@ namespace FS
return path1 + "/" + path2;
}
int Head(const std::string &path, void* buffer, uint16_t len)
int Head(const std::string &path, void *buffer, uint16_t len)
{
FILE *file = OpenRead(path);
if (file == nullptr)
return 0;
int ret = Read(file, buffer, len);
if (ret != len)
{
@@ -432,4 +411,73 @@ namespace FS
Close(file);
return 1;
}
bool Copy(const std::string &from, const std::string &to)
{
MkDirs(to, true);
FILE *src = fopen(from.c_str(), "rb");
if (!src)
{
return false;
}
struct stat file_stat = {0};
if (stat(from.c_str(), &file_stat) != 0)
{
return false;
}
bytes_to_download = file_stat.st_size;
FILE *dest = fopen(to.c_str(), "wb");
if (!dest)
{
fclose(src);
return false;
}
size_t bytes_read = 0;
bytes_transfered = 0;
const size_t buf_size = 0x10000;
unsigned char *buf = new unsigned char[buf_size];
do
{
bytes_read = fread(buf, sizeof(unsigned char), buf_size, src);
if (bytes_read < 0)
{
delete[] buf;
fclose(src);
fclose(dest);
return false;
}
size_t bytes_written = fwrite(buf, sizeof(unsigned char), bytes_read, dest);
if (bytes_written != bytes_read)
{
delete[] buf;
fclose(src);
fclose(dest);
return false;
}
bytes_transfered += bytes_read;
} while (bytes_transfered < bytes_to_download);
delete[] buf;
fclose(src);
fclose(dest);
return true;
}
bool Move(const std::string &from, const std::string &to)
{
bool res = Copy(from, to);
if (res)
Rm(from);
else
return res;
return true;
}
}
+4 -2
View File
@@ -28,6 +28,10 @@ namespace FS
void Rename(const std::string &from, const std::string &to);
bool Copy(const std::string &from, const std::string &to);
bool Move(const std::string &from, const std::string &to);
// creates file (if it exists, truncates size to 0)
FILE *Create(const std::string &path);
@@ -52,8 +56,6 @@ namespace FS
std::vector<std::string> ListFiles(const std::string &path);
std::vector<DirEntry> ListDir(const std::string &path, int *err);
void Sort(std::vector<DirEntry> &list);
int hasEndSlash(const char *path);
int Head(const std::string &path, void* buffer, uint16_t len);
+36 -16
View File
@@ -1592,6 +1592,7 @@ std::vector<DirEntry> FtpClient::ListDir(const std::string &path)
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
ftphandle *nData;
@@ -1608,6 +1609,7 @@ std::vector<DirEntry> FtpClient::ListDir(const std::string &path)
{
DirEntry entry;
memset(&entry, 0, sizeof(entry));
entry.selectable = true;
if (ParseDirEntry(buf, &entry) > 0)
{
sprintf(entry.directory, "%s", path.c_str());
@@ -1626,22 +1628,7 @@ std::vector<DirEntry> FtpClient::ListDir(const std::string &path)
}
else
{
if (entry.file_size < 1024)
{
sprintf(entry.display_size, "%ldB", entry.file_size);
}
else if (entry.file_size < 1024 * 1024)
{
sprintf(entry.display_size, "%.2fKB", entry.file_size * 1.0f / 1024);
}
else if (entry.file_size < 1024 * 1024 * 1024)
{
sprintf(entry.display_size, "%.2fMB", entry.file_size * 1.0f / (1024 * 1024));
}
else
{
sprintf(entry.display_size, "%.2fGB", entry.file_size * 1.0f / (1024 * 1024 * 1024));
}
DirEntry::SetDisplaySize(&entry);
}
if (strcmp(entry.name, "..") != 0 && strcmp(entry.name, ".") != 0)
out.push_back(entry);
@@ -1681,6 +1668,11 @@ ClientType FtpClient::clientType()
return CLIENT_TYPE_FTP;
}
uint32_t FtpClient::SupportedActions()
{
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE;
}
std::string FtpClient::GetPath(std::string ppath1, std::string ppath2)
{
std::string path1 = ppath1;
@@ -1690,3 +1682,31 @@ std::string FtpClient::GetPath(std::string ppath1, std::string ppath2)
path1 = path1 + "/" + path2;
return path1;
}
int FtpClient::Copy(const std::string &from, const std::string &to)
{
sprintf(mp_ftphandle->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int FtpClient::Move(const std::string &from, const std::string &to)
{
sprintf(mp_ftphandle->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int FtpClient::Head(const std::string &path, void *buffer, uint64_t len)
{
ftphandle *nData;
if (!FtpAccess(path, FtpClient::fileread, FtpClient::transfermode::image, mp_ftphandle, &nData))
{
return 0;
}
int l = FtpRead(buffer, len, nData);
FtpClose(nData);
if (l != len)
return 0;
return 1;
}
+4
View File
@@ -81,6 +81,9 @@ public:
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);
int Copy(const std::string &from, const std::string &to);
int Move(const std::string &from, const std::string &to);
int Head(const std::string &path, void *buffer, uint64_t len);
std::vector<DirEntry> ListDir(const std::string &path);
void SetCallbackXferFunction(FtpCallbackXfer pointer);
void SetCallbackArg(void *arg);
@@ -94,6 +97,7 @@ public:
int Quit();
std::string GetPath(std::string path1, std::string path2);
ClientType clientType();
uint32_t SupportedActions();
private:
ftphandle *mp_ftphandle;
+239
View File
@@ -0,0 +1,239 @@
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include "common.h"
#include "remote_client.h"
#include "http/apache.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
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;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
if (auto res = client->Get(GetFullPath(path)))
{
lxb_status_t status;
lxb_dom_attr_t *attr;
lxb_dom_node_t *node;
lxb_dom_element_t *element;
lxb_html_document_t *document;
lxb_dom_collection_t *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;
}
collection = lxb_dom_collection_make(&document->dom_document, 128);
if (collection == NULL)
{
lxb_html_document_destroy(document);
goto finish;
}
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
collection, (const lxb_char_t *)"tr", 2);
if (status != LXB_STATUS_OK)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
goto finish;
}
int coll_size = lxb_dom_collection_length(collection);
if (coll_size < 1)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
goto finish;
}
const lxb_char_t *value;
size_t value_len;
std::string tmp_string;
for (size_t i = 0; i < lxb_dom_collection_length(collection); i++)
{
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
element = lxb_dom_collection_element(collection, i);
node = nextChildElement(element);
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);
if (tmp_string.compare("th") == 0)
continue; // skip th, which are the headers
// file/folder indicator
if (tmp_string.compare("td") == 0)
{
// get the child img element
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);
tmp_string = std::string((const char *)value, value_len);
if (tmp_string.compare("img") == 0)
{
value = lxb_dom_element_get_attribute(lxb_dom_interface_element(img), (const lxb_char_t *)"alt", 3, &value_len);
tmp_string = std::string((const char *)value, value_len);
if (tmp_string.compare("[PARENTDIR]") == 0)
continue;
else if (tmp_string.compare("[DIR]") == 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;
}
} else continue; // invalid record
}
else continue; // invalid record
// file/folder name
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);
if (tmp_string.compare("td") == 0)
{
value = lxb_dom_node_text_content(node, &value_len);
tmp_string = std::string((const char *)value, value_len);
tmp_string = Util::Rtrim(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);
}
}
else continue; // not valid record
// datetime
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);
if (tmp_string.compare("td") == 0)
{
value = lxb_dom_node_text_content(node, &value_len);
tmp_string = std::string((const char *)value, value_len);
std::vector<std::string> date_time = Util::Split(tmp_string, " ");
if (date_time.size() == 2)
{
std::vector<std::string> adate = Util::Split(date_time[0], "-");
if (adate.size() == 3)
{
entry.modified.year = atoi(adate[0].c_str());
entry.modified.month = atoi(adate[1].c_str());
entry.modified.day = atoi(adate[2].c_str());
}
std::vector<std::string> atime = Util::Split(date_time[1], ":");
if (atime.size() == 2)
{
entry.modified.hours = atoi(atime[0].c_str());
entry.modified.minutes = atoi(atime[1].c_str());
}
}
}
else continue; // invalid record
// filesize
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);
if (tmp_string.compare("td") == 0)
{
value = lxb_dom_node_text_content(node, &value_len);
tmp_string = std::string((const char *)value, value_len);
tmp_string = Util::Trim(tmp_string, " ");
if (!entry.isDir)
{
char multiplier = tmp_string[tmp_string.length()-1];
std::string filesize = tmp_string.substr(0, tmp_string.length()-1);
sprintf(entry.display_size, "%s", tmp_string.c_str());
if (multiplier == 'K')
entry.file_size = atof(filesize.c_str()) * 1024;
else if (multiplier == 'M')
entry.file_size = atof(filesize.c_str()) * 1024 * 1024;
else if (multiplier == 'G')
entry.file_size = atof(filesize.c_str()) * 1024 * 1024 * 1024;
else if (multiplier == 'G')
entry.file_size = atof(filesize.c_str()) * 1024 * 1024 * 1024 * 1024;
else
entry.file_size = atoi(tmp_string.c_str());
}
}
out.push_back(entry);
}
lxb_dom_collection_destroy(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 APACHE_H
#define APACHE_H
#include <string>
#include <vector>
#include "http/httplib.h"
#include "http/baseclient.h"
#include "common.h"
#include "remote_client.h"
class ApacheClient : public BaseClient
{
public:
std::vector<DirEntry> ListDir(const std::string &path);
};
#endif
+244
View File
@@ -0,0 +1,244 @@
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include "common.h"
#include "remote_client.h"
#include "http/npxserve.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
using httplib::Client;
using httplib::Headers;
using httplib::Result;
BaseClient::BaseClient(){};
BaseClient::~BaseClient()
{
if (client != nullptr)
delete client;
};
int BaseClient::Connect(const std::string &url, const std::string &username, const std::string &password)
{
std::string scheme_host_port = url;
size_t scheme_pos = url.find("://");
size_t root_pos = url.find("/", scheme_pos + 3);
if (root_pos != std::string::npos)
{
scheme_host_port = url.substr(0, root_pos);
this->base_path = url.substr(root_pos);
}
client = new httplib::Client(scheme_host_port);
if (username.length() > 0)
client->set_basic_auth(username, password);
client->set_keep_alive(true);
client->set_follow_location(true);
client->set_connection_timeout(30);
client->set_read_timeout(30);
client->enable_server_certificate_verification(false);
if (Ping())
this->connected = true;
return 1;
}
int BaseClient::Mkdir(const std::string &path)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int BaseClient::Rmdir(const std::string &path, bool recursive)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int BaseClient::Size(const std::string &path, int64_t *size)
{
if (auto res = client->Head(GetFullPath(path)))
{
std::string content_length = res->get_header_value("Content-Length");
if (content_length.length() > 0)
*size = atoll(content_length.c_str());
return 1;
}
else
{
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
}
return 0;
}
int BaseClient::Get(const std::string &outputfile, const std::string &path, uint64_t offset)
{
std::ofstream file_stream(outputfile, std::ios::binary);
bytes_transfered = 0;
if (auto res = client->Get(GetFullPath(path),
[&](const char *data, size_t data_length)
{
file_stream.write(data, data_length);
bytes_transfered += data_length;
return true;
}))
{
file_stream.close();
return 1;
}
else
{
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
}
return 0;
}
int BaseClient::Put(const std::string &inputfile, const std::string &path, uint64_t offset)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int BaseClient::Rename(const std::string &src, const std::string &dst)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int BaseClient::Delete(const std::string &path)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int BaseClient::Copy(const std::string &from, const std::string &to)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int BaseClient::Move(const std::string &from, const std::string &to)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int BaseClient::Head(const std::string &path, void *buffer, uint64_t len)
{
char range_header[64];
sprintf(range_header, "bytes=%lu-%lu", 0L, len-1);
Headers headers = {{"Range", range_header}};
size_t bytes_read = 0;
std::vector<char> body;
if (auto res = client->Get(GetFullPath(path), headers,
[&](const char *data, size_t data_length)
{
body.insert(body.end(), data, data+data_length);
bytes_read += data_length;
if (bytes_read > len)
return false;
return true;
}))
{
if (body.size() < len) return 0;
memcpy(buffer, body.data(), len);
return 1;
}
else
{
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
}
return 0;
}
bool BaseClient::FileExists(const std::string &path)
{
int64_t file_size;
return Size(path, &file_size);
}
std::vector<DirEntry> BaseClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
return out;
}
std::string BaseClient::GetPath(std::string ppath1, std::string ppath2)
{
std::string path1 = ppath1;
std::string path2 = ppath2;
path1 = Util::Trim(Util::Trim(path1, " "), "/");
path2 = Util::Trim(Util::Trim(path2, " "), "/");
path1 = this->base_path + "/" + path1 + "/" + path2;
return path1;
}
std::string BaseClient::GetFullPath(std::string ppath1)
{
std::string path1 = ppath1;
path1 = Util::Trim(Util::Trim(path1, " "), "/");
path1 = this->base_path + "/" + path1;
Util::ReplaceAll(path1, "//", "/");
return path1;
}
bool BaseClient::IsConnected()
{
return this->connected;
}
bool BaseClient::Ping()
{
if (auto res = client->Head("/"))
{
return true;
}
else
{
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
}
return false;
}
const char *BaseClient::LastResponse()
{
return this->response;
}
int BaseClient::Quit()
{
if (client != nullptr)
{
delete client;
client = nullptr;
}
return 1;
}
ClientType BaseClient::clientType()
{
return CLIENT_TYPE_HTTP_SERVER;
}
uint32_t BaseClient::SupportedActions()
{
return REMOTE_ACTION_DOWNLOAD | REMOTE_ACTION_INSTALL;
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef BASESERVER_H
#define BASESERVER_H
#include <string>
#include <vector>
#include "http/httplib.h"
#include "common.h"
#include "remote_client.h"
class BaseClient : public RemoteClient
{
public:
BaseClient();
~BaseClient();
int Connect(const std::string &url, const std::string &username, const std::string &password);
int Mkdir(const std::string &path);
int Rmdir(const std::string &path, bool recursive);
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
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);
int Copy(const std::string &from, const std::string &to);
int Move(const std::string &from, const std::string &to);
int Head(const std::string &path, void *buffer, uint64_t len);
bool FileExists(const std::string &path);
std::vector<DirEntry> ListDir(const std::string &path);
std::string GetPath(std::string path1, std::string path2);
std::string GetFullPath(std::string path1);
bool IsConnected();
bool Ping();
const char *LastResponse();
int Quit();
ClientType clientType();
uint32_t SupportedActions();
protected:
httplib::Client *client;
std::string base_path;
char response[512];
bool connected = false;
};
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+167
View File
@@ -0,0 +1,167 @@
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include "common.h"
#include "remote_client.h"
#include "http/iis.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
using httplib::Client;
using httplib::Headers;
using httplib::Result;
std::vector<DirEntry> IISClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
if (auto res = client->Get(GetFullPath(path)))
{
lxb_status_t status;
lxb_dom_attr_t *attr;
lxb_dom_node_t *node;
lxb_dom_element_t *element;
lxb_html_document_t *document;
lxb_dom_collection_t *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;
}
collection = lxb_dom_collection_make(&document->dom_document, 128);
if (collection == NULL)
{
lxb_html_document_destroy(document);
goto finish;
}
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
collection, (const lxb_char_t *)"pre", 3);
if (status != LXB_STATUS_OK)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
goto finish;
}
int coll_size = lxb_dom_collection_length(collection);
if (coll_size < 1)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
goto finish;
}
element = lxb_dom_collection_element(collection, 0);
const lxb_char_t *name;
size_t name_len;
std::string tmp;
node = element->node.first_child;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
do
{
if (node->type == LXB_DOM_NODE_TYPE_ELEMENT)
{
name = lxb_dom_element_local_name(lxb_dom_interface_element(node), &name_len);
tmp = std::string((const char *)name, name_len);
if (tmp.compare("a") == 0)
{
name = lxb_dom_node_text_content(node, &name_len);
tmp = std::string((const char *)name, name_len);
if (tmp.compare("[To Parent Directory]") != 0)
{
sprintf(entry.directory, "%s", path.c_str());
sprintf(entry.name, "%s", tmp.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);
}
out.push_back(entry);
memset(&entry, 0, sizeof(DirEntry));
}
}
}
else if (node->type == LXB_DOM_NODE_TYPE_TEXT)
{
name = lxb_dom_node_text_content(node, &name_len);
std::vector<std::string> tokens = Util::Split(std::string((const char *)name, name_len), " ");
if (tokens.size() == 4)
{
if (tokens[3].compare("<dir>") == 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;
entry.file_size = atoll(tokens[3].c_str());
DirEntry::SetDisplaySize(&entry);
}
std::vector<std::string> adate = Util::Split(tokens[0], "/");
if (adate.size() == 3)
{
entry.modified.month = atoi(adate[0].c_str());
entry.modified.day = atoi(adate[1].c_str());
entry.modified.year = atoi(adate[2].c_str());
}
std::vector<std::string> atime = Util::Split(tokens[1], ":");
if (atime.size() == 2)
{
entry.modified.hours = atoi(atime[0].c_str());
entry.modified.minutes = atoi(atime[1].c_str());
}
if (tokens[3].compare("PM") == 0)
{
if (entry.modified.hours < 12)
entry.modified.hours += 11;
}
}
}
node = node->next;
} while (node != nullptr);
lxb_dom_collection_destroy(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 IIS_H
#define IIS_H
#include <string>
#include <vector>
#include "http/httplib.h"
#include "http/baseclient.h"
#include "common.h"
#include "remote_client.h"
class IISClient : public BaseClient
{
public:
std::vector<DirEntry> ListDir(const std::string &path);
};
#endif
+172
View File
@@ -0,0 +1,172 @@
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include <map>
#include <vector>
#include "common.h"
#include "remote_client.h"
#include "http/nginx.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
using httplib::Client;
using httplib::Headers;
using httplib::Result;
static std::map<std::string, int> months = {
{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4}, {"May", 5}, {"Jun", 6},
{"Jul", 7}, {"Aug", 8}, {"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}
};
std::vector<DirEntry> NginxClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
if (auto res = client->Get(GetFullPath(path)))
{
lxb_status_t status;
lxb_dom_attr_t *attr;
lxb_dom_node_t *node;
lxb_dom_element_t *element;
lxb_html_document_t *document;
lxb_dom_collection_t *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;
}
collection = lxb_dom_collection_make(&document->dom_document, 128);
if (collection == NULL)
{
lxb_html_document_destroy(document);
goto finish;
}
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
collection, (const lxb_char_t *)"pre", 3);
if (status != LXB_STATUS_OK)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
goto finish;
}
int coll_size = lxb_dom_collection_length(collection);
if (coll_size < 1)
{
lxb_dom_collection_destroy(collection, true);
lxb_html_document_destroy(document);
goto finish;
}
element = lxb_dom_collection_element(collection, 0);
const lxb_char_t *value;
size_t value_len;
std::string tmp;
node = element->node.first_child;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
do
{
if (node->type == LXB_DOM_NODE_TYPE_ELEMENT)
{
value = lxb_dom_element_local_name(lxb_dom_interface_element(node), &value_len);
tmp = std::string((const char *)value, value_len);
if (tmp.compare("a") == 0)
{
value = lxb_dom_node_text_content(node, &value_len);
tmp = std::string((const char *)value, value_len);
tmp = Util::Rtrim(tmp, "/");
if (tmp.compare("..") != 0)
{
sprintf(entry.directory, "%s", path.c_str());
sprintf(entry.name, "%s", tmp.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);
}
}
}
}
else if (node->type == LXB_DOM_NODE_TYPE_TEXT)
{
value = lxb_dom_node_text_content(node, &value_len);
tmp = std::string((const char *)value, value_len);
std::vector<std::string> tokens = Util::Split(tmp, " ");
if (tokens.size() == 3)
{
tmp = Util::Trim(tokens[2], "\n");
tmp = Util::Trim(tmp, "\r");
if (tmp.compare("-") == 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;
entry.file_size = atoll(tmp.c_str());
DirEntry::SetDisplaySize(&entry);
}
std::vector<std::string> adate = Util::Split(tokens[0], "-");
if (adate.size() == 3)
{
entry.modified.day = atoi(adate[0].c_str());
entry.modified.month = months.find(adate[1])->second;
entry.modified.year = atoi(adate[2].c_str());
}
std::vector<std::string> atime = Util::Split(tokens[1], ":");
if (atime.size() == 2)
{
entry.modified.hours = atoi(atime[0].c_str());
entry.modified.minutes = atoi(atime[1].c_str());
}
out.push_back(entry);
memset(&entry, 0, sizeof(DirEntry));
}
}
node = node->next;
} while (node != nullptr);
lxb_dom_collection_destroy(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 NGINX_H
#define NGINX_H
#include <string>
#include <vector>
#include "http/httplib.h"
#include "http/baseclient.h"
#include "common.h"
#include "remote_client.h"
class NginxClient : public BaseClient
{
public:
std::vector<DirEntry> ListDir(const std::string &path);
};
#endif
+122
View File
@@ -0,0 +1,122 @@
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include "common.h"
#include "remote_client.h"
#include "http/npxserve.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
using httplib::Client;
using httplib::Headers;
using httplib::Result;
std::vector<DirEntry> NpxServeClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
if (auto res = client->Get(GetFullPath(path)))
{
lxb_status_t status;
lxb_dom_attr_t *attr;
lxb_dom_element_t *element;
lxb_html_document_t *document;
lxb_dom_collection_t *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;
}
collection = lxb_dom_collection_make(&document->dom_document, 128);
if (collection == NULL)
{
lxb_html_document_destroy(document);
goto finish;
}
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);
goto finish;
}
for (size_t i = 0; i < lxb_dom_collection_length(collection); i++)
{
DirEntry entry;
std::string title, aclass;
memset(&entry.modified, 0, sizeof(DateTime));
element = lxb_dom_collection_element(collection, i);
attr = lxb_dom_element_attr_by_name(element, (lxb_char_t *)"title", 5);
if (attr != nullptr)
title = std::string((char *)attr->value->data, attr->value->length);
attr = lxb_dom_element_attr_by_name(element, (lxb_char_t *)"class", 5);
if (attr != nullptr)
aclass = std::string((char *)attr->value->data, attr->value->length);
sprintf(entry.directory, "%s", path.c_str());
sprintf(entry.name, "%s", Util::Rtrim(title, "/").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);
}
sprintf(entry.display_date, "%s", "--");
size_t space_pos = aclass.find(" ");
std::string ent_type = aclass.substr(0, space_pos);
if (ent_type.compare("folder") == 0)
{
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.isDir = true;
entry.selectable = true;
}
else if (ent_type.compare("file") == 0)
{
sprintf(entry.display_size, "%s", "???B");
entry.isDir = false;
entry.selectable = true;
entry.file_size = 0;
}
else
continue;
out.push_back(entry);
}
lxb_dom_collection_destroy(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 NPXSERVE_H
#define NPXSERVE_H
#include <string>
#include <vector>
#include "http/httplib.h"
#include "http/baseclient.h"
#include "common.h"
#include "remote_client.h"
class NpxServeClient : public BaseClient
{
public:
std::vector<DirEntry> ListDir(const std::string &path);
};
#endif
+126 -23
View File
@@ -10,8 +10,8 @@
#include <orbis/AppInstUtil.h>
#include <orbis/UserService.h>
#include <curl/curl.h>
#include <request.hpp>
#include <urn.hpp>
#include <web/request.hpp>
#include <web/urn.hpp>
#include "installer.h"
#include "util.h"
#include "config.h"
@@ -19,6 +19,7 @@
#include "lang.h"
#include "rtc.h"
#include "fs.h"
#include "webdavclient.h"
#define BGFT_HEAP_SIZE (1 * 1024 * 1024)
@@ -96,20 +97,85 @@ namespace INSTALLER
s_bgft_initialized = false;
}
std::string getRemoteUrl(const std::string filename)
{
if (remoteclient->clientType() == CLIENT_TYPE_WEBDAV || remoteclient->clientType() == CLIENT_TYPE_HTTP_SERVER)
{
std::string full_url = WebDAV::GetHttpUrl(remote_settings->server + filename);
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(0, root_pos);
std::string path = full_url.substr(root_pos);
Web::Urn::Path uri(path);
CURL *curl = curl_easy_init();
path = uri.quote(curl);
curl_easy_cleanup(curl);
return host + path;
}
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 path = std::string(filename);
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 "";
}
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;
}
int InstallRemotePkg(const std::string &filename, pkg_header *header)
{
std::string full_url = remote_settings->server + filename;
size_t scheme_pos = full_url.find("://");
size_t root_pos = full_url.find("/", scheme_pos+3);
std::string host = full_url.substr(0, root_pos);
std::string path = full_url.substr(root_pos);
WebDAV::Urn::Path uri(path);
CURL *curl = curl_easy_init();
path = uri.quote(curl);
curl_easy_cleanup(curl);
char url[2000];
sprintf(url, "%s%s", host.c_str(), path.c_str());
std::string url = getRemoteUrl(filename);
if (url.empty())
return 0;
int ret;
std::string cid = std::string((char *)header->pkg_content_id);
@@ -142,7 +208,7 @@ namespace INSTALLER
}
if (flags & PKG_CONTENT_FLAGS_FIRST_PATCH ||
flags & PKG_CONTENT_FLAGS_SUBSEQUENT_PATCH ||
flags & PKG_CONTENT_FLAGS_SUBSEQUENT_PATCH ||
flags & PKG_CONTENT_FLAGS_DELTA_PATCH ||
flags & PKG_CONTENT_FLAGS_CUMULATIVE_PATCH)
{
@@ -155,7 +221,7 @@ namespace INSTALLER
params.userId = user_id;
params.entitlementType = 5;
params.id = (char *)header->pkg_content_id;
params.contentUrl = url;
params.contentUrl = url.c_str();
params.contentName = cid.c_str();
params.iconPath = "";
params.playgoScenarioId = "0";
@@ -165,15 +231,34 @@ namespace INSTALLER
params.packageSize = BE64(header->pkg_size);
}
retry:
int task_id = -1;
if (!is_patch)
ret = sceBgftServiceIntDownloadRegisterTask(&params, &task_id);
else
ret = sceBgftServiceIntDebugDownloadRegisterPkg(&params, &task_id);
if (ret)
if (ret == 0x80990088 || ret == 0x80990015)
{
goto err;
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)
{
sceKernelUsleep(100000);
}
activity_inprogess = true;
selected_action = action_to_take;
if (confirm_state == CONFIRM_YES)
{
ret = sceAppInstUtilAppUnInstall(cid.c_str());
if (ret != 0)
goto err;
goto retry;
}
}
else if (ret > 0) goto err;
ret = sceBgftServiceDownloadStartTask(task_id);
if (ret)
@@ -217,21 +302,39 @@ 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 = (char *)header->pkg_content_id;
;
download_params.params.iconPath = "";
download_params.params.playgoScenarioId = "0";
download_params.params.option = ORBIS_BGFT_TASK_OPT_FORCE_UPDATE;
download_params.slot = 0;
}
retry:
int task_id = -1;
ret = sceBgftServiceIntDownloadRegisterTaskByStorageEx(&download_params, &task_id);
if (ret)
if (ret == 0x80990088 || ret == 0x80990015)
{
if (ret == 0x80990088)
return -2;
goto err;
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)
{
sceKernelUsleep(100000);
}
activity_inprogess = true;
selected_action = action_to_take;
if (confirm_state == CONFIRM_YES)
{
ret = sceAppInstUtilAppUnInstall(titleId);
if (ret != 0)
goto err;
goto retry;
}
}
else if (ret > 0) goto err;
ret = sceBgftServiceDownloadStartTask(task_id);
if (ret)
+2
View File
@@ -110,6 +110,8 @@ namespace INSTALLER
int Init(void);
void Exit(void);
bool canInstallRemotePkg(const std::string &url);
std::string getRemoteUrl(const std::string filename);
int InstallRemotePkg(const std::string &filename, pkg_header *header);
int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install=false);
}
+119 -96
View File
@@ -10,102 +10,125 @@ 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
"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 server requires at least a username.", // 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
"Files", // STR_FILES
};
bool needs_extended_font = false;
+25 -4
View File
@@ -99,7 +99,28 @@
FUNC(STR_COMPRESS) \
FUNC(STR_ZIP_FILE_PATH) \
FUNC(STR_COMPRESSING) \
FUNC(STR_ERROR_CREATE_ZIP)
FUNC(STR_ERROR_CREATE_ZIP) \
FUNC(STR_UNSUPPORTED_FILE_FORMAT) \
FUNC(STR_CUT) \
FUNC(STR_COPY) \
FUNC(STR_PASTE) \
FUNC(STR_MOVING) \
FUNC(STR_COPYING) \
FUNC(STR_FAIL_MOVE_MSG) \
FUNC(STR_FAIL_COPY_MSG) \
FUNC(STR_CANT_MOVE_TO_SUBDIR_MSG) \
FUNC(STR_CANT_COPY_TO_SUBDIR_MSG) \
FUNC(STR_UNSUPPORTED_OPERATION_MSG) \
FUNC(STR_HTTP_PORT) \
FUNC(STR_REINSTALL_CONFIRM_MSG) \
FUNC(STR_REMOTE_NOT_SUPPORT_MSG) \
FUNC(STR_CANNOT_CONNECT_REMOTE_MSG) \
FUNC(STR_DOWNLOAD_INSTALL_MSG) \
FUNC(STR_CHECKING_REMOTE_SERVER_MSG) \
FUNC(STR_ENABLE_RPI) \
FUNC(STR_ENABLE_RPI_FTP_SMB_MSG) \
FUNC(STR_ENABLE_RPI_WEBDAV_MSG) \
FUNC(STR_FILES)
#define GET_VALUE(x) x,
#define GET_STRING(x) #x,
@@ -109,9 +130,9 @@ enum
FOREACH_STR(GET_VALUE)
};
#define LANG_STRINGS_NUM 96
#define LANG_ID_SIZE LANG_STRINGS_NUM
#define LANG_STR_SIZE 256
#define LANG_STRINGS_NUM 117
#define LANG_ID_SIZE 64
#define LANG_STR_SIZE 384
extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE];
extern char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE];
extern bool needs_extended_font;
+48 -39
View File
@@ -97,6 +97,30 @@ void InitImgui()
0,
};
static const ImWchar icons[] {
0xF07B, 0xF07B, // folder
0xF65E, 0xF65E, // new folder
0xF15B, 0xF15B, // file
0xF021, 0xF021, // refresh
0xF0CA, 0xF0CA, // select all
0xF0C9, 0xF0C9, // unselect all
0x2700, 0x2700, // cut
0xF0C5, 0xF0C5, // copy
0xF0EA, 0xF0EA, // paste
0xF31C, 0xF31C, // edit
0xE0AC, 0xE0AC, // rename
0xE5A1, 0xE5A1, // delete
0xF002, 0xF002, // search
0x2699, 0x2699, // settings
0xF0ED, 0xF0ED, // download
0xF0EE, 0xF0EE, // upload
0xF56E, 0xF56E, // extract
0xF56F, 0xF56F, // compress
0xF0F6, 0xF0F6, // properties
0xF112, 0xF112, // cancel
0,
};
std::string lang = std::string(language);
int32_t lang_idx;
sceSystemServiceParamGetInt( ORBIS_SYSTEM_SERVICE_PARAM_ID_LANG, &lang_idx );
@@ -108,11 +132,17 @@ void InitImgui()
}
else if (lang.compare("Simplified Chinese") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_CHINESE_S))
{
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
ImFontConfig config;
config.OversampleH = 1;
config.OversampleV = 1;
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, &config, io.Fonts->GetGlyphRangesChineseFull());
}
else if (lang.compare("Traditional Chinese") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_CHINESE_T))
{
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());
ImFontConfig config;
config.OversampleH = 1;
config.OversampleV = 1;
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, &config, io.Fonts->GetGlyphRangesChineseFull());
}
else if (lang.compare("Japanese") == 0 || lang.compare("Ryukyuan") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_JAPANESE))
{
@@ -138,6 +168,13 @@ void InitImgui()
{
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto.ttf", 26.0f, NULL, ranges);
}
ImFontConfig config;
config.MergeMode = true;
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/fa-solid-900.ttf", 20.0f, &config, icons);
io.Fonts->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;
io.Fonts->Build();
Lang::SetTranslation(lang_idx);
auto &style = ImGui::GetStyle();
@@ -232,44 +269,16 @@ int main()
}
// load common modules
int ret = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_SYSTEM_SERVICE);
if (ret < 0)
{
return 0;
}
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_IME_DIALOG) < 0) return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_SYSTEM_SERVICE) < 0) return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_USER_SERVICE) < 0) return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_BGFT) < 0) return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_APP_INST_UTIL) < 0) return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_PAD) < 0) return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_AUDIOOUT) < 0 || sceAudioOutInit() != 0) return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_NET) < 0 || sceNetInit() != 0) return 0;
ret = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_USER_SERVICE);
if (ret < 0)
{
return 0;
}
ret = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_BGFT);
if (ret) {
return 0;
}
ret = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_APP_INST_UTIL);
if (ret) {
return 0;
}
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_PAD) < 0)
return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_AUDIOOUT) < 0 ||
sceAudioOutInit() != 0)
{
return 0;
}
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_IME_DIALOG) < 0)
return 0;
if(sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_NET) < 0 || sceNetInit() != 0)
return 0;
sceNetPoolCreate("simple", NET_HEAP_SIZE, 0);
sceNetPoolCreate("simple", NET_HEAP_SIZE, 0);
if (INSTALLER::Init() < 0)
return 0;
+24 -1
View File
@@ -5,9 +5,28 @@
#include <vector>
#include "common.h"
enum RemoteActions
{
REMOTE_ACTION_NONE = 0,
REMOTE_ACTION_CUT = 1,
REMOTE_ACTION_COPY = 2,
REMOTE_ACTION_PASTE = 4,
REMOTE_ACTION_DELETE = 8,
REMOTE_ACTION_RENAME = 16,
REMOTE_ACTION_NEW_FOLDER = 32,
REMOTE_ACTION_DOWNLOAD = 64,
REMOTE_ACTION_UPLOAD = 128,
REMOTE_ACTION_INSTALL = 256,
REMOTE_ACTION_ALL = 511
};
enum ClientType
{
CLIENT_TYPE_FTP, CLIENT_TYPE_SMB, CLIENT_TYPE_WEBDAV
CLIENT_TYPE_FTP,
CLIENT_TYPE_SMB,
CLIENT_TYPE_WEBDAV,
CLIENT_TYPE_HTTP_SERVER,
CLINET_TYPE_UNKNOWN
};
class RemoteClient
@@ -23,6 +42,9 @@ public:
virtual int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0) = 0;
virtual int Rename(const std::string &src, const std::string &dst) = 0;
virtual int Delete(const std::string &path) = 0;
virtual int Copy(const std::string &from, const std::string &to) = 0;
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 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;
@@ -31,6 +53,7 @@ public:
virtual const char *LastResponse() = 0;
virtual int Quit() = 0;
virtual ClientType clientType() = 0;
virtual uint32_t SupportedActions() = 0;
};
#endif
+23 -19
View File
@@ -228,7 +228,19 @@ int SmbClient::Get(const std::string &outputfile, const std::string &ppath, uint
return 1;
}
int SmbClient::Copy(const std::string &ppath, int socket_fd)
int SmbClient::Copy(const std::string &ffrom, const std::string &tto)
{
sprintf(response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int SmbClient::Move(const std::string &ffrom, const std::string &tto)
{
sprintf(response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int SmbClient::CopyToSocket(const std::string &ppath, int socket_fd)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
@@ -398,6 +410,7 @@ std::vector<DirEntry> SmbClient::ListDir(const std::string &path)
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
struct smb2dir *dir;
@@ -416,6 +429,7 @@ std::vector<DirEntry> SmbClient::ListDir(const std::string &path)
DirEntry entry;
memset(&entry, 0, sizeof(entry));
entry.selectable = true;
snprintf(entry.directory, 511, "%s", path.c_str());
snprintf(entry.name, 255, "%s", ent->name);
entry.file_size = ent->st.smb2_size;
@@ -445,22 +459,7 @@ std::vector<DirEntry> SmbClient::ListDir(const std::string &path)
sprintf(entry.display_size, "%s", lang_strings[STR_LINK]);
break;
case SMB2_TYPE_FILE:
if (entry.file_size < 1024)
{
sprintf(entry.display_size, "%ldB", entry.file_size);
}
else if (entry.file_size < 1024 * 1024)
{
sprintf(entry.display_size, "%.2fKB", entry.file_size * 1.0f / 1024);
}
else if (entry.file_size < 1024 * 1024 * 1024)
{
sprintf(entry.display_size, "%.2fMB", entry.file_size * 1.0f / (1024 * 1024));
}
else
{
sprintf(entry.display_size, "%.2fGB", entry.file_size * 1.0f / (1024 * 1024 * 1024));
}
DirEntry::SetDisplaySize(&entry);
break;
case SMB2_TYPE_DIRECTORY:
entry.isDir = true;
@@ -486,7 +485,7 @@ std::string SmbClient::GetPath(std::string ppath1, std::string ppath2)
return Util::Ltrim(path1, "/");
}
int SmbClient::Head(const std::string &ppath, void* buffer, uint16_t len)
int SmbClient::Head(const std::string &ppath, void *buffer, uint64_t len)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
@@ -512,4 +511,9 @@ int SmbClient::Head(const std::string &ppath, void* buffer, uint16_t len)
ClientType SmbClient::clientType()
{
return CLIENT_TYPE_SMB;
}
}
uint32_t SmbClient::SupportedActions()
{
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE;
}
+5 -2
View File
@@ -27,15 +27,18 @@ public:
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
bool FileExists(const std::string &path);
int Copy(const std::string &path, int socket_fd);
int Copy(const std::string &from, const std::string &to);
int Move(const std::string &from, const std::string &to);
int CopyToSocket(const std::string &path, int socket_fd);
std::vector<DirEntry> ListDir(const std::string &path);
bool IsConnected();
bool Ping();
const char *LastResponse();
int Quit();
std::string GetPath(std::string ppath1, std::string ppath2);
int Head(const std::string &path, void* buffer, uint16_t len);
int Head(const std::string &path, void *buffer, uint64_t len);
ClientType clientType();
uint32_t SupportedActions();
private:
int _Rmdir(const std::string &path);
+19
View File
@@ -46,6 +46,25 @@ namespace Util
return s;
}
static inline std::vector<std::string> Split(const std::string &str, const std::string &delimiter)
{
std::string text = std::string(str);
std::vector<std::string> tokens;
size_t pos = 0;
while ((pos = text.find(delimiter)) != std::string::npos)
{
if (text.substr(0, pos).length() > 0)
tokens.push_back(text.substr(0, pos));
text.erase(0, pos + delimiter.length());
}
if (text.length() > 0)
{
tokens.push_back(text);
}
return tokens;
}
static inline void Notify(const char *fmt, ...)
{
OrbisNotificationRequest request;
@@ -26,7 +26,7 @@
#include "callback.hpp"
namespace WebDAV
namespace Web
{
namespace Callback
{
@@ -106,4 +106,4 @@ namespace WebDAV
}
} // namespace Append
} // namespace Callback
} // namespace WebDAV
} // namespace Web
@@ -20,10 +20,10 @@
#
############################################################################*/
#ifndef WEBDAV_CALLBACK_HPP
#define WEBDAV_CALLBACK_HPP
#ifndef WEB_CALLBACK_HPP
#define WEB_CALLBACK_HPP
namespace WebDAV
namespace Web
{
struct Data
{
@@ -62,6 +62,6 @@ namespace WebDAV
size_t buffer(char* data, size_t size, size_t count, void* buffer);
}
}
} // namespace WebDAV
} // namespace Web
#endif
@@ -23,7 +23,7 @@
#include "fsinfo.hpp"
#include <fstream>
namespace WebDAV
namespace Web
{
namespace FileInfo
{
@@ -39,4 +39,4 @@ namespace WebDAV
return static_cast<unsigned long long>(file.tellg());
}
} // namespace FileInfo
} // namespace WebDAV
} // namespace Web
@@ -20,19 +20,19 @@
#
############################################################################*/
#ifndef WEBDAV_FSINFO_HPP
#define WEBDAV_FSINFO_HPP
#ifndef WEB_FSINFO_HPP
#define WEB_FSINFO_HPP
#include <fstream>
#include <string>
namespace WebDAV
namespace Web
{
namespace FileInfo
{
auto exists(const std::string& path) -> bool;
auto size(const std::string& path_file) -> unsigned long long;
} // namespace FileInfo
} // namespace WebDAV
} // namespace Web
#endif
@@ -24,7 +24,7 @@
#include <curl/curl.h>
namespace WebDAV
namespace Web
{
Header::Header(const std::initializer_list<std::string>& init_list) noexcept : handle(nullptr)
{
@@ -66,4 +66,4 @@ namespace WebDAV
{
this->handle = curl_slist_append(reinterpret_cast<curl_slist*>(this->handle), item.c_str());
}
} // namespace WebDAV
} // namespace Web
@@ -20,13 +20,13 @@
#
############################################################################*/
#ifndef WEBDAV_HEADER_HPP
#define WEBDAV_HEADER_HPP
#ifndef WEB_HEADER_HPP
#define WEB_HEADER_HPP
#include <initializer_list>
#include <string>
namespace WebDAV
namespace Web
{
class Header final
{
@@ -46,6 +46,6 @@ namespace WebDAV
private:
auto swap(Header& other) noexcept -> void;
};
} // namespace WebDAV
} // namespace Web
#endif
@@ -20,8 +20,8 @@
#
############################################################################*/
#ifndef WEBDAV_PUGIEXT_HPP
#define WEBDAV_PUGIEXT_HPP
#ifndef WEB_PUGIEXT_HPP
#define WEB_PUGIEXT_HPP
#include <pugixml.hpp>
@@ -24,7 +24,7 @@
#include "fsinfo.hpp"
#include "util.h"
namespace WebDAV
namespace Web
{
static int sockopt_callback(void *clientp, curl_socket_t curlfd, curlsocktype purpose)
{
@@ -56,9 +56,10 @@ namespace WebDAV
Request::Request(dict_t &&options_) : options(options_)
{
auto webdav_hostname = get(options, "webdav_hostname");
auto webdav_username = get(options, "webdav_username");
auto webdav_password = get(options, "webdav_password");
auto hostname = get(options, "hostname");
auto username = get(options, "username");
auto password = get(options, "password");
auto timeout = get(options, "password");
auto proxy_hostname = get(options, "proxy_hostname");
auto proxy_username = get(options, "proxy_username");
@@ -85,17 +86,25 @@ namespace WebDAV
this->set(CURLOPT_SSLKEY, const_cast<char *>(key_path.c_str()));
}
this->set(CURLOPT_URL, const_cast<char *>(webdav_hostname.c_str()));
if (!webdav_username.empty())
this->set(CURLOPT_URL, const_cast<char *>(hostname.c_str()));
if (!username.empty())
{
this->set(CURLOPT_HTTPAUTH, static_cast<int>(CURLAUTH_BASIC));
auto token = webdav_username + ":" + webdav_password;
auto token = username + ":" + password;
this->set(CURLOPT_USERPWD, const_cast<char *>(token.c_str()));
}
this->set(CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
this->set(CURLOPT_FOLLOWLOCATION, 1);
this->set(CURLOPT_COOKIEJAR, "/data/ps4-webdav-client/cookies.txt");
this->set(CURLOPT_COOKIEFILE, "/data/ps4-webdav-client/cookies.txt");
if (timeout.empty())
{
this->set(CURLOPT_CONNECTTIMEOUT, 15L);
}
else
{
this->set(CURLOPT_CONNECTTIMEOUT, atoi(timeout.c_str()));
}
if (!this->proxy_enabled())
return;
@@ -112,7 +121,7 @@ namespace WebDAV
}
else
{
if (!webdav_username.empty() && !webdav_password.empty())
if (!username.empty() && !password.empty())
{
auto token = proxy_username + ":" + proxy_password;
this->set(CURLOPT_PROXYUSERPWD, const_cast<char *>(token.c_str()));
@@ -151,7 +160,8 @@ namespace WebDAV
{
if (this->handle == nullptr)
return false;
auto is_performed = check_code(curl_easy_perform(this->handle));
this->res = curl_easy_perform(this->handle);
auto is_performed = this->res == CURLE_OK;
if (!is_performed)
return false;
this->http_code = 0;
@@ -195,4 +205,23 @@ namespace WebDAV
return this->http_code;
}
} // namespace WebDAV
int Request::result() const noexcept
{
return this->res;
}
class Environment
{
public:
Environment()
{
curl_global_init(CURL_GLOBAL_ALL);
}
~Environment()
{
curl_global_cleanup();
}
};
} // namespace Web
static const Web::Environment env;
@@ -20,14 +20,14 @@
#
############################################################################*/
#ifndef WEBDAV_REQUEST_HPP
#define WEBDAV_REQUEST_HPP
#ifndef WEB_REQUEST_HPP
#define WEB_REQUEST_HPP
#include <curl/curl.h>
#include <map>
#include <string>
namespace WebDAV
namespace Web
{
bool inline check_code(CURLcode code)
{
@@ -57,16 +57,18 @@ namespace WebDAV
bool perform() noexcept;
long status_code() const noexcept;
int result() const noexcept;
void *handle;
private:
const dict_t options;
dict_t response_header = {};
long http_code;
int res;
bool proxy_enabled() const noexcept;
bool cert_required() const noexcept;
auto swap(Request &other) noexcept -> void;
};
} // namespace WebDAV
} // namespace Web
#endif
+15 -3
View File
@@ -33,7 +33,7 @@ using std::vector;
#include "urn.hpp"
namespace WebDAV
namespace Web
{
namespace Urn
{
@@ -43,6 +43,18 @@ namespace WebDAV
const string Path::param_separate = "&";
const string Path::query_separate = "?";
string encodeUrl(const string &url, void *request)
{
size_t scheme_pos = url.find("://");
size_t root_pos = url.find("/", scheme_pos+3);
if (root_pos == string::npos)
return url;
string uri = url.substr(root_pos);
auto path = Path(uri);
return url.substr(0, root_pos) + path.quote(request);
}
Path::Path(const string& path_, bool force_dir)
{
string path = path_;
@@ -242,9 +254,9 @@ namespace WebDAV
return lhs_path == rhs_path;
}
} // namespace Urn
} // namespace WebDAV
} // namespace Web
auto operator<<(std::ostream& stream, const WebDAV::Urn::Path& path) -> std::ostream&
auto operator<<(std::ostream& stream, const Web::Urn::Path& path) -> std::ostream&
{
return stream << path.path();
}
+6 -4
View File
@@ -20,20 +20,22 @@
#
############################################################################*/
#ifndef WEBDAV_URN_HPP
#define WEBDAV_URN_HPP
#ifndef WEB_URN_HPP
#define WEB_URN_HPP
#include <cstddef>
#include <iostream>
#include <string>
namespace WebDAV
namespace Web
{
namespace Urn
{
using std::string;
using std::nullptr_t;
string encodeUrl(const string &url, void *request);
class Path
{
public:
@@ -63,6 +65,6 @@ namespace WebDAV
}
}
auto operator<<(std::ostream& stream, const WebDAV::Urn::Path& path) -> std::ostream&;
auto operator<<(std::ostream& stream, const Web::Urn::Path& path) -> std::ostream&;
#endif
+50 -46
View File
@@ -20,21 +20,24 @@
#
############################################################################*/
#include <client.hpp>
#include <webdav/client.hpp>
#include "callback.hpp"
#include "fsinfo.hpp"
#include "header.hpp"
#include "pugiext.hpp"
#include "request.hpp"
#include "urn.hpp"
#include "web/callback.hpp"
#include "web/fsinfo.hpp"
#include "web/header.hpp"
#include "web/pugiext.hpp"
#include "web/request.hpp"
#include "web/urn.hpp"
#include "util.h"
#include <algorithm>
#include <thread>
namespace WebDAV
{
using Urn::Path;
using Web::Urn::Path;
using Web::Request;
using Web::Data;
using Web::Header;
using progress_funptr = int (*)(void *context, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
@@ -62,10 +65,9 @@ namespace WebDAV
Client::options()
{
return dict_t{
{"webdav_hostname", this->webdav_hostname},
{"webdav_root", this->webdav_root},
{"webdav_username", this->webdav_username},
{"webdav_password", this->webdav_password},
{"hostname", this->webdav_hostname},
{"username", this->webdav_username},
{"password", this->webdav_password},
{"proxy_hostname", this->proxy_hostname},
{"proxy_username", this->proxy_username},
{"proxy_password", this->proxy_password},
@@ -104,7 +106,7 @@ namespace WebDAV
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&file_stream));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Write::stream));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Write::stream));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
@@ -117,6 +119,7 @@ namespace WebDAV
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (callback != nullptr)
callback(is_performed);
@@ -148,7 +151,7 @@ namespace WebDAV
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
@@ -161,6 +164,7 @@ namespace WebDAV
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (callback != nullptr)
callback(is_performed);
@@ -205,7 +209,7 @@ bool
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_HTTPHEADER, list);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
@@ -218,6 +222,7 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (callback != nullptr)
callback(is_performed);
if (!is_performed)
@@ -252,7 +257,7 @@ bool
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&stream));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Write::stream));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Write::stream));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
@@ -265,6 +270,7 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (callback != nullptr)
callback(is_performed);
@@ -279,7 +285,7 @@ bool
progress_data_t progress_data,
progress_t progress)
{
bool is_existed = FileInfo::exists(local_file);
bool is_existed = Web::FileInfo::exists(local_file);
if (!is_existed)
return false;
@@ -287,7 +293,7 @@ bool
auto file_urn = root_urn + remote_file;
std::ifstream file_stream(local_file, std::ios::binary);
auto size = FileInfo::size(local_file);
auto size = Web::FileInfo::size(local_file);
Request request(this->options());
@@ -298,11 +304,11 @@ bool
request.set(CURLOPT_UPLOAD, 1L);
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_READDATA, reinterpret_cast<size_t>(&file_stream));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Callback::Read::stream));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Web::Callback::Read::stream));
request.set(CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(size));
request.set(CURLOPT_BUFFERSIZE, static_cast<long>(Client::buffer_size));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&response));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
@@ -315,6 +321,7 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (callback != nullptr)
callback(is_performed);
return is_performed;
@@ -343,11 +350,11 @@ bool
request.set(CURLOPT_UPLOAD, 1L);
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_READDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Callback::Read::buffer));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Web::Callback::Read::buffer));
request.set(CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(buffer_size));
request.set(CURLOPT_BUFFERSIZE, static_cast<long>(Client::buffer_size));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&response));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
@@ -360,6 +367,7 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (callback != nullptr)
callback(is_performed);
@@ -390,11 +398,11 @@ bool
request.set(CURLOPT_UPLOAD, 1L);
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_READDATA, reinterpret_cast<size_t>(&stream));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Callback::Read::stream));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Web::Callback::Read::stream));
request.set(CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(stream_size));
request.set(CURLOPT_BUFFERSIZE, static_cast<long>(Client::buffer_size));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&response));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
@@ -407,6 +415,7 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (callback != nullptr)
callback(is_performed);
@@ -464,13 +473,14 @@ bool
request.set(CURLOPT_POSTFIELDSIZE, static_cast<long>(size));
request.set(CURLOPT_HEADER, 0);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
auto is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (!is_performed)
return 0;
@@ -509,13 +519,14 @@ bool
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
return is_performed;
}
@@ -540,12 +551,13 @@ bool
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (!is_performed)
return dict_t{};
@@ -621,6 +633,7 @@ bool
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
return is_performed;
}
@@ -660,13 +673,14 @@ bool
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
request.set(CURLOPT_HEADER, 0);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Web::Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
if (!is_performed)
return dict_items_t{};
@@ -814,6 +828,7 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
return is_performed;
}
@@ -829,12 +844,12 @@ bool
auto source_resource_urn = root_urn + remote_source_resource;
auto destination_resource_urn = root_urn + remote_destination_resource;
Request request(this->options());
Header header =
{
"Accept: */*",
"Destination: " + destination_resource_urn.path()};
"Destination: " + destination_resource_urn.quote(request.handle)};
Request request(this->options());
auto url = this->webdav_hostname + source_resource_urn.quote(request.handle);
@@ -847,6 +862,7 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
return is_performed;
}
@@ -862,12 +878,11 @@ bool
auto source_resource_urn = root_urn + remote_source_resource;
auto destination_resource_urn = root_urn + remote_destination_resource;
Request request(this->options());
Header header =
{
"Accept: */*",
"Destination: " + destination_resource_urn.path()};
Request request(this->options());
"Destination: " + destination_resource_urn.quote(request.handle)};
auto url = this->webdav_hostname + source_resource_urn.quote(request.handle);
@@ -880,6 +895,7 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
return is_performed;
}
@@ -955,21 +971,9 @@ bool
bool is_performed = request.perform();
this->http_code = request.status_code();
this->result = request.result();
return is_performed;
}
class Environment
{
public:
Environment()
{
curl_global_init(CURL_GLOBAL_ALL);
}
~Environment()
{
curl_global_cleanup();
}
};
} // namespace WebDAV
static const WebDAV::Environment env;
+1
View File
@@ -380,6 +380,7 @@ namespace WebDAV
dict_t options();
long http_code;
int result;
int check_enabled = 0;
};
} // namespace WebDAV
+24 -18
View File
@@ -43,7 +43,7 @@ namespace WebDAV
int WebDavClient::Connect(const std::string &host, const std::string &user, const std::string &pass, bool check_enabled)
{
std::string url = std::string(host);
std::string url = GetHttpUrl(host);
std::size_t scheme_pos = url.find_first_of("://");
std::string root_folder = "/";
if (scheme_pos != std::string::npos)
@@ -228,6 +228,20 @@ namespace WebDAV
return ret;
}
int WebDavClient::Copy(const std::string &from, const std::string &to)
{
bool ret = client->copy(from, to);
sprintf(response, "Http Code %ld", client->status_code());
return ret;
}
int WebDavClient::Move(const std::string &from, const std::string &to)
{
bool ret = client->move(from, to);
sprintf(response, "Http Code %ld", client->status_code());
return ret;
}
int WebDavClient::Size(const std::string &ppath, int64_t *size)
{
WebDAV::dict_t file_info = client->info(ppath);
@@ -256,6 +270,7 @@ namespace WebDAV
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
out.push_back(entry);
WebDAV::dict_items_t files = client->list(path);
@@ -263,6 +278,7 @@ namespace WebDAV
{
DirEntry entry;
memset(&entry, 0, sizeof(entry));
entry.selectable = true;
sprintf(entry.directory, "%s", path.c_str());
sprintf(entry.name, "%s", WebDAV::get(files[i], "name").c_str());
@@ -281,22 +297,7 @@ namespace WebDAV
if (!entry.isDir)
{
entry.file_size = std::stoll(WebDAV::get(files[i], "size"));
if (entry.file_size < 1024)
{
sprintf(entry.display_size, "%luB", entry.file_size);
}
else if (entry.file_size < 1024 * 1024)
{
sprintf(entry.display_size, "%.2fKB", entry.file_size * 1.0f / 1024);
}
else if (entry.file_size < 1024 * 1024 * 1024)
{
sprintf(entry.display_size, "%.2fMB", entry.file_size * 1.0f / (1024 * 1024));
}
else
{
sprintf(entry.display_size, "%.2fGB", entry.file_size * 1.0f / (1024 * 1024 * 1024));
}
DirEntry::SetDisplaySize(&entry);
}
else
{
@@ -345,7 +346,7 @@ namespace WebDAV
return path1;
}
int WebDavClient::Head(const std::string &path, void *buffer, int64_t len)
int WebDavClient::Head(const std::string &path, void *buffer, uint64_t len)
{
char *buffer_ptr = nullptr;
unsigned long long buffer_size = 0;
@@ -374,4 +375,9 @@ namespace WebDAV
{
return CLIENT_TYPE_WEBDAV;
}
uint32_t WebDavClient::SupportedActions()
{
return REMOTE_ACTION_ALL;
}
}
+12 -1
View File
@@ -4,12 +4,20 @@
#include <time.h>
#include <string>
#include <vector>
#include <regex>
#include "webdav/client.hpp"
#include "common.h"
#include "remote_client.h"
namespace WebDAV
{
inline std::string GetHttpUrl(std::string url)
{
std::string http_url = std::regex_replace(url, std::regex("webdav://"), "http://");
http_url = std::regex_replace(http_url, std::regex("webdavs://"), "https://");
return http_url;
}
class WebDavClient : public RemoteClient
{
public:
@@ -23,6 +31,8 @@ namespace WebDAV
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);
int Copy(const std::string &from, const std::string &to);
int Move(const std::string &from, const std::string &to);
bool FileExists(const std::string &path);
std::vector<DirEntry> ListDir(const std::string &path);
bool IsConnected();
@@ -30,10 +40,11 @@ namespace WebDAV
const char *LastResponse();
int Quit();
std::string GetPath(std::string path1, std::string path2);
int Head(const std::string &path, void *buffer, int64_t len);
int Head(const std::string &path, void *buffer, uint64_t len);
bool GetHeaders(const std::string &path, dict_t *headers);
WebDAV::Client *GetClient();
ClientType clientType();
uint32_t SupportedActions();
private:
int _Rmdir(const std::string &path);
+329 -96
View File
@@ -12,6 +12,7 @@
#include "util.h"
#include "lang.h"
#include "ime_dialog.h"
#include "IconsFontAwesome6.h"
extern "C"
{
@@ -39,9 +40,12 @@ std::vector<DirEntry> local_files;
std::vector<DirEntry> remote_files;
std::set<DirEntry> multi_selected_local_files;
std::set<DirEntry> multi_selected_remote_files;
std::vector<DirEntry> local_paste_files;
std::vector<DirEntry> remote_paste_files;
DirEntry selected_local_file;
DirEntry selected_remote_file;
ACTIONS selected_action;
ACTIONS paste_action;
char status_message[1024];
char local_file_to_select[256];
char remote_file_to_select[256];
@@ -60,6 +64,7 @@ bool select_url_inprogress = false;
int favorite_url_idx = 0;
char extract_zip_folder[256];
char zip_file_path[384];
char label[256];
bool dont_prompt_overwrite = false;
bool dont_prompt_overwrite_cb = false;
@@ -86,10 +91,13 @@ namespace Windows
sprintf(status_message, "");
sprintf(local_filter, "");
sprintf(remote_filter, "");
sprintf(txt_http_port, "%d", remote_settings->http_port);
dont_prompt_overwrite = false;
confirm_transfer_state = -1;
dont_prompt_overwrite_cb = false;
overwrite_type = OVERWRITE_PROMPT;
local_paste_files.clear();
remote_paste_files.clear();
Actions::RefreshLocalFiles(false);
}
@@ -162,27 +170,34 @@ namespace Windows
{
std::string zipfolder;
std::string zipname;
if (strncmp(multi_selected_local_files.begin()->directory, "/data", 5) != 0)
std::vector<DirEntry> files;
if (multi_selected_local_files.size() > 0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(files));
else
files.push_back(selected_local_file);
if (strncmp(files.begin()->directory, "/data", 5) != 0 &&
strncmp(files.begin()->directory, "/mnt/usb", 8) != 0)
{
zipfolder = "/data";
}
else
{
zipfolder = multi_selected_local_files.begin()->directory;
zipfolder = files.begin()->directory;
}
if (multi_selected_local_files.size() == 1)
if (files.size() == 1)
{
zipname = multi_selected_local_files.begin()->name;
zipname = files.begin()->name;
}
else if (strcmp(multi_selected_local_files.begin()->directory, "/") == 0)
else if (strcmp(files.begin()->directory, "/") == 0)
{
zipname = "new_zip";
}
else
{
zipname = std::string(multi_selected_local_files.begin()->directory);
zipname = zipname.substr(zipname.find_last_of("/")+1);
zipname = std::string(files.begin()->directory);
zipname = zipname.substr(zipname.find_last_of("/") + 1);
}
std::string zip_path;
@@ -198,6 +213,34 @@ namespace Windows
}
}
std::string getExtractFolder()
{
std::string zipfolder;
std::vector<DirEntry> files;
if (multi_selected_local_files.size() > 0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(files));
else
files.push_back(selected_local_file);
if (strncmp(files.begin()->directory, "/data", 5) != 0 &&
strncmp(files.begin()->directory, "/mnt/usb", 8) != 0)
{
zipfolder = "/data";
}
else if (files.size() > 1)
{
zipfolder = files.begin()->directory;
}
else
{
std::string filename = std::string(files.begin()->name);
size_t dot_pos = filename.find_last_of(".");
zipfolder = std::string(local_directory) + "/" + filename.substr(0, dot_pos);
}
return zipfolder;
}
void ConnectionPanel()
{
ImGuiStyle *style = &ImGui::GetStyle();
@@ -207,7 +250,7 @@ namespace Windows
BeginGroupPanel(title, ImVec2(1905, 100));
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10);
char id[256];
std::string hidden_password = std::string("xxxxxxx");
std::string hidden_password = (strlen(remote_settings->password) > 0) ? std::string("*******") : "";
ImVec2 pos;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 4);
@@ -217,51 +260,25 @@ namespace Windows
{
ImGui::SetItemDefaultFocus();
}
if (is_connected)
sprintf(id, "%s###connectbutton", is_connected ? lang_strings[STR_DISCONNECT] : lang_strings[STR_CONNECT]);
if (ImGui::Button(id, ImVec2(200, 0)))
{
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.3f);
}
if (ImGui::Button(lang_strings[STR_CONNECT], ImVec2(180, 0)))
{
selected_action = ACTION_CONNECT;
}
if (is_connected)
{
ImGui::PopItemFlag();
ImGui::PopStyleVar();
selected_action = is_connected ? ACTION_DISCONNECT : ACTION_CONNECT;
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("%s", lang_strings[STR_CONNECT]);
ImGui::EndTooltip();
}
ImGui::SameLine();
if (!is_connected)
{
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.3f);
}
if (ImGui::Button(lang_strings[STR_DISCONNECT], ImVec2(200, 0)))
{
selected_action = ACTION_DISCONNECT;
}
if (!is_connected)
{
ImGui::PopItemFlag();
ImGui::PopStyleVar();
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("%s", lang_strings[STR_DISCONNECT]);
ImGui::Text("%s", is_connected ? lang_strings[STR_DISCONNECT] : lang_strings[STR_CONNECT]);
ImGui::EndTooltip();
}
ImGui::SameLine();
ImGui::SetNextItemWidth(120);
if (is_connected)
{
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.3f);
}
if (ImGui::BeginCombo("##Site", display_site, ImGuiComboFlags_PopupAlignLeft | ImGuiComboFlags_HeightLargest | ImGuiComboFlags_NoArrowButton))
{
static char site_id[64];
@@ -274,6 +291,7 @@ namespace Windows
sprintf(last_site, "%s", sites[n].c_str());
sprintf(display_site, "%s", site_id);
remote_settings = &site_settings[sites[n]];
sprintf(txt_http_port, "%d", remote_settings->http_port);
}
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
@@ -282,22 +300,52 @@ namespace Windows
}
ImGui::EndCombo();
}
if (is_connected)
{
ImGui::PopItemFlag();
ImGui::PopStyleVar();
}
ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 1.0f));
sprintf(id, "%s##server", remote_settings->server);
int width = 550;
if (remote_settings->type == CLIENT_TYPE_HTTP_SERVER)
width = 500;
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(650, 0)))
if (ImGui::Button(id, ImVec2(width, 0)))
{
ime_single_field = remote_settings->server;
ResetImeCallbacks();
ime_field_size = 255;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_SERVER], remote_settings->server, 255, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
ime_after_update = AferServerChangeCallback;
Dialog::initImeDialog(lang_strings[STR_SERVER], remote_settings->server, 255, ORBIS_TYPE_TYPE_URL, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
}
ImGui::SameLine();
if (remote_settings->type == CLIENT_TYPE_HTTP_SERVER)
{
ImGui::SetNextItemWidth(140);
if (ImGui::BeginCombo("##HttpServer", remote_settings->http_server_type, ImGuiComboFlags_PopupAlignLeft | ImGuiComboFlags_HeightLargest | ImGuiComboFlags_NoArrowButton))
{
for (int n = 0; n < http_servers.size(); n++)
{
const bool is_selected = strcmp(http_servers[n].c_str(), remote_settings->http_server_type) == 0;
if (ImGui::Selectable(http_servers[n].c_str(), is_selected))
{
sprintf(remote_settings->http_server_type, "%s", http_servers[n].c_str());
}
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
ImGui::SameLine();
}
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_USERNAME]);
ImGui::SameLine();
@@ -331,6 +379,46 @@ namespace Windows
gui_mode = GUI_MODE_IME;
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_RPI]);
ImGui::SameLine();
if (ImGui::Checkbox("###enable_rpi", &remote_settings->enable_rpi))
{
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();
}
if ((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();
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;
}
}
ImGui::PopStyleVar();
ImGui::Dummy(ImVec2(0, 10));
EndGroupPanel();
@@ -593,6 +681,10 @@ namespace Windows
selected_action = ACTION_CHANGE_REMOTE_DIRECTORY;
}
}
if (ImGui::IsItemFocused())
{
selected_remote_file = item;
}
if (ImGui::IsItemHovered())
{
if (ImGui::CalcTextSize(item.name).x > 740)
@@ -603,10 +695,6 @@ namespace Windows
}
}
ImGui::PopID();
if (ImGui::IsItemFocused())
{
selected_remote_file = item;
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows))
{
if (strcmp(remote_file_to_select, item.name) == 0)
@@ -641,7 +729,8 @@ namespace Windows
ImVec2 pos = ImGui::GetCursorPos();
ImGui::Dummy(ImVec2(1880, 30));
ImGui::SetCursorPos(pos);
ImGui::PushTextWrapPos(1880);
ImGui::SetCursorPosX(pos.x + 10);
ImGui::PushTextWrapPos(1870);
if (strncmp(status_message, "4", 1) == 0 || strncmp(status_message, "3", 1) == 0)
{
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "%s", status_message);
@@ -655,6 +744,21 @@ namespace Windows
EndGroupPanel();
}
int getSelectableFlag(uint32_t remote_action)
{
int flag = ImGuiSelectableFlags_Disabled;
bool local_browser_selected = saved_selected_browser & LOCAL_BROWSER;
bool remote_browser_selected = saved_selected_browser & REMOTE_BROWSER;
if ((local_browser_selected && selected_local_file.selectable) ||
(remote_browser_selected && selected_remote_file.selectable &&
remoteclient != nullptr && (remoteclient->SupportedActions() & remote_action)))
{
flag = ImGuiSelectableFlags_None;
}
return flag;
}
void ShowActionsDialog()
{
ImGuiIO &io = ImGui::GetIO();
@@ -679,13 +783,13 @@ namespace Windows
bool remote_browser_selected = saved_selected_browser & REMOTE_BROWSER;
if (local_browser_selected)
{
ImGui::SetNextWindowPos(ImVec2(410, 350));
ImGui::SetNextWindowPos(ImVec2(410, 300));
}
else if (remote_browser_selected)
{
ImGui::SetNextWindowPos(ImVec2(1330, 350));
ImGui::SetNextWindowPos(ImVec2(1330, 300));
}
ImGui::SetNextWindowSizeConstraints(ImVec2(230, 150), ImVec2(230, 450), NULL, NULL);
ImGui::SetNextWindowSizeConstraints(ImVec2(230, 150), ImVec2(230, 550), NULL, NULL);
if (ImGui::BeginPopupModal(lang_strings[STR_ACTIONS], NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::PushID("Select All##settings");
@@ -714,12 +818,64 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Cut##settings");
if (ImGui::Selectable(lang_strings[STR_CUT], false, getSelectableFlag(REMOTE_ACTION_CUT) | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
selected_action = local_browser_selected ? ACTION_LOCAL_CUT : ACTION_REMOTE_CUT;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Copy##settings");
if (ImGui::Selectable(lang_strings[STR_COPY], false, getSelectableFlag(REMOTE_ACTION_COPY) | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
selected_action = local_browser_selected ? ACTION_LOCAL_COPY : ACTION_REMOTE_COPY;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Paste##settings");
flags = ImGuiSelectableFlags_Disabled;
if ((local_browser_selected && multi_selected_local_files.size() > 0) ||
(remote_browser_selected && multi_selected_remote_files.size() > 0 && remoteclient != nullptr))
if ((local_browser_selected && local_paste_files.size() > 0) ||
(remote_browser_selected && remote_paste_files.size() > 0 &&
remoteclient != nullptr && (remoteclient->SupportedActions() | REMOTE_ACTION_PASTE)))
flags = ImGuiSelectableFlags_None;
if (ImGui::Selectable(lang_strings[STR_PASTE], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
SetModalMode(false);
selected_action = local_browser_selected ? ACTION_LOCAL_PASTE : ACTION_REMOTE_PASTE;
file_transfering = true;
confirm_transfer_state = 0;
dont_prompt_overwrite_cb = dont_prompt_overwrite;
ImGui::CloseCurrentPopup();
}
if (ImGui::IsItemHovered())
{
int height = local_browser_selected ? (local_paste_files.size() * 30) + 42 : (remote_paste_files.size() * 30) + 42;
ImGui::SetNextWindowSize(ImVec2(500, height));
ImGui::BeginTooltip();
int text_width = ImGui::CalcTextSize(lang_strings[STR_FILES]).x;
int file_pos = ImGui::GetCursorPosX() + text_width + 15;
ImGui::Text("%s: %s", lang_strings[STR_TYPE], (paste_action == ACTION_LOCAL_CUT | paste_action == ACTION_REMOTE_CUT) ? lang_strings[STR_CUT] : lang_strings[STR_COPY]);
ImGui::Text("%s:", lang_strings[STR_FILES]);
ImGui::SameLine();
std::vector<DirEntry> files = (local_browser_selected) ? local_paste_files : remote_paste_files;
for (std::vector<DirEntry>::iterator it = files.begin(); it != files.end(); ++it)
{
ImGui::SetCursorPosX(file_pos);
ImGui::Text("%s", it->path);
}
ImGui::EndTooltip();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Delete##settings");
if (ImGui::Selectable(lang_strings[STR_DELETE], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
if (ImGui::Selectable(lang_strings[STR_DELETE], false, getSelectableFlag(REMOTE_ACTION_DELETE) | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
confirm_state = CONFIRM_WAIT;
sprintf(confirm_message, "%s", lang_strings[STR_DEL_CONFIRM_MSG]);
@@ -731,11 +887,11 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
flags = ImGuiSelectableFlags_Disabled;
if ((local_browser_selected && multi_selected_local_files.size() == 1) ||
(remote_browser_selected && multi_selected_remote_files.size() == 1 && remoteclient != nullptr))
flags = ImGuiSelectableFlags_None;
ImGui::PushID("Rename##settings");
flags = getSelectableFlag(REMOTE_ACTION_RENAME);
if ((local_browser_selected && multi_selected_local_files.size() > 1) ||
(remote_browser_selected && multi_selected_remote_files.size() > 1))
flags = ImGuiSelectableFlags_Disabled;
if (ImGui::Selectable(lang_strings[STR_RENAME], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
if (local_browser_selected)
@@ -748,10 +904,12 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
flags = ImGuiSelectableFlags_Disabled;
if (local_browser_selected || (remote_browser_selected && remoteclient != nullptr))
flags = ImGuiSelectableFlags_None;
ImGui::PushID("New Folder##settings");
flags = ImGuiSelectableFlags_None;
if (remote_browser_selected && remoteclient != nullptr && !(remoteclient->SupportedActions() & REMOTE_ACTION_NEW_FOLDER))
{
flags = ImGuiSelectableFlags_Disabled;
}
if (ImGui::Selectable(lang_strings[STR_NEW_FOLDER], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
if (local_browser_selected)
@@ -764,15 +922,13 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
flags = ImGuiSelectableFlags_Disabled;
if (local_browser_selected)
{
(multi_selected_local_files.size() > 0) ? flags = ImGuiSelectableFlags_None : flags = ImGuiSelectableFlags_Disabled;
ImGui::PushID("Extract##settings");
if (ImGui::Selectable(lang_strings[STR_EXTRACT], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
if (ImGui::Selectable(lang_strings[STR_EXTRACT], false, getSelectableFlag(REMOTE_ACTION_NONE) | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
ResetImeCallbacks();
sprintf(extract_zip_folder, "%s", local_directory);
sprintf(extract_zip_folder, "%s", getExtractFolder().c_str());
ime_single_field = extract_zip_folder;
ime_field_size = 255;
ime_callback = SingleValueImeCallback;
@@ -787,7 +943,7 @@ namespace Windows
ImGui::Separator();
ImGui::PushID("Compress##settings");
if (ImGui::Selectable(lang_strings[STR_COMPRESS], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
if (ImGui::Selectable(lang_strings[STR_COMPRESS], false, getSelectableFlag(REMOTE_ACTION_NONE) | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
std::string zipname;
std::string zipfolder;
@@ -807,10 +963,10 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
flags = ImGuiSelectableFlags_Disabled;
if (multi_selected_local_files.size() > 0 && remoteclient != nullptr)
flags = getSelectableFlag(REMOTE_ACTION_UPLOAD);
if (remote_browser_selected && remoteclient != nullptr && !(remoteclient->SupportedActions() & REMOTE_ACTION_UPLOAD))
{
flags = ImGuiSelectableFlags_None;
flags = ImGuiSelectableFlags_Disabled;
}
ImGui::PushID("Upload##settings");
if (ImGui::Selectable(lang_strings[STR_UPLOAD], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
@@ -825,9 +981,8 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
(multi_selected_local_files.size() > 0) ? flags = ImGuiSelectableFlags_None : flags = ImGuiSelectableFlags_Disabled;
ImGui::PushID("Install##local");
if (ImGui::Selectable(lang_strings[STR_INSTALL], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
if (ImGui::Selectable(lang_strings[STR_INSTALL], false, getSelectableFlag(REMOTE_ACTION_INSTALL) | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
SetModalMode(false);
selected_action = ACTION_INSTALL_LOCAL_PKG;
@@ -839,12 +994,8 @@ namespace Windows
if (remote_browser_selected)
{
if (multi_selected_remote_files.size() > 0 && remoteclient != nullptr)
{
flags = ImGuiSelectableFlags_None;
}
ImGui::PushID("Download##settings");
if (ImGui::Selectable(lang_strings[STR_DOWNLOAD], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
if (ImGui::Selectable(lang_strings[STR_DOWNLOAD], false, getSelectableFlag(REMOTE_ACTION_DOWNLOAD) | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
SetModalMode(false);
selected_action = ACTION_DOWNLOAD;
@@ -857,11 +1008,7 @@ namespace Windows
ImGui::Separator();
ImGui::PushID("Install##remote");
if (remoteclient != nullptr && remoteclient->clientType() != CLIENT_TYPE_WEBDAV)
{
flags = ImGuiSelectableFlags_Disabled;
}
if (ImGui::Selectable(lang_strings[STR_INSTALL], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
if (ImGui::Selectable(lang_strings[STR_INSTALL], false, getSelectableFlag(REMOTE_ACTION_INSTALL) | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
SetModalMode(false);
selected_action = ACTION_INSTALL_REMOTE_PKG;
@@ -880,11 +1027,8 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
flags = ImGuiSelectableFlags_Disabled;
if (local_browser_selected || remote_browser_selected)
flags = ImGuiSelectableFlags_None;
ImGui::PushID("Properties##settings");
if (ImGui::Selectable(lang_strings[STR_PROPERTIES], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
if (ImGui::Selectable(lang_strings[STR_PROPERTIES], false, ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
if (local_browser_selected)
selected_action = ACTION_SHOW_LOCAL_PROPERTIES;
@@ -894,7 +1038,6 @@ namespace Windows
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Cancel##settings");
@@ -1108,12 +1251,12 @@ namespace Windows
if (ImGui::Button(lang_strings[STR_ONETIME_URL], ImVec2(535, 0)))
{
ResetImeCallbacks();
sprintf(install_pkg_url, "%s", "");
ime_single_field = install_pkg_url;
sprintf(install_pkg_url.url, "%s", "");
ime_single_field = install_pkg_url.url;
ime_field_size = 511;
ime_after_update = AfterPackageUrlCallback;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog("URL", install_pkg_url, 511, ORBIS_TYPE_BASIC_LATIN, 600, 340);
Dialog::initImeDialog("URL", install_pkg_url.url, 511, ORBIS_TYPE_BASIC_LATIN, 600, 340);
gui_mode = GUI_MODE_IME;
select_url_inprogress = false;
SetModalMode(false);
@@ -1146,7 +1289,9 @@ namespace Windows
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 1.0f));
if (ImGui::Button(favorite_urls[j], ImVec2(875, 0)))
{
sprintf(install_pkg_url, "%s", favorite_urls[j]);
sprintf(install_pkg_url.url, "%s", favorite_urls[j]);
memset(install_pkg_url.username, 0, sizeof(install_pkg_url.username));
memset(install_pkg_url.password, 0, sizeof(install_pkg_url.password));
selected_action = ACTION_INSTALL_URL_PKG;
SetModalMode(false);
select_url_inprogress = false;
@@ -1300,7 +1445,10 @@ namespace Windows
case ACTION_RENAME_LOCAL:
if (gui_mode != GUI_MODE_IME)
{
sprintf(editor_text, "%s", multi_selected_local_files.begin()->name);
if (multi_selected_local_files.size() > 0)
sprintf(editor_text, "%s", multi_selected_local_files.begin()->name);
else
sprintf(editor_text, "%s", selected_local_file.name);
ime_single_field = editor_text;
ResetImeCallbacks();
ime_field_size = 128;
@@ -1314,7 +1462,10 @@ namespace Windows
case ACTION_RENAME_REMOTE:
if (gui_mode != GUI_MODE_IME)
{
sprintf(editor_text, "%s", multi_selected_remote_files.begin()->name);
if (multi_selected_remote_files.size() > 0)
sprintf(editor_text, "%s", multi_selected_remote_files.begin()->name);
else
sprintf(editor_text, "%s", selected_remote_file.name);
ime_single_field = editor_text;
ResetImeCallbacks();
ime_field_size = 128;
@@ -1383,6 +1534,66 @@ namespace Windows
Actions::InstallUrlPkg();
selected_action = ACTION_NONE;
break;
case ACTION_LOCAL_CUT:
case ACTION_LOCAL_COPY:
paste_action = selected_action;
local_paste_files.clear();
if (multi_selected_local_files.size() > 0)
std::copy(multi_selected_local_files.begin(), multi_selected_local_files.end(), std::back_inserter(local_paste_files));
else
local_paste_files.push_back(selected_local_file);
multi_selected_local_files.clear();
selected_action = ACTION_NONE;
break;
case ACTION_REMOTE_CUT:
case ACTION_REMOTE_COPY:
paste_action = selected_action;
remote_paste_files.clear();
if (multi_selected_remote_files.size() > 0)
std::copy(multi_selected_remote_files.begin(), multi_selected_remote_files.end(), std::back_inserter(remote_paste_files));
else
remote_paste_files.push_back(selected_remote_file);
multi_selected_remote_files.clear();
selected_action = ACTION_NONE;
break;
case ACTION_LOCAL_PASTE:
sprintf(status_message, "%s", "");
sprintf(activity_message, "%s", "");
if (dont_prompt_overwrite || (!dont_prompt_overwrite && confirm_transfer_state == 1))
{
activity_inprogess = true;
stop_activity = false;
confirm_transfer_state = -1;
if (paste_action == ACTION_LOCAL_CUT)
Actions::MoveLocalFiles();
else if (paste_action == ACTION_LOCAL_COPY)
Actions::CopyLocalFiles();
else
{
activity_inprogess = false;
}
selected_action = ACTION_NONE;
}
break;
case ACTION_REMOTE_PASTE:
sprintf(status_message, "%s", "");
sprintf(activity_message, "%s", "");
if (dont_prompt_overwrite || (!dont_prompt_overwrite && confirm_transfer_state == 1))
{
activity_inprogess = true;
stop_activity = false;
confirm_transfer_state = -1;
if (paste_action == ACTION_REMOTE_CUT)
Actions::MoveRemoteFiles();
else if (paste_action == ACTION_REMOTE_COPY)
Actions::CopyRemoteFiles();
else
{
activity_inprogess = false;
}
selected_action = ACTION_NONE;
}
break;
default:
break;
}
@@ -1498,11 +1709,17 @@ namespace Windows
}
else if (selected_action == ACTION_RENAME_LOCAL)
{
Actions::RenameLocalFolder(multi_selected_local_files.begin()->path, editor_text);
if (multi_selected_local_files.size() > 0)
Actions::RenameLocalFolder(multi_selected_local_files.begin()->path, editor_text);
else
Actions::RenameLocalFolder(selected_local_file.path, editor_text);
}
else if (selected_action == ACTION_RENAME_REMOTE)
{
Actions::RenameRemoteFolder(multi_selected_remote_files.begin()->path, editor_text);
if (multi_selected_remote_files.size() > 0)
Actions::RenameRemoteFolder(multi_selected_remote_files.begin()->path, editor_text);
else
Actions::RenameRemoteFolder(selected_remote_file.path, editor_text);
}
selected_action = ACTION_NONE;
}
@@ -1521,4 +1738,20 @@ namespace Windows
{
selected_action = ACTION_CREATE_LOCAL_ZIP;
}
void AferServerChangeCallback(int ime_result)
{
if (ime_result == IME_DIALOG_RESULT_FINISHED)
{
CONFIG::SetClientType(remote_settings);
}
}
void AfterHttpPortChangeCallback(int ime_result)
{
if (ime_result == IME_DIALOG_RESULT_FINISHED)
{
remote_settings->http_port = atoi(txt_http_port);
}
}
}
+5
View File
@@ -20,6 +20,9 @@ extern std::vector<DirEntry> local_files;
extern std::vector<DirEntry> remote_files;
extern std::set<DirEntry> multi_selected_local_files;
extern std::set<DirEntry> multi_selected_remote_files;
extern std::vector<DirEntry> local_paste_files;
extern std::vector<DirEntry> remote_paste_files;
extern ACTIONS paste_action;
extern DirEntry selected_local_file;
extern DirEntry selected_remote_file;
extern ACTIONS selected_action;
@@ -203,6 +206,8 @@ namespace Windows
void AfterFavoriteUrlCallback(int ime_result);
void AfterExtractFolderCallback(int ime_result);
void AfterZipFileCallback(int ime_result);
void AferServerChangeCallback(int ime_result);
void AfterHttpPortChangeCallback(int ime_result);
}
#endif
+99 -3
View File
@@ -7,16 +7,26 @@
#include <sys/stat.h>
#include <minizip/unzip.h>
#include <minizip/zip.h>
#include <un7zip.h>
#include <unrar.h>
#include "common.h"
#include "fs.h"
#include "lang.h"
#include "rtc.h"
#include "windows.h"
#include "zip_util.h"
#define TRANSFER_SIZE (128 * 1024)
namespace ZipUtil
{
static char filename_extracted[256];
void callback_7zip(const char *fileName, unsigned long fileSize, unsigned fileNum, unsigned numFiles)
{
sprintf(activity_message, "%s %s: %s", lang_strings[STR_EXTRACTING], filename_extracted, fileName);
}
void convertToZipTime(time_t time, tm_zip *tmzip)
{
OrbisDateTime gmt;
@@ -135,7 +145,7 @@ namespace ZipUtil
// Open new file in zip
std::string folder = path.substr(filename_start);
if (folder[folder.length()-1] != '/')
if (folder[folder.length() - 1] != '/')
folder = folder + "/";
res = zipOpenNewFileInZip3_64(zf, folder.c_str(), &zi,
@@ -170,7 +180,7 @@ namespace ZipUtil
if (dirent != NULL && strcmp(dirent->d_name, ".") != 0 && strcmp(dirent->d_name, "..") != 0)
{
int new_path_length = path.length() + strlen(dirent->d_name) + 2;
char *new_path = (char*)malloc(new_path_length);
char *new_path = (char *)malloc(new_path_length);
snprintf(new_path, new_path_length, "%s%s%s", path.c_str(), FS::hasEndSlash(path.c_str()) ? "" : "/", dirent->d_name);
int ret = 0;
@@ -200,14 +210,35 @@ namespace ZipUtil
}
else
{
sprintf(activity_message, "%s %s", lang_strings[STR_COMPRESSING], path.c_str());
return ZipAddFile(zf, path, filename_start, level);
}
return 1;
}
int Extract(const DirEntry &file, const std::string &dir)
CompressFileType getCompressFileType(const std::string &file)
{
char buf[8];
memset(buf, 0, 8);
int ret = FS::Head(file, buf, 8);
if (ret == 0)
return COMPRESS_FILE_TYPE_UNKNOWN;
if (strncmp(buf, (const char *)MAGIC_7Z_1, 6) == 0)
return COMPRESS_FILE_TYPE_7Z;
else if (strncmp(buf, (const char *)MAGIC_RAR_1, 7) == 0 || strncmp(buf, (const char *)MAGIC_RAR_2, 8) == 0)
return COMPRESS_FILE_TYPE_RAR;
else if (strncmp(buf, (const char *)MAGIC_ZIP_1, 4) == 0 || strncmp(buf, (const char *)MAGIC_ZIP_2, 4) == 0 || strncmp(buf, (const char *)MAGIC_ZIP_3, 4) == 0)
return COMPRESS_FILE_TYPE_ZIP;
return COMPRESS_FILE_TYPE_UNKNOWN;
}
int ExtractZip(const DirEntry &file, const std::string &dir)
{
file_transfering = true;
unz_global_info global_info;
unz_file_info file_info;
unzFile zipfile = unzOpen(file.path);
@@ -259,6 +290,10 @@ namespace ZipUtil
fclose(f);
unzCloseCurrentFile(zipfile);
}
else
{
FS::MkDirs(ext_fname, true);
}
if ((zip_idx + 1) < num_files)
{
unzGoToNextFile(zipfile);
@@ -267,4 +302,65 @@ namespace ZipUtil
unzClose(zipfile);
return 1;
}
int Extract7Zip(const DirEntry &file, const std::string &dir)
{
file_transfering = false;
FS::MkDirs(dir, true);
sprintf(filename_extracted, "%s", file.name);
int res = Extract7zFileEx(file.path, dir.c_str(), callback_7zip, DEFAULT_IN_BUF_SIZE);
return res == 0;
}
int ExtractRar(const DirEntry &file, const std::string &dir)
{
file_transfering = false;
HANDLE hArcData; // Archive Handle
struct RAROpenArchiveDataEx rarOpenArchiveData;
struct RARHeaderDataEx rarHeaderData;
char destPath[256];
memset(&rarOpenArchiveData, 0, sizeof(rarOpenArchiveData));
memset(&rarHeaderData, 0, sizeof(rarHeaderData));
sprintf(destPath, "%s", dir.c_str());
rarOpenArchiveData.ArcName = (char *)file.path;
rarOpenArchiveData.CmtBuf = NULL;
rarOpenArchiveData.CmtBufSize = 0;
rarOpenArchiveData.OpenMode = RAR_OM_EXTRACT;
hArcData = RAROpenArchiveEx(&rarOpenArchiveData);
if (rarOpenArchiveData.OpenResult != ERAR_SUCCESS)
{
return 0;
}
while (RARReadHeaderEx(hArcData, &rarHeaderData) == ERAR_SUCCESS)
{
sprintf(activity_message, "%s %s: %s", lang_strings[STR_EXTRACTING], file.name, rarHeaderData.FileName);
if (RARProcessFile(hArcData, RAR_EXTRACT, destPath, NULL) != ERAR_SUCCESS)
{
RARCloseArchive(hArcData);
return 0;
}
}
RARCloseArchive(hArcData);
return 1;
}
int Extract(const DirEntry &file, const std::string &dir)
{
CompressFileType fileType = getCompressFileType(file.path);
if (fileType == COMPRESS_FILE_TYPE_ZIP)
return ExtractZip(file, dir);
else if (fileType == COMPRESS_FILE_TYPE_7Z)
return Extract7Zip(file, dir);
else if (fileType == COMPRESS_FILE_TYPE_RAR)
return ExtractRar(file, dir);
else
sprintf(status_message, "%s - %s", file.name, lang_strings[STR_UNSUPPORTED_FILE_FORMAT]);
return 1;
}
}
+16
View File
@@ -8,6 +8,22 @@
#include "common.h"
#include "fs.h"
static uint8_t MAGIC_ZIP_1[4] = {0x50, 0x4B, 0x03, 0x04};
static uint8_t MAGIC_ZIP_2[4] = {0x50, 0x4B, 0x05, 0x06};
static uint8_t MAGIC_ZIP_3[4] = {0x50, 0x4B, 0x07, 0x08};
static uint8_t MAGIC_7Z_1[6] = {0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C};
static uint8_t MAGIC_RAR_1[7] = {0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00};
static uint8_t MAGIC_RAR_2[8] = {0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00};
enum CompressFileType {
COMPRESS_FILE_TYPE_7Z,
COMPRESS_FILE_TYPE_ZIP,
COMPRESS_FILE_TYPE_RAR,
COMPRESS_FILE_TYPE_UNKNOWN
};
namespace ZipUtil
{
int ZipAddPath(zipFile zf, const std::string &path, int filename_start, int level);