Compare commits

..

60 Commits

Author SHA1 Message Date
cy33hc d34df2cf94 Update README.md 2023-03-14 11:59:03 -07:00
Chee Yee f6cf00974b changed RPI install message 2023-03-13 22:35:03 -07:00
Chee Yee 9788b7e963 disable upload if remote server does not support it 2023-03-13 22:24:20 -07:00
Chee Yee aa9ef34991 some bug fixes related to RPI and add option to show hidden files 2023-03-13 22:07:57 -07:00
Chee Yee fc96b76260 fix for bug #7 2023-03-13 19:39:14 -07:00
Chee Yee c54fc8fcbc Merge branch 'master' of github.com:cy33hc/ps4-ezremote-client 2023-03-13 04:56:12 -07:00
Chee Yee 5ca56b47df add copy/paste function in text editor 2023-03-13 04:56:04 -07:00
cy33hc 05d253edd8 Update README.md 2023-03-11 18:36:16 -08:00
cy33hc d752dd8fed Update README.md 2023-03-11 18:35:08 -08:00
cy33hc 45320ed2ca Update README.md 2023-03-10 23:30:36 -08:00
cy33hc 8aef5d0233 Update README.md 2023-03-10 21:08:40 -08:00
cy33hc 2c9d31fbcc Update README.md 2023-03-10 18:05:41 -08:00
Chee Yee a4510e0b47 missed set the date of files 2023-03-10 01:35:53 -08:00
Chee Yee d6ec9ac1a5 more fixes 2023-03-10 01:13:49 -08:00
Chee Yee 2975f736de fix copy of empty folders 2023-03-10 01:05:48 -08:00
Chee Yee 9a9308244c Merge branch 'master' of github.com:cy33hc/ps4-ezremote-client 2023-03-09 23:55:19 -08:00
Chee Yee 649f6daac2 open fine in binary mode 2023-03-09 23:55:12 -08:00
cy33hc cc541c6da5 Update README.md 2023-03-09 23:07:49 -08:00
Chee Yee ec7b845bdc add SFTP support 2023-03-09 23:05:58 -08:00
Chee Yee eed0e5193b forgot to delete object 2023-03-03 23:51:59 -08:00
Chee Yee 9d7e46dcc6 clear activity_message 2023-03-02 22:52:28 -08:00
Chee Yee 2164443969 update strings 2023-03-02 22:34:41 -08:00
Chee Yee d3f8cdc774 add missing string 2023-03-02 22:27:58 -08:00
Chee Yee f58e9fdecd put dialog at correct position 2023-03-02 22:20:30 -08:00
Chee Yee ea768a3528 Merge branch 'master' of github.com:cy33hc/ps4-ezremote-client 2023-03-02 22:06:48 -08:00
Chee Yee 6371c6fd29 fix crash when client_id is empty 2023-03-02 22:06:37 -08:00
cy33hc 456b1aa075 Update README.md 2023-03-02 19:40:15 -08:00
cy33hc e654667621 Update README.md 2023-03-02 19:39:43 -08:00
cy33hc a4ac55ca88 Update README.md 2023-03-01 21:35:16 -08:00
cy33hc f0c291eb0c Update README.md 2023-03-01 21:32:09 -08:00
cy33hc d96734aeeb Update README.md 2023-03-01 21:30:48 -08:00
cy33hc 4aa6b7c02a Update README.md 2023-03-01 21:30:15 -08:00
cy33hc c632f0d7cb Update README.md 2023-03-01 21:29:54 -08:00
Chee Yee 686caec0f7 undo imguilistclipper 2023-03-01 19:32:25 -08:00
cy33hc 4c5429902a Merge pull request #4 from cy33hc/gdrive_client
Gdrive client
2023-03-01 04:31:38 -08:00
Chee Yee 7378736b3f add ability to browse shared with me files 2023-03-01 03:27:53 -08:00
Chee Yee 05c7207b7c add ability to create new empty file 2023-03-01 00:57:57 -08:00
Chee Yee cd26aeaa77 add gui for google settings 2023-02-28 23:26:55 -08:00
Chee Yee 5aef0f648d fix crash 2023-02-28 19:46:05 -08:00
Chee Yee 2ee0e9ae74 allow multiple google accounts 2023-02-28 19:19:17 -08:00
Chee Yee c6143be6f0 fix type 2023-02-28 03:15:53 -08:00
Chee Yee 23c8c678f1 disable cut/copy/paste for gdrive 2023-02-28 03:15:11 -08:00
Chee Yee f314c94ddc fix a crash 2023-02-28 03:10:08 -08:00
Chee Yee e3c908bfbf fixed upload of duplicate 2023-02-28 02:27:55 -08:00
Chee Yee d772b3d3f5 upload working but creates duplicates if existing file exists 2023-02-28 00:49:23 -08:00
Chee Yee 837258afda download working and improve transfer speed 2023-02-27 00:59:08 -08:00
Chee Yee 98c71d3411 dont need to refresh token from start 2023-02-27 00:30:58 -08:00
Chee Yee b156fea640 fix token refresh and added rename/delete/mkdir functions 2023-02-27 00:24:02 -08:00
Chee Yee 7508ec12da fix url for refresh token 2023-02-26 05:20:50 -08:00
Chee Yee ad43c48454 implement dir listing and rename 2023-02-26 05:08:39 -08:00
Chee Yee 32ba34fefb initial gdrive client 2023-02-26 00:17:19 -08:00
Chee Yee ba3c2d5600 replace all original key with account/mac values 2023-02-24 20:45:15 -08:00
Chee Yee a18971a62f combine user account_id and mac for encrypt key 2023-02-24 20:27:29 -08:00
Chee Yee 5e6710c815 encrypt passwords 2023-02-24 20:01:42 -08:00
Chee Yee 89c8fd652a remove sample code 2023-02-23 23:50:01 -08:00
Chee Yee 951f1f8f45 load methods for ShellUI sys modules 2023-02-23 23:44:43 -08:00
Chee Yee b0ca95338f Merge branch 'master' of github.com:cy33hc/ps4-ezremote-client 2023-02-23 04:16:58 -08:00
Chee Yee e519343164 add a simple text editor 2023-02-23 04:16:49 -08:00
Chee Yee 1cfeece53f move imgui code to folder 2023-02-22 15:49:27 -08:00
cy33hc fc60358a1e Update README.md 2023-02-22 09:12:07 -08:00
77 changed files with 3234 additions and 463 deletions
+23 -17
View File
@@ -10,9 +10,16 @@ add_definitions(-DCPPHTTPLIB_OPENSSL_SUPPORT)
include_directories(
source
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/web/callback.cpp
source/web/fsinfo.cpp
@@ -21,15 +28,21 @@ add_executable(ezremote_client
source/web/urn.cpp
source/webdav/client.cpp
source/http/httplib.cpp
source/http/baseclient.cpp
source/http/apache.cpp
source/http/iis.cpp
source/http/nginx.cpp
source/http/npxserve.cpp
source/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/clients/sftpclient.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
@@ -38,22 +51,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.01" 32 0)
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.05" 32 0)
target_link_libraries(ezremote_client
c
@@ -72,6 +77,8 @@ target_link_libraries(ezremote_client
minizip
un7zip
unrar
json-c
ssh2
kernel
SceShellCoreUtil
SceSysmodule
@@ -87,5 +94,4 @@ target_link_libraries(ezremote_client
SceNet
SceBgft
SceAppInstUtil
SceLncUtil
)
+25 -6
View File
@@ -1,16 +1,22 @@
# ezRemote Client
ezRemote Client is an application that allows you to connect the PS4 to remote FTP, SMB, WebDAV and HTTP servers to transfer files. The interface is inspired by Filezilla client which provides a commander like GUI.
ezRemote Client is an application that allows you to connect the PS4 to remote FTP/SFTP, SMB, WebDAV, HTTP servers and Google Drive to transfer files. The interface is inspired by Filezilla client which provides a commander like GUI.
![Preview](/screenshot.jpg)
## Usage
To distinguish between FTP, SMB, WebDAV or HTTP, the URL must be prefix with **ftp://**, **smb://**, **webdav://**, **webdavs://**, **http://** and **https://**
To distinguish between FTP, SMB, WebDAV or HTTP, the URL must be prefix with **ftp://**, **sftp://**, **smb://**, **webdav://**, **webdavs://**, **http://** and **https://**
- The url format for FTP is
```
ftp://hostname[:port]
sftp://hostname[:port]
- hostname can be the textual hostname or an IP address. hostname is required
- port is optional and defaults to 21 if not provided
- port is optional and defaults to 21(ftp) and 22(sftp) if not provided
```
For Secure FTP (sftp), use of identity files is possible. Put both the **id_rsa** and **id_rsa.pub** into a folder in the PS4 hard drive. Then in the password field in the UI, instead of putting a password reference the folder where id_rsa and id_rsa.pub is place. Prefix the folder with **"file://"** and **do not** password protect the identity file.
```
Example: If you had placed the id_rsa and id_rsa.pub files into the folder /data/ezremote-client,
then in the password field enter file:///data/ezremote-client
```
- The url format for SMB is
@@ -40,7 +46,9 @@ To distinguish between FTP, SMB, WebDAV or HTTP, the URL must be prefix with **f
- 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.
@@ -54,15 +62,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
- Support for connecting to Http Servers like (Apache/Nginx,Microsoft IIS, Serve) with directory listings to download or install pkg.
- 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 for files on PS4 local drive or usb or WebDAV Server.
- 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. Limited to edit files over 32kb and limited to edit lines up to 1023 characters. If you try edit lines longer then 1023 characters, it will be truncated.
## Installation
Copy the **ezremote_client.pkg** in to a FAT32 format usb drive then install from package installer
@@ -161,12 +172,20 @@ Build and install libsmb2 - https://github.com/cy33hc/libsmb2/blob/ps4/README_PS
Build and install lexbor - https://github.com/lexbor/lexbor.git
Build and install libssh2 - https://www.libssh2.org/
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
Build libjson-c - https://github.com/json-c/json-c
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
```
source /opt/pacbrew/ps4/openorbis/ps4vars.sh
+22
View File
@@ -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-----
+17
View File
@@ -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-----
+7
View File
@@ -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 = *
+30
View File
@@ -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-----
+22
View File
@@ -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-----
+30
View File
@@ -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-----
+1
View File
@@ -0,0 +1 @@
4A5531796DA232C2C3F0B937F9F7C651FC5E8FA5
Binary file not shown.
+26 -2
View File
@@ -107,11 +107,35 @@ 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_REMOTE_NOT_SUPPORT_MSG=Remote package installation is not supported for protected servers.
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_DOWNLOAD_INSTALL_MSG=Remote Package Install not possible. Would you like to download package and install instead?
STR_CHECKING_REMOTE_SERVER_MSG=Checking remote server for Remote Package Install.
STR_ENABLE_RPI=RPI
STR_ENABLE_RPI_FTP_SMB_MSG=This option enables Remote Package Installation. This requires a HTTP Server setup on the same host sharing the same folder with anonymous access.
STR_ENABLE_RPI_WEBDAV_MSG=This option enables Remote Package Installation. This requires the Server with anonymous access that does not need username/password.
STR_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_MODIFIED=Modified
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
STR_GOOGLE=Google
STR_COPY_LINE=Copy selected line
STR_PASTE_LINE=Paste into selected line
STR_SHOW_HIDDEN_FILES=Show hidden files
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#define ICON_OF_SQUARE "\xee\x83\x8b" // U+E0CB
#define ICON_OF_TRIANGLE "\xee\x83\x9e" // U+E0CB
+70 -14
View File
@@ -4,6 +4,15 @@
#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 "clients/sftpclient.h"
#include "common.h"
#include "fs.h"
#include "config.h"
@@ -14,14 +23,7 @@
#include "installer.h"
#include "web/request.hpp"
#include "web/urn.hpp"
#include "rtc.h"
#include "ftpclient.h"
#include "smbclient.h"
#include "webdavclient.h"
#include "http/apache.h"
#include "http/nginx.h"
#include "http/npxserve.h"
#include "http/iis.h"
#include "system.h"
#include "zip_util.h"
namespace Actions
@@ -819,7 +821,7 @@ namespace Actions
void *ExtractZipThread(void *argp)
{
FS::MkDirs(extract_zip_folder, true);
FS::MkDirs(extract_zip_folder);
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));
@@ -1107,7 +1109,13 @@ 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();
@@ -1134,6 +1142,10 @@ namespace Actions
client->SetCallbackXferFunction(FtpCallback);
remoteclient = client;
}
else if (strncmp(remote_settings->server, "sftp://", 7) == 0)
{
remoteclient = new SFTPClient();
}
else
{
sprintf(status_message, "%s", lang_strings[STR_PROTOCOL_NOT_SUPPORTED]);
@@ -1173,6 +1185,7 @@ namespace Actions
remote_files.clear();
sprintf(remote_directory, "%s", "/");
sprintf(status_message, "%s", "");
delete remoteclient;
remoteclient = nullptr;
}
}
@@ -1262,7 +1275,7 @@ namespace Actions
{
int err;
std::vector<DirEntry> entries = FS::ListDir(src.path, &err);
FS::MkDirs(dest, true);
FS::MkDirs(dest);
for (int i = 0; i < entries.size(); i++)
{
if (stop_activity)
@@ -1277,7 +1290,7 @@ namespace Actions
if (strcmp(entries[i].name, "..") == 0)
continue;
FS::MkDirs(new_path, true);
FS::MkDirs(new_path);
ret = CopyOrMove(entries[i], new_path, isCopy);
if (ret <= 0)
{
@@ -1526,7 +1539,7 @@ namespace Actions
if (strcmp(entries[i].name, "..") == 0)
continue;
FS::MkDirs(new_path, true);
remoteclient->Mkdir(new_path);
ret = CopyRemotePath(entries[i], new_path);
if (ret <= 0)
{
@@ -1594,7 +1607,7 @@ namespace Actions
}
else
{
int res = CopyRemotePath(*it, remote_directory);
int res = CopyRemotePath(*it, remote_directory);
if (res == 0)
sprintf(status_message, "%s - %s", it->name, lang_strings[STR_FAIL_COPY_MSG]);
}
@@ -1639,4 +1652,47 @@ namespace Actions
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());
}
}
+7 -1
View File
@@ -44,9 +44,13 @@ enum ACTIONS
ACTION_LOCAL_CUT,
ACTION_LOCAL_COPY,
ACTION_LOCAL_PASTE,
ACTION_LOCAL_EDIT,
ACTION_REMOTE_CUT,
ACTION_REMOTE_COPY,
ACTION_REMOTE_PASTE
ACTION_REMOTE_PASTE,
ACTION_REMOTE_EDIT,
ACTION_NEW_LOCAL_FILE,
ACTION_NEW_REMOTE_FILE
};
enum OverWriteType
@@ -104,6 +108,8 @@ namespace Actions
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
View File
@@ -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
@@ -2,8 +2,8 @@
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include "common.h"
#include "remote_client.h"
#include "http/apache.h"
#include "clients/remote_client.h"
#include "clients/apache.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
@@ -4,9 +4,9 @@
#include <string>
#include <vector>
#include "http/httplib.h"
#include "http/baseclient.h"
#include "clients/remote_client.h"
#include "clients/baseclient.h"
#include "common.h"
#include "remote_client.h"
class ApacheClient : public BaseClient
{
@@ -1,9 +1,10 @@
#include <lexbor/html/parser.h>
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include <curl/curl.h>
#include "common.h"
#include "remote_client.h"
#include "http/npxserve.h"
#include "clients/remote_client.h"
#include "clients/baseclient.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
@@ -76,12 +77,12 @@ int BaseClient::Get(const std::string &outputfile, const std::string &path, uint
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;
}))
[&](const char *data, size_t data_length)
{
file_stream.write(data, data_length);
bytes_transfered += data_length;
return true;
}))
{
file_stream.close();
return 1;
@@ -126,21 +127,22 @@ int BaseClient::Move(const std::string &from, const std::string &to)
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);
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;
}))
[&](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;
if (body.size() < len)
return 0;
memcpy(buffer, body.data(), len);
return 1;
}
@@ -161,21 +163,7 @@ std::vector<DirEntry> BaseClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
Util::SetupPreviousFolder(path, &entry);
out.push_back(entry);
return out;
@@ -187,7 +175,7 @@ std::string BaseClient::GetPath(std::string ppath1, std::string ppath2)
std::string path2 = ppath2;
path1 = Util::Trim(Util::Trim(path1, " "), "/");
path2 = Util::Trim(Util::Trim(path2, " "), "/");
path1 = this->base_path + "/" + path1 + "/" + path2;
path1 = this->base_path + ((this->base_path.length() > 0) ? "/" : "") + path1 + "/" + path2;
return path1;
}
@@ -242,3 +230,38 @@ 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 "";
}
@@ -4,8 +4,8 @@
#include <string>
#include <vector>
#include "http/httplib.h"
#include "clients/remote_client.h"
#include "common.h"
#include "remote_client.h"
class BaseClient : public RemoteClient
{
@@ -33,6 +33,8 @@ public:
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;
@@ -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,21 +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;
entry.selectable = false;
Util::SetupPreviousFolder(path, &entry);
out.push_back(entry);
ftphandle *nData;
@@ -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
+741
View File
@@ -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 *)&param.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(), &param);
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);
}
+44
View File
@@ -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
+3 -17
View File
@@ -2,8 +2,8 @@
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include "common.h"
#include "remote_client.h"
#include "http/iis.h"
#include "clients/remote_client.h"
#include "clients/iis.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
@@ -16,21 +16,7 @@ std::vector<DirEntry> IISClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
Util::SetupPreviousFolder(path, &entry);
out.push_back(entry);
if (auto res = client->Get(GetFullPath(path)))
+2 -2
View File
@@ -4,9 +4,9 @@
#include <string>
#include <vector>
#include "http/httplib.h"
#include "http/baseclient.h"
#include "clients/remote_client.h"
#include "clients/baseclient.h"
#include "common.h"
#include "remote_client.h"
class IISClient : public BaseClient
{
@@ -4,8 +4,8 @@
#include <map>
#include <vector>
#include "common.h"
#include "remote_client.h"
#include "http/nginx.h"
#include "clients/remote_client.h"
#include "clients/nginx.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
@@ -23,21 +23,7 @@ std::vector<DirEntry> NginxClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
Util::SetupPreviousFolder(path, &entry);
out.push_back(entry);
if (auto res = client->Get(GetFullPath(path)))
@@ -95,9 +81,10 @@ std::vector<DirEntry> NginxClient::ListDir(const std::string &path)
tmp = std::string((const char *)value, value_len);
if (tmp.compare("a") == 0)
{
value = lxb_dom_node_text_content(node, &value_len);
value = lxb_dom_element_get_attribute(lxb_dom_interface_element(node), (const lxb_char_t *)"href", 4, &value_len);
tmp = std::string((const char *)value, value_len);
tmp = Util::Rtrim(tmp, "/");
tmp = BaseClient::DecodeUrl(tmp);
if (tmp.compare("..") != 0)
{
sprintf(entry.directory, "%s", path.c_str());
@@ -4,9 +4,9 @@
#include <string>
#include <vector>
#include "http/httplib.h"
#include "http/baseclient.h"
#include "clients/baseclient.h"
#include "common.h"
#include "remote_client.h"
#include "clients/remote_client.h"
class NginxClient : public BaseClient
{
@@ -2,8 +2,8 @@
#include <lexbor/dom/interfaces/element.h>
#include <fstream>
#include "common.h"
#include "remote_client.h"
#include "http/npxserve.h"
#include "clients/remote_client.h"
#include "clients/npxserve.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
@@ -16,21 +16,7 @@ std::vector<DirEntry> NpxServeClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path[path.length() - 1] == '/' && path.length() > 1)
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
entry.selectable = false;
Util::SetupPreviousFolder(path, &entry);
out.push_back(entry);
if (auto res = client->Get(GetFullPath(path)))
@@ -4,9 +4,9 @@
#include <string>
#include <vector>
#include "http/httplib.h"
#include "http/baseclient.h"
#include "clients/baseclient.h"
#include "clients/remote_client.h"
#include "common.h"
#include "remote_client.h"
class NpxServeClient : public BaseClient
{
@@ -17,7 +17,9 @@ enum RemoteActions
REMOTE_ACTION_DOWNLOAD = 64,
REMOTE_ACTION_UPLOAD = 128,
REMOTE_ACTION_INSTALL = 256,
REMOTE_ACTION_ALL = 511
REMOTE_ACTION_EDIT = 512,
REMOTE_ACTION_NEW_FILE = 1024,
REMOTE_ACTION_ALL = 2047
};
enum ClientType
@@ -26,6 +28,7 @@ enum ClientType
CLIENT_TYPE_SMB,
CLIENT_TYPE_WEBDAV,
CLIENT_TYPE_HTTP_SERVER,
CLIENT_TYPE_GOOGLE,
CLINET_TYPE_UNKNOWN
};
+587
View File
@@ -0,0 +1,587 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include "common.h"
#include "clients/remote_client.h"
#include "clients/sftpclient.h"
#include "fs.h"
#include "lang.h"
#include "util.h"
#include "windows.h"
#include "system.h"
#define FTP_CLIENT_BUFSIZ 1048576
SFTPClient::SFTPClient()
{
session = nullptr;
sftp_session = nullptr;
sock = 0;
};
SFTPClient::~SFTPClient(){};
int SFTPClient::Connect(const std::string &url, const std::string &username, const std::string &password)
{
int port = 22;
std::string host = url.substr(7);
size_t colon_pos = host.find(":");
if (colon_pos != std::string::npos)
{
port = std::atoi(host.substr(colon_pos + 1).c_str());
host = host.substr(0, colon_pos);
}
struct hostent *he;
struct in_addr **addr_list;
char ip[20];
int i;
if (strcmp(host.c_str(), "localhost") == 0)
{
sprintf(ip, "%s", "127.0.0.1");
}
else
{
if ((he = gethostbyname(host.c_str())) == NULL)
{
sprintf(this->response, "%s", lang_strings[STR_COULD_NOT_RESOLVE_HOST]);
return 0;
}
addr_list = (struct in_addr **)he->h_addr_list;
for (i = 0; addr_list[i] != NULL; i++)
{
strcpy(ip, inet_ntoa(*addr_list[i]));
break;
}
}
in_addr dst_addr;
sockaddr_in server_addr;
int on = 1;
int32_t retval;
memset(&server_addr, 0, sizeof(server_addr));
inet_pton(AF_INET, ip, (void *)&dst_addr);
server_addr.sin_addr = dst_addr;
server_addr.sin_port = htons(port);
server_addr.sin_family = AF_INET;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
retval = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on));
int const size = FTP_CLIENT_BUFSIZ;
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) == -1)
{
close(sock);
return 0;
}
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) == -1)
{
close(sock);
return 0;
}
if (connect(sock, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr_in)) != 0)
{
sprintf(this->response, "%s", "Failed to connect!");
return 0;
}
/* Create a session instance
*/
session = libssh2_session_init();
libssh2_session_set_blocking(session, 1);
libssh2_keepalive_config(session, 1, 5);
if (!session)
{
sprintf(this->response, "%s", lang_strings[STR_FAILED]);
return 0;
}
/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
sceKernelUsleep(100000);
int rc = libssh2_session_handshake(session, sock);
if (rc)
{
sprintf(this->response, "Failed SSL handshake %d", rc);
return 0;
}
/* At this point we havn't yet authenticated. The first thing to do
* is check the hostkey's fingerprint against our known hosts Your app
* may have it hard coded, may go to a file, may present it to the
* user, that's your call
*/
const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
/* check what authentication methods are available */
char *userauthlist = libssh2_userauth_list(session, username.c_str(), username.length());
int auth_pw = 0;
if (strstr(userauthlist, "password") != NULL)
{
auth_pw |= 1;
}
if (strstr(userauthlist, "keyboard-interactive") != NULL)
{
auth_pw |= 2;
}
if (strstr(userauthlist, "publickey") != NULL)
{
auth_pw |= 4;
}
bool use_identity = password.find("file://") != std::string::npos;
if (auth_pw & 1 && !use_identity)
{
/* We could authenticate via password */
if (libssh2_userauth_password(session, username.c_str(), password.c_str()))
{
sprintf(this->response, "%s", "Authentication by password failed!");
goto shutdown;
}
}
else if (auth_pw & 4 && use_identity)
{
/* Or by public key */
std::string publickey = password.substr(7) + "/id_rsa.pub";
std::string privatekey = password.substr(7) + "/id_rsa";
if (!FS::FileExists(publickey.c_str()))
{
sprintf(response, "SSH public key %s is not found", publickey.c_str());
goto shutdown;
}
if (!FS::FileExists(privatekey.c_str()))
{
sprintf(response, "SSH private key %s is not found", privatekey.c_str());
goto shutdown;
}
if (libssh2_userauth_publickey_fromfile(session, username.c_str(), publickey.c_str(), privatekey.c_str(), ""))
{
sprintf(this->response, "%s", "Authentication by public key failed!");
goto shutdown;
}
}
else
{
sprintf(this->response, "%s", "No supported authentication methods found!");
goto shutdown;
}
sftp_session = libssh2_sftp_init(session);
this->connected = true;
return 1;
shutdown:
libssh2_session_disconnect(session, "Normal Shutdown");
libssh2_session_free(session);
close(sock);
libssh2_exit();
session = nullptr;
sock = 0;
return 0;
}
int SFTPClient::Mkdir(const std::string &path)
{
int rc = libssh2_sftp_mkdir(sftp_session, path.c_str(),
LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IXGRP | LIBSSH2_SFTP_S_IROTH | LIBSSH2_SFTP_S_IXOTH);
if (rc)
{
return 0;
}
return 1;
}
int SFTPClient::Rmdir(const std::string &path, bool recursive)
{
if (stop_activity)
return 1;
std::vector<DirEntry> list = ListDir(path);
int ret;
for (int i = 0; i < list.size(); i++)
{
if (stop_activity)
return 1;
if (list[i].isDir && recursive)
{
if (strcmp(list[i].name, "..") == 0)
continue;
ret = Rmdir(list[i].path, recursive);
if (ret == 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], list[i].path);
return 0;
}
}
else
{
sprintf(activity_message, "%s %s\n", lang_strings[STR_DELETING], list[i].path);
ret = Delete(list[i].path);
if (ret == 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_FILE_MSG], list[i].path);
return 0;
}
}
}
ret = Rmdir(path);
return 1;
}
int SFTPClient::Rmdir(const std::string &path)
{
int rc = libssh2_sftp_rmdir(sftp_session, path.c_str());
if (rc)
{
return 0;
}
return 1;
}
int SFTPClient::Size(const std::string &path, int64_t *size)
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
int rc = libssh2_sftp_stat(sftp_session, path.c_str(), &attrs);
if (rc)
{
return 0;
}
*size = attrs.filesize;
return 1;
}
int SFTPClient::Get(const std::string &outputfile, const std::string &path, uint64_t offset)
{
if (!Size(path, &bytes_to_download))
{
return 0;
}
LIBSSH2_SFTP_HANDLE *sftp_handle = libssh2_sftp_open(sftp_session, path.c_str(), LIBSSH2_FXF_READ, 0);
if (!sftp_handle)
{
sprintf(response, "Unable to open file with SFTP: %ld", libssh2_sftp_last_error(sftp_session));
return 0;
}
FILE *out = FS::Create(outputfile);
if (out == NULL)
{
sprintf(response, "%s", lang_strings[STR_FAILED]);
return 0;
}
char *buff = (char *)malloc(FTP_CLIENT_BUFSIZ);
int rc, count = 0;
bytes_transfered = 0;
do
{
rc = libssh2_sftp_read(sftp_handle, buff, FTP_CLIENT_BUFSIZ);
if (rc > 0)
{
bytes_transfered += rc;
FS::Write(out, buff, rc);
}
else
{
break;
}
} while (1);
FS::Close(out);
libssh2_sftp_close(sftp_handle);
return 1;
}
int SFTPClient::Put(const std::string &inputfile, const std::string &path, uint64_t offset)
{
char *ptr, *buff;
int rc;
bytes_to_download = FS::GetSize(inputfile);
if (bytes_to_download < 0)
{
sprintf(response, "%s", lang_strings[STR_FAILED]);
return 0;
}
FILE *in = FS::OpenRead(inputfile);
if (in == NULL)
{
sprintf(response, "%s", lang_strings[STR_FAILED]);
return 0;
}
LIBSSH2_SFTP_HANDLE *sftp_handle = libssh2_sftp_open(sftp_session, path.c_str(),
LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC,
LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR |
LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IROTH);
if (!sftp_handle)
{
sprintf(response, "%s", "Unable to open file with SFTP");
return 0;
}
buff = (char *)malloc(FTP_CLIENT_BUFSIZ);
int nread, count = 0;
bytes_transfered = 0;
do
{
nread = FS::Read(in, buff, FTP_CLIENT_BUFSIZ);
if (nread <= 0)
{
/* end of file */
break;
}
ptr = buff;
do
{
/* write data in a loop until we block */
rc = libssh2_sftp_write(sftp_handle, ptr, nread);
if (rc < 0)
break;
ptr += rc;
nread -= rc;
bytes_transfered += rc;
} while (nread);
} while (rc > 0);
libssh2_sftp_close(sftp_handle);
FS::Close(in);
free(buff);
return 1;
}
int SFTPClient::Rename(const std::string &src, const std::string &dst)
{
int rc = libssh2_sftp_rename_ex(sftp_session, src.c_str(), src.length(),
dst.c_str(), dst.length(), LIBSSH2_SFTP_RENAME_ATOMIC | LIBSSH2_SFTP_RENAME_NATIVE);
if (rc)
{
return 0;
}
return 1;
}
int SFTPClient::Delete(const std::string &path)
{
int rc = libssh2_sftp_unlink(sftp_session, path.c_str());
if (rc)
{
return 0;
}
return 1;
}
int SFTPClient::Copy(const std::string &from, const std::string &to)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int SFTPClient::Move(const std::string &from, const std::string &to)
{
sprintf(this->response, "%s", lang_strings[STR_UNSUPPORTED_OPERATION_MSG]);
return 0;
}
int SFTPClient::Head(const std::string &path, void *buffer, uint64_t len)
{
if (!Size(path.c_str(), &bytes_to_download))
{
return 0;
}
LIBSSH2_SFTP_HANDLE *sftp_handle = libssh2_sftp_open(sftp_session, path.c_str(), LIBSSH2_FXF_READ, 0);
if (!sftp_handle)
{
return 0;
}
int count = libssh2_sftp_read(sftp_handle, (char *)buffer, len);
libssh2_sftp_close(sftp_handle);
if (count != len)
return 0;
return 1;
}
bool SFTPClient::FileExists(const std::string &path)
{
int64_t file_size;
return Size(path, &file_size);
}
std::vector<DirEntry> SFTPClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
Util::SetupPreviousFolder(path, &entry);
out.push_back(entry);
/* Request a dir listing via SFTP */
LIBSSH2_SFTP_HANDLE *sftp_handle = libssh2_sftp_opendir(sftp_session, path.c_str());
if (!sftp_handle)
{
return out;
}
do
{
char mem[512];
LIBSSH2_SFTP_ATTRIBUTES attrs;
DirEntry entry;
memset(&entry, 0, sizeof(entry));
entry.selectable = true;
/* loop until we fail */
int rc = libssh2_sftp_readdir(sftp_handle, mem, sizeof(mem), &attrs);
if (rc > 0)
{
std::string new_path = std::string(mem, rc);
if (new_path.compare(".") == 0 || new_path.compare("..") == 0)
continue;
;
if (!show_hidden_files && new_path[0] == '.')
continue;
sprintf(entry.name, "%s", new_path.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);
}
if (LIBSSH2_SFTP_S_ISDIR(attrs.permissions))
{
entry.isDir = true;
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
}
else if (LIBSSH2_SFTP_S_ISREG(attrs.permissions))
{
entry.file_size = attrs.filesize;
DirEntry::SetDisplaySize(&entry);
entry.isDir = false;
}
else if (LIBSSH2_SFTP_S_ISLNK(attrs.permissions))
{
entry.file_size = 0;
sprintf(entry.display_size, "%s", lang_strings[STR_LINK]);
entry.isDir = false;
entry.isLink = true;
entry.selectable = false;
}
else // skip any files that aren't regular files/directory
{
entry.file_size = attrs.filesize;
DirEntry::SetDisplaySize(&entry);
entry.isDir = false;
entry.selectable = false;
}
struct tm tm = *localtime((const time_t *)&attrs.mtime);
OrbisDateTime gmt;
OrbisDateTime lt;
gmt.day = tm.tm_mday;
gmt.month = tm.tm_mon + 1;
gmt.year = tm.tm_year + 1900;
gmt.hour = tm.tm_hour;
gmt.minute = tm.tm_min;
gmt.second = tm.tm_sec;
convertUtcToLocalTime(&gmt, &lt);
entry.modified.day = lt.day;
entry.modified.month = lt.month;
entry.modified.year = lt.year;
entry.modified.hours = lt.hour;
entry.modified.minutes = lt.minute;
entry.modified.seconds = lt.second;
out.push_back(entry);
}
else
break;
} while (1);
return out;
}
std::string SFTPClient::GetPath(std::string ppath1, std::string ppath2)
{
std::string path1 = ppath1;
std::string path2 = ppath2;
path1 = Util::Rtrim(Util::Trim(path1, " "), "/");
path2 = Util::Rtrim(Util::Trim(path2, " "), "/");
path1 = path1 + "/" + path2;
return path1;
}
bool SFTPClient::IsConnected()
{
return this->connected;
}
bool SFTPClient::Ping()
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
int rc = libssh2_sftp_stat(sftp_session, "/", &attrs);
if (rc)
{
this->connected = false;
return false;
}
return true;
}
const char *SFTPClient::LastResponse()
{
return this->response;
}
int SFTPClient::Quit()
{
if (sftp_session != nullptr)
libssh2_sftp_shutdown(sftp_session);
if (session != nullptr)
{
libssh2_session_disconnect(session, "Normal Shutdown");
libssh2_session_free(session);
close(sock);
libssh2_exit();
}
session = nullptr;
sftp_session = nullptr;
sock = 0;
return 1;
}
ClientType SFTPClient::clientType()
{
return CLIENT_TYPE_FTP;
}
uint32_t SFTPClient::SupportedActions()
{
return REMOTE_ACTION_ALL ^ REMOTE_ACTION_CUT ^ REMOTE_ACTION_COPY ^ REMOTE_ACTION_PASTE;
}
+46
View File
@@ -0,0 +1,46 @@
#ifndef SFTPCLIENT_H
#define SFTPCLIENT_H
#include <libssh2.h>
#include <libssh2_sftp.h>
#include <string>
#include <vector>
#include "clients/remote_client.h"
#include "common.h"
class SFTPClient : public RemoteClient
{
public:
SFTPClient();
~SFTPClient();
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 Rmdir(const std::string &path);
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);
bool IsConnected();
bool Ping();
const char *LastResponse();
int Quit();
ClientType clientType();
uint32_t SupportedActions();
protected:
LIBSSH2_SESSION *session;
LIBSSH2_SFTP *sftp_session;
int sock;
char response[512];
bool connected = false;
};
#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"
@@ -396,21 +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;
entry.selectable = false;
Util::SetupPreviousFolder(path, &entry);
out.push_back(entry);
struct smb2dir *dir;
@@ -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
@@ -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))
@@ -256,21 +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;
entry.selectable = false;
Util::SetupPreviousFolder(path, &entry);
out.push_back(entry);
WebDAV::dict_items_t files = client->list(path);
@@ -6,8 +6,8 @@
#include <vector>
#include <regex>
#include "webdav/client.hpp"
#include "clients/remote_client.h"
#include "common.h"
#include "remote_client.h"
namespace WebDAV
{
+2
View File
@@ -5,6 +5,8 @@
#include <vector>
#include <string.h>
#define HTTP_SUCCESS(x) (x >= 200 && x < 300)
typedef struct
{
uint16_t year;
+198 -56
View File
@@ -1,12 +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"
{
@@ -27,10 +32,47 @@ std::map<std::string, RemoteSettings> site_settings;
PackageUrlInfo install_pkg_url;
char favorite_urls[MAX_FAVORITE_URLS][512];
bool auto_delete_tmp_pkg;
int max_edit_file_size;
GoogleAppInfo gg_app;
bool show_hidden_files;
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)
{
@@ -38,7 +80,7 @@ namespace CONFIG
{
setting->type = CLIENT_TYPE_SMB;
}
else if (strncmp(setting->server, "ftp://", 6) == 0)
else if (strncmp(setting->server, "ftp://", 6) == 0 || strncmp(setting->server, "sftp://", 7) == 0)
{
setting->type = CLIENT_TYPE_FTP;
}
@@ -46,6 +88,10 @@ namespace CONFIG
{
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;
@@ -56,8 +102,37 @@ namespace CONFIG
}
}
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);
@@ -66,7 +141,7 @@ namespace CONFIG
sites = {"Site 1", "Site 2", "Site 3", "Site 4", "Site 5", "Site 6", "Site 7", "Site 8", "Site 9", "Site 10",
"Site 11", "Site 12", "Site 13", "Site 14", "Site 15", "Site 16", "Site 17", "Site 18", "Site 19", "Site 20"};
http_servers = { HTTP_SERVER_APACHE, HTTP_SERVER_MS_IIS, HTTP_SERVER_NGINX, HTTP_SERVER_NPX_SERVE};
http_servers = {HTTP_SERVER_APACHE, HTTP_SERVER_MS_IIS, HTTP_SERVER_NGINX, HTTP_SERVER_NPX_SERVE};
OpenIniFile(CONFIG_INI_FILE);
@@ -91,13 +166,47 @@ 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);
show_hidden_files = ReadBool(CONFIG_GLOBAL, CONFIG_SHOW_HIDDEN_FILES, false);
WriteBool(CONFIG_GLOBAL, CONFIG_SHOW_HIDDEN_FILES, show_hidden_files);
// 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)
if (conversion_needed && strlen(setting.server) > 0)
{
std::string tmp = std::string(setting.server);
tmp = std::regex_replace(tmp, std::regex("http://"), "webdav://");
@@ -109,8 +218,20 @@ namespace CONFIG
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[128];
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);
@@ -121,6 +242,40 @@ namespace CONFIG
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));
}
@@ -129,14 +284,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();
}
@@ -145,14 +298,51 @@ 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);
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);
WriteBool(CONFIG_GLOBAL, CONFIG_SHOW_HIDDEN_FILES, show_hidden_files);
WriteIniFile(CONFIG_INI_FILE);
CloseIniFile();
}
@@ -165,52 +355,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);
}
}
+53 -5
View File
@@ -3,18 +3,45 @@
#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_SHOW_HIDDEN_FILES "show_hidden_files"
#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"
@@ -28,6 +55,7 @@
#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"
@@ -42,17 +70,34 @@
#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[25];
char password[128];
int http_port;
ClientType type;
bool enable_rpi;
uint32_t supported_actions;
char http_server_type[24];
GoogleAccountInfo gg_account;
};
struct PackageUrlInfo
@@ -76,15 +121,18 @@ extern RemoteClient *remoteclient;
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;
extern bool show_hidden_files;
namespace CONFIG
{
void LoadConfig();
void SaveConfig();
void SaveGlobalConfig();
void SaveFavoriteUrl(int index, char *url);
void SetClientType(RemoteSettings *settings);
void RemoveFromMultiValues(std::vector<std::string> &multi_values, std::string value);
void ParseMultiValueString(const char *prefix_list, std::vector<std::string> &prefixes, bool toLower);
std::string GetMultiValueString(std::vector<std::string> &multi_values);
}
#endif
+87
View File
@@ -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;
}
+18
View File
@@ -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
+63 -1
View File
@@ -11,7 +11,7 @@
#include "util.h"
#include "lang.h"
#include "rtc.h"
#include "system.h"
#include "windows.h"
namespace FS
@@ -150,6 +150,68 @@ namespace FS
return data;
}
bool LoadText(std::vector<std::string> *lines, const std::string &path)
{
FILE *fd = fopen(path.c_str(), "rb");
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+");
+3
View File
@@ -51,6 +51,9 @@ 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);
+1 -1
View File
@@ -23,7 +23,7 @@ namespace GUI
{
ImGui_ImplSDL2_ProcessEvent(&event);
}
GImGui->GcCompactAll = true;
ImGui_ImplSDLRenderer_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
+4
View File
@@ -932,6 +932,10 @@ socket_t create_client_socket(
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(write_timeout_usec);
setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));
#endif
int const size = 1048576;
setsockopt(sock2, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
setsockopt(sock2, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
}
error = Error::Success;
+3
View File
@@ -1637,6 +1637,9 @@ inline void default_socket_options(socket_t sock) {
sizeof(yes));
#endif
#endif
int const size = 1048576;
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
}
template <class Rep, class Period>
+5 -5
View File
@@ -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.
@@ -1200,7 +1200,7 @@ typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitAr
#define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1
#define ImGuiKey_NavGamepadActivate ImGuiKey_GamepadFaceDown
#define ImGuiKey_NavGamepadCancel ImGuiKey_GamepadFaceRight
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft
#define ImGuiKey_NavGamepadMenu ImGuiKey_Keypad0
#define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp
enum ImGuiInputEventType
+34 -13
View File
@@ -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
View File
@@ -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);
+24 -12
View File
@@ -17,9 +17,9 @@
#include "config.h"
#include "windows.h"
#include "lang.h"
#include "rtc.h"
#include "system.h"
#include "fs.h"
#include "webdavclient.h"
#include "clients/webdavclient.h"
#define BGFT_HEAP_SIZE (1 * 1024 * 1024)
@@ -97,7 +97,7 @@ namespace INSTALLER
s_bgft_initialized = false;
}
std::string getRemoteUrl(const std::string filename)
std::string getRemoteUrl(const std::string filename, bool encodeUrl)
{
if (remoteclient->clientType() == CLIENT_TYPE_WEBDAV || remoteclient->clientType() == CLIENT_TYPE_HTTP_SERVER)
{
@@ -109,11 +109,14 @@ namespace INSTALLER
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);
if (encodeUrl)
{
Web::Urn::Path uri(path);
CURL *curl = curl_easy_init();
path = uri.quote(curl);
curl_easy_cleanup(curl);
}
return host + path;
}
else
@@ -129,9 +132,12 @@ namespace INSTALLER
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);
if (encodeUrl)
{
Web::Urn::Path uri(path);
CURL *curl = curl_easy_init();
path = uri.quote(curl);
}
return "http://" + host + ":" + std::to_string(remote_settings->http_port) + path;
}
@@ -161,6 +167,7 @@ namespace INSTALLER
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]);
@@ -173,7 +180,7 @@ namespace INSTALLER
int InstallRemotePkg(const std::string &filename, pkg_header *header)
{
std::string url = getRemoteUrl(filename);
std::string url = getRemoteUrl(filename, true);
if (url.empty())
return 0;
@@ -333,6 +340,11 @@ namespace INSTALLER
goto err;
goto retry;
}
else
{
if (auto_delete_tmp_pkg)
FS::Rm(filename);
}
}
else if (ret > 0) goto err;
+1 -1
View File
@@ -111,7 +111,7 @@ namespace INSTALLER
void Exit(void);
bool canInstallRemotePkg(const std::string &url);
std::string getRemoteUrl(const std::string filename);
std::string getRemoteUrl(const std::string filename, bool encodeUrl=false);
int InstallRemotePkg(const std::string &filename, pkg_header *header);
int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install=false);
}
+27 -3
View File
@@ -119,7 +119,7 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
"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 package installation is not supported for protected servers.", // STR_REMOTE_NOT_SUPPORT_MSG
"Remote HTTP Server not reachable.", // STR_CANNOT_CONNECT_REMOTE_MSG
"Remote Package Install not possible. Would you like to download package and install?", // STR_DOWNLOAD_INSTALL_MSG
"Checking remote server for Remote Package Install.", // STR_CHECKING_REMOTE_SERVER_MSG
@@ -127,8 +127,32 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
"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
"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
"Copy selected line", // STR_COPY_LINE
"Paste into selected line", // STR_PASTE_LINE
"Show hidden files", // STR_SHOW_HIDDEN_FILES
};
bool needs_extended_font = false;
+26 -2
View File
@@ -120,7 +120,31 @@
FUNC(STR_ENABLE_RPI) \
FUNC(STR_ENABLE_RPI_FTP_SMB_MSG) \
FUNC(STR_ENABLE_RPI_WEBDAV_MSG) \
FUNC(STR_FILES)
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) \
FUNC(STR_COPY_LINE) \
FUNC(STR_PASTE_LINE) \
FUNC(STR_SHOW_HIDDEN_FILES)
#define GET_VALUE(x) x,
#define GET_STRING(x) #x,
@@ -130,7 +154,7 @@ enum
FOREACH_STR(GET_VALUE)
};
#define LANG_STRINGS_NUM 117
#define LANG_STRINGS_NUM 141
#define LANG_ID_SIZE 64
#define LANG_STR_SIZE 384
extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE];
+21 -9
View File
@@ -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,7 +99,7 @@ void InitImgui()
0,
};
static const ImWchar icons[] {
static const ImWchar fa_icons[] {
0xF07B, 0xF07B, // folder
0xF65E, 0xF65E, // new folder
0xF15B, 0xF15B, // file
@@ -111,13 +113,23 @@ void InitImgui()
0xE0AC, 0xE0AC, // rename
0xE5A1, 0xE5A1, // delete
0xF002, 0xF002, // search
0x2699, 0x2699, // settings
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,
};
static const ImWchar of_icons[] {
0xE0CB, 0xE0CB, // square
0xE0DE, 0xE0DE, // triangle
0,
};
@@ -171,7 +183,8 @@ void InitImgui()
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->AddFontFromFileTTF("/app0/assets/fonts/fa-solid-900.ttf", 20.0f, &config, fa_icons);
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/OpenFontIcons.ttf", 20.0f, &config, of_icons);
io.Fonts->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;
io.Fonts->Build();
@@ -240,7 +253,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;
@@ -284,6 +297,7 @@ int main()
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);
@@ -300,24 +314,22 @@ int main()
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer_Init(renderer);
ImGui_ImplSDLRenderer_CreateFontsTexture();
ImGui_ImplSDL2_DisableButton(SDL_CONTROLLER_BUTTON_X, true);
if (!initialize_jbc())
{
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;
}
}
-70
View File
@@ -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;
}
+171
View File
@@ -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();
}
}
+19
View File
@@ -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
+106
View File
@@ -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;
}
+12 -2
View File
@@ -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);
+19
View File
@@ -6,6 +6,7 @@
#include <algorithm>
#include <stdarg.h>
#include <orbis/libkernel.h>
#include "lang.h"
namespace Util
{
@@ -81,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
+426 -89
View File
@@ -13,6 +13,9 @@
#include "lang.h"
#include "ime_dialog.h"
#include "IconsFontAwesome6.h"
#include "OpenFontIcons.h"
#include "server/http_server.h"
#include "clients/gdrive.h"
extern "C"
{
@@ -51,7 +54,7 @@ char local_file_to_select[256];
char remote_file_to_select[256];
char local_filter[32];
char remote_filter[32];
char editor_text[1024];
char dialog_editor_text[1024];
char activity_message[1024];
int selected_browser = 0;
int saved_selected_browser;
@@ -64,8 +67,20 @@ bool select_url_inprogress = false;
int favorite_url_idx = 0;
char extract_zip_folder[256];
char zip_file_path[384];
char label[256];
bool show_settings = false;
// Editor variables
std::vector<std::string> edit_buffer;
bool editor_inprogress = false;
char edit_line[1024];
int edit_line_num = 0;
char label[256];
bool editor_modified = false;
char edit_file[256];
int edit_line_to_select = -1;
std::string copy_text;
// Overwrite dialog variables
bool dont_prompt_overwrite = false;
bool dont_prompt_overwrite_cb = false;
int confirm_transfer_state = -1;
@@ -312,6 +327,8 @@ namespace Windows
int width = 550;
if (remote_settings->type == CLIENT_TYPE_HTTP_SERVER)
width = 500;
else if (remote_settings->type == CLIENT_TYPE_GOOGLE)
width = 600;
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(width, 0)))
{
@@ -350,9 +367,12 @@ namespace Windows
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_USERNAME]);
ImGui::SameLine();
width = 180;
if (remote_settings->type == CLIENT_TYPE_GOOGLE)
width = 480;
sprintf(id, "%s##username", remote_settings->username);
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(180, 0)))
if (ImGui::Button(id, ImVec2(width, 0)))
{
ime_single_field = remote_settings->username;
ResetImeCallbacks();
@@ -363,63 +383,79 @@ namespace Windows
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_PASSWORD]);
ImGui::SameLine();
sprintf(id, "%s##password", hidden_password.c_str());
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(100, 0)))
if (remote_settings->type != CLIENT_TYPE_GOOGLE)
{
ime_single_field = remote_settings->password;
ResetImeCallbacks();
ime_field_size = 24;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_PASSWORD], remote_settings->password, 24, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_PASSWORD]);
ImGui::SameLine();
sprintf(id, "%s##password", hidden_password.c_str());
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(100, 0)))
{
ime_single_field = remote_settings->password;
ResetImeCallbacks();
ime_field_size = 127;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_PASSWORD], remote_settings->password, 127, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_RPI]);
ImGui::SameLine();
if (ImGui::Checkbox("###enable_rpi", &remote_settings->enable_rpi))
{
CONFIG::SaveConfig();
}
if (ImGui::IsItemHovered())
{
ImGui::SetNextWindowSize(ImVec2(450, 135));
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
ImGui::Text("%s", (remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) ? lang_strings[STR_ENABLE_RPI_FTP_SMB_MSG] : lang_strings[STR_ENABLE_RPI_WEBDAV_MSG]);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
if ((remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) && remote_settings->enable_rpi)
{
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_HTTP_PORT]);
ImGui::SameLine();
sprintf(id, "%s##http_port", txt_http_port);
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(65, 0)))
{
ime_single_field = txt_http_port;
ResetImeCallbacks();
ime_field_size = 24;
ime_callback = SingleValueImeCallback;
ime_after_update = AfterHttpPortChangeCallback;
Dialog::initImeDialog(lang_strings[STR_PASSWORD], txt_http_port, 24, ORBIS_TYPE_NUMBER, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
}
}
}
ImGui::PopStyleVar();
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_RPI]);
ImGui::SameLine();
if (ImGui::Checkbox("###enable_rpi", &remote_settings->enable_rpi))
ImGui::SetCursorPosX(1870);
if (ImGui::Button(ICON_FA_GEAR, ImVec2(35, 0)))
{
CONFIG::SaveConfig();
show_settings = true;
}
if (ImGui::IsItemHovered())
{
ImGui::SetNextWindowSize(ImVec2(450, 135));
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
ImGui::Text("%s", (remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) ? lang_strings[STR_ENABLE_RPI_FTP_SMB_MSG] : lang_strings[STR_ENABLE_RPI_WEBDAV_MSG]);
ImGui::PopTextWrapPos();
ImGui::Text("%s", lang_strings[STR_SETTINGS]);
ImGui::EndTooltip();
}
if ((remote_settings->type == CLIENT_TYPE_SMB || remote_settings->type == CLIENT_TYPE_FTP) && remote_settings->enable_rpi)
{
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_HTTP_PORT]);
ImGui::SameLine();
sprintf(id, "%s##http_port", txt_http_port);
pos = ImGui::GetCursorPos();
if (ImGui::Button(id, ImVec2(65, 0)))
{
ime_single_field = txt_http_port;
ResetImeCallbacks();
ime_field_size = 24;
ime_callback = SingleValueImeCallback;
ime_after_update = AfterHttpPortChangeCallback;
Dialog::initImeDialog(lang_strings[STR_PASSWORD], txt_http_port, 24, ORBIS_TYPE_NUMBER, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
}
}
ImGui::PopStyleVar();
ImGui::Dummy(ImVec2(0, 10));
EndGroupPanel();
}
@@ -767,7 +803,7 @@ namespace Windows
ImVec4 *colors = style->Colors;
int flags;
if (ImGui::IsKeyDown(ImGuiKey_GamepadFaceUp))
if (ImGui::IsKeyDown(ImGuiKey_GamepadFaceUp) && !paused)
{
if (!paused)
saved_selected_browser = selected_browser;
@@ -783,13 +819,13 @@ namespace Windows
bool remote_browser_selected = saved_selected_browser & REMOTE_BROWSER;
if (local_browser_selected)
{
ImGui::SetNextWindowPos(ImVec2(410, 300));
ImGui::SetNextWindowPos(ImVec2(410, 280));
}
else if (remote_browser_selected)
{
ImGui::SetNextWindowPos(ImVec2(1330, 300));
ImGui::SetNextWindowPos(ImVec2(1330, 280));
}
ImGui::SetNextWindowSizeConstraints(ImVec2(230, 150), ImVec2(230, 550), NULL, NULL);
ImGui::SetNextWindowSizeConstraints(ImVec2(230, 150), ImVec2(230, 625), NULL, NULL);
if (ImGui::BeginPopupModal(lang_strings[STR_ACTIONS], NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::PushID("Select All##settings");
@@ -922,6 +958,65 @@ namespace Windows
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("New File##settings");
flags = ImGuiSelectableFlags_None;
if (remote_browser_selected && remoteclient != nullptr && !(remoteclient->SupportedActions() & REMOTE_ACTION_NEW_FILE))
{
flags = ImGuiSelectableFlags_Disabled;
}
if (ImGui::Selectable(lang_strings[STR_NEW_FILE], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
if (local_browser_selected)
selected_action = ACTION_NEW_LOCAL_FILE;
else if (remote_browser_selected)
selected_action = ACTION_NEW_REMOTE_FILE;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
ImGui::PushID("Edit##settings");
flags = ImGuiSelectableFlags_None;
if ((remote_browser_selected && remoteclient != nullptr && (!(remoteclient->SupportedActions() & REMOTE_ACTION_EDIT) || selected_remote_file.isDir)) ||
(local_browser_selected && selected_local_file.isDir))
{
flags = ImGuiSelectableFlags_Disabled;
}
if (ImGui::Selectable(lang_strings[STR_EDIT], false, flags | ImGuiSelectableFlags_DontClosePopups, ImVec2(220, 0)))
{
bool can_edit = true;
if (local_browser_selected)
{
if (selected_local_file.file_size > max_edit_file_size)
can_edit = false;
else
{
snprintf(edit_file, 255, "%s", selected_local_file.path);
FS::LoadText(&edit_buffer, selected_local_file.path);
}
}
else
{
if (selected_remote_file.file_size > max_edit_file_size)
can_edit = false;
else if (remoteclient != nullptr && remoteclient->Get(TMP_EDITOR_FILE, selected_remote_file.path))
{
snprintf(edit_file, 255, "%s", selected_remote_file.path);
FS::LoadText(&edit_buffer, TMP_EDITOR_FILE);
}
}
if (can_edit)
editor_inprogress = true;
else
sprintf(status_message, "%s %d", lang_strings[STR_MAX_EDIT_FILE_SIZE_MSG], max_edit_file_size);
editor_modified = false;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::PopID();
ImGui::Separator();
if (local_browser_selected)
{
ImGui::PushID("Extract##settings");
@@ -964,7 +1059,7 @@ namespace Windows
ImGui::Separator();
flags = getSelectableFlag(REMOTE_ACTION_UPLOAD);
if (remote_browser_selected && remoteclient != nullptr && !(remoteclient->SupportedActions() & REMOTE_ACTION_UPLOAD))
if (local_browser_selected && remoteclient != nullptr && !(remoteclient->SupportedActions() & REMOTE_ACTION_UPLOAD))
{
flags = ImGuiSelectableFlags_Disabled;
}
@@ -1271,13 +1366,6 @@ namespace Windows
ImGui::CloseCurrentPopup();
}
if (ImGui::Checkbox("##auto_delete_tmp_pkg", &auto_delete_tmp_pkg))
{
CONFIG::SaveConfig();
}
ImGui::SameLine();
ImGui::Text("%s", lang_strings[STR_AUTO_DELETE_TMP_PKG]);
ImGui::Separator();
for (int j = 0; j < MAX_FAVORITE_URLS; j++)
{
@@ -1329,6 +1417,227 @@ namespace Windows
}
}
void ShowEditorDialog()
{
if (editor_inprogress)
{
ImGuiIO &io = ImGui::GetIO();
(void)io;
ImGuiStyle *style = &ImGui::GetStyle();
ImVec4 *colors = style->Colors;
SetModalMode(true);
ImGui::OpenPopup(lang_strings[STR_EDITOR]);
ImGui::SetNextWindowPos(ImVec2(320, 115));
ImGui::SetNextWindowSizeConstraints(ImVec2(1280, 80), ImVec2(1280, 850), NULL, NULL);
if (ImGui::BeginPopupModal(lang_strings[STR_EDITOR], NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImVec2 cur_pos = ImGui::GetCursorPos();
char id[128];
sprintf(id, "%s##editor", lang_strings[STR_CLOSE]);
if (ImGui::Button(id, ImVec2(635, 0)))
{
editor_inprogress = false;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
sprintf(id, "%s##editor", lang_strings[STR_SAVE]);
if (ImGui::Button(id, ImVec2(635, 0)))
{
bool local_browser_selected = saved_selected_browser & LOCAL_BROWSER;
bool remote_browser_selected = saved_selected_browser & REMOTE_BROWSER;
if (local_browser_selected)
{
FS::SaveText(&edit_buffer, selected_local_file.path);
selected_action = ACTION_REFRESH_LOCAL_FILES;
}
else
{
FS::SaveText(&edit_buffer, TMP_EDITOR_FILE);
if (remoteclient != nullptr)
{
remoteclient->Put(TMP_EDITOR_FILE, selected_remote_file.path);
selected_action = ACTION_REFRESH_REMOTE_FILES;
}
}
editor_inprogress = false;
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
ImGui::Separator();
ImGui::BeginChild("Editor##ChildWindow", ImVec2(1275, 680));
int j = 0;
static int insert_item = -1;
for (std::vector<std::string>::iterator it = edit_buffer.begin(); it != edit_buffer.end(); it++)
{
ImGui::Text("%s", ICON_FA_CARET_RIGHT);
ImGui::SameLine();
sprintf(id, "%d##editor", j);
ImGui::PushID(id);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 1.0f));
if (ImGui::Selectable(it->c_str(), false, ImGuiSelectableFlags_DontClosePopups, ImVec2(1275, 0)))
{
edit_line_num = j;
snprintf(edit_line, 1023, "%s", it->c_str());
ResetImeCallbacks();
ime_single_field = edit_line;
ime_field_size = 1023;
ime_after_update = AfterEditorCallback;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_EDIT], edit_line, 1023, ORBIS_TYPE_BASIC_LATIN, 420, 290);
gui_mode = GUI_MODE_IME;
}
ImGui::PopStyleVar();
ImGui::PopID();
if ((gui_mode != GUI_MODE_IME && j == edit_line_num) || edit_line_to_select == j)
{
SetNavFocusHere();
edit_line_num = -1;
edit_line_to_select = -1;
}
if (ImGui::IsItemHovered())
{
if (ImGui::CalcTextSize(it->c_str()).x > 1275)
{
ImGui::BeginTooltip();
ImGui::Text("%s", it->c_str());
ImGui::EndTooltip();
}
}
if (ImGui::IsItemFocused())
{
if (ImGui::IsKeyPressed(ImGuiKey_GamepadR1, false))
{
insert_item = j;
editor_modified = true;
}
else if (ImGui::IsKeyPressed(ImGuiKey_GamepadL1, false))
{
edit_buffer.erase(it--);
editor_modified = true;
edit_line_to_select = j;
}
else if (ImGui::IsKeyPressed(ImGuiKey_GamepadFaceLeft, false))
{
copy_text = std::string(it->c_str());
}
else if (ImGui::IsKeyPressed(ImGuiKey_GamepadFaceUp, false))
{
it->clear();
it->append(copy_text);
}
}
j++;
}
if (insert_item > -1)
{
if (insert_item == edit_buffer.size() - 1)
edit_buffer.push_back(std::string());
else
edit_buffer.insert(edit_buffer.begin() + insert_item + 1, std::string());
}
insert_item = -1;
ImGui::EndChild();
ImGui::Text("%s%s", (editor_modified ? "**" : ""), edit_file);
ImGui::Separator();
ImGui::Text("L1 - %s R1 - %s %s - %s %s - %s", lang_strings[STR_DELETE_LINE], lang_strings[STR_INSERT_LINE],
ICON_OF_SQUARE, lang_strings[STR_COPY_LINE], ICON_OF_TRIANGLE, lang_strings[STR_PASTE_LINE]);
ImGui::EndPopup();
}
}
}
void ShowSettingsDialog()
{
if (show_settings)
{
ImGuiIO &io = ImGui::GetIO();
(void)io;
ImGuiStyle *style = &ImGui::GetStyle();
ImVec4 *colors = style->Colors;
SetModalMode(true);
ImGui::OpenPopup(lang_strings[STR_SETTINGS]);
ImGui::SetNextWindowPos(ImVec2(1150, 80));
ImGui::SetNextWindowSizeConstraints(ImVec2(750, 80), ImVec2(750, 400), NULL, NULL);
if (ImGui::BeginPopupModal(lang_strings[STR_SETTINGS], NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s", lang_strings[STR_GLOBAL]);
ImGui::Separator();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 15);
ImGui::Text("%s", lang_strings[STR_AUTO_DELETE_TMP_PKG]);
ImGui::SameLine();
ImGui::SetCursorPosX(705);
ImGui::Checkbox("##auto_delete_tmp_pkg", &auto_delete_tmp_pkg);
ImGui::Separator();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 15);
ImGui::Text("%s", lang_strings[STR_SHOW_HIDDEN_FILES]);
ImGui::SameLine();
ImGui::SetCursorPosX(705);
ImGui::Checkbox("##show_hidden_files", &show_hidden_files);
ImGui::Separator();
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s", lang_strings[STR_GOOGLE]);
ImGui::Separator();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 15);
ImGui::Text("%s", lang_strings[STR_CLIENT_ID]);
ImGui::SameLine();
ImGui::SetCursorPosX(163);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 1.0f));
char id[192];
sprintf(id, "%s##client_id_input", gg_app.client_id);
if (ImGui::Button(id, ImVec2(580, 0)))
{
ResetImeCallbacks();
ime_single_field = gg_app.client_id;
ime_field_size = 139;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_CLIENT_ID], gg_app.client_id, 139, ORBIS_TYPE_BASIC_LATIN, 1150, 80);
gui_mode = GUI_MODE_IME;
}
ImGui::Separator();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 15);
ImGui::Text("%s", lang_strings[STR_CLIENT_SECRET]);
ImGui::SameLine();
ImGui::SetCursorPosX(163);
if (strlen(gg_app.client_secret) > 0)
sprintf(id, "%s", "*********************************************##client_secret_input");
else
sprintf(id, "%s", "##client_secret_input");
if (ImGui::Button(id, ImVec2(580, 0)))
{
ResetImeCallbacks();
ime_single_field = gg_app.client_secret;
ime_field_size = 63;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_CLIENT_SECRET], gg_app.client_secret, 63, ORBIS_TYPE_BASIC_LATIN, 1150, 80);
gui_mode = GUI_MODE_IME;
}
ImGui::PopStyleVar();
ImGui::Separator();
sprintf(id, "%s##settings", lang_strings[STR_CLOSE]);
if (ImGui::Button(id, ImVec2(735, 0)))
{
show_settings = false;
CONFIG::SaveGlobalConfig();
SetModalMode(false);
ImGui::CloseCurrentPopup();
}
if (ImGui::IsWindowAppearing())
{
ImGui::SetItemDefaultFocus();
}
ImGui::SameLine();
ImGui::EndPopup();
}
}
}
void MainWindow()
{
Windows::SetupWindow();
@@ -1346,6 +1655,8 @@ namespace Windows
ShowProgressDialog();
ShowActionsDialog();
ShowFavoriteUrlsDialog();
ShowEditorDialog();
ShowSettingsDialog();
}
ImGui::End();
}
@@ -1376,17 +1687,19 @@ namespace Windows
break;
case ACTION_NEW_LOCAL_FOLDER:
case ACTION_NEW_REMOTE_FOLDER:
case ACTION_NEW_LOCAL_FILE:
case ACTION_NEW_REMOTE_FILE:
if (gui_mode != GUI_MODE_IME)
{
sprintf(editor_text, "");
ime_single_field = editor_text;
sprintf(dialog_editor_text, "");
ime_single_field = dialog_editor_text;
ResetImeCallbacks();
ime_field_size = 128;
ime_after_update = AfterFolderNameCallback;
ime_cancelled = CancelActionCallBack;
ime_callback = SingleValueImeCallback;
ImVec2 pos = selected_action == ACTION_NEW_LOCAL_FOLDER ? ImVec2(410, 350) : ImVec2(1330, 350);
Dialog::initImeDialog(lang_strings[STR_NEW_FOLDER], editor_text, 128, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
ImVec2 pos = (selected_action == ACTION_NEW_LOCAL_FOLDER || selected_action == ACTION_NEW_LOCAL_FILE) ? ImVec2(410, 350) : ImVec2(1330, 350);
Dialog::initImeDialog((selected_action == ACTION_NEW_LOCAL_FILE || selected_action == ACTION_NEW_REMOTE_FILE)? lang_strings[STR_NEW_FILE]: lang_strings[STR_NEW_FOLDER], dialog_editor_text, 128, ORBIS_TYPE_BASIC_LATIN, pos.x, pos.y);
gui_mode = GUI_MODE_IME;
}
break;
@@ -1409,6 +1722,7 @@ namespace Windows
if (dont_prompt_overwrite || (!dont_prompt_overwrite && confirm_transfer_state == 1))
{
activity_inprogess = true;
sprintf(activity_message, "%s", "");
stop_activity = false;
Actions::UploadFiles();
confirm_transfer_state = -1;
@@ -1420,6 +1734,7 @@ namespace Windows
if (dont_prompt_overwrite || (!dont_prompt_overwrite && confirm_transfer_state == 1))
{
activity_inprogess = true;
sprintf(activity_message, "%s", "");
stop_activity = false;
Actions::DownloadFiles();
confirm_transfer_state = -1;
@@ -1429,6 +1744,7 @@ namespace Windows
case ACTION_EXTRACT_LOCAL_ZIP:
sprintf(status_message, "%s", "");
activity_inprogess = true;
sprintf(activity_message, "%s", "");
stop_activity = false;
file_transfering = true;
selected_action = ACTION_NONE;
@@ -1437,6 +1753,7 @@ namespace Windows
case ACTION_CREATE_LOCAL_ZIP:
sprintf(status_message, "%s", "");
activity_inprogess = true;
sprintf(activity_message, "%s", "");
stop_activity = false;
file_transfering = true;
selected_action = ACTION_NONE;
@@ -1446,16 +1763,16 @@ namespace Windows
if (gui_mode != GUI_MODE_IME)
{
if (multi_selected_local_files.size() > 0)
sprintf(editor_text, "%s", multi_selected_local_files.begin()->name);
sprintf(dialog_editor_text, "%s", multi_selected_local_files.begin()->name);
else
sprintf(editor_text, "%s", selected_local_file.name);
ime_single_field = editor_text;
sprintf(dialog_editor_text, "%s", selected_local_file.name);
ime_single_field = dialog_editor_text;
ResetImeCallbacks();
ime_field_size = 128;
ime_after_update = AfterFolderNameCallback;
ime_cancelled = CancelActionCallBack;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_RENAME], editor_text, 128, ORBIS_TYPE_BASIC_LATIN, 410, 350);
Dialog::initImeDialog(lang_strings[STR_RENAME], dialog_editor_text, 128, ORBIS_TYPE_BASIC_LATIN, 410, 350);
gui_mode = GUI_MODE_IME;
}
break;
@@ -1463,16 +1780,16 @@ namespace Windows
if (gui_mode != GUI_MODE_IME)
{
if (multi_selected_remote_files.size() > 0)
sprintf(editor_text, "%s", multi_selected_remote_files.begin()->name);
sprintf(dialog_editor_text, "%s", multi_selected_remote_files.begin()->name);
else
sprintf(editor_text, "%s", selected_remote_file.name);
ime_single_field = editor_text;
sprintf(dialog_editor_text, "%s", selected_remote_file.name);
ime_single_field = dialog_editor_text;
ResetImeCallbacks();
ime_field_size = 128;
ime_after_update = AfterFolderNameCallback;
ime_cancelled = CancelActionCallBack;
ime_callback = SingleValueImeCallback;
Dialog::initImeDialog(lang_strings[STR_RENAME], editor_text, 128, ORBIS_TYPE_BASIC_LATIN, 1330, 350);
Dialog::initImeDialog(lang_strings[STR_RENAME], dialog_editor_text, 128, ORBIS_TYPE_BASIC_LATIN, 1330, 350);
gui_mode = GUI_MODE_IME;
}
break;
@@ -1508,6 +1825,8 @@ namespace Windows
break;
case ACTION_DISCONNECT_AND_EXIT:
Actions::Disconnect();
HttpServer::Stop();
GDriveClient::StopRefreshToken();
done = true;
break;
case ACTION_INSTALL_REMOTE_PKG:
@@ -1562,6 +1881,7 @@ namespace Windows
if (dont_prompt_overwrite || (!dont_prompt_overwrite && confirm_transfer_state == 1))
{
activity_inprogess = true;
sprintf(activity_message, "%s", "");
stop_activity = false;
confirm_transfer_state = -1;
if (paste_action == ACTION_LOCAL_CUT)
@@ -1581,6 +1901,7 @@ namespace Windows
if (dont_prompt_overwrite || (!dont_prompt_overwrite && confirm_transfer_state == 1))
{
activity_inprogess = true;
sprintf(activity_message, "%s", "");
stop_activity = false;
confirm_transfer_state = -1;
if (paste_action == ACTION_REMOTE_CUT)
@@ -1626,7 +1947,6 @@ namespace Windows
{
ime_callback(ime_result);
}
if (ime_after_update != nullptr)
{
ime_after_update(ime_result);
@@ -1699,27 +2019,34 @@ namespace Windows
void AfterFolderNameCallback(int ime_result)
{
if (selected_action == ACTION_NEW_LOCAL_FOLDER)
{
Actions::CreateNewLocalFolder(editor_text);
}
else if (selected_action == ACTION_NEW_REMOTE_FOLDER)
{
Actions::CreateNewRemoteFolder(editor_text);
}
else if (selected_action == ACTION_RENAME_LOCAL)
switch (selected_action)
{
case ACTION_NEW_LOCAL_FOLDER:
Actions::CreateNewLocalFolder(dialog_editor_text);
break;
case ACTION_NEW_REMOTE_FOLDER:
Actions::CreateNewRemoteFolder(dialog_editor_text);
break;
case ACTION_RENAME_LOCAL:
if (multi_selected_local_files.size() > 0)
Actions::RenameLocalFolder(multi_selected_local_files.begin()->path, editor_text);
Actions::RenameLocalFolder(multi_selected_local_files.begin()->path, dialog_editor_text);
else
Actions::RenameLocalFolder(selected_local_file.path, editor_text);
}
else if (selected_action == ACTION_RENAME_REMOTE)
{
Actions::RenameLocalFolder(selected_local_file.path, dialog_editor_text);
break;
case ACTION_RENAME_REMOTE:
if (multi_selected_remote_files.size() > 0)
Actions::RenameRemoteFolder(multi_selected_remote_files.begin()->path, editor_text);
Actions::RenameRemoteFolder(multi_selected_remote_files.begin()->path, dialog_editor_text);
else
Actions::RenameRemoteFolder(selected_remote_file.path, editor_text);
Actions::RenameRemoteFolder(selected_remote_file.path, dialog_editor_text);
break;
case ACTION_NEW_LOCAL_FILE:
Actions::CreateLocalFile(dialog_editor_text);
break;
case ACTION_NEW_REMOTE_FILE:
Actions::CreateRemoteFile(dialog_editor_text);
break;
default:
break;
}
selected_action = ACTION_NONE;
}
@@ -1754,4 +2081,14 @@ namespace Windows
remote_settings->http_port = atoi(txt_http_port);
}
}
void AfterEditorCallback(int ime_result)
{
if (ime_result == IME_DIALOG_RESULT_FINISHED)
{
std::string str = std::string(edit_line);
edit_buffer[edit_line_num] = str;
editor_modified = true;
}
}
}
+2
View File
@@ -41,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;
@@ -208,6 +209,7 @@ namespace Windows
void AfterZipFileCallback(int ime_result);
void AferServerChangeCallback(int ime_result);
void AfterHttpPortChangeCallback(int ime_result);
void AfterEditorCallback(int ime_result);
}
#endif
+1 -1
View File
@@ -12,7 +12,7 @@
#include "common.h"
#include "fs.h"
#include "lang.h"
#include "rtc.h"
#include "system.h"
#include "windows.h"
#include "zip_util.h"