Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 456b1aa075 | |||
| e654667621 | |||
| a4ac55ca88 | |||
| f0c291eb0c | |||
| d96734aeeb | |||
| 4aa6b7c02a | |||
| c632f0d7cb | |||
| 686caec0f7 | |||
| 4c5429902a | |||
| 7378736b3f | |||
| 05c7207b7c | |||
| cd26aeaa77 | |||
| 5aef0f648d | |||
| 2ee0e9ae74 | |||
| c6143be6f0 | |||
| 23c8c678f1 | |||
| f314c94ddc | |||
| e3c908bfbf | |||
| d772b3d3f5 | |||
| 837258afda | |||
| 98c71d3411 | |||
| b156fea640 | |||
| 7508ec12da | |||
| ad43c48454 | |||
| 32ba34fefb | |||
| ba3c2d5600 | |||
| a18971a62f | |||
| 5e6710c815 | |||
| 89c8fd652a | |||
| 951f1f8f45 | |||
| b0ca95338f | |||
| e519343164 | |||
| 1cfeece53f | |||
| fc60358a1e | |||
| 2f7017ad10 | |||
| e8f77d94de | |||
| 3a08ceee37 | |||
| acb770ca50 | |||
| 85a5657821 | |||
| d248e9e3ea | |||
| d3fd550e90 | |||
| 8f59465bb9 | |||
| 6b8289ab8e | |||
| 75e1283db7 | |||
| 9ce8c2ef11 | |||
| 4786c54bd5 | |||
| afdc3cd468 | |||
| 957e3a0dc0 | |||
| 8f77e62867 | |||
| ec94c22d99 | |||
| 0be5c6707c | |||
| 43d3ef1c78 | |||
| 43a9b6063f | |||
| 7e0b2d6661 | |||
| 3f5ecdd9a3 | |||
| 40ac1b95ff | |||
| 2cf692df0c | |||
| 88859b17f4 | |||
| fe91eaabe3 | |||
| 52235d7d1c | |||
| 4a883a6af2 | |||
| 833aede808 | |||
| ae64596cff | |||
| c315d58d19 | |||
| 36c4b7dcbb | |||
| 0aef91ada2 | |||
| e4449cfc0f | |||
| 2784994260 | |||
| 44851833a3 | |||
| 864015ba17 | |||
| cb10992d49 | |||
| 83070356d4 | |||
| 2be520d9cf | |||
| a9d97f35b4 | |||
| 24943cca88 | |||
| 951e3e686e | |||
| d5a850dd10 | |||
| 11f7f2eb25 | |||
| c404a08387 | |||
| e2b75307f0 | |||
| 58c8b24751 | |||
| b240de455b | |||
| 7043453cb4 | |||
| 6292f21bfa | |||
| 259fc496ab | |||
| 7b24c8e53a | |||
| c3bb044d87 |
+31
-17
@@ -5,24 +5,43 @@ 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
|
||||
source/imgui
|
||||
)
|
||||
|
||||
add_executable(ezremote_client
|
||||
source/imgui/imgui_draw.cpp
|
||||
source/imgui/imgui_impl_sdl.cpp
|
||||
source/imgui/imgui_impl_sdlrenderer.cpp
|
||||
source/imgui/imgui_tables.cpp
|
||||
source/imgui/imgui_widgets.cpp
|
||||
source/imgui/imgui.cpp
|
||||
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/clients/baseclient.cpp
|
||||
source/clients/apache.cpp
|
||||
source/clients/ftpclient.cpp
|
||||
source/clients/gdrive.cpp
|
||||
source/clients/iis.cpp
|
||||
source/clients/nginx.cpp
|
||||
source/clients/npxserve.cpp
|
||||
source/clients/smbclient.cpp
|
||||
source/clients/webdavclient.cpp
|
||||
source/server/http_server.cpp
|
||||
source/actions.cpp
|
||||
source/config.cpp
|
||||
source/crypt.c
|
||||
source/fs.cpp
|
||||
source/ftpclient.cpp
|
||||
source/gui.cpp
|
||||
source/getentropy.c
|
||||
source/ime_dialog.cpp
|
||||
@@ -31,22 +50,14 @@ add_executable(ezremote_client
|
||||
source/lang.cpp
|
||||
source/main.cpp
|
||||
source/orbis_jbc.c
|
||||
source/rtc.cpp
|
||||
source/smbclient.cpp
|
||||
source/system.cpp
|
||||
source/windows.cpp
|
||||
source/webdavclient.cpp
|
||||
source/zip_util.cpp
|
||||
source/imgui_draw.cpp
|
||||
source/imgui_impl_sdl.cpp
|
||||
source/imgui_impl_sdlrenderer.cpp
|
||||
source/imgui_tables.cpp
|
||||
source/imgui_widgets.cpp
|
||||
source/imgui.cpp
|
||||
)
|
||||
|
||||
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.02" 32 0)
|
||||
|
||||
target_link_libraries(ezremote_client
|
||||
c
|
||||
@@ -63,6 +74,9 @@ target_link_libraries(ezremote_client
|
||||
lexbor
|
||||
smb2
|
||||
minizip
|
||||
un7zip
|
||||
unrar
|
||||
json-c
|
||||
kernel
|
||||
SceShellCoreUtil
|
||||
SceSysmodule
|
||||
|
||||
@@ -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, HTTP servers and Google Drive to transfer files. The interface is inspired by Filezilla client which provides a commander like GUI.
|
||||

|
||||
## 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,19 +17,32 @@ 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
|
||||
- port is optional and defaults to 80(http) and 443(https) if not provided
|
||||
- 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
|
||||
```
|
||||
- For Google Drive use the following URL for the server **https://drive.google.com**
|
||||
<br />[Go to the following wiki for instructions on how to setup the app to connect to Google Drive]( https://github.com/cy33hc/ps4-ezremote-client/wiki/Setup-App-for-use-with-Google-Drive)
|
||||
|
||||
Tested with following WebDAV server:
|
||||
- **(Recommeded)** [Dufs](https://github.com/sigoden/dufs) - For hosting your own WebDAV server. (Recommended since this allow anonymous access which is required for Remote Package Install)
|
||||
- [SFTPgo](https://github.com/drakkan/sftpgo) - For local hosted WebDAV server. Can also be used as a webdav frontend for Cloud Storage like AWS S3, Azure Blob or Google Storage.
|
||||
@@ -43,10 +56,18 @@ 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 html directory listings to download or install pkg.
|
||||
- Install Remote Packages from connected WebDAV server
|
||||
- Ability to connect to your "Google Drive" to transfer files back and fort. Can also install packages from it. The app will download the file to the PS4's harddrive and then install it. You need to keep the app opened. Here is a link to the wiki for what you need to do to make it work. Also able to access files that are shared to you.
|
||||
- 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/file for files on PS4 local drive or usb or WebDAV Server.
|
||||
- Simple Text Editor to make simply changes to config text files.
|
||||
|
||||
|
||||
## Installation
|
||||
Copy the **ezremote_client.pkg** in to a FAT32 format usb drive then install from package installer
|
||||
@@ -126,8 +147,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 +162,19 @@ 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
|
||||
|
||||
I have included the source code from the following 2 projects embedded into this repo.
|
||||
<br/>https://github.com/yhirose/cpp-httplib
|
||||
<br/>https://github.com/CloudPolis/webdav-client-cpp
|
||||
|
||||
Finally build the app
|
||||
```
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDqDCCApCgAwIBAgIUSlUxeW2iMsLD8Lk3+ffGUfxej6QwDQYJKoZIhvcNAQEL
|
||||
BQAwYzELMAkGA1UEBhMCWloxDDAKBgNVBAgMA1N1bjENMAsGA1UEBwwETW9vbjEQ
|
||||
MA4GA1UECgwHTWVyY3VyeTERMA8GA1UECwwISG9tZWJyZXcxEjAQBgNVBAMMCWxv
|
||||
Y2FsaG9zdDAgFw0yMzAyMjUwNzAyMTNaGA8yMDUzMDIxNzA3MDIxM1owYzELMAkG
|
||||
A1UEBhMCWloxDDAKBgNVBAgMA1N1bjENMAsGA1UEBwwETW9vbjEQMA4GA1UECgwH
|
||||
TWVyY3VyeTERMA8GA1UECwwISG9tZWJyZXcxEjAQBgNVBAMMCWxvY2FsaG9zdDCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOWQx+pfhpDqd2wPkV5BL6Yf
|
||||
8UVTCsP13+1YlxZiD93VHhcK23T/YYqSxx6tDHAR4sA/oKELT+dFuhMhC/QE5Sw6
|
||||
HD/FwCwdNJ7Ke3z+iUActtInDU5URC0XwdW7wTAt1MLx4T9j7CkoVHsaiDlf6LTG
|
||||
165bIXD8JKzud26WXHmTCCBCgIU3zcq13jpFeb4Po4rJtuDLwb3gloZzEzdS9S6O
|
||||
mjVNUSlZeb+ksep3TbJHIACy6WrPJZ+u2aScDOBOt9Gv/UeOYHcvGIFHXddG+kHl
|
||||
/ay6b7JxNbBNWL57/PswmXcpB16gkBNWCfL1PDmDFEkvd6uJTnPUnMge7CBNzX8C
|
||||
AwEAAaNSMFAwHwYDVR0jBBgwFoAUeCZ0CXLAs8C5xVsPGIhzu4haXpEwCQYDVR0T
|
||||
BAIwADAiBgNVHREEGzAZgglsb2NhbGhvc3SCCTEyNy4wLjAuMYIBKjANBgkqhkiG
|
||||
9w0BAQsFAAOCAQEAsgC/89C7+OAspaOgU5Tr9WFcZ1Nph21WTltBM0z9f4NyeR1Y
|
||||
b/YoJrvocRWw9gpgCcj7AArSHNsha2+QMBEko3PIpkdMoSHylf2WqYNTCIb8cvJA
|
||||
pHDYJJR99Cajo0meP5h1mtQdjOVv70Q3jtS6iSdD/KI5VwIRcfDutjHys78Bb2NQ
|
||||
1KEZuHKwmhE3209OQ5ZbjDQ0gViJFPnfPfnbWuOllpIN27ZwGvlhhM9x7xRvwsWt
|
||||
puh5wV2TBAYagOT+canBOxugv7L1eOpnNVE49YS0vr5y8JhLuKFoZ0hTi7PeqO4c
|
||||
mE4zIVwKjIQ6w+N2Vj/ghNjkyJm0azpmnbPtFg==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICqDCCAZACAQAwYzELMAkGA1UEBhMCWloxDDAKBgNVBAgMA1N1bjENMAsGA1UE
|
||||
BwwETW9vbjEQMA4GA1UECgwHTWVyY3VyeTERMA8GA1UECwwISG9tZWJyZXcxEjAQ
|
||||
BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AOWQx+pfhpDqd2wPkV5BL6Yf8UVTCsP13+1YlxZiD93VHhcK23T/YYqSxx6tDHAR
|
||||
4sA/oKELT+dFuhMhC/QE5Sw6HD/FwCwdNJ7Ke3z+iUActtInDU5URC0XwdW7wTAt
|
||||
1MLx4T9j7CkoVHsaiDlf6LTG165bIXD8JKzud26WXHmTCCBCgIU3zcq13jpFeb4P
|
||||
o4rJtuDLwb3gloZzEzdS9S6OmjVNUSlZeb+ksep3TbJHIACy6WrPJZ+u2aScDOBO
|
||||
t9Gv/UeOYHcvGIFHXddG+kHl/ay6b7JxNbBNWL57/PswmXcpB16gkBNWCfL1PDmD
|
||||
FEkvd6uJTnPUnMge7CBNzX8CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQB2gc2Z
|
||||
7bzytAja4uDQQjQOxZMzwwgfODyQTWhvyEVJxq7iK8Saogn/dpjgeVhNaIgMAGRs
|
||||
RNQ26cBQxvs9ZfNmNcNvc1eFw9NJicRpHOUjNf0mMHtqiFIpGc9Fnu34p1DLGKJ4
|
||||
qp5Kd9cl4Vx96xaPWqCyH+sXFxnIt8lK6K0yKHaDXLKzFmuJvEEc2Z/g0/RRfgq7
|
||||
cO9+otlsD3sF6TziNL/KFFYPqgn4Wkx8K8z9ovpMnyvYH1KnQsuhCNr9nUhmA8Wu
|
||||
o9DMKQbqDYq9NLUmTJMgX75Vi71idbkgOZN7kvmUnEW+Ltf1FLl9AnF5kpkvMTvR
|
||||
KIcPUOLLdpzwZ8jc
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
@@ -0,0 +1,7 @@
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
subjectAltName = @alt_names
|
||||
[alt_names]
|
||||
DNS.1 = localhost
|
||||
DNS.2 = 127.0.0.1
|
||||
DNS.3 = *
|
||||
@@ -0,0 +1,30 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIDkuJpr20dpYCAggA
|
||||
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECAKW47FhDo5vBIIEyNJd7CLIboON
|
||||
iXmQ5Vzj7nHna+HXfPdrNGUnAtRKQ7oZmAvPJQMqrEO88am5zl/puOThwdJ/b+tp
|
||||
Ftt76zi8JffShf0fwNeL3zOfiVEUSmGeOfRzx4MV1flivbk70UjHx4ga9Nqdab6t
|
||||
0dvV8copWkmj+B/sP2zk3+S9Urv6VPz97hq6PTqrmjWm+VwssDJyv9s7KGM/+9bC
|
||||
/9DQR5AAQbd4e7sxW45cL9desyRfs0XNcYj6Go9sVHzFhKaSx75u6Shd5Rb2N5sX
|
||||
2Dmm349cy3XimqNBCsrPIp76uLfCIhSp/pgC6phMeIu52SrFwM2OOwCuPkGZyVQv
|
||||
I6n0vagltBHXYj5a371P9imV8LWTCy326yb6Ro1Mjy6XEMWVIBk/XI/U12APHytf
|
||||
c1VvCk1pGemD3ArVYpuECdjtwZxxCOneOxeIYgSV/h3GHMHKmQiK36zQOslNNdfy
|
||||
l7AO6kokITWoW/VPk2FG0tclWJe1aA8WOiqI3ZYRwBlovk9jUrjNqEA3BG/rzAWU
|
||||
VbApXd4FvbsgLETHRZl1KWvwZFhO9vZ02+CznrnzzMWCb13UipCA7RuePuhdbViT
|
||||
jOy1JJG408NcwRu0PNwr77oIZu7OrdEPu0u7YJ+SR/q3pxS6u86l6O3lvbUhtOyC
|
||||
1grybOa+lJXrAL07yrbriCoy8igNIMKiA8blwpwCC/22CtGrY5UJqzpLIZuTLcnB
|
||||
8pVoFioSGetvsjpzRsv6jCsacdAZwhuYEUCi82wFW1yd3UNCVMh6U8ypspQp3wz3
|
||||
tbdoGbzlwbwbgd2o9+MpxzW66s2emEsCBjG+SrNElZBkfAG8ZgSbF3yGlSe778BJ
|
||||
7O71TEjxmYfUglvn90ZWpV7IH1TNbaKeIOJXkmuqQDaiG6U61kHcq//QvuZfU/tv
|
||||
TEUlQGqbdYS1E7+byCxubUnD3rclSP1cMTGyUtacHGUzFhiCZfuuDc+1P1Q8wKTe
|
||||
NkGfMpmXWLSncVUDEPgpsuz+hCtt65BAb0BfCWLZPyBXQ4Qbovk6Z/O5Ta5tyWEl
|
||||
g2wRqFXUL8ZYk+TKbmSclU+1h3QfFwvyEmEGFi+igKRZR1ERB4cAEEDjOJP+uI7B
|
||||
3K7lomdeh4kuPG6move8PCm9Dw1GhWPVFCKoan0MW2sNfnhmoOqXkoMT6P+M4U7+
|
||||
DjHY+G5Op2jkP+BrHQ99VRApXz40MtLaOdfu6S+IWURnqqwPuL99We8XFMgX3xX4
|
||||
++v7lSkcp54uSoN5e/fY/2fYG/RPxaI6+W6oxP4YmxUZjdvGdZvJiJJGqIBzCj1p
|
||||
26WynwFu25wnsyXBzWo4wzH4Ga6ZtUvb59KFRTSJqQKieLVmX2zNjSps2B2/twax
|
||||
EQt03AGIbtr677NeYKM3BUws+iw9TyBUjEMsqnpp6EuWhDcPga8WJn1ivw04BenP
|
||||
uaOw2w1nLe8InaJxahmBKmRiSjX7XX4+PPgB/FwGN89nMBpy8+ujitteOYvlY6Hf
|
||||
050aTysBmYWu4oCsx/kz8OHpwt7zPO8zkVdtHCGa8+5bm//pLUGHyoDVY2Xj68MD
|
||||
OMfwbJl0Q4W+bOkCEK4fYhkB7HWPZqxZKujcR/goXBsUCvIk/WuDx8pNnjIas1Qm
|
||||
MUDSs9XQFGWE8ydRYN4RRw==
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDqTCCApGgAwIBAgIUbNUnFW+Ibevm3bOTzzznsNO4laIwDQYJKoZIhvcNAQEL
|
||||
BQAwYzELMAkGA1UEBhMCWloxDDAKBgNVBAgMA1N1bjENMAsGA1UEBwwETW9vbjEQ
|
||||
MA4GA1UECgwHTWVyY3VyeTERMA8GA1UECwwISG9tZWJyZXcxEjAQBgNVBAMMCWxv
|
||||
Y2FsaG9zdDAgFw0yMzAyMjUwNjU4MTJaGA8yMDUzMDIxNzA2NTgxMlowYzELMAkG
|
||||
A1UEBhMCWloxDDAKBgNVBAgMA1N1bjENMAsGA1UEBwwETW9vbjEQMA4GA1UECgwH
|
||||
TWVyY3VyeTERMA8GA1UECwwISG9tZWJyZXcxEjAQBgNVBAMMCWxvY2FsaG9zdDCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBF0q8GELLjXu6zTTNtCovU
|
||||
QVsgg8kSN56p8Xxv5gZHEuhUXjan+UyiklW2aoxJZpyRbE8dpAR78ca6kLUG1LMf
|
||||
2RX8FDjA6W5xXR2C2FmSYGnPyLigRFPbZv3sb7PyOYhqgPuu1xKMEmq5n1lE9pCV
|
||||
nO7hAsfwqS3mZrPFL3MZIqrT6HqeSO1tVe8gUUWTm3dm9Yb0E/sVExdG6u0RfbVu
|
||||
eqHykO4iCUonm3lOigskDbZ7WFKQyVRM3vZbALEpE7YlltcgT14GmG+L8aeFY6iT
|
||||
FoPDV7bFAGtgg30os4kV135HUNJ80koIoUocwxThuyBpADltIZ5R2FSHBl1XzK8C
|
||||
AwEAAaNTMFEwHQYDVR0OBBYEFHgmdAlywLPAucVbDxiIc7uIWl6RMB8GA1UdIwQY
|
||||
MBaAFHgmdAlywLPAucVbDxiIc7uIWl6RMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
|
||||
hvcNAQELBQADggEBAGW6HVweWcsIxp2vVzspBaKSp2ECYRpx4xunge/eDWlokAj3
|
||||
OCW7kxgPfEbtClLOeQj3p9WolHzABgG+qqIB6kPbGtNXYaXrQbsD6j9f56GFklNK
|
||||
tuYH3WtDpp5TLsYyj2cLeK2x02Z8k3+r11SqB1DeMPTBAkhXiTwrkUt3axnZuiZC
|
||||
2Miwzi0b5muMbdecYukB+50xlV8TkiVmWUtQ5cVVE/U640sC6O1GMZG0zO9Ys0+U
|
||||
xTeB/3Xq5Wg6OQx86GpbD7+8xRhSkdJxoVbuFgh0KNUlBREC/pYobehnwji7WWFH
|
||||
F7nBdVyedi6qZTa7dVEk4eaXgalemTp9k4rzbZ8=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,30 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIoyT8iwjhZBECAggA
|
||||
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECKy1pYbVGbtDBIIEyIIY1X/XVv5q
|
||||
ihMCTQbnesuyEstQCw/9BFQ/ka4Ee2D6yJp59gSiEODwce+EgIn1jrgJImOZbnsz
|
||||
xKtRJXNd+ENBwsZgh8am15o+bJ2WeOztuKcrhOvrRmj8wrDPAon4+sdcfphqRUbG
|
||||
hilLbV7T8jpE1ScTD/zYU/KKWEIytYTxT+vfHvXYv8oQY9IscwNqx6cnXxNtoO7C
|
||||
SO87/Apkul3irVHnad29gV/jyj4imlm6gVCmqByaD/JaV/d9Y0hWhZVeSzceP64Q
|
||||
95kfhUM8AsTJi5A25vWAQAxa2Gi8ywiv+/NRVC4qhzMID4wbqI/2Oy8iEMJJfkaK
|
||||
Ah/S5lY8sVRpenUmX4kSZs+oKbITc5LNccx5OUESvVZCj/mW9t91uZfTWTt23iac
|
||||
snYzhH4PvYxCGU7LXzrgS5suv/N3R33E5kcND0dJbKkW4VVVxmv7HUDfs8YqduJn
|
||||
teQFQNsoNuQO5Te9WsMpamickF/65nrg+OOhsbVkLsuCRPzyXIRgAPBBGFqlr3IG
|
||||
XK41kQR5I4HTAeFXCClz00LfLrCl+T7IO3NbH+AD1EVGUHYPuwgJBRic/cMbXZwT
|
||||
Kcxo98Apwsm+OHKRAq4c5wEmUb9ipVSwq6CRUojklrGMclJfXnd9r57FFl/9eYdY
|
||||
ZEp+jnAqq3M8v2m29dPjja07CTIuimIRgIPaIjWZuZX8oW1GVpapV3JfIun5KXE4
|
||||
Sc+ScLA015Gzm/3hgKNke5HGYH49x9V/lYhr9j5AxgdWnoj4H3qbJSu2jJKooYmS
|
||||
tsimgs3pqz/dygyx9Zmy2L5eb597MYEQwg4kZdFPyixAttmFXRdXVvRmQCB9H8VX
|
||||
kx6z4Rus/Zh6NM6z0aHvWoaih9jJ444CdnOPLYSngLL5yzI3xunwT67Di9rrkNeL
|
||||
nVBJP9Ljc9cE4LgK63xAy+25+bZWv/mZ07CBXatc91CCSa/O3KM4eLmOMNaZNU+T
|
||||
P8EYHR3r24V6TCzud7dLp3k+Glkxj1feiXEktmFxnfUbGoS5Ihw4cVGqrst7hSSE
|
||||
IaQFIx0X70sKyl/ixxVHWIMdV4Zqdxhf2boNZk7aHx8+yOhCnOEY4/8KUJM98W+W
|
||||
a6VRhxYucKsz+B3i0BKEZg4sB1bT/6G17JAentfGmKp42IFJR3JeRydEF6ppCaWT
|
||||
gdLnRlsYDHEpAMcTPsbDiQK3Crid3E0i/2QU5V5VEhR2ncq+oKZ0oy7nwoOV232W
|
||||
TuodV43urEshbh8RDr321+2UxCgT6AGMAt6BPgx9D/mIZHMVgZalvHqtzPDyN5Av
|
||||
5LiXct8nl4fO+c0iMdfAw2TfCvl6sIkaAW5ClqbHXxiSg9OUXSrfgBVMkcCmcnB0
|
||||
cNbx6Xc6jdLZEtnch+IcYZzj4wmLFx01zVAs9daPxbGw6mg1TloDQ0fYhgixkRSi
|
||||
NDkztXZzLFx9MB4rYy/v8h08OWwNi/R6IOZDI4DNf7qXEtgqouqa85srsT9Pspc4
|
||||
SAN5YzHlo6AKujmUNRo+uYbJGqsssMXQPWNvozxnXIgQsiZ5/Y/x3KsUJu49RveL
|
||||
baNm/ScI3ghTbt92bPE16ebtodULkxuPFAqXdjWXLjblSVihiKxvQ9wTULB97zHI
|
||||
1oX6YdWladLddzK/De6JMA==
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
@@ -0,0 +1 @@
|
||||
4A5531796DA232C2C3F0B937F9F7C651FC5E8FA5
|
||||
Binary file not shown.
@@ -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
@@ -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
|
||||
|
||||
@@ -94,3 +94,43 @@ 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
|
||||
STR_EDITOR=Editor
|
||||
STR_SAVE=Save
|
||||
STR_MAX_EDIT_FILE_SIZE_MSG=Cannot edit files bigger than
|
||||
STR_DELETE_LINE=Delete Selected Line
|
||||
STR_INSERT_LINE=Insert Below Selected Line
|
||||
STR_FAIL_GET_TOKEN_MSG=Failed to obtain an access token from
|
||||
STR_GET_TOKEN_SUCCESS_MSG=Login Success. You may close the browser and return to the application
|
||||
STR_PERM_DRIVE=See, edit, create, and delete all of your Google Drive files
|
||||
STR_PERM_DRIVE_APPDATA=See, create, and delete its own configuration data in your Google Drive
|
||||
STR_PERM_DRIVE_FILE=See, edit, create, and delete only the specific Google Drive files you use with this app
|
||||
STR_PERM_DRIVE_METADATA=View and manage metadata of files in your Google Drive
|
||||
STR_PERM_DRIVE_METADATA_RO=See information about your Google Drive files
|
||||
STR_GOOGLE_LOGIN_FAIL_MSG=Google login failed
|
||||
STR_GOOGLE_LOGIN_TIMEOUT_MSG=Google login timed out
|
||||
STR_NEW_FILE=New File
|
||||
STR_SETTINGS=Settings
|
||||
STR_CLIENT_ID=Client ID
|
||||
STR_CLIENT_SECRET=Client Secret
|
||||
STR_GLOBAL=Global
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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=Удалено
|
||||
|
||||
@@ -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
+612
-31
@@ -4,6 +4,14 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <minizip/unzip.h>
|
||||
#include "clients/gdrive.h"
|
||||
#include "clients/ftpclient.h"
|
||||
#include "clients/smbclient.h"
|
||||
#include "clients/webdavclient.h"
|
||||
#include "clients/apache.h"
|
||||
#include "clients/nginx.h"
|
||||
#include "clients/npxserve.h"
|
||||
#include "clients/iis.h"
|
||||
#include "common.h"
|
||||
#include "fs.h"
|
||||
#include "config.h"
|
||||
@@ -12,12 +20,9 @@
|
||||
#include "lang.h"
|
||||
#include "actions.h"
|
||||
#include "installer.h"
|
||||
#include "request.hpp"
|
||||
#include "urn.hpp"
|
||||
#include "rtc.h"
|
||||
#include "ftpclient.h"
|
||||
#include "smbclient.h"
|
||||
#include "webdavclient.h"
|
||||
#include "web/request.hpp"
|
||||
#include "web/urn.hpp"
|
||||
#include "system.h"
|
||||
#include "zip_util.h"
|
||||
|
||||
namespace Actions
|
||||
@@ -52,7 +57,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 +93,7 @@ namespace Actions
|
||||
{
|
||||
remote_files = remoteclient->ListDir(remote_directory);
|
||||
}
|
||||
FS::Sort(remote_files);
|
||||
DirEntry::Sort(remote_files);
|
||||
}
|
||||
|
||||
void HandleChangeLocalDirectory(const DirEntry entry)
|
||||
@@ -246,7 +251,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 +282,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 +434,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 +455,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 +582,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 +629,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 +682,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 +717,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 +743,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 +821,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 +866,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 +1002,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 +1019,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);
|
||||
@@ -1014,7 +1108,24 @@ namespace Actions
|
||||
void Connect()
|
||||
{
|
||||
CONFIG::SaveConfig();
|
||||
if (strncmp(remote_settings->server, "https://", 8) == 0 || strncmp(remote_settings->server, "http://", 7) == 0)
|
||||
|
||||
if (strncmp(remote_settings->server, GOOGLE_DRIVE_BASE_URL, strlen(GOOGLE_DRIVE_BASE_URL)) == 0)
|
||||
{
|
||||
remoteclient = new GDriveClient();
|
||||
remoteclient->Connect("", "", "");
|
||||
}
|
||||
else 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 +1140,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 +1151,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 +1207,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 +1222,471 @@ 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);
|
||||
}
|
||||
|
||||
void CreateLocalFile(char *filename)
|
||||
{
|
||||
std::string new_file = FS::GetPath(local_directory, filename);
|
||||
std::string temp_file = new_file;
|
||||
int i = 1;
|
||||
while (true)
|
||||
{
|
||||
if (!FS::FileExists(temp_file))
|
||||
break;
|
||||
temp_file = new_file + "." + std::to_string(i);
|
||||
i++;
|
||||
}
|
||||
FILE* f = FS::Create(temp_file);
|
||||
FS::Close(f);
|
||||
RefreshLocalFiles(false);
|
||||
sprintf(local_file_to_select, "%s", temp_file.c_str());
|
||||
}
|
||||
|
||||
void CreateRemoteFile(char *filename)
|
||||
{
|
||||
std::string new_file = FS::GetPath(remote_directory, filename);
|
||||
std::string temp_file = new_file;
|
||||
int i = 1;
|
||||
while (true)
|
||||
{
|
||||
if (!remoteclient->FileExists(temp_file))
|
||||
break;
|
||||
temp_file = new_file + "." + std::to_string(i);
|
||||
i++;
|
||||
}
|
||||
|
||||
OrbisTick tick;
|
||||
sceRtcGetCurrentTick(&tick);
|
||||
std::string local_tmp = std::string(DATA_PATH) + "/" + std::to_string(tick.mytick);
|
||||
FILE *f = FS::Create(local_tmp);
|
||||
FS::Close(f);
|
||||
remoteclient->Put(local_tmp, temp_file);
|
||||
FS::Rm(local_tmp);
|
||||
RefreshRemoteFiles(false);
|
||||
sprintf(remote_file_to_select, "%s", temp_file.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-1
@@ -2,6 +2,7 @@
|
||||
#define ACTIONS_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include "installer.h"
|
||||
#include "common.h"
|
||||
|
||||
#define CONFIRM_NONE -1
|
||||
@@ -39,7 +40,17 @@ 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_LOCAL_EDIT,
|
||||
ACTION_REMOTE_CUT,
|
||||
ACTION_REMOTE_COPY,
|
||||
ACTION_REMOTE_PASTE,
|
||||
ACTION_REMOTE_EDIT,
|
||||
ACTION_NEW_LOCAL_FILE,
|
||||
ACTION_NEW_REMOTE_FILE
|
||||
};
|
||||
|
||||
enum OverWriteType
|
||||
@@ -88,6 +99,17 @@ 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);
|
||||
void CreateLocalFile(char *filename);
|
||||
void CreateRemoteFile(char *filename);
|
||||
}
|
||||
|
||||
#endif
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
#ifndef BASE64_H_
|
||||
#define BASE64_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
class Base64
|
||||
{
|
||||
public:
|
||||
static int Encode(const std::string &input, std::string &out)
|
||||
{
|
||||
static constexpr char sEncodingTable[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'};
|
||||
|
||||
size_t in_len = input.size();
|
||||
size_t out_len = 4 * ((in_len + 2) / 3);
|
||||
out.resize(out_len);
|
||||
size_t i;
|
||||
char *p = const_cast<char *>(out.c_str());
|
||||
|
||||
for (i = 0; i < in_len - 2; i += 3)
|
||||
{
|
||||
*p++ = sEncodingTable[(input[i] >> 2) & 0x3F];
|
||||
*p++ = sEncodingTable[((input[i] & 0x3) << 4) | ((int)(input[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = sEncodingTable[((input[i + 1] & 0xF) << 2) | ((int)(input[i + 2] & 0xC0) >> 6)];
|
||||
*p++ = sEncodingTable[input[i + 2] & 0x3F];
|
||||
}
|
||||
if (i < in_len)
|
||||
{
|
||||
*p++ = sEncodingTable[(input[i] >> 2) & 0x3F];
|
||||
if (i == (in_len - 1))
|
||||
{
|
||||
*p++ = sEncodingTable[((input[i] & 0x3) << 4)];
|
||||
*p++ = '=';
|
||||
}
|
||||
else
|
||||
{
|
||||
*p++ = sEncodingTable[((input[i] & 0x3) << 4) | ((int)(input[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = sEncodingTable[((input[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Decode(const std::string &input, std::string &out)
|
||||
{
|
||||
static constexpr unsigned char kDecodingTable[] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
|
||||
|
||||
size_t in_len = input.size();
|
||||
if (in_len % 4 != 0)
|
||||
return 0;
|
||||
|
||||
size_t out_len = in_len / 4 * 3;
|
||||
if (input[in_len - 1] == '=')
|
||||
out_len--;
|
||||
if (input[in_len - 2] == '=')
|
||||
out_len--;
|
||||
|
||||
out.resize(out_len);
|
||||
|
||||
for (size_t i = 0, j = 0; i < in_len;)
|
||||
{
|
||||
uint32_t a = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
|
||||
uint32_t b = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
|
||||
uint32_t c = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
|
||||
uint32_t d = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
|
||||
|
||||
uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
|
||||
|
||||
if (j < out_len)
|
||||
out[j++] = (triple >> 2 * 8) & 0xFF;
|
||||
if (j < out_len)
|
||||
out[j++] = (triple >> 1 * 8) & 0xFF;
|
||||
if (j < out_len)
|
||||
out[j++] = (triple >> 0 * 8) & 0xFF;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,239 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <fstream>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/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;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef APACHE_H
|
||||
#define APACHE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "common.h"
|
||||
|
||||
class ApacheClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,267 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <fstream>
|
||||
#include <curl/curl.h>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/baseclient.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;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
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 + ((this->base_path.length() > 0) ? "/" : "") + 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;
|
||||
}
|
||||
|
||||
std::string BaseClient::EncodeUrl(const std::string &url)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if (curl)
|
||||
{
|
||||
char *output = curl_easy_escape(curl, url.c_str(), url.length());
|
||||
if (output)
|
||||
{
|
||||
std::string encoded_url = std::string(output);
|
||||
curl_free(output);
|
||||
return encoded_url;
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string BaseClient::DecodeUrl(const std::string &url)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if (curl)
|
||||
{
|
||||
int decode_len;
|
||||
char *output = curl_easy_unescape(curl, url.c_str(), url.length(), &decode_len);
|
||||
if (output)
|
||||
{
|
||||
std::string decoded_url = std::string(output, decode_len);
|
||||
curl_free(output);
|
||||
return decoded_url;
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef BASESERVER_H
|
||||
#define BASESERVER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "common.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();
|
||||
static std::string EncodeUrl(const std::string &url);
|
||||
static std::string DecodeUrl(const std::string &url);
|
||||
|
||||
protected:
|
||||
httplib::Client *client;
|
||||
std::string base_path;
|
||||
char response[512];
|
||||
bool connected = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <sys/errno.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "lang.h"
|
||||
#include "ftpclient.h"
|
||||
#include "clients/ftpclient.h"
|
||||
#include "util.h"
|
||||
#include "windows.h"
|
||||
|
||||
@@ -1578,20 +1578,7 @@ std::vector<DirEntry> FtpClient::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;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
|
||||
ftphandle *nData;
|
||||
@@ -1608,6 +1595,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 +1614,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 +1654,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 +1668,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;
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "remote_client.h"
|
||||
#include "clients/remote_client.h"
|
||||
|
||||
#define FTP_CLIENT_MAX_FILENAME_LEN 128
|
||||
|
||||
@@ -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;
|
||||
@@ -0,0 +1,741 @@
|
||||
#include <orbis/UserService.h>
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <json-c/json.h>
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "server/http_server.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/gdrive.h"
|
||||
#include "fs.h"
|
||||
#include "lang.h"
|
||||
#include "util.h"
|
||||
#include "windows.h"
|
||||
#include "system.h"
|
||||
|
||||
#define GOOGLE_BUF_SIZE 262144
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
static std::string shared_with_me("Shared with me");
|
||||
|
||||
using namespace httplib;
|
||||
|
||||
std::string GetRedirectUrl()
|
||||
{
|
||||
return std::string("https://localhost:" + std::to_string(http_server_port) + "/google_auth");
|
||||
}
|
||||
|
||||
std::string GetScopes()
|
||||
{
|
||||
std::vector<std::string> permissions = Util::Split(gg_app.permissions, ",");
|
||||
std::string scopes;
|
||||
for (int i = 0; i < permissions.size(); i++)
|
||||
{
|
||||
scopes.append("https://www.googleapis.com/auth/");
|
||||
scopes.append(permissions[i]);
|
||||
if (i < permissions.size() - 1)
|
||||
{
|
||||
scopes.append(" ");
|
||||
}
|
||||
}
|
||||
return scopes;
|
||||
}
|
||||
|
||||
int RefreshAccessToken()
|
||||
{
|
||||
Client client(GOOGLE_OAUTH_HOST);
|
||||
client.enable_server_certificate_verification(false);
|
||||
client.set_follow_location(true);
|
||||
std::string url = std::string("/token");
|
||||
std::string post_data = std::string("grant_type=refresh_token") +
|
||||
"&client_id=" + gg_app.client_id +
|
||||
"&client_secret=" + gg_app.client_secret +
|
||||
"&refresh_token=" + remote_settings->gg_account.refresh_token;
|
||||
|
||||
if (auto res = client.Post(url, post_data.c_str(), post_data.length(), "application/x-www-form-urlencoded"))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
json_object *jobj = json_tokener_parse(res->body.c_str());
|
||||
enum json_type type;
|
||||
json_object_object_foreach(jobj, key, val)
|
||||
{
|
||||
if (strcmp(key, "access_token") == 0)
|
||||
snprintf(remote_settings->gg_account.access_token, 255, "%s", json_object_get_string(val));
|
||||
else if (strcmp(key, "expires_in") == 0)
|
||||
{
|
||||
OrbisTick tick;
|
||||
sceRtcGetCurrentTick(&tick);
|
||||
remote_settings->gg_account.token_expiry = tick.mytick + (json_object_get_uint64(val) * 1000000);
|
||||
}
|
||||
}
|
||||
if (remoteclient != nullptr && remoteclient->clientType() == CLIENT_TYPE_GOOGLE)
|
||||
{
|
||||
GDriveClient *client = (GDriveClient*)remoteclient;
|
||||
client->SetAccessToken(remote_settings->gg_account.access_token);
|
||||
}
|
||||
CONFIG::SaveConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int login_state;
|
||||
|
||||
std::string GetValue(const std::map<std::string, std::string> &options, const std::string &name)
|
||||
{
|
||||
auto it = options.find(name);
|
||||
if (it == options.end())
|
||||
{
|
||||
return std::string{""};
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
int GDriveClient::RequestAuthorization()
|
||||
{
|
||||
SceShellUIUtilLaunchByUriParam param;
|
||||
param.size = sizeof(SceShellUIUtilLaunchByUriParam);
|
||||
sceUserServiceGetForegroundUser((int *)¶m.userId);
|
||||
|
||||
std::string auth_url = std::string(GOOGLE_AUTH_URL "?client_id=") + gg_app.client_id + "&redirect_uri=" + GetRedirectUrl() +
|
||||
"&response_type=code&access_type=offline&scope=" + GetScopes() + "&include_granted_scopes=true";
|
||||
auth_url = EncodeUrl(auth_url);
|
||||
std::string launch_uri = std::string("pswebbrowser:search?url=") + auth_url;
|
||||
int ret = sceShellUIUtilLaunchByUri(launch_uri.c_str(), ¶m);
|
||||
|
||||
login_state = 0;
|
||||
OrbisTick tick;
|
||||
sceRtcGetCurrentTick(&tick);
|
||||
while (login_state == 0)
|
||||
{
|
||||
OrbisTick cur_tick;
|
||||
sceRtcGetCurrentTick(&cur_tick);
|
||||
if (cur_tick.mytick - tick.mytick > 120000000)
|
||||
{
|
||||
login_state = -2;
|
||||
break;
|
||||
}
|
||||
sceKernelUsleep(100000);
|
||||
}
|
||||
|
||||
if (login_state == -1)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_GOOGLE_LOGIN_FAIL_MSG]);
|
||||
return 0;
|
||||
}
|
||||
else if (login_state == -2)
|
||||
{
|
||||
sprintf(response, "%s", lang_strings[STR_GOOGLE_LOGIN_TIMEOUT_MSG]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
GDriveClient::GDriveClient()
|
||||
{
|
||||
client = nullptr;
|
||||
path_id_map.insert(std::make_pair("/", "root"));
|
||||
path_id_map.insert(std::make_pair("/"+shared_with_me, shared_with_me));
|
||||
}
|
||||
|
||||
int GDriveClient::Connect(const std::string &url, const std::string &user, const std::string &pass)
|
||||
{
|
||||
if (strlen(remote_settings->gg_account.refresh_token) > 0)
|
||||
{
|
||||
int ret = RefreshAccessToken();
|
||||
if (ret == 0)
|
||||
{
|
||||
RequestAuthorization();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RequestAuthorization();
|
||||
}
|
||||
StartRefreshToken();
|
||||
|
||||
client = new Client(GOOGLE_API_URL);
|
||||
client->set_bearer_token_auth(remote_settings->gg_account.access_token);
|
||||
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);
|
||||
this->connected = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GDriveClient::Rename(const std::string &src, const std::string &dst)
|
||||
{
|
||||
if (src.find(shared_with_me) != std::string::npos || dst.find(shared_with_me) != std::string::npos)
|
||||
return 0;
|
||||
|
||||
std::string id = GetValue(path_id_map, src);
|
||||
std::string url = std::string("/drive/v3/files/") + BaseClient::EncodeUrl(id);
|
||||
std::string filename = dst.substr(dst.find_last_of("/") + 1);
|
||||
std::string body = "{'name' : '" + filename + "'}";
|
||||
if (auto res = client->Patch(url, body.c_str(), body.length(), "application/json; charset=UTF-8"))
|
||||
{
|
||||
sprintf(response, "%d", res->status);
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
path_id_map.erase(src);
|
||||
path_id_map.insert(std::make_pair(dst, id));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(response, "%s", to_string(res.error()).c_str());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool GDriveClient::FileExists(const std::string &path)
|
||||
{
|
||||
std::string id = GetValue(path_id_map, path);
|
||||
if (id.empty()) // then find it parent folder to see if it exists
|
||||
{
|
||||
size_t name_separator = path.find_last_of("/");
|
||||
std::string parent = path.substr(0, name_separator);
|
||||
if (parent.empty())
|
||||
parent = "/";
|
||||
|
||||
if (FileExists(parent))
|
||||
{
|
||||
ListDir(parent);
|
||||
id = GetValue(path_id_map, path);
|
||||
if (!id.empty())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int GDriveClient::Head(const std::string &path, void *buffer, uint64_t len)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
std::vector<char> body;
|
||||
std::string id = GetValue(path_id_map, path);
|
||||
std::string url = std::string("/drive/v3/files/") + BaseClient::EncodeUrl(id) + "?alt=media";
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("Range", "bytes=" + std::to_string(0) + "-" + std::to_string(len - 1)));
|
||||
if (auto res = client->Get(url, 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;
|
||||
}
|
||||
|
||||
int GDriveClient::Get(const std::string &outputfile, const std::string &path, uint64_t offset)
|
||||
{
|
||||
std::ofstream file_stream(outputfile, std::ios::binary);
|
||||
bytes_transfered = 0;
|
||||
|
||||
std::string id = GetValue(path_id_map, path);
|
||||
std::string url = std::string("/drive/v3/files/") + BaseClient::EncodeUrl(id) + "?alt=media";
|
||||
if (auto res = client->Get(url,
|
||||
[&](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 GDriveClient::Update(const std::string &inputfile, const std::string &path)
|
||||
{
|
||||
bytes_to_download = FS::GetSize(inputfile);
|
||||
bytes_transfered = 0;
|
||||
|
||||
std::ifstream file_stream(inputfile, std::ios::binary);
|
||||
bytes_transfered = 0;
|
||||
|
||||
std::string id = GetValue(path_id_map, path);
|
||||
|
||||
std::string url = "/upload/drive/v3/files/" + BaseClient::EncodeUrl(id) + "?uploadType=resumable";
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("X-Upload-Content-Type", "application/octet-stream"));
|
||||
headers.insert(std::make_pair("X-Upload-Content-Length", std::to_string(bytes_to_download)));
|
||||
char *buf = new char[GOOGLE_BUF_SIZE];
|
||||
if (auto res = client->Patch(url))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
std::string upload_uri = res->get_header_value("location");
|
||||
upload_uri = std::regex_replace(upload_uri, std::regex(GOOGLE_API_URL), "");
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("Content-Length", std::to_string(bytes_to_download)));
|
||||
std::string range_value = "bytes 0-" + std::to_string(bytes_to_download - 1) + "/" + std::to_string(bytes_to_download);
|
||||
headers.insert(std::make_pair("Content-Range", range_value));
|
||||
|
||||
if (auto res = client->Put(
|
||||
upload_uri, bytes_to_download,
|
||||
[&file_stream, &buf](size_t offset, size_t length, DataSink &sink)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
uint32_t bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
do
|
||||
{
|
||||
file_stream.read(buf, bytes_to_transfer);
|
||||
sink.write(buf, bytes_to_transfer);
|
||||
count += bytes_to_transfer;
|
||||
bytes_transfered += bytes_to_transfer;
|
||||
bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
} while (count < length);
|
||||
return true;
|
||||
},
|
||||
"application/octet-stream"))
|
||||
{
|
||||
// success
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GDriveClient::Put(const std::string &inputfile, const std::string &path, uint64_t offset)
|
||||
{
|
||||
if (path.find(shared_with_me) != std::string::npos)
|
||||
return 0;
|
||||
|
||||
if (FileExists(path))
|
||||
return Update(inputfile, path);
|
||||
|
||||
bytes_to_download = FS::GetSize(inputfile);
|
||||
bytes_transfered = 0;
|
||||
|
||||
std::ifstream file_stream(inputfile, std::ios::binary);
|
||||
bytes_transfered = 0;
|
||||
|
||||
size_t path_pos = path.find_last_of("/");
|
||||
std::string parent_dir;
|
||||
if (path_pos == 0)
|
||||
parent_dir = "/";
|
||||
else
|
||||
parent_dir = path.substr(0, path_pos);
|
||||
|
||||
std::string filename = path.substr(path_pos + 1);
|
||||
std::string parent_id = GetValue(path_id_map, parent_dir);
|
||||
|
||||
std::string url = "/upload/drive/v3/files?uploadType=resumable";
|
||||
std::string post_data = std::string("{'name': '") + filename + "', 'parents': ['" + parent_id + "']}";
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("X-Upload-Content-Type", "application/octet-stream"));
|
||||
headers.insert(std::make_pair("X-Upload-Content-Length", std::to_string(bytes_to_download)));
|
||||
char *buf = new char[GOOGLE_BUF_SIZE];
|
||||
if (auto res = client->Post(url, headers, post_data.c_str(), post_data.length(), "application/json"))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
std::string upload_uri = res->get_header_value("location");
|
||||
upload_uri = std::regex_replace(upload_uri, std::regex(GOOGLE_API_URL), "");
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("Content-Length", std::to_string(bytes_to_download)));
|
||||
std::string range_value = "bytes 0-" + std::to_string(bytes_to_download - 1) + "/" + std::to_string(bytes_to_download);
|
||||
headers.insert(std::make_pair("Content-Range", range_value));
|
||||
|
||||
if (auto res = client->Put(
|
||||
upload_uri, bytes_to_download,
|
||||
[&file_stream, &buf](size_t offset, size_t length, DataSink &sink)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
uint32_t bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
do
|
||||
{
|
||||
file_stream.read(buf, bytes_to_transfer);
|
||||
sink.write(buf, bytes_to_transfer);
|
||||
count += bytes_to_transfer;
|
||||
bytes_transfered += bytes_to_transfer;
|
||||
bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
} while (count < length);
|
||||
return true;
|
||||
},
|
||||
"application/octet-stream"))
|
||||
{
|
||||
// success
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GDriveClient::Size(const std::string &path, int64_t *size)
|
||||
{
|
||||
std::string id = GetValue(path_id_map, path);
|
||||
std::string url = std::string("/drive/v3/files/") + BaseClient::EncodeUrl(id) + "?fields=size";
|
||||
if (auto res = client->Get(url))
|
||||
{
|
||||
sprintf(response, "%d", res->status);
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
json_object *jobj = json_tokener_parse(res->body.c_str());
|
||||
*size = json_object_get_uint64(json_object_object_get(jobj, "size"));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(response, "%s", to_string(res.error()).c_str());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GDriveClient::Mkdir(const std::string &path)
|
||||
{
|
||||
if (path.find(shared_with_me) != std::string::npos)
|
||||
return 0;
|
||||
|
||||
// if path already exists return;
|
||||
if (FileExists(path))
|
||||
return 1;
|
||||
|
||||
size_t path_pos = path.find_last_of("/");
|
||||
std::string parent_dir;
|
||||
if (path_pos == 0)
|
||||
parent_dir = "/";
|
||||
else
|
||||
parent_dir = path.substr(0, path_pos);
|
||||
|
||||
std::string folder_name = path.substr(path_pos + 1);
|
||||
std::string parent_id = GetValue(path_id_map, parent_dir);
|
||||
|
||||
// if parent dir does not exists, create it first
|
||||
if (parent_id.length() == 0 || parent_id.empty())
|
||||
{
|
||||
Mkdir(parent_dir);
|
||||
parent_id = GetValue(path_id_map, parent_dir);
|
||||
}
|
||||
|
||||
std::string url = std::string("/drive/v3/files?fields=id");
|
||||
std::string folder_metadata = "{'name' : '" + folder_name + "'," +
|
||||
"'parents' : ['" + parent_id + "']," +
|
||||
"'mimeType' : 'application/vnd.google-apps.folder'}";
|
||||
|
||||
if (auto res = client->Post(url, folder_metadata.c_str(), folder_metadata.length(), "application/json; charset=UTF-8"))
|
||||
{
|
||||
sprintf(response, "%d", res->status);
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
json_object *jobj = json_tokener_parse(res->body.c_str());
|
||||
const char *id = json_object_get_string(json_object_object_get(jobj, "id"));
|
||||
path_id_map.insert(std::make_pair(path, id));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(response, "%s", to_string(res.error()).c_str());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rmdir in google drive deletes all files/folders in subdirectories also.
|
||||
* Delete file/folder is the same api
|
||||
*/
|
||||
int GDriveClient::Rmdir(const std::string &path, bool recursive)
|
||||
{
|
||||
if (path.find(shared_with_me) != std::string::npos)
|
||||
return 0;
|
||||
|
||||
int ret = Delete(path);
|
||||
if (ret != 0)
|
||||
{
|
||||
std::string subfolders = path + "/";
|
||||
for (std::map<std::string, std::string>::iterator it = path_id_map.begin(); it != path_id_map.end();)
|
||||
{
|
||||
if (strncmp(it->first.c_str(), subfolders.c_str(), path.length()) == 0)
|
||||
{
|
||||
it = path_id_map.erase(it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GDriveClient::Delete(const std::string &path)
|
||||
{
|
||||
std::string id = GetValue(path_id_map, path);
|
||||
if (strcmp(id.c_str(), "root") == 0)
|
||||
return 0;
|
||||
|
||||
std::string url = std::string("/drive/v3/files/") + BaseClient::EncodeUrl(id);
|
||||
if (auto res = client->Delete(url))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
path_id_map.erase(path);
|
||||
sprintf(response, "%d", res->status);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(response, "%s", to_string(res.error()).c_str());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SetupSharedWithMeFolder(DirEntry *entry)
|
||||
{
|
||||
memset(entry, 0, sizeof(DirEntry));
|
||||
sprintf(entry->directory, "%s", "/");
|
||||
sprintf(entry->name, "%s", shared_with_me.c_str());
|
||||
sprintf(entry->path, "/%s", shared_with_me.c_str());
|
||||
sprintf(entry->display_size, "%s", lang_strings[STR_FOLDER]);
|
||||
entry->file_size = 0;
|
||||
entry->isDir = true;
|
||||
entry->selectable = false;
|
||||
}
|
||||
|
||||
std::vector<DirEntry> GDriveClient::ListDir(const std::string &path)
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
DirEntry entry;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
|
||||
if (strcmp(path.c_str(), "/") == 0)
|
||||
{
|
||||
SetupSharedWithMeFolder(&entry);
|
||||
out.push_back(entry);
|
||||
}
|
||||
|
||||
std::string id = GetValue(path_id_map, path);
|
||||
std::string base_url = std::string("/drive/v3/files?q=") + BaseClient::EncodeUrl("\"" + id + "\" in parents") +
|
||||
"&pageSize=1000&fields=" + BaseClient::EncodeUrl("files(id,mimeType,name,modifiedTime,size),nextPageToken");
|
||||
bool find_no_parent = false;
|
||||
if (id.compare(shared_with_me) == 0)
|
||||
{
|
||||
base_url = std::string("/drive/v3/files?q=sharedWithMe&pageSize=1000&fields=") + BaseClient::EncodeUrl("files(id,mimeType,name,modifiedTime,size),nextPageToken");
|
||||
}
|
||||
|
||||
std::string next_page_url = base_url;
|
||||
while (true)
|
||||
{
|
||||
if (auto res = client->Get(next_page_url))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
json_object *jobj = json_tokener_parse(res->body.c_str());
|
||||
json_object *next_page_token = json_object_object_get(jobj, "nextPageToken");
|
||||
json_object *files = json_object_object_get(jobj, "files");
|
||||
if (json_object_get_type(files) == json_type_array)
|
||||
{
|
||||
struct array_list *afiles = json_object_get_array(files);
|
||||
for (size_t idx = 0; idx < afiles->length; ++idx)
|
||||
{
|
||||
json_object *file = (json_object *)array_list_get_idx(afiles, idx);
|
||||
DirEntry entry;
|
||||
memset(&entry, 0, sizeof(DirEntry));
|
||||
|
||||
sprintf(entry.directory, "%s", path.c_str());
|
||||
entry.selectable = true;
|
||||
entry.file_size = 0;
|
||||
|
||||
const char *id = json_object_get_string(json_object_object_get(file, "id"));
|
||||
const char *name = json_object_get_string(json_object_object_get(file, "name"));
|
||||
const char *mime_type = json_object_get_string(json_object_object_get(file, "mimeType"));
|
||||
const char *modified_time = json_object_get_string(json_object_object_get(file, "modifiedTime"));
|
||||
|
||||
snprintf(entry.name, 255, "%s", name);
|
||||
if (path.length() > 0 && path[path.length() - 1] == '/')
|
||||
{
|
||||
snprintf(entry.path, 767, "%s%s", path.c_str(), entry.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(entry.path, "%s/%s", path.c_str(), entry.name);
|
||||
}
|
||||
path_id_map.insert(std::make_pair(entry.path, id));
|
||||
|
||||
if (strncmp(mime_type, "application/vnd.google-apps.folder", 35) != 0)
|
||||
{
|
||||
entry.file_size = json_object_get_uint64(json_object_object_get(file, "size"));
|
||||
entry.isDir = false;
|
||||
DirEntry::SetDisplaySize(&entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.isDir = true;
|
||||
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
|
||||
}
|
||||
|
||||
std::vector<std::string> date_time_arr = Util::Split(modified_time, "T");
|
||||
std::vector<std::string> adate = Util::Split(date_time_arr[0], "-");
|
||||
std::vector<std::string> atime = Util::Split(Util::Split(date_time_arr[1], ".")[0], ":");
|
||||
OrbisDateTime utc, local;
|
||||
utc.year = std::atoi(adate[0].c_str());
|
||||
utc.month = std::atoi(adate[1].c_str());
|
||||
utc.day = std::atoi(adate[2].c_str());
|
||||
utc.hour = std::atoi(atime[0].c_str());
|
||||
utc.minute = std::atoi(atime[1].c_str());
|
||||
utc.second = std::atoi(atime[2].c_str());
|
||||
|
||||
convertUtcToLocalTime(&utc, &local);
|
||||
|
||||
entry.modified.year = local.year;
|
||||
entry.modified.month = local.month;
|
||||
entry.modified.day = local.day;
|
||||
entry.modified.hours = local.hour;
|
||||
entry.modified.minutes = local.minute;
|
||||
entry.modified.seconds = local.second;
|
||||
|
||||
out.push_back(entry);
|
||||
}
|
||||
}
|
||||
if (next_page_token != nullptr)
|
||||
next_page_url = base_url + "&pageToken=" + BaseClient::EncodeUrl(json_object_get_string(next_page_token));
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
};
|
||||
return out;
|
||||
}
|
||||
|
||||
ClientType GDriveClient::clientType()
|
||||
{
|
||||
return CLIENT_TYPE_GOOGLE;
|
||||
}
|
||||
|
||||
uint32_t GDriveClient::SupportedActions()
|
||||
{
|
||||
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE;
|
||||
}
|
||||
|
||||
void *GDriveClient::RefreshTokenThread(void *argp)
|
||||
{
|
||||
while (refresh_token_running)
|
||||
{
|
||||
OrbisTick tick;
|
||||
memset(&tick, 0, sizeof(OrbisTick));
|
||||
sceRtcGetCurrentTick(&tick);
|
||||
if (tick.mytick >= (remote_settings->gg_account.token_expiry - 300000000) &&
|
||||
remote_settings->type == CLIENT_TYPE_GOOGLE) // refresh token 5mins before expiry
|
||||
{
|
||||
RefreshAccessToken();
|
||||
}
|
||||
sceKernelUsleep(500000); // check every 0.5s
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GDriveClient::StartRefreshToken()
|
||||
{
|
||||
if (refresh_token_running)
|
||||
return;
|
||||
|
||||
refresh_token_running = true;
|
||||
int ret = pthread_create(&refresh_token_thid, NULL, RefreshTokenThread, NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
refresh_token_running = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GDriveClient::StopRefreshToken()
|
||||
{
|
||||
refresh_token_running = false;
|
||||
}
|
||||
|
||||
int GDriveClient::Quit()
|
||||
{
|
||||
StopRefreshToken();
|
||||
if (client != nullptr)
|
||||
{
|
||||
delete client;
|
||||
client = nullptr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GDriveClient::SetAccessToken(const std::string &token)
|
||||
{
|
||||
if (this->client != nullptr)
|
||||
this->client->set_bearer_token_auth(token);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef GDRIVE_H
|
||||
#define GDRIVE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "common.h"
|
||||
|
||||
static pthread_t refresh_token_thid;
|
||||
static bool refresh_token_running = false;
|
||||
extern int login_state;
|
||||
|
||||
class GDriveClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
GDriveClient();
|
||||
int Connect(const std::string &url, const std::string &user, const std::string &pass);
|
||||
int Rename(const std::string &src, const std::string &dst);
|
||||
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
|
||||
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
|
||||
int Head(const std::string &path, void *buffer, uint64_t len);
|
||||
int Update(const std::string &inputfile, const std::string &path);
|
||||
int Size(const std::string &path, int64_t *size);
|
||||
int Mkdir(const std::string &path);
|
||||
int Rmdir(const std::string &path, bool recursive);
|
||||
int Delete(const std::string &path);
|
||||
bool FileExists(const std::string &path);
|
||||
void SetAccessToken(const std::string &token);
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
static void *RefreshTokenThread(void *argp);
|
||||
static void StartRefreshToken();
|
||||
static void StopRefreshToken();
|
||||
ClientType clientType();
|
||||
uint32_t SupportedActions();
|
||||
int Quit();
|
||||
|
||||
private:
|
||||
int RequestAuthorization();
|
||||
std::map<std::string, std::string> path_id_map;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,153 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <fstream>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/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;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef IIS_H
|
||||
#define IIS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "common.h"
|
||||
|
||||
class IISClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,158 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/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;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef NGINX_H
|
||||
#define NGINX_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
|
||||
class NginxClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <fstream>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/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;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef NPXSERVE_H
|
||||
#define NPXSERVE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "common.h"
|
||||
|
||||
class NpxServeClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -5,9 +5,31 @@
|
||||
#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_EDIT = 512,
|
||||
REMOTE_ACTION_NEW_FILE = 1024,
|
||||
REMOTE_ACTION_ALL = 2047
|
||||
};
|
||||
|
||||
enum ClientType
|
||||
{
|
||||
CLIENT_TYPE_FTP, CLIENT_TYPE_SMB, CLIENT_TYPE_WEBDAV
|
||||
CLIENT_TYPE_FTP,
|
||||
CLIENT_TYPE_SMB,
|
||||
CLIENT_TYPE_WEBDAV,
|
||||
CLIENT_TYPE_HTTP_SERVER,
|
||||
CLIENT_TYPE_GOOGLE,
|
||||
CLINET_TYPE_UNKNOWN
|
||||
};
|
||||
|
||||
class RemoteClient
|
||||
@@ -23,6 +45,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 +56,7 @@ public:
|
||||
virtual const char *LastResponse() = 0;
|
||||
virtual int Quit() = 0;
|
||||
virtual ClientType clientType() = 0;
|
||||
virtual uint32_t SupportedActions() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <orbis/Net.h>
|
||||
#include "fs.h"
|
||||
#include "lang.h"
|
||||
#include "smbclient.h"
|
||||
#include "clients/smbclient.h"
|
||||
#include "windows.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -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, "/");
|
||||
@@ -384,20 +396,7 @@ std::vector<DirEntry> SmbClient::ListDir(const std::string &path)
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
DirEntry entry;
|
||||
memset(&entry, 0, sizeof(DirEntry));
|
||||
if (path.length() > 1 && path[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;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
|
||||
struct smb2dir *dir;
|
||||
@@ -416,6 +415,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 +445,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 +471,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 +497,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;
|
||||
}
|
||||
@@ -8,8 +8,8 @@
|
||||
#include <vector>
|
||||
#include <smb2/smb2.h>
|
||||
#include <smb2/libsmb2.h>
|
||||
#include "clients/remote_client.h"
|
||||
#include "common.h"
|
||||
#include "remote_client.h"
|
||||
|
||||
#define SMB_CLIENT_MAX_FILENAME_LEN 256
|
||||
|
||||
@@ -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);
|
||||
@@ -9,10 +9,10 @@
|
||||
#include <fcntl.h>
|
||||
#include "lang.h"
|
||||
#include "webdav/client.hpp"
|
||||
#include "webdavclient.h"
|
||||
#include "clients/webdavclient.h"
|
||||
#include "windows.h"
|
||||
#include "util.h"
|
||||
#include "rtc.h"
|
||||
#include "system.h"
|
||||
|
||||
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
|
||||
|
||||
@@ -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);
|
||||
@@ -242,20 +256,7 @@ namespace WebDAV
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
DirEntry entry;
|
||||
memset(&entry, 0, sizeof(DirEntry));
|
||||
if (path.length() > 1 && path[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;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
|
||||
WebDAV::dict_items_t files = client->list(path);
|
||||
@@ -263,6 +264,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 +283,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 +332,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 +361,9 @@ namespace WebDAV
|
||||
{
|
||||
return CLIENT_TYPE_WEBDAV;
|
||||
}
|
||||
|
||||
uint32_t WebDavClient::SupportedActions()
|
||||
{
|
||||
return REMOTE_ACTION_ALL;
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,20 @@
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <regex>
|
||||
#include "webdav/client.hpp"
|
||||
#include "clients/remote_client.h"
|
||||
#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);
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
||||
#define HTTP_SUCCESS(x) (x >= 200 && x < 300)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t year;
|
||||
@@ -28,6 +30,7 @@ struct DirEntry
|
||||
bool isDir;
|
||||
bool isLink;
|
||||
DateTime modified;
|
||||
bool selectable;
|
||||
|
||||
friend bool operator<(DirEntry const &a, DirEntry const &b)
|
||||
{
|
||||
@@ -59,6 +62,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
|
||||
+247
-54
@@ -1,11 +1,17 @@
|
||||
#include <orbis/UserService.h>
|
||||
#include <orbis/Net.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <regex>
|
||||
#include <stdlib.h>
|
||||
#include "server/http_server.h"
|
||||
#include "config.h"
|
||||
#include "fs.h"
|
||||
#include "lang.h"
|
||||
#include "crypt.h"
|
||||
#include "base64.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -21,17 +27,111 @@ 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;
|
||||
int max_edit_file_size;
|
||||
GoogleAppInfo gg_app;
|
||||
|
||||
unsigned char cipher_key[32] = {'s', '5', 'v', '8', 'y', '/', 'B', '?', 'E', '(', 'H', '+', 'M', 'b', 'Q', 'e', 'T', 'h', 'W', 'm', 'Z', 'q', '4', 't', '7', 'w', '9', 'z', '$', 'C', '&', 'F'};
|
||||
unsigned char cipher_iv[16] = {'Y', 'p', '3', 's', '6', 'v', '9', 'y', '$', 'B', '&', 'E', ')', 'H', '@', 'M'};
|
||||
|
||||
RemoteClient *remoteclient;
|
||||
|
||||
namespace CONFIG
|
||||
{
|
||||
int Encrypt(const std::string &text, std::string &encrypt_text)
|
||||
{
|
||||
unsigned char tmp_encrypt_text[text.length() * 2];
|
||||
int encrypt_text_len;
|
||||
memset(tmp_encrypt_text, 0, sizeof(tmp_encrypt_text));
|
||||
int ret = openssl_encrypt((unsigned char *)text.c_str(), text.length(), cipher_key, cipher_iv, tmp_encrypt_text, &encrypt_text_len);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
return Base64::Encode(std::string((const char *)tmp_encrypt_text, encrypt_text_len), encrypt_text);
|
||||
}
|
||||
|
||||
int Decrypt(const std::string &text, std::string &decrypt_text)
|
||||
{
|
||||
std::string tmp_decode_text;
|
||||
int ret = Base64::Decode(text, tmp_decode_text);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
unsigned char tmp_decrypt_text[tmp_decode_text.length() * 2];
|
||||
int decrypt_text_len;
|
||||
memset(tmp_decrypt_text, 0, sizeof(tmp_decrypt_text));
|
||||
ret = openssl_decrypt((unsigned char *)tmp_decode_text.c_str(), tmp_decode_text.length(), cipher_key, cipher_iv, tmp_decrypt_text, &decrypt_text_len);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
decrypt_text.clear();
|
||||
decrypt_text.append(std::string((const char *)tmp_decrypt_text, decrypt_text_len));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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, "https://drive.google.com", 24) == 0)
|
||||
{
|
||||
setting->type = CLIENT_TYPE_GOOGLE;
|
||||
}
|
||||
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 LoadCipherKeys()
|
||||
{
|
||||
// Get the key and iv for encryption. Inject the account_id/MAC address as part of the key and iv.
|
||||
int user_id;
|
||||
uint64_t account_id = 0;
|
||||
sceUserServiceGetForegroundUser(&user_id);
|
||||
sceUserServiceGetNpAccountId(user_id, &account_id);
|
||||
unsigned char data[sizeof(account_id)];
|
||||
memcpy(data, &account_id, sizeof(account_id));
|
||||
OrbisNetEtherAddr addr;
|
||||
memset(&addr, 0x0, sizeof(OrbisNetEtherAddr));
|
||||
sceNetGetMacAddress(&addr, 0);
|
||||
for (int i = 0; i < sizeof(data); i++)
|
||||
{
|
||||
cipher_key[i] = data[i];
|
||||
cipher_key[i + 16] = data[i];
|
||||
cipher_iv[i] = data[i];
|
||||
}
|
||||
int offset = sizeof(data);
|
||||
for (int i = 0; i < sizeof(addr.data); i++)
|
||||
{
|
||||
cipher_key[offset + i] = addr.data[i];
|
||||
cipher_key[offset + i + 16] = data[i];
|
||||
cipher_iv[offset + i] = addr.data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void LoadConfig()
|
||||
{
|
||||
LoadCipherKeys();
|
||||
|
||||
if (!FS::FolderExists(DATA_PATH))
|
||||
{
|
||||
FS::MkDirs(DATA_PATH);
|
||||
@@ -40,8 +140,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);
|
||||
@@ -55,20 +165,114 @@ namespace CONFIG
|
||||
auto_delete_tmp_pkg = ReadBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, true);
|
||||
WriteBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, auto_delete_tmp_pkg);
|
||||
|
||||
max_edit_file_size = ReadInt(CONFIG_GLOBAL, CONFIG_MAX_EDIT_FILE_SIZE, MAX_EDIT_FILE_SIZE);
|
||||
WriteInt(CONFIG_GLOBAL, CONFIG_MAX_EDIT_FILE_SIZE, max_edit_file_size);
|
||||
|
||||
// Load Google Account Info
|
||||
sprintf(gg_app.client_id, "%s", ReadString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_ID, ""));
|
||||
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_ID, gg_app.client_id);
|
||||
|
||||
// Client Secret
|
||||
char tmp_gg_secret[512];
|
||||
sprintf(tmp_gg_secret, "%s", ReadString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_SECRET, ""));
|
||||
std::string encrypted_secret;
|
||||
if (strlen(tmp_gg_secret) > 0)
|
||||
{
|
||||
std::string decrypted_secret;
|
||||
int ret = Decrypt(tmp_gg_secret, decrypted_secret);
|
||||
if (ret == 0)
|
||||
sprintf(gg_app.client_secret, "%s", tmp_gg_secret);
|
||||
else
|
||||
sprintf(gg_app.client_secret, "%s", decrypted_secret.c_str());
|
||||
Encrypt(gg_app.client_secret, encrypted_secret);
|
||||
}
|
||||
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_SECRET, encrypted_secret.c_str());
|
||||
|
||||
sprintf(gg_app.permissions, "%s", ReadString(CONFIG_GOOGLE, CONFIG_GOOGLE_PERMISSIONS, GOOGLE_DEFAULT_PERMISSIONS));
|
||||
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_PERMISSIONS, gg_app.permissions);
|
||||
|
||||
// Http Server Info
|
||||
http_server_port = ReadInt(CONFIG_HTTP_SERVER, CONFIG_HTTP_SERVER_PORT, 8080);
|
||||
WriteInt(CONFIG_HTTP_SERVER, CONFIG_HTTP_SERVER_PORT, http_server_port);
|
||||
|
||||
for (int i = 0; i < sites.size(); i++)
|
||||
{
|
||||
RemoteSettings setting;
|
||||
memset(&setting, 0, sizeof(RemoteSettings));
|
||||
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, ""));
|
||||
WriteString(sites[i].c_str(), CONFIG_REMOTE_SERVER_USER, setting.username);
|
||||
|
||||
sprintf(setting.password, "%s", ReadString(sites[i].c_str(), CONFIG_REMOTE_SERVER_PASSWORD, ""));
|
||||
WriteString(sites[i].c_str(), CONFIG_REMOTE_SERVER_PASSWORD, setting.password);
|
||||
char tmp_password[64];
|
||||
sprintf(tmp_password, "%s", ReadString(sites[i].c_str(), CONFIG_REMOTE_SERVER_PASSWORD, ""));
|
||||
std::string encrypted_password;
|
||||
if (strlen(tmp_password) > 0)
|
||||
{
|
||||
std::string decrypted_password;
|
||||
int ret = Decrypt(tmp_password, decrypted_password);
|
||||
if (ret == 0)
|
||||
sprintf(setting.password, "%s", tmp_password);
|
||||
else
|
||||
sprintf(setting.password, "%s", decrypted_password.c_str());
|
||||
Encrypt(setting.password, encrypted_password);
|
||||
}
|
||||
WriteString(sites[i].c_str(), CONFIG_REMOTE_SERVER_PASSWORD, encrypted_password.c_str());
|
||||
|
||||
setting.http_port = ReadInt(sites[i].c_str(), CONFIG_REMOTE_SERVER_HTTP_PORT, 80);
|
||||
WriteInt(sites[i].c_str(), CONFIG_REMOTE_SERVER_HTTP_PORT, setting.http_port);
|
||||
|
||||
setting.enable_rpi = ReadBool(sites[i].c_str(), CONFIG_ENABLE_RPI, false);
|
||||
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);
|
||||
|
||||
// Token Expiry
|
||||
setting.gg_account.token_expiry = ReadLong(sites[i].c_str(), CONFIG_GOOGLE_TOKEN_EXPIRY, 0);
|
||||
WriteLong(sites[i].c_str(), CONFIG_GOOGLE_TOKEN_EXPIRY, setting.gg_account.token_expiry);
|
||||
|
||||
// Access Token
|
||||
sprintf(tmp_gg_secret, "%s", ReadString(sites[i].c_str(), CONFIG_GOOGLE_ACCESS_TOKEN, ""));
|
||||
std::string encrypted_token;
|
||||
if (strlen(tmp_gg_secret) > 0)
|
||||
{
|
||||
std::string decrypted_secret;
|
||||
int ret = Decrypt(tmp_gg_secret, decrypted_secret);
|
||||
if (ret == 0)
|
||||
sprintf(setting.gg_account.access_token, "%s", tmp_gg_secret);
|
||||
else
|
||||
sprintf(setting.gg_account.access_token, "%s", decrypted_secret.c_str());
|
||||
Encrypt(setting.gg_account.access_token, encrypted_token);
|
||||
}
|
||||
WriteString(sites[i].c_str(), CONFIG_GOOGLE_ACCESS_TOKEN, encrypted_token.c_str());
|
||||
|
||||
// Refresh Token
|
||||
sprintf(tmp_gg_secret, "%s", ReadString(sites[i].c_str(), CONFIG_GOOGLE_REFRESH_TOKEN, ""));
|
||||
std::string encrypted_refresh_token;
|
||||
if (strlen(tmp_gg_secret) > 0)
|
||||
{
|
||||
std::string decrypted_secret;
|
||||
int ret = Decrypt(tmp_gg_secret, decrypted_secret);
|
||||
if (ret == 0)
|
||||
sprintf(setting.gg_account.refresh_token, "%s", tmp_gg_secret);
|
||||
else
|
||||
sprintf(setting.gg_account.refresh_token, "%s", decrypted_secret.c_str());
|
||||
Encrypt(setting.gg_account.refresh_token, encrypted_refresh_token);
|
||||
}
|
||||
WriteString(sites[i].c_str(), CONFIG_GOOGLE_REFRESH_TOKEN, encrypted_refresh_token.c_str());
|
||||
|
||||
SetClientType(&setting);
|
||||
site_settings.insert(std::make_pair(sites[i], setting));
|
||||
}
|
||||
|
||||
@@ -76,14 +280,12 @@ namespace CONFIG
|
||||
WriteString(CONFIG_GLOBAL, CONFIG_LAST_SITE, last_site);
|
||||
|
||||
remote_settings = &site_settings[std::string(last_site)];
|
||||
|
||||
for (int i = 0; i < MAX_FAVORITE_URLS; i++)
|
||||
{
|
||||
const char *index = std::to_string(i).c_str();
|
||||
sprintf(favorite_urls[i], "%s", ReadString(CONFIG_FAVORITE_URLS, index, ""));
|
||||
WriteString(CONFIG_FAVORITE_URLS, index, favorite_urls[i]);
|
||||
}
|
||||
|
||||
WriteIniFile(CONFIG_INI_FILE);
|
||||
CloseIniFile();
|
||||
}
|
||||
@@ -92,11 +294,50 @@ namespace CONFIG
|
||||
{
|
||||
OpenIniFile(CONFIG_INI_FILE);
|
||||
|
||||
std::string encrypted_text;
|
||||
if (strlen(remote_settings->password) > 0)
|
||||
Encrypt(remote_settings->password, encrypted_text);
|
||||
else
|
||||
encrypted_text = std::string(remote_settings->password);
|
||||
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);
|
||||
WriteString(last_site, CONFIG_REMOTE_SERVER_PASSWORD, encrypted_text.c_str());
|
||||
WriteInt(last_site, CONFIG_REMOTE_SERVER_HTTP_PORT, remote_settings->http_port);
|
||||
WriteBool(last_site, CONFIG_ENABLE_RPI, remote_settings->enable_rpi);
|
||||
WriteString(last_site, CONFIG_REMOTE_HTTP_SERVER_TYPE, remote_settings->http_server_type);
|
||||
WriteString(CONFIG_GLOBAL, CONFIG_LAST_SITE, last_site);
|
||||
WriteBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, auto_delete_tmp_pkg);
|
||||
std::string encrypted_token;
|
||||
if (strlen(remote_settings->gg_account.access_token) > 0)
|
||||
Encrypt(remote_settings->gg_account.access_token, encrypted_token);
|
||||
else
|
||||
encrypted_token = std::string(remote_settings->gg_account.access_token);
|
||||
WriteString(last_site, CONFIG_GOOGLE_ACCESS_TOKEN, encrypted_token.c_str());
|
||||
|
||||
std::string encrypted_refresh_token;
|
||||
if (strlen(remote_settings->gg_account.refresh_token) > 0)
|
||||
Encrypt(remote_settings->gg_account.refresh_token, encrypted_refresh_token);
|
||||
else
|
||||
encrypted_refresh_token = std::string(remote_settings->gg_account.refresh_token);
|
||||
WriteString(last_site, CONFIG_GOOGLE_REFRESH_TOKEN, encrypted_refresh_token.c_str());
|
||||
WriteLong(last_site, CONFIG_GOOGLE_TOKEN_EXPIRY, remote_settings->gg_account.token_expiry);
|
||||
WriteIniFile(CONFIG_INI_FILE);
|
||||
CloseIniFile();
|
||||
}
|
||||
|
||||
void SaveGlobalConfig()
|
||||
{
|
||||
OpenIniFile(CONFIG_INI_FILE);
|
||||
|
||||
std::string encrypted_secret;
|
||||
if (strlen(gg_app.client_secret) > 0)
|
||||
Encrypt(gg_app.client_secret, encrypted_secret);
|
||||
else
|
||||
encrypted_secret = std::string(gg_app.client_secret);
|
||||
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_SECRET, encrypted_secret.c_str());
|
||||
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_CLIENT_ID, gg_app.client_id);
|
||||
WriteString(CONFIG_GOOGLE, CONFIG_GOOGLE_PERMISSIONS, gg_app.permissions);
|
||||
WriteBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, auto_delete_tmp_pkg);
|
||||
WriteIniFile(CONFIG_INI_FILE);
|
||||
CloseIniFile();
|
||||
}
|
||||
@@ -109,52 +350,4 @@ namespace CONFIG
|
||||
WriteIniFile(CONFIG_INI_FILE);
|
||||
CloseIniFile();
|
||||
}
|
||||
|
||||
void ParseMultiValueString(const char *prefix_list, std::vector<std::string> &prefixes, bool toLower)
|
||||
{
|
||||
std::string prefix = "";
|
||||
int length = strlen(prefix_list);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
char c = prefix_list[i];
|
||||
if (c != ' ' && c != '\t' && c != ',')
|
||||
{
|
||||
if (toLower)
|
||||
{
|
||||
prefix += std::tolower(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix += c;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == ',' || i == length - 1)
|
||||
{
|
||||
prefixes.push_back(prefix);
|
||||
prefix = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetMultiValueString(std::vector<std::string> &multi_values)
|
||||
{
|
||||
std::string vts = std::string("");
|
||||
if (multi_values.size() > 0)
|
||||
{
|
||||
for (int i = 0; i < multi_values.size() - 1; i++)
|
||||
{
|
||||
vts.append(multi_values[i]).append(",");
|
||||
}
|
||||
vts.append(multi_values[multi_values.size() - 1]);
|
||||
}
|
||||
return vts;
|
||||
}
|
||||
|
||||
void RemoveFromMultiValues(std::vector<std::string> &multi_values, std::string value)
|
||||
{
|
||||
auto itr = std::find(multi_values.begin(), multi_values.end(), value);
|
||||
if (itr != multi_values.end())
|
||||
multi_values.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
+75
-5
@@ -3,25 +3,57 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include "remote_client.h"
|
||||
#include "clients/remote_client.h"
|
||||
|
||||
#define APP_ID "ezremote-client"
|
||||
#define DATA_PATH "/data/" APP_ID
|
||||
#define CONFIG_INI_FILE DATA_PATH "/config.ini"
|
||||
#define COOKIE_FILE DATA_PATH "/cookies.txt"
|
||||
#define TMP_EDITOR_FILE DATA_PATH "/tmp_editor.txt"
|
||||
|
||||
#define CONFIG_GLOBAL "Global"
|
||||
|
||||
#define CONFIG_GOOGLE "Google"
|
||||
#define CONFIG_GOOGLE_CLIENT_ID "google_client_id"
|
||||
#define CONFIG_GOOGLE_CLIENT_SECRET "google_client_secret"
|
||||
#define CONFIG_GOOGLE_PERMISSIONS "google_client_permissions"
|
||||
#define CONFIG_GOOGLE_ACCESS_TOKEN "google_access_token"
|
||||
#define CONFIG_GOOGLE_REFRESH_TOKEN "google_refresh_token"
|
||||
#define CONFIG_GOOGLE_TOKEN_EXPIRY "google_token_expiry"
|
||||
|
||||
#define GOOGLE_OAUTH_HOST "https://oauth2.googleapis.com"
|
||||
#define GOOGLE_AUTH_URL "https://accounts.google.com/o/oauth2/v2/auth"
|
||||
#define GOOGLE_API_URL "https://www.googleapis.com"
|
||||
#define GOOGLE_DRIVE_API_PATH "/drive/v2/files"
|
||||
#define GOOGLE_DRIVE_BASE_URL "https://drive.google.com"
|
||||
#define GOOGLE_PERM_DRIVE "drive"
|
||||
#define GOOGLE_PERM_DRIVE_APPDATA "drive.appdata"
|
||||
#define GOOGLE_PERM_DRIVE_FILE "drive.file"
|
||||
#define GOOGLE_PERM_DRIVE_METADATA "drive.metadata"
|
||||
#define GOOGLE_PERM_DRIVE_METADATA_RO "drive.metadata.readonly"
|
||||
#define GOOGLE_DEFAULT_PERMISSIONS GOOGLE_PERM_DRIVE
|
||||
|
||||
#define CONFIG_HTTP_SERVER "HttpServer"
|
||||
#define CONFIG_HTTP_SERVER_PORT "http_server_port"
|
||||
|
||||
#define CONFIG_REMOTE_SERVER_NAME "remote_server_name"
|
||||
#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
|
||||
#define CONFIG_MAX_EDIT_FILE_SIZE "max_edit_file_size"
|
||||
|
||||
#define CONFIG_LAST_SITE "last_site"
|
||||
#define CONFIG_AUTO_DELETE_TMP_PKG "auto_delete_tmp_pkg"
|
||||
@@ -31,15 +63,50 @@
|
||||
|
||||
#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"
|
||||
|
||||
#define MAX_EDIT_FILE_SIZE 32768
|
||||
|
||||
struct GoogleAccountInfo
|
||||
{
|
||||
char access_token[256];
|
||||
char refresh_token[256];
|
||||
uint64_t token_expiry;
|
||||
};
|
||||
|
||||
struct GoogleAppInfo
|
||||
{
|
||||
char client_id[140];
|
||||
char client_secret[64];
|
||||
char permissions[92];
|
||||
};
|
||||
|
||||
struct RemoteSettings
|
||||
{
|
||||
char site_name[32];
|
||||
char server[256];
|
||||
char username[33];
|
||||
char password[64];
|
||||
int http_port;
|
||||
ClientType type;
|
||||
bool enable_rpi;
|
||||
uint32_t supported_actions;
|
||||
char http_server_type[24];
|
||||
GoogleAccountInfo gg_account;
|
||||
};
|
||||
|
||||
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,17 +116,20 @@ 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;
|
||||
extern int max_edit_file_size;
|
||||
extern unsigned char cipher_key[32];
|
||||
extern unsigned char cipher_iv[16];
|
||||
extern GoogleAppInfo gg_app;
|
||||
|
||||
namespace CONFIG
|
||||
{
|
||||
void LoadConfig();
|
||||
void SaveConfig();
|
||||
void SaveGlobalConfig();
|
||||
void SaveFavoriteUrl(int index, char *url);
|
||||
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);
|
||||
void SetClientType(RemoteSettings *settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#include "crypt.h"
|
||||
|
||||
int openssl_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *ciphertext, int *ciphertext_len)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
int len;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if (!(ctx = EVP_CIPHER_CTX_new()))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Initialise the encryption operation. IMPORTANT - ensure you use a key
|
||||
* and IV size appropriate for your cipher
|
||||
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
|
||||
* IV size for *most* modes is the same as the block size. For AES this
|
||||
* is 128 bits
|
||||
*/
|
||||
if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Provide the message to be encrypted, and obtain the encrypted output.
|
||||
* EVP_EncryptUpdate can be called multiple times if necessary
|
||||
*/
|
||||
if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
|
||||
return 0;
|
||||
*ciphertext_len = len;
|
||||
|
||||
/*
|
||||
* Finalise the encryption. Further ciphertext bytes may be written at
|
||||
* this stage.
|
||||
*/
|
||||
if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
|
||||
return 0;
|
||||
*ciphertext_len += len;
|
||||
|
||||
/* Clean up */
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int openssl_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext, int *plaintext_len)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
int len;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if (!(ctx = EVP_CIPHER_CTX_new()))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Initialise the decryption operation. IMPORTANT - ensure you use a key
|
||||
* and IV size appropriate for your cipher
|
||||
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
|
||||
* IV size for *most* modes is the same as the block size. For AES this
|
||||
* is 128 bits
|
||||
*/
|
||||
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Provide the message to be decrypted, and obtain the plaintext output.
|
||||
* EVP_DecryptUpdate can be called multiple times if necessary.
|
||||
*/
|
||||
if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
|
||||
return 0;
|
||||
*plaintext_len = len;
|
||||
|
||||
/*
|
||||
* Finalise the decryption. Further plaintext bytes may be written at
|
||||
* this stage.
|
||||
*/
|
||||
if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
|
||||
return 0;
|
||||
*plaintext_len += len;
|
||||
|
||||
/* Clean up */
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int openssl_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *ciphertext, int *ciphertext_len);
|
||||
|
||||
int openssl_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext, int *plaintext_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+141
-31
@@ -7,10 +7,11 @@
|
||||
#include <filesystem>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#include "util.h"
|
||||
#include "lang.h"
|
||||
#include "rtc.h"
|
||||
#include "system.h"
|
||||
#include "windows.h"
|
||||
|
||||
namespace FS
|
||||
@@ -149,6 +150,68 @@ namespace FS
|
||||
return data;
|
||||
}
|
||||
|
||||
bool LoadText(std::vector<std::string> *lines, const std::string &path)
|
||||
{
|
||||
FILE *fd = fopen(path.c_str(), "r");
|
||||
if (fd == nullptr)
|
||||
return false;
|
||||
|
||||
lines->clear();
|
||||
|
||||
char buffer[1024];
|
||||
short bytes_read;
|
||||
std::vector<char> line = std::vector<char>(0);
|
||||
do
|
||||
{
|
||||
bytes_read = fread(buffer, sizeof(char), 1024, fd);
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
fclose(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (short i = 0; i < bytes_read; i++)
|
||||
{
|
||||
if (buffer[i] != '\r' && buffer[i] != '\n')
|
||||
{
|
||||
line.push_back(buffer[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines->push_back(std::string(line.data(), line.size()));
|
||||
line = std::vector<char>(0);
|
||||
if (buffer[i] == '\r' && buffer[i+1] == '\n')
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} while (bytes_read == 1024);
|
||||
if (line.size()>0)
|
||||
lines->push_back(std::string(line.data(), line.size()));
|
||||
|
||||
fclose(fd);
|
||||
if (lines->size() == 0)
|
||||
lines->push_back("");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveText(std::vector<std::string> *lines, const std::string &path)
|
||||
{
|
||||
FILE *fd = OpenRW(path);
|
||||
if (fd == nullptr)
|
||||
return false;
|
||||
|
||||
char nl[1] = {'\n'};
|
||||
for (int i=0; i < lines->size(); i++)
|
||||
{
|
||||
Write(fd, lines->at(i).c_str(), lines->at(i).length());
|
||||
Write(fd, nl, 1);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Save(const std::string &path, const void *data, uint32_t size)
|
||||
{
|
||||
FILE *fd = fopen(path.c_str(), "w+");
|
||||
@@ -176,10 +239,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 +273,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 +311,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 +385,7 @@ namespace FS
|
||||
{
|
||||
if (stop_activity)
|
||||
return 1;
|
||||
|
||||
|
||||
DIR *dfd = opendir(path.c_str());
|
||||
if (dfd != NULL)
|
||||
{
|
||||
@@ -386,32 +451,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 +459,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 +473,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;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -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);
|
||||
|
||||
@@ -47,13 +51,14 @@ namespace FS
|
||||
int Write(FILE *f, const void *buffer, uint32_t size);
|
||||
|
||||
std::vector<char> Load(const std::string &path);
|
||||
bool LoadText(std::vector<std::string> *lines, const std::string &path);
|
||||
bool SaveText(std::vector<std::string> *lines, const std::string &path);
|
||||
|
||||
void Save(const std::string &path, const void *data, uint32_t size);
|
||||
|
||||
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);
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ namespace GUI
|
||||
{
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
}
|
||||
|
||||
GImGui->GcCompactAll = true;
|
||||
ImGui_ImplSDLRenderer_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -10,9 +10,9 @@
|
||||
#include "ime_dialog.h"
|
||||
|
||||
static int ime_dialog_running = 0;
|
||||
static uint16_t inputTextBuffer[512+1];
|
||||
static uint8_t storebuffer[512];
|
||||
static char initial_ime_text[512];
|
||||
static uint16_t inputTextBuffer[1024+1];
|
||||
static uint8_t storebuffer[1024];
|
||||
static char initial_ime_text[1024];
|
||||
static int max_text_length;
|
||||
|
||||
static void utf16_to_utf8(const uint16_t *src, uint8_t *dst)
|
||||
@@ -83,7 +83,7 @@ namespace Dialog
|
||||
|
||||
uint16_t title[100];
|
||||
|
||||
if ((initialTextBuffer && strlen(initialTextBuffer) > 511) || (Title && strlen(Title) > 99))
|
||||
if ((initialTextBuffer && strlen(initialTextBuffer) > 1023) || (Title && strlen(Title) > 99))
|
||||
{
|
||||
ime_dialog_running = 0;
|
||||
return -1;
|
||||
@@ -95,7 +95,7 @@ namespace Dialog
|
||||
|
||||
if (initialTextBuffer)
|
||||
{
|
||||
snprintf(initial_ime_text, 511, "%s", initialTextBuffer);
|
||||
snprintf(initial_ime_text, 1023, "%s", initialTextBuffer);
|
||||
}
|
||||
|
||||
// converts the multibyte string src to a wide-character string starting at dest.
|
||||
|
||||
+34
-13
@@ -52,7 +52,7 @@
|
||||
|
||||
------------------------------------------------------------------------
|
||||
Copyright (c) 2000 Carsten Breuer
|
||||
/************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
/* defines for, or consts and inline functions for C++ */
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
struct ENTRY *Entry = NULL;
|
||||
struct ENTRY *CurEntry = NULL;
|
||||
char Result[4096] =
|
||||
char Result[520] =
|
||||
{""};
|
||||
FILE *IniFile;
|
||||
|
||||
@@ -84,7 +84,7 @@ struct ENTRY *MakeNewEntry(void);
|
||||
strupr -de-
|
||||
-------------------------------------------------------------------------
|
||||
Job : String to Uppercase 22.03.2001 Dieter Engelbrecht dieter@wintop.net
|
||||
/*========================================================================*/
|
||||
*========================================================================*/
|
||||
#ifdef DONT_HAVE_STRUPR
|
||||
/* DONT_HAVE_STRUPR is set when INI_REMOVE_CR is defined */
|
||||
void strupr(char *str)
|
||||
@@ -99,6 +99,7 @@ void strupr(char *str)
|
||||
str++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
/*=========================================================================
|
||||
@@ -109,10 +110,10 @@ void strupr(char *str)
|
||||
|
||||
Att : Be sure to call CloseIniFile to free all mem allocated during
|
||||
operation!
|
||||
/*========================================================================*/
|
||||
*========================================================================*/
|
||||
bool OpenIniFile(cchr *FileName)
|
||||
{
|
||||
char Str[5120];
|
||||
char Str[512];
|
||||
char *pStr;
|
||||
struct ENTRY *pEntry;
|
||||
|
||||
@@ -127,7 +128,7 @@ bool OpenIniFile(cchr *FileName)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (fgets(Str, 5120, IniFile) != NULL)
|
||||
while (fgets(Str, 512, IniFile) != NULL)
|
||||
{
|
||||
pStr = strchr(Str, '\n');
|
||||
if (pStr != NULL)
|
||||
@@ -191,7 +192,7 @@ bool OpenIniFile(cchr *FileName)
|
||||
Job : Frees the memory and closes the ini file without any
|
||||
modifications. If you want to write the file use
|
||||
WriteIniFile instead.
|
||||
/*========================================================================*/
|
||||
*========================================================================*/
|
||||
void CloseIniFile(void)
|
||||
{
|
||||
FreeAllMem();
|
||||
@@ -207,7 +208,7 @@ void CloseIniFile(void)
|
||||
-------------------------------------------------------------------------
|
||||
Job : Writes the iniFile to the disk and close it. Frees all memory
|
||||
allocated by WriteIniFile;
|
||||
/*========================================================================*/
|
||||
==========================================================================*/
|
||||
bool WriteIniFile(const char *FileName)
|
||||
{
|
||||
struct ENTRY *pEntry = Entry;
|
||||
@@ -242,7 +243,7 @@ bool WriteIniFile(const char *FileName)
|
||||
void WriteString(cchr *Section, cchr *pKey, cchr *Value)
|
||||
{
|
||||
EFIND List;
|
||||
char Str[5120];
|
||||
char Str[512];
|
||||
|
||||
if (ArePtrValid(Section, pKey, Value) == FALSE)
|
||||
{
|
||||
@@ -291,6 +292,16 @@ void WriteInt(cchr *Section, cchr *pKey, int Value)
|
||||
WriteString(Section, pKey, Val);
|
||||
}
|
||||
|
||||
/*=========================================================================
|
||||
WriteLong : Writes an long to the ini file
|
||||
*========================================================================*/
|
||||
void WriteLong(cchr *Section, cchr *pKey, long Value)
|
||||
{
|
||||
char Val[22]; /* 64bit maximum + sign + \0 */
|
||||
sprintf(Val, "%ld", Value);
|
||||
WriteString(Section, pKey, Val);
|
||||
}
|
||||
|
||||
/*=========================================================================
|
||||
WriteDouble : Writes a double to the ini file
|
||||
*========================================================================*/
|
||||
@@ -343,6 +354,16 @@ int ReadInt(cchr *Section, cchr *pKey, int Default)
|
||||
return (atoi(ReadString(Section, pKey, Val)));
|
||||
}
|
||||
|
||||
/*=========================================================================
|
||||
ReadLong : Reads a long from the ini file
|
||||
*========================================================================*/
|
||||
long ReadLong(cchr *Section, cchr *pKey, long Default)
|
||||
{
|
||||
char Val[22];
|
||||
sprintf(Val, "%ld", Default);
|
||||
return (atol(ReadString(Section, pKey, Val)));
|
||||
}
|
||||
|
||||
/*=========================================================================
|
||||
ReadDouble : Reads a double from the ini file
|
||||
*========================================================================*/
|
||||
@@ -463,7 +484,7 @@ bool FindpKey(cchr *Section, cchr *pKey, EFIND *List)
|
||||
{
|
||||
char Search[130];
|
||||
char Found[130];
|
||||
char Text[5120];
|
||||
char Text[512];
|
||||
char *pText;
|
||||
struct ENTRY *pEntry;
|
||||
List->pSec = NULL;
|
||||
@@ -595,7 +616,7 @@ bool AddItemAt(struct ENTRY *EntryAt, char Mode, cchr *Text)
|
||||
*========================================================================*/
|
||||
bool AddSectionAndpKey(cchr *Section, cchr *pKey, cchr *Value)
|
||||
{
|
||||
char Text[5120];
|
||||
char Text[512];
|
||||
sprintf(Text, "[%s]", Section);
|
||||
if (AddItem(tpSECTION, Text) == FALSE)
|
||||
{
|
||||
@@ -610,7 +631,7 @@ bool AddSectionAndpKey(cchr *Section, cchr *pKey, cchr *Value)
|
||||
*========================================================================*/
|
||||
void AddpKey(struct ENTRY *SecEntry, cchr *pKey, cchr *Value)
|
||||
{
|
||||
char Text[5120];
|
||||
char Text[512];
|
||||
sprintf(Text, "%s=%s", pKey, Value);
|
||||
AddItemAt(SecEntry, tpKEYVALUE, Text);
|
||||
}
|
||||
@@ -678,7 +699,7 @@ void GetSections(char *sections[])
|
||||
{
|
||||
if (pEntry->Type == tpSECTION)
|
||||
{
|
||||
sprintf(sections[i], pEntry->Text);
|
||||
sprintf(sections[i], "%s", pEntry->Text);
|
||||
i++;
|
||||
}
|
||||
pEntry = pEntry->pNext;
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
Author(s) : Carsten Breuer
|
||||
------------------------------------------------------------------------
|
||||
Copyright (c) 2000 by Carsten Breuer (C.Breuer@openwin.de)
|
||||
/************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
#ifndef INIFILE_H
|
||||
#define INIFILE_H
|
||||
@@ -54,11 +54,13 @@ bool OpenIniFile(cchr *FileName);
|
||||
|
||||
bool ReadBool(cchr *Section, cchr *Key, bool Default);
|
||||
int ReadInt(cchr *Section, cchr *Key, int Default);
|
||||
long ReadLong(cchr *Section, cchr *Key, long Default);
|
||||
double ReadDouble(cchr *Section, cchr *Key, double Default);
|
||||
cchr *ReadString(cchr *Section, cchr *Key, cchr *Default);
|
||||
|
||||
void WriteBool(cchr *Section, cchr *Key, bool Value);
|
||||
void WriteInt(cchr *Section, cchr *Key, int Value);
|
||||
void WriteLong(cchr *Section, cchr *Key, long Value);
|
||||
void WriteDouble(cchr *Section, cchr *Key, double Value);
|
||||
void WriteString(cchr *Section, cchr *Key, cchr *Value);
|
||||
|
||||
|
||||
+132
-24
@@ -10,15 +10,16 @@
|
||||
#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"
|
||||
#include "windows.h"
|
||||
#include "lang.h"
|
||||
#include "rtc.h"
|
||||
#include "system.h"
|
||||
#include "fs.h"
|
||||
#include "clients/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(¶ms, &task_id);
|
||||
else
|
||||
ret = sceBgftServiceIntDebugDownloadRegisterPkg(¶ms, &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,44 @@ 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 (auto_delete_tmp_pkg)
|
||||
FS::Rm(filename);
|
||||
}
|
||||
}
|
||||
else if (ret > 0) goto err;
|
||||
|
||||
ret = sceBgftServiceDownloadStartTask(task_id);
|
||||
if (ret)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
+140
-96
@@ -10,102 +10,146 @@ 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
|
||||
"Editor", // STR_EDITOR
|
||||
"Save", // STR_SAVE
|
||||
"Cannot edit files bigger than", // STR_MAX_EDIT_FILE_SIZE_MSG
|
||||
"Delete Selected Line", // STR_DELETE_LINE
|
||||
"Insert Below Selected Line", // STR_INSERT_LINE
|
||||
"Modified", // STR_MODIFIED
|
||||
"Failed to obtain an access token from", // STR_FAIL_GET_TOKEN_MSG
|
||||
"Login Success. You may close the browser and return to the application", // STR_GET_TOKEN_SUCCESS_MSG
|
||||
"See, edit, create, and delete all of your Google Drive files", // STR_PERM_DRIVE
|
||||
"See, create, and delete its own configuration data in your Google Drive", // STR_PERM_DRIVE_APPDATA
|
||||
"See, edit, create, and delete only the specific Google Drive files you use with this app", // STR_PERM_DRIVE_FILE
|
||||
"View and manage metadata of files in your Google Drive", // STR_PERM_DRIVE_METADATA
|
||||
"See information about your Google Drive files", // STR_PERM_DRIVE_METADATA_RO
|
||||
"Google login failed", // STR_GOOGLE_LOGIN_FAIL_MSG
|
||||
"Google login timed out", // STR_GOOGLE_LOGIN_TIMEOUT_MSG
|
||||
"New File", // STR_NEW_FILE
|
||||
"Settings", // STR_SETTINGS
|
||||
"Client ID", // STR_CLIENT_ID
|
||||
"Client Secret", // STR_CLIENT_SECRET
|
||||
"Global", // STR_GLOBAL
|
||||
"Google", // STR_GOOGLE
|
||||
};
|
||||
|
||||
bool needs_extended_font = false;
|
||||
|
||||
+46
-4
@@ -99,7 +99,49 @@
|
||||
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) \
|
||||
FUNC(STR_EDITOR) \
|
||||
FUNC(STR_SAVE) \
|
||||
FUNC(STR_MAX_EDIT_FILE_SIZE_MSG) \
|
||||
FUNC(STR_DELETE_LINE) \
|
||||
FUNC(STR_INSERT_LINE) \
|
||||
FUNC(STR_MODIFIED) \
|
||||
FUNC(STR_FAIL_GET_TOKEN_MSG) \
|
||||
FUNC(STR_GET_TOKEN_SUCCESS_MSG) \
|
||||
FUNC(STR_PERM_DRIVE) \
|
||||
FUNC(STR_PERM_DRIVE_APPDATA) \
|
||||
FUNC(STR_PERM_DRIVE_FILE) \
|
||||
FUNC(STR_PERM_DRIVE_METADATA) \
|
||||
FUNC(STR_PERM_DRIVE_METADATA_RO) \
|
||||
FUNC(STR_GOOGLE_LOGIN_FAIL_MSG) \
|
||||
FUNC(STR_GOOGLE_LOGIN_TIMEOUT_MSG) \
|
||||
FUNC(STR_NEW_FILE) \
|
||||
FUNC(STR_SETTINGS) \
|
||||
FUNC(STR_CLIENT_ID) \
|
||||
FUNC(STR_CLIENT_SECRET) \
|
||||
FUNC(STR_GLOBAL) \
|
||||
FUNC(STR_GOOGLE)
|
||||
|
||||
#define GET_VALUE(x) x,
|
||||
#define GET_STRING(x) #x,
|
||||
@@ -109,9 +151,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 138
|
||||
#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;
|
||||
|
||||
+59
-44
@@ -17,12 +17,14 @@
|
||||
#include "SDL2/SDL.h"
|
||||
#include "imgui_impl_sdl.h"
|
||||
#include "imgui_impl_sdlrenderer.h"
|
||||
#include "server/http_server.h"
|
||||
#include "clients/gdrive.h"
|
||||
#include "config.h"
|
||||
#include "lang.h"
|
||||
#include "gui.h"
|
||||
#include "util.h"
|
||||
#include "installer.h"
|
||||
#include "rtc.h"
|
||||
#include "system.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -97,6 +99,34 @@ 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
|
||||
0xF013, 0xF013, // settings
|
||||
0xF0ED, 0xF0ED, // download
|
||||
0xF0EE, 0xF0EE, // upload
|
||||
0xF56E, 0xF56E, // extract
|
||||
0xF56F, 0xF56F, // compress
|
||||
0xF0F6, 0xF0F6, // properties
|
||||
0xF112, 0xF112, // cancel
|
||||
0xF0DA, 0xF0DA, // arrow right
|
||||
0x0031, 0x0031, // 1
|
||||
0x004C, 0x004C, // L
|
||||
0x0052, 0x0052, // R
|
||||
0,
|
||||
};
|
||||
|
||||
std::string lang = std::string(language);
|
||||
int32_t lang_idx;
|
||||
sceSystemServiceParamGetInt( ORBIS_SYSTEM_SERVICE_PARAM_ID_LANG, &lang_idx );
|
||||
@@ -108,11 +138,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 +174,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();
|
||||
@@ -203,7 +246,7 @@ void InitImgui()
|
||||
colors[ImGuiCol_PlotHistogramHovered] = panelHoverColor;
|
||||
colors[ImGuiCol_ModalWindowDimBg] = bgColorBlur;
|
||||
colors[ImGuiCol_DragDropTarget] = bgColor;
|
||||
colors[ImGuiCol_NavHighlight] = bgColor;
|
||||
colors[ImGuiCol_NavHighlight] = titleColor;
|
||||
colors[ImGuiCol_Tab] = bgColor;
|
||||
colors[ImGuiCol_TabActive] = panelActiveColor;
|
||||
colors[ImGuiCol_TabUnfocused] = bgColor;
|
||||
@@ -232,49 +275,22 @@ 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;
|
||||
|
||||
CONFIG::LoadConfig();
|
||||
HttpServer::Start();
|
||||
|
||||
// Create a window context
|
||||
window = SDL_CreateWindow("main", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, FRAME_WIDTH, FRAME_HEIGHT, 0);
|
||||
@@ -298,17 +314,16 @@ int main()
|
||||
terminate();
|
||||
}
|
||||
|
||||
if (load_rtc_module() != 0)
|
||||
if (load_sys_modules() != 0)
|
||||
return 0;
|
||||
|
||||
atexit(terminate);
|
||||
|
||||
GUI::RenderLoop(renderer);
|
||||
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
ImGui::DestroyContext();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <orbis/libkernel.h>
|
||||
#include <orbis/Sysmodule.h>
|
||||
|
||||
#include "rtc.h"
|
||||
|
||||
int (*sceRtcGetTick)(const OrbisDateTime *inOrbisDateTime, OrbisTick *outTick);
|
||||
int (*sceRtcSetTick)(OrbisDateTime *outOrbisDateTime, const OrbisTick *inputTick);
|
||||
int (*sceRtcConvertLocalTimeToUtc)(const OrbisTick *local_time, OrbisTick *utc);
|
||||
int (*sceRtcConvertUtcToLocalTime)(const OrbisTick *utc, OrbisTick *local_time);
|
||||
int (*sceRtcGetCurrentClockLocalTime)(OrbisDateTime *time);
|
||||
|
||||
void convertUtcToLocalTime(const OrbisDateTime *utc, OrbisDateTime *local_time)
|
||||
{
|
||||
OrbisTick utc_tick;
|
||||
OrbisTick local_tick;
|
||||
sceRtcGetTick(utc, &utc_tick);
|
||||
sceRtcConvertUtcToLocalTime(&utc_tick, &local_tick);
|
||||
sceRtcSetTick(local_time, &local_tick);
|
||||
}
|
||||
|
||||
void convertLocalTimeToUtc(const OrbisDateTime *local_time, OrbisDateTime *utc)
|
||||
{
|
||||
OrbisTick utc_tick;
|
||||
OrbisTick local_tick;
|
||||
sceRtcGetTick(local_time, &local_tick);
|
||||
sceRtcConvertLocalTimeToUtc(&local_tick, &utc_tick);
|
||||
sceRtcSetTick(utc, &utc_tick);
|
||||
}
|
||||
|
||||
int load_rtc_module()
|
||||
{
|
||||
int rtc_handle = sceKernelLoadStartModule("/system/common/lib/libSceRtc.sprx", 0, NULL, 0, NULL, NULL);
|
||||
if (rtc_handle == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(rtc_handle, "sceRtcGetTick", (void **)&sceRtcGetTick);
|
||||
if (sceRtcGetTick == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(rtc_handle, "sceRtcSetTick", (void **)&sceRtcSetTick);
|
||||
if (sceRtcSetTick == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(rtc_handle, "sceRtcConvertLocalTimeToUtc", (void **)&sceRtcConvertLocalTimeToUtc);
|
||||
if (sceRtcConvertLocalTimeToUtc == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(rtc_handle, "sceRtcConvertUtcToLocalTime", (void **)&sceRtcConvertUtcToLocalTime);
|
||||
if (sceRtcConvertUtcToLocalTime == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(rtc_handle, "sceRtcGetCurrentClockLocalTime", (void **)&sceRtcGetCurrentClockLocalTime);
|
||||
if (sceRtcGetCurrentClockLocalTime == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
#include <string>
|
||||
#include <json-c/json.h>
|
||||
#include "http/httplib.h"
|
||||
#include "server/http_server.h"
|
||||
#include "clients/gdrive.h"
|
||||
#include "config.h"
|
||||
#include "windows.h"
|
||||
#include "lang.h"
|
||||
#include "system.h"
|
||||
|
||||
#define SERVER_CERT_FILE "/app0/assets/certs/domain.crt"
|
||||
#define SERVER_PRIVATE_KEY_FILE "/app0/assets/certs/domain.key"
|
||||
#define SERVER_PRIVATE_KEY_PASSWORD "12345678"
|
||||
|
||||
using namespace httplib;
|
||||
SSLServer *svr;
|
||||
int http_server_port = 8080;
|
||||
|
||||
namespace HttpServer
|
||||
{
|
||||
std::string dump_headers(const Headers &headers)
|
||||
{
|
||||
std::string s;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
for (auto it = headers.begin(); it != headers.end(); ++it)
|
||||
{
|
||||
const auto &x = *it;
|
||||
snprintf(buf, sizeof(buf), "%s: %s\n", x.first.c_str(), x.second.c_str());
|
||||
s += buf;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string log(const Request &req, const Response &res)
|
||||
{
|
||||
std::string s;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
s += "================================\n";
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s %s %s", req.method.c_str(),
|
||||
req.version.c_str(), req.path.c_str());
|
||||
s += buf;
|
||||
|
||||
std::string query;
|
||||
for (auto it = req.params.begin(); it != req.params.end(); ++it)
|
||||
{
|
||||
const auto &x = *it;
|
||||
snprintf(buf, sizeof(buf), "%c%s=%s",
|
||||
(it == req.params.begin()) ? '?' : '&', x.first.c_str(),
|
||||
x.second.c_str());
|
||||
query += buf;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s\n", query.c_str());
|
||||
s += buf;
|
||||
|
||||
s += dump_headers(req.headers);
|
||||
|
||||
s += "--------------------------------\n";
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d %s\n", res.status, res.version.c_str());
|
||||
s += buf;
|
||||
s += dump_headers(res.headers);
|
||||
s += "\n";
|
||||
|
||||
if (!res.body.empty())
|
||||
{
|
||||
s += res.body;
|
||||
}
|
||||
|
||||
s += "\n";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void *ServerThread(void *argp)
|
||||
{
|
||||
svr->Get("/google_auth", [](const Request &req, Response &res)
|
||||
{
|
||||
std::string auth_code = req.get_param_value("code");
|
||||
Client client(GOOGLE_OAUTH_HOST);
|
||||
client.set_follow_location(true);
|
||||
client.enable_server_certificate_verification(false);
|
||||
|
||||
std::string url = std::string("/token");
|
||||
std::string post_data = std::string("code=") + auth_code +
|
||||
"&client_id=" + gg_app.client_id +
|
||||
"&client_secret=" + gg_app.client_secret +
|
||||
"&redirect_uri=https%3A//localhost%3A" + std::to_string(http_server_port) + "/google_auth"
|
||||
"&grant_type=authorization_code";
|
||||
|
||||
if (auto result = client.Post(url, post_data.c_str(), post_data.length(), "application/x-www-form-urlencoded"))
|
||||
{
|
||||
if (HTTP_SUCCESS(result->status))
|
||||
{
|
||||
json_object *jobj = json_tokener_parse(result.value().body.c_str());
|
||||
enum json_type type;
|
||||
json_object_object_foreach(jobj, key, val)
|
||||
{
|
||||
if (strcmp(key, "access_token")==0)
|
||||
snprintf(remote_settings->gg_account.access_token, 255, "%s", json_object_get_string(val));
|
||||
else if (strcmp(key, "refresh_token")==0)
|
||||
snprintf(remote_settings->gg_account.refresh_token, 255, "%s", json_object_get_string(val));
|
||||
else if (strcmp(key, "expires_in")==0)
|
||||
{
|
||||
OrbisTick tick;
|
||||
sceRtcGetCurrentTick(&tick);
|
||||
remote_settings->gg_account.token_expiry = tick.mytick + (json_object_get_uint64(val)*1000000);
|
||||
}
|
||||
}
|
||||
CONFIG::SaveConfig();
|
||||
login_state = 1;
|
||||
res.set_content(lang_strings[STR_GET_TOKEN_SUCCESS_MSG], "text/plain");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
login_state = -1;
|
||||
std::string str = std::string(lang_strings[STR_FAIL_GET_TOKEN_MSG]) + " Google";
|
||||
res.set_content(str.c_str(), "text/plain");
|
||||
}
|
||||
}
|
||||
login_state = -1;
|
||||
std::string str = std::string(lang_strings[STR_FAIL_GET_TOKEN_MSG]) + " Google";
|
||||
res.set_content(str.c_str(), "text/plain");
|
||||
});
|
||||
|
||||
svr->Get("/stop", [&](const Request & /*req*/, Response & /*res*/)
|
||||
{
|
||||
svr->stop();
|
||||
});
|
||||
|
||||
svr->set_error_handler([](const Request & /*req*/, Response &res)
|
||||
{
|
||||
const char *fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
|
||||
char buf[BUFSIZ];
|
||||
snprintf(buf, sizeof(buf), fmt, res.status);
|
||||
res.set_content(buf, "text/html");
|
||||
});
|
||||
|
||||
/*
|
||||
svr->set_logger([](const Request &req, const Response &res)
|
||||
{
|
||||
dbglogger_log("%s", log(req, res).c_str());
|
||||
});
|
||||
*/
|
||||
|
||||
svr->listen("127.0.0.1", http_server_port);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (svr == nullptr)
|
||||
svr = new SSLServer(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE, nullptr, nullptr, SERVER_PRIVATE_KEY_PASSWORD);
|
||||
if (!svr->is_valid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
int ret = pthread_create(&http_server_thid, NULL, ServerThread, NULL);
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
if (svr != nullptr)
|
||||
svr->stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef HTTP_SERVER_H
|
||||
#define HTTP_SERVER_H
|
||||
|
||||
#include "http/httplib.h"
|
||||
|
||||
using namespace httplib;
|
||||
extern SSLServer *svr;
|
||||
|
||||
static pthread_t http_server_thid;
|
||||
extern int http_server_port;
|
||||
|
||||
namespace HttpServer
|
||||
{
|
||||
void *ServerThread(void *argp);
|
||||
void Start();
|
||||
void Stop();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
#include <stdlib.h>
|
||||
#include <orbis/libkernel.h>
|
||||
#include <orbis/Sysmodule.h>
|
||||
|
||||
#include "system.h"
|
||||
|
||||
int (*sceRtcGetTick)(const OrbisDateTime *inOrbisDateTime, OrbisTick *outTick);
|
||||
int (*sceRtcSetTick)(OrbisDateTime *outOrbisDateTime, const OrbisTick *inputTick);
|
||||
int (*sceRtcConvertLocalTimeToUtc)(const OrbisTick *local_time, OrbisTick *utc);
|
||||
int (*sceRtcConvertUtcToLocalTime)(const OrbisTick *utc, OrbisTick *local_time);
|
||||
int (*sceRtcGetCurrentClockLocalTime)(OrbisDateTime *time);
|
||||
int (*sceRtcGetCurrentTick)(OrbisTick *outTick);
|
||||
unsigned int (*sceRtcGetTickResolution)();
|
||||
int (*sceShellUIUtilLaunchByUri)(const char *uri, SceShellUIUtilLaunchByUriParam *param);
|
||||
int (*sceShellUIUtilInitialize)();
|
||||
|
||||
void convertUtcToLocalTime(const OrbisDateTime *utc, OrbisDateTime *local_time)
|
||||
{
|
||||
OrbisTick utc_tick;
|
||||
OrbisTick local_tick;
|
||||
sceRtcGetTick(utc, &utc_tick);
|
||||
sceRtcConvertUtcToLocalTime(&utc_tick, &local_tick);
|
||||
sceRtcSetTick(local_time, &local_tick);
|
||||
}
|
||||
|
||||
void convertLocalTimeToUtc(const OrbisDateTime *local_time, OrbisDateTime *utc)
|
||||
{
|
||||
OrbisTick utc_tick;
|
||||
OrbisTick local_tick;
|
||||
sceRtcGetTick(local_time, &local_tick);
|
||||
sceRtcConvertLocalTimeToUtc(&local_tick, &utc_tick);
|
||||
sceRtcSetTick(utc, &utc_tick);
|
||||
}
|
||||
|
||||
int load_sys_modules()
|
||||
{
|
||||
int handle = sceKernelLoadStartModule("/system/common/lib/libSceRtc.sprx", 0, NULL, 0, NULL, NULL);
|
||||
if (handle == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceRtcGetTick", (void **)&sceRtcGetTick);
|
||||
if (sceRtcGetTick == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceRtcSetTick", (void **)&sceRtcSetTick);
|
||||
if (sceRtcSetTick == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceRtcConvertLocalTimeToUtc", (void **)&sceRtcConvertLocalTimeToUtc);
|
||||
if (sceRtcConvertLocalTimeToUtc == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceRtcConvertUtcToLocalTime", (void **)&sceRtcConvertUtcToLocalTime);
|
||||
if (sceRtcConvertUtcToLocalTime == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceRtcGetCurrentClockLocalTime", (void **)&sceRtcGetCurrentClockLocalTime);
|
||||
if (sceRtcGetCurrentClockLocalTime == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceRtcGetCurrentTick", (void **)&sceRtcGetCurrentTick);
|
||||
if (sceRtcGetCurrentTick == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceRtcGetTickResolution", (void **)&sceRtcGetTickResolution);
|
||||
if (sceRtcGetTickResolution == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle = sceKernelLoadStartModule("/system/common/lib/libSceShellUIUtil.sprx", 0, NULL, 0, 0, 0);
|
||||
if (handle == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceShellUIUtilInitialize", (void **)&sceShellUIUtilInitialize);
|
||||
if (sceShellUIUtilInitialize == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelDlsym(handle, "sceShellUIUtilLaunchByUri", (void **)&sceShellUIUtilLaunchByUri);
|
||||
if (sceShellUIUtilLaunchByUri == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sceShellUIUtilInitialize() < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,6 +4,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int size;
|
||||
uint32_t userId;
|
||||
} SceShellUIUtilLaunchByUriParam;
|
||||
|
||||
typedef struct OrbisTick {
|
||||
uint64_t mytick;
|
||||
} OrbisTick;
|
||||
@@ -22,9 +28,13 @@ extern int (*sceRtcGetTick)(const OrbisDateTime *inOrbisDateTime, OrbisTick *out
|
||||
extern int (*sceRtcSetTick)(OrbisDateTime *outOrbisDateTime, const OrbisTick *inputTick);
|
||||
extern int (*sceRtcConvertLocalTimeToUtc)(const OrbisTick *local_time, OrbisTick *utc);
|
||||
extern int (*sceRtcConvertUtcToLocalTime)(const OrbisTick *utc, OrbisTick *local_time);
|
||||
extern int (*sceRtcGetCurrentClockLocalTime)(OrbisDateTime *time) ;
|
||||
extern int (*sceRtcGetCurrentClockLocalTime)(OrbisDateTime *time);
|
||||
extern int (*sceRtcGetCurrentTick)(OrbisTick *outTick);
|
||||
extern unsigned int (*sceRtcGetTickResolution)();
|
||||
extern int (*sceShellUIUtilLaunchByUri)(const char *uri, SceShellUIUtilLaunchByUriParam *param);
|
||||
extern int (*sceShellUIUtilInitialize)();
|
||||
|
||||
int load_rtc_module();
|
||||
int load_sys_modules();
|
||||
void convertUtcToLocalTime(const OrbisDateTime *utc, OrbisDateTime *local_time);
|
||||
void convertLocalTimeToUtc(const OrbisDateTime *local_time, OrbisDateTime *utc);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <algorithm>
|
||||
#include <stdarg.h>
|
||||
#include <orbis/libkernel.h>
|
||||
#include "lang.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
@@ -46,6 +47,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;
|
||||
@@ -62,5 +82,23 @@ namespace Util
|
||||
sceKernelSendNotificationRequest(0, &request, sizeof(request), 0);
|
||||
}
|
||||
|
||||
static inline void SetupPreviousFolder(const std::string &path, 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, "%s", "..");
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -380,6 +380,7 @@ namespace WebDAV
|
||||
dict_t options();
|
||||
|
||||
long http_code;
|
||||
int result;
|
||||
int check_enabled = 0;
|
||||
};
|
||||
} // namespace WebDAV
|
||||
|
||||
+684
-139
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
@@ -38,6 +41,7 @@ extern ACTIONS action_to_take;
|
||||
extern bool file_transfering;
|
||||
extern char extract_zip_folder[];
|
||||
extern char zip_file_path[];
|
||||
extern std::vector<std::string> edit_buffer;
|
||||
|
||||
static ImVector<ImRect> s_GroupPanelLabelStack;
|
||||
|
||||
@@ -203,6 +207,9 @@ 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);
|
||||
void AfterEditorCallback(int ime_result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+100
-4
@@ -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 "system.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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user