Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ed3f8a71c4 | |||
| 13279b6040 | |||
| eb465356b6 | |||
| 8602a5353e | |||
| 467a459665 | |||
| b7fe46cb94 | |||
| 3bcf136d2a | |||
| e5d5ddb8bc | |||
| 3e4b5e3ea2 | |||
| c4889ec160 | |||
| 3076f4b179 | |||
| 93fb338ce0 | |||
| 785a073bce | |||
| a71bd1eb28 | |||
| 0a1420dd96 | |||
| dcdc1fc54b | |||
| 5c254589e6 | |||
| 2b25272379 | |||
| 6b66d39eba | |||
| b143c3e3c5 | |||
| c3cc6d5954 | |||
| cfcb420b9d | |||
| 294455c735 | |||
| 4ff119b34d |
+5
-2
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(ezremote_client)
|
||||
|
||||
@@ -25,8 +25,11 @@ add_executable(ezremote_client
|
||||
source/http/httplib.cpp
|
||||
source/clients/baseclient.cpp
|
||||
source/clients/apache.cpp
|
||||
source/clients/archiveorg.cpp
|
||||
source/clients/ftpclient.cpp
|
||||
source/clients/gdrive.cpp
|
||||
source/clients/github.cpp
|
||||
source/clients/myrient.cpp
|
||||
source/clients/iis.cpp
|
||||
source/clients/nginx.cpp
|
||||
source/clients/npxserve.cpp
|
||||
@@ -67,7 +70,7 @@ add_executable(ezremote_client
|
||||
|
||||
add_self(ezremote_client)
|
||||
|
||||
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.27" 32 0)
|
||||
add_pkg(ezremote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "ezRemote Client" "01.35" 32 0)
|
||||
|
||||
target_link_libraries(ezremote_client
|
||||
c
|
||||
|
||||
@@ -81,7 +81,13 @@ To distinguish between FTP, SMB, NFS, WebDAV or HTTP, the URL must be prefix wit
|
||||
```
|
||||
- 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)
|
||||
|
||||
|
||||
- For Internet Archive repos download URLs
|
||||
- Only supports parsing of the download URL (ie the URL where you see a list of files). Example
|
||||
| | | |
|
||||
|----------|-----------|---|
|
||||
|  | |  |
|
||||
|
||||
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.
|
||||
@@ -136,6 +142,7 @@ Circle - Un-Select the file list to navigate to other widgets or Close Dialog wi
|
||||
Square - Mark file(s)/folder(s) for Delete/Rename/Upload/Download
|
||||
R1 - Navigate to the Remote list of files
|
||||
L1 - Navigate to the Local list of files
|
||||
L2 - To go up a directory from current directory
|
||||
TouchPad Button - Exit Application (versions prior to 1.06)
|
||||
Options Button - Exit Application (versions 1.06 and above)
|
||||
```
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
@@ -113,7 +113,7 @@ STR_DOWNLOAD_INSTALL_MSG=تثبيت الحزمة عن بعد غير ممكن. ه
|
||||
STR_CHECKING_REMOTE_SERVER_MSG=التحقق من الخادم البعيد لتثبيت الحزمة عن بعد.
|
||||
STR_ENABLE_RPI=RPI
|
||||
STR_ENABLE_RPI_FTP_SMB_MSG=يتيح هذا الخيار تثبيت الحزمة عن بُعد عبر خادم الويب المضمن.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG==يتيح هذا الخيار تثبيت الحزمة عن بُعد عبر خادم الويب المضمن.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG=يتيح هذا الخيار تثبيت الحزمة عن بُعد عبر خادم الويب المضمن.
|
||||
STR_FILES=الملفات
|
||||
STR_EDITOR=المحرر
|
||||
STR_SAVE=حفظ
|
||||
|
||||
@@ -112,8 +112,8 @@ STR_CANNOT_CONNECT_REMOTE_MSG=Remote HTTP Server not reachable.
|
||||
STR_DOWNLOAD_INSTALL_MSG=Remote Package Install not possible. Would you like to download package and install instead?
|
||||
STR_CHECKING_REMOTE_SERVER_MSG=Checking remote server for Remote Package Install.
|
||||
STR_ENABLE_RPI=RPI
|
||||
STR_ENABLE_RPI_FTP_SMB_MSG=This option enables Remote Package Installation via embedded Web Server.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG==This option enables Remote Package Installation via embedded Web Server.
|
||||
STR_ENABLE_RPI_FTP_SMB_MSG=This option enables Remote Package Installation via embedded Web Server proxy.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG=This option enables Remote Package Installation via embedded Web Server proxy.
|
||||
STR_FILES=Files
|
||||
STR_EDITOR=Editor
|
||||
STR_SAVE=Save
|
||||
@@ -160,4 +160,7 @@ STR_LANGUAGE=Language
|
||||
STR_TEMP_DIRECTORY=Temp Directory
|
||||
STR_REALDEBRID=Real-Debrid
|
||||
STR_BACKGROUND_INSTALL_INPROGRESS=Package install is running in the background. Don't close the app while install is in progress
|
||||
STR_ENABLE_DISC_CACHE_MSG=Enable disk caching. Can improve package install speed in cases where connection to remote is slow
|
||||
STR_ENABLE_DISC_CACHE_MSG=Enable disk caching. Can improve Remote Package Install speed in cases where connection to remote is slow, but breaks resuming of install
|
||||
STR_ENABLE_ALLDEBRID_MSG=Install Via AllDebrid
|
||||
STR_ENABLE_REALDEBRID_MSG=Install Via RealDebrid
|
||||
STR_ENABLE_DISKCACHE_DESC=Enable Disk Cache
|
||||
@@ -25,7 +25,7 @@ STR_FILE=파일
|
||||
STR_TYPE=종류
|
||||
STR_NAME=이름
|
||||
STR_SIZE=크기
|
||||
STR_DATE=일시
|
||||
STR_DATE=날짜
|
||||
STR_NEW_FOLDER=새 폴더
|
||||
STR_RENAME=이름 변경
|
||||
STR_DELETE=삭제
|
||||
@@ -39,7 +39,7 @@ STR_OVERWRITE=덮어쓰기
|
||||
STR_DONT_OVERWRITE=덮어쓰기 금지
|
||||
STR_ASK_FOR_CONFIRM=수락여부를 질문
|
||||
STR_DONT_ASK_CONFIRM=수락여부를 묻지 않음
|
||||
STR_ALLWAYS_USE_OPTION=두번다시 묻지 않고 항상 이 설정을 사용
|
||||
STR_ALLWAYS_USE_OPTION=두 번 다시 묻지 않고 항상 이 설정을 사용
|
||||
STR_ACTIONS=실행
|
||||
STR_CONFIRM=확인
|
||||
STR_OVERWRITE_OPTIONS=덮어쓰기 옵션
|
||||
@@ -59,3 +59,75 @@ STR_FAIL_DEL_DIR_MSG=디렉토리 삭제에 실패하였습니다.
|
||||
STR_DELETING=삭제 중
|
||||
STR_FAIL_DEL_FILE_MSG=파일 삭제에 실패하였습니다.
|
||||
STR_DELETED=삭제됨
|
||||
STR_LINK=링크
|
||||
STR_SHARE=공유
|
||||
STR_FAILED=310 실패함
|
||||
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 로컬에서 파일을 만들기 실패함
|
||||
STR_INSTALL=설치
|
||||
STR_INSTALLING=설치 중
|
||||
STR_INSTALL_SUCCESS=성공
|
||||
STR_INSTALL_FAILED=실패함
|
||||
STR_INSTALL_SKIPPED=건너뜀
|
||||
STR_CHECK_HTTP_MSG=원격 HTTP 서버에 대한 연결 확인
|
||||
STR_FAILED_HTTP_CHECK=HTTP 서버에 연결에 실패함
|
||||
STR_REMOTE_NOT_HTTP=원격이 HTTP 서버가 아님
|
||||
STR_INSTALL_FROM_DATA_MSG=패키지가 /data 또는 /mnt/usbX 폴더에 없음
|
||||
STR_ALREADY_INSTALLED_MSG=패키지가 이미 설치되었음
|
||||
STR_INSTALL_FROM_URL=URL에서 설치
|
||||
STR_CANNOT_READ_PKG_HDR_MSG=패키지 헤더 정보를 읽을 수 없음
|
||||
STR_FAVORITE_URLS=즐겨찾기 URL
|
||||
STR_SLOT=슬롯
|
||||
STR_EDIT=편집
|
||||
STR_ONETIME_URL=한 번만 Url
|
||||
STR_NOT_A_VALID_PACKAGE=유효하지 않은 패키지
|
||||
STR_WAIT_FOR_INSTALL_MSG=패키지 설치가 완료되기를 기다리는 중
|
||||
STR_FAIL_INSTALL_TMP_PKG_MSG=pkg 파일을 설치하지 못했습니다. tmp pkg를 수동으로 삭제하세요.
|
||||
STR_AUTO_DELETE_TMP_PKG=설치 후 임시로 다운로드한 pkg 파일을 자동으로 삭제
|
||||
STR_PROTOCOL_NOT_SUPPORTED=지원되지 않는 프로토콜
|
||||
STR_COULD_NOT_RESOLVE_HOST=호스트 이름을 확인할 수 없음
|
||||
STR_EXTRACT=압축 해제
|
||||
STR_EXTRACTING=압축 해제 중
|
||||
STR_FAILED_TO_EXTRACT=압축 해제 실패함
|
||||
STR_EXTRACT_LOCATION=압축 해제 위치
|
||||
STR_COMPRESS=압축
|
||||
STR_ZIP_FILE_PATH=Zip 파일 이름
|
||||
STR_COMPRESSING=압축 중
|
||||
STR_ERROR_CREATE_ZIP=zip 파일을 만드는 동안 오류 발생
|
||||
STR_UNSUPPORTED_FILE_FORMAT=지원되지 않는 압축 파일 형식
|
||||
STR_CUT=잘라내기
|
||||
STR_COPY=복사
|
||||
STR_PASTE=붙여넣기
|
||||
STR_MOVING=이동 중
|
||||
STR_COPYING=복사 중
|
||||
STR_FAIL_MOVE_MSG=파일 이동 실패함
|
||||
STR_FAIL_COPY_MSG=파일 복사 실패함
|
||||
STR_CANT_MOVE_TO_SUBDIR_MSG=상위 디렉토리를 하위 디렉토리로 이동할 수 없음
|
||||
STR_CANT_COPY_TO_SUBDIR_MSG=상위 디렉토리를 하위 디렉토리로 복사할 수 없음
|
||||
STR_UNSUPPORTED_OPERATION_MSG=지원되지 않는 작업
|
||||
STR_HTTP_PORT=Http 포트
|
||||
STR_REINSTALL_CONFIRM_MSG=콘텐츠가 이미 설치되었습니다. 설치를 계속할까요?
|
||||
STR_REMOTE_NOT_SUPPORT_MSG=보호된 서버에서는 원격 패키지 설치가 지원되지 않습니다.
|
||||
STR_CANNOT_CONNECT_REMOTE_MSG=원격 HTTP 서버에 연결할 수 없습니다.
|
||||
STR_DOWNLOAD_INSTALL_MSG=원격 패키지 설치가 불가능합니다. 패키지를 다운로드하여 설치할까요?
|
||||
STR_CHECKING_REMOTE_SERVER_MSG=원격 패키지 설치를 위해 원격 서버를 확인하고 있습니다.
|
||||
STR_FILES=파일
|
||||
STR_EDITOR=편집기
|
||||
STR_SAVE=저장
|
||||
STR_MAX_EDIT_FILE_SIZE_MSG=다음보다 큰 파일을 편집할 수 없음
|
||||
STR_DELETE_LINE=선택한 줄 삭제
|
||||
STR_INSERT_LINE=선택한 줄 아래에 삽입
|
||||
STR_MODIFIED=수정됨
|
||||
STR_FAIL_GET_TOKEN_MSG=다음에서 접속 토큰을 얻는데 실패함
|
||||
STR_GET_TOKEN_SUCCESS_MSG=로그인에 성공했습니다. 브라우저를 닫고 애플리케이션으로 돌아갈 수 있음
|
||||
STR_NEW_FILE=새 파일
|
||||
STR_SETTINGS=설정
|
||||
STR_GLOBAL=글로벌
|
||||
STR_COPY_LINE=선택한 줄 복사
|
||||
STR_PASTE_LINE=선택한 줄에 붙여넣기
|
||||
STR_SHOW_HIDDEN_FILES=숨겨진 파일 표시
|
||||
STR_SET_DEFAULT_DIRECTORY=기본 폴더 설정
|
||||
STR_SET_DEFAULT_DIRECTORY_MSG=기본 디렉터리로 설정됨
|
||||
STR_NFS_EXP_PATH_MISSING_MSG=URL에 NFS 내보내기 경로 없음
|
||||
STR_FAIL_INIT_NFS_CONTEXT=NFS 컨텍스트를 초기화 실패함
|
||||
STR_FAIL_MOUNT_NFS_MSG=NFS 공유를 마운트 실패함
|
||||
STR_VIEW_IMAGE=이미지 보기
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
STR_CONNECTION_SETTINGS=Tilkoblingsinnstillinger
|
||||
STR_SITE=Side
|
||||
STR_LOCAL=Lokal
|
||||
STR_REMOTE=Ekstern
|
||||
STR_MESSAGES=Meldinger
|
||||
STR_UPDATE_SOFTWARE=Oppdater programvare
|
||||
STR_CONNECT=Koble til
|
||||
STR_DISCONNECT=Koble fra
|
||||
STR_SEARCH=Søk
|
||||
STR_REFRESH=Oppdater
|
||||
STR_SERVER=Tjener
|
||||
STR_USERNAME=Brukernavn
|
||||
STR_PASSWORD=Passord
|
||||
STR_PORT=Port
|
||||
STR_PASV=Pasv
|
||||
STR_DIRECTORY=Mappe
|
||||
STR_FILTER=Filter
|
||||
STR_YES=Ja
|
||||
STR_NO=Nei
|
||||
STR_CANCEL=Avbryt
|
||||
STR_CONTINUE=Fortsett
|
||||
STR_CLOSE=Lukk
|
||||
STR_FOLDER=Mappe
|
||||
STR_FILE=Fil
|
||||
STR_TYPE=Type
|
||||
STR_NAME=Navn
|
||||
STR_SIZE=Størrelse
|
||||
STR_DATE=Dato
|
||||
STR_NEW_FOLDER=Ny mappe
|
||||
STR_RENAME=Gi nytt navn
|
||||
STR_DELETE=Slett
|
||||
STR_UPLOAD=Last opp
|
||||
STR_DOWNLOAD=Last ned
|
||||
STR_SELECT_ALL=Marker alle
|
||||
STR_CLEAR_ALL=Fjern alle
|
||||
STR_UPLOADING=Laster opp
|
||||
STR_DOWNLOADING=Laster ned
|
||||
STR_OVERWRITE=Skriv over
|
||||
STR_DONT_OVERWRITE=Ikke skriv over
|
||||
STR_ASK_FOR_CONFIRM=Spør om bekreftelse
|
||||
STR_DONT_ASK_CONFIRM=Ikke spør om bekreftelse
|
||||
STR_ALLWAYS_USE_OPTION=Bruk alltid dette valget og ikke spør igjen
|
||||
STR_ACTIONS=Handlinger
|
||||
STR_CONFIRM=Bekreft
|
||||
STR_OVERWRITE_OPTIONS=Overskriv innstillinger
|
||||
STR_PROPERTIES=Egenskaper
|
||||
STR_PROGRESS=Framdrift
|
||||
STR_UPDATES=Oppdateringer
|
||||
STR_DEL_CONFIRM_MSG=Er du sikker på at du vil slette filen(e)/mappen(e)?
|
||||
STR_CANCEL_ACTION_MSG=Avbryter. Venter på at siste handling skal fullføres
|
||||
STR_FAIL_UPLOAD_MSG=Opplasting av fil mislykkes
|
||||
STR_FAIL_DOWNLOAD_MSG=Nedlasting av fil mislykkes
|
||||
STR_FAIL_READ_LOCAL_DIR_MSG=Lesing av mappe mislykkes, eller mappen finnes ikke.
|
||||
STR_CONNECTION_CLOSE_ERR_MSG=426 Tilkobling Lukket.
|
||||
STR_REMOTE_TERM_CONN_MSG=426 Ekstern Tjener har lukket tilkoblingen.
|
||||
STR_FAIL_LOGIN_MSG=300 Innlogging Mislykkes. Vennligst sjekk ditt brukernavn og passord.
|
||||
STR_FAIL_TIMEOUT_MSG=426 Mislykkes. Tilkoblingen timet ut.
|
||||
STR_FAIL_DEL_DIR_MSG=Sletting av mappe mislykkes
|
||||
STR_DELETING=Sletter
|
||||
STR_FAIL_DEL_FILE_MSG=Sletting av fil mislykkes
|
||||
STR_DELETED=Slettet
|
||||
STR_LINK=Lenke
|
||||
STR_SHARE=Del
|
||||
STR_FAILED=310 Mislykket
|
||||
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 Oppretting av lokal fil mislykkes
|
||||
STR_INSTALL=Installér
|
||||
STR_INSTALLING=Installerer
|
||||
STR_INSTALL_SUCCESS=Vellykket
|
||||
STR_INSTALL_FAILED=Mislykket
|
||||
STR_INSTALL_SKIPPED=Hoppet over
|
||||
STR_CHECK_HTTP_MSG=Sjekker tilkobling til ekstern HTTP-tjener
|
||||
STR_FAILED_HTTP_CHECK=Mislykket tilkobling til HTTP-tjener
|
||||
STR_REMOTE_NOT_HTTP=Ekstern tjener er ikke en HTTP-tjener
|
||||
STR_INSTALL_FROM_DATA_MSG=Pakke finnes ikke i mappene /data eller /mnt/usbX
|
||||
STR_ALREADY_INSTALLED_MSG=Pakken er allerede installert
|
||||
STR_INSTALL_FROM_URL=Installer fra URL
|
||||
STR_CANNOT_READ_PKG_HDR_MSG=Kunne ikke lese pakkens header
|
||||
STR_FAVORITE_URLS=Favoritt-URLer
|
||||
STR_SLOT=Spor
|
||||
STR_EDIT=Redigér
|
||||
STR_ONETIME_URL=Engangs-URL
|
||||
STR_NOT_A_VALID_PACKAGE=Ikke en gyldig pakke
|
||||
STR_WAIT_FOR_INSTALL_MSG=Venter på at pakke skal bli ferdig å installere
|
||||
STR_FAIL_INSTALL_TMP_PKG_MSG=Installasjon av PKG-fil mislykkes. Vennligst slett den midlertidlige PKG-filen manuelt
|
||||
STR_FAIL_TO_OBTAIN_GG_DL_MSG=Kunne ikke hente nedlastings-URL
|
||||
STR_AUTO_DELETE_TMP_PKG=Automatisk slett midlertidig nedlastet PKG-fil etter installasjon
|
||||
STR_PROTOCOL_NOT_SUPPORTED=Protokollen er ikke støttet
|
||||
STR_COULD_NOT_RESOLVE_HOST=Kunne ikke koble til tjenernavnet
|
||||
STR_EXTRACT=Pakk ut
|
||||
STR_EXTRACTING=Pakker ut
|
||||
STR_FAILED_TO_EXTRACT=Utpakking mislykkes
|
||||
STR_EXTRACT_LOCATION=Utpakkingsbane
|
||||
STR_COMPRESS=Komprimér
|
||||
STR_ZIP_FILE_PATH=ZIP-filnavn
|
||||
STR_COMPRESSING=Komprimerer
|
||||
STR_ERROR_CREATE_ZIP=Oppretting av ZIP mislykket
|
||||
STR_UNSUPPORTED_FILE_FORMAT=Arkivformatet er ikke støttet
|
||||
STR_CUT=Klipp ut
|
||||
STR_COPY=Kopiér
|
||||
STR_PASTE=Lim inn
|
||||
STR_MOVING=Flytter
|
||||
STR_COPYING=Kopierer
|
||||
STR_FAIL_MOVE_MSG=Flytting av fil mislykkes
|
||||
STR_FAIL_COPY_MSG=Kopiering av fil mislykkes
|
||||
STR_CANT_MOVE_TO_SUBDIR_MSG=Kan ikke flytte overordnet mappe til undermappe
|
||||
STR_CANT_COPY_TO_SUBDIR_MSG=Kan ikke kopiere overordnet mappe til undermappe
|
||||
STR_UNSUPPORTED_OPERATION_MSG=Handling ikke støttet
|
||||
STR_HTTP_PORT=HTTP-port
|
||||
STR_REINSTALL_CONFIRM_MSG=Innholdet er allerede installert. Vil du fortsette installasjonen
|
||||
STR_REMOTE_NOT_SUPPORT_MSG=Fjerninstallasjon av pakker er ikke støttet for beskyttede tjenere.
|
||||
STR_CANNOT_CONNECT_REMOTE_MSG=Ekstern HTTP-tjener kan ikke nås.
|
||||
STR_DOWNLOAD_INSTALL_MSG=Fjerninstallasjon er ikke mulig. Vil du laste ned pakken og installere den istedet?
|
||||
STR_CHECKING_REMOTE_SERVER_MSG=Sjekker tjener for fjerninstallasjon av pakke.
|
||||
STR_ENABLE_RPI=FIP
|
||||
STR_ENABLE_RPI_FTP_SMB_MSG=Dette valget skrur på fjerninstallasjon av pakke via innebygd Web-tjenerproxy.
|
||||
STR_ENABLE_RPI_WEBDAV_MSG=Dette valget skrur på fjerninstallasjon av pakke via innebygd Web-tjenerproxy.
|
||||
STR_FILES=Filer
|
||||
STR_EDITOR=Redigeringsprogram
|
||||
STR_SAVE=Lagre
|
||||
STR_MAX_EDIT_FILE_SIZE_MSG=Kan ikke redigere filer større enn
|
||||
STR_DELETE_LINE=Slett markert linje
|
||||
STR_INSERT_LINE=Sett inn under markert linje
|
||||
STR_MODIFIED=Endret
|
||||
STR_FAIL_GET_TOKEN_MSG=Kunne ikke hente en tilgangstoken fra
|
||||
STR_GET_TOKEN_SUCCESS_MSG=Innlogging vellykket. Du kan lukke nettleseren og gå tilbake til applikasjonen
|
||||
STR_PERM_DRIVE=Se, endre, opprette og slette dine Google Drive-filer
|
||||
STR_PERM_DRIVE_APPDATA=Se, opprette og slette dens egen konfigurasjonsdata i din Google Drive
|
||||
STR_PERM_DRIVE_FILE=Se, endre, opprette og slette kun de spesifikke Google Drive-filene du bruker med denne appen
|
||||
STR_PERM_DRIVE_METADATA=Vise og behandle metadataen til filer i din Google Drive
|
||||
STR_PERM_DRIVE_METADATA_RO=Se informasjon om dine Google Drive-filer
|
||||
STR_GOOGLE_LOGIN_FAIL_MSG=Google-innlogging mislykkes
|
||||
STR_GOOGLE_LOGIN_TIMEOUT_MSG=Google-innlogging timet ut
|
||||
STR_NEW_FILE=Ny Fil
|
||||
STR_SETTINGS=Innstillinger
|
||||
STR_CLIENT_ID=Klient-ID
|
||||
STR_CLIENT_SECRET=Klienthemmelighet (Client Secret)
|
||||
STR_GLOBAL=Global
|
||||
STR_GOOGLE=Google
|
||||
STR_COPY_LINE=Kopier markert linje
|
||||
STR_PASTE_LINE=Lim inn i markert linje
|
||||
STR_SHOW_HIDDEN_FILES=Vis skjulte filer
|
||||
STR_SET_DEFAULT_DIRECTORY=Sett oppstartsmappe
|
||||
STR_SET_DEFAULT_DIRECTORY_MSG=har blitt satt som oppstartsmappe
|
||||
STR_VIEW_IMAGE=Vis bilde
|
||||
STR_VIEW_PKG_INFO=Pakkeinformasjon
|
||||
STR_NFS_EXP_PATH_MISSING_MSG=NFS-eksportbane mangler fra URL
|
||||
STR_FAIL_INIT_NFS_CONTEXT=Initialisering av NFS-kontekst mislykkes
|
||||
STR_FAIL_MOUNT_NFS_MSG=Montering av NFS-share mislykkes
|
||||
STR_WEB_SERVER=Web-tjener
|
||||
STR_ENABLE=Skru på
|
||||
STR_COMPRESSED_FILE_PATH=Lokasjon for komprimerte filer
|
||||
STR_COMPRESSED_FILE_PATH_MSG=Lokasjon for komprimerte filer på Web-tjener
|
||||
STR_ALLDEBRID=AllDebrid
|
||||
STR_API_KEY=API-nøkkel
|
||||
STR_CANT_EXTRACT_URL_MSG=Kunne ikke utvinne nedlastings-URL
|
||||
STR_FAIL_INSTALL_FROM_URL_MSG=Installasjon fra URL mislykkes
|
||||
STR_INVALID_URL=Ugyldig URL
|
||||
STR_ALLDEBRID_API_KEY_MISSING_MSG=For å bruke denne funksjonen, må du konfigurere en API-nøkkel i instillingene for ezRemote Client.
|
||||
STR_LANGUAGE=Språk
|
||||
STR_TEMP_DIRECTORY=Midlertidig mappe
|
||||
STR_REALDEBRID=Real-Debrid
|
||||
STR_BACKGROUND_INSTALL_INPROGRESS=Pakkeinstallasjon kjører i bakrunnen. Ikke lykk denne appen mens installasjonen pågår
|
||||
STR_ENABLE_DISC_CACHE_MSG=Skru på disk-caching. Kan gjøre fjerninstallasjon av pakker kjappere når tilkoblingen er treg, men lar deg ikke fortsette en avbrutt installasjon
|
||||
STR_ENABLE_ALLDEBRID_MSG=Installér via AllDebrid
|
||||
STR_ENABLE_REALDEBRID_MSG=Installér via RealDebrid
|
||||
STR_ENABLE_DISKCACHE_DESC=Skru på disk-cache
|
||||
@@ -1,75 +1,133 @@
|
||||
STR_CONNECTION_SETTINGS=Bağlantı Ayarları
|
||||
STR_SITE=Site
|
||||
STR_LOCAL=Yerel
|
||||
STR_REMOTE=Uzaktan
|
||||
STR_REMOTE=Uzak
|
||||
STR_MESSAGES=Mesajlar
|
||||
STR_UPDATE_SOFTWARE=Yazılımı Güncelle
|
||||
STR_CONNECT=Bağlan
|
||||
STR_DISCONNECT=Bağlantıyı kes
|
||||
STR_SEARCH=Ara
|
||||
STR_DISCONNECT=Bağlantıyı Kes
|
||||
STR_SEARCH=Arama
|
||||
STR_REFRESH=Yenile
|
||||
STR_SERVER=Sunucu
|
||||
STR_USERNAME=Kullanıcı Adı
|
||||
STR_PASSWORD=Şifre
|
||||
STR_PASSWORD=Parola
|
||||
STR_PORT=Port
|
||||
STR_PASV=Pasv
|
||||
STR_PASV=Pasif
|
||||
STR_DIRECTORY=Dizin
|
||||
STR_FILTER=Filtre
|
||||
STR_YES=Evet
|
||||
STR_NO=Hayır
|
||||
STR_CANCEL=İptal
|
||||
STR_CONTINUE=Devam
|
||||
STR_CONTINUE=Devam Et
|
||||
STR_CLOSE=Kapat
|
||||
STR_FOLDER=Klasör
|
||||
STR_FILE=Dosya
|
||||
STR_TYPE=Tip
|
||||
STR_TYPE=Tür
|
||||
STR_NAME=Ad
|
||||
STR_SIZE=Boyut
|
||||
STR_DATE=Tarih
|
||||
STR_NEW_FOLDER=Yeni Klasör
|
||||
STR_RENAME=Yeniden Adlandır
|
||||
STR_DELETE=Sil
|
||||
STR_UPLOAD=Karşıya Yükle
|
||||
STR_UPLOAD=Yükle
|
||||
STR_DOWNLOAD=İndir
|
||||
STR_SELECT_ALL=Tümünü Seç
|
||||
STR_CLEAR_ALL=Tümünü Temizle
|
||||
STR_UPLOADING=Karşıya Yükleniyor
|
||||
STR_SELECT_ALL=Hepsini Seç
|
||||
STR_CLEAR_ALL=Hepsini Temizle
|
||||
STR_UPLOADING=Yükleniyor
|
||||
STR_DOWNLOADING=İndiriliyor
|
||||
STR_OVERWRITE=Üzerine yaz
|
||||
STR_DONT_OVERWRITE=Üzerine yazma
|
||||
STR_ASK_FOR_CONFIRM=Onaylamak için sor
|
||||
STR_DONT_ASK_CONFIRM=Onaylamak için sorma
|
||||
STR_ALLWAYS_USE_OPTION=Daima bu seçeneği kullan ve bir daha sorma
|
||||
STR_ACTIONS=Eylemler
|
||||
STR_OVERWRITE=Üzerine Yaz
|
||||
STR_DONT_OVERWRITE=Üzerine Yazma
|
||||
STR_ASK_FOR_CONFIRM=Onay İste
|
||||
STR_DONT_ASK_CONFIRM=Onay İsteme
|
||||
STR_ALLWAYS_USE_OPTION=Bu seçeneği her zaman kullan ve bir daha sorma
|
||||
STR_ACTIONS=İşlemler
|
||||
STR_CONFIRM=Onayla
|
||||
STR_OVERWRITE_OPTIONS=Ayarların üzerine yaz
|
||||
STR_OVERWRITE_OPTIONS=Üzerine Yazma Seçenekleri
|
||||
STR_PROPERTIES=Özellikler
|
||||
STR_PROGRESS=Durum
|
||||
STR_PROGRESS=İlerleme
|
||||
STR_UPDATES=Güncellemeler
|
||||
STR_DEL_CONFIRM_MSG=Bu dosya(ları)/klasör(leri) silmek istediğinizden emin misiniz?
|
||||
STR_CANCEL_ACTION_MSG=İptal ediliyor. Son işlemin tamamlanması bekleniyor
|
||||
STR_FAIL_UPLOAD_MSG=Dosya karşıya yükleme başarısız
|
||||
STR_FAIL_DOWNLOAD_MSG=Dosya indirme başarısız
|
||||
STR_FAIL_READ_LOCAL_DIR_MSG=Dizindeki içerikler okunamadı ya da öyle bir klasör yok
|
||||
STR_CONNECTION_CLOSE_ERR_MSG=426 Bağlantı kesildi.
|
||||
STR_REMOTE_TERM_CONN_MSG=426 Uzaktan Sunucu bağlantıyı kesti.
|
||||
STR_FAIL_LOGIN_MSG=300 Giriş başarısız. Lütfen kullanıcı adınızı ve şifrenizi kontrol edin.
|
||||
STR_CANCEL_ACTION_MSG=İptal ediliyor. Son eylemin tamamlanması bekleniyor
|
||||
STR_FAIL_UPLOAD_MSG=Dosya yüklenemedi
|
||||
STR_FAIL_DOWNLOAD_MSG=Dosya indirilemedi
|
||||
STR_FAIL_READ_LOCAL_DIR_MSG=Yerel dizinin içeriği okunamadı veya klasör mevcut değil.
|
||||
STR_CONNECTION_CLOSE_ERR_MSG=426 Bağlantı kapatıldı.
|
||||
STR_REMOTE_TERM_CONN_MSG=426 Uzak Sunucu bağlantıyı sonlandırdı.
|
||||
STR_FAIL_LOGIN_MSG=300 Giriş Başarısız. Lütfen kullanıcı adınızı veya şifrenizi kontrol edin.
|
||||
STR_FAIL_TIMEOUT_MSG=426 Başarısız. Bağlantı zaman aşımına uğradı.
|
||||
STR_FAIL_DEL_DIR_MSG=Dizin silme başarısız
|
||||
STR_FAIL_DEL_DIR_MSG=Dizin silinemedi
|
||||
STR_DELETING=Siliniyor
|
||||
STR_FAIL_DEL_FILE_MSG=Dosya silme başarısız
|
||||
STR_FAIL_DEL_FILE_MSG=Dosya silinemedi
|
||||
STR_DELETED=Silindi
|
||||
STR_LINK=Link
|
||||
STR_LINK=Bağlantı
|
||||
STR_SHARE=Paylaş
|
||||
STR_FAILED=310 Başarısız
|
||||
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 Yerelde dosya oluşturulumu başarısız
|
||||
STR_INSTALL=Yükle
|
||||
STR_INSTALLING=Yükleniyor
|
||||
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 Yerelde dosya oluşturulamadı
|
||||
STR_INSTALL=Kur
|
||||
STR_INSTALLING=Kuruluyor
|
||||
STR_INSTALL_SUCCESS=Başarılı
|
||||
STR_INSTALL_FAILED=Başarısız
|
||||
STR_INSTALL_SKIPPED=Atlandı
|
||||
STR_CHECK_HTTP_MSG=Uzaktan HTTP Sunucusu bağlantısı kontrol ediliyor
|
||||
STR_FAILED_HTTP_CHECK=HTTP Sunucusuna bağlantı başarısız
|
||||
STR_REMOTE_NOT_HTTP=Uzaktaki HTTP Sunucusu değil
|
||||
STR_INSTALL_FROM_DATA_MSG=Paket /data ya da /mnt/usbX dizininde değil
|
||||
STR_CHECK_HTTP_MSG=Uzak HTTP Sunucusuna bağlantı kontrol ediliyor
|
||||
STR_FAILED_HTTP_CHECK=HTTP Sunucusuna bağlanılamadı
|
||||
STR_REMOTE_NOT_HTTP=Uzak bir HTTP Sunucusu değil
|
||||
STR_INSTALL_FROM_DATA_MSG=Paket /data veya /mnt/usbX klasöründe değil
|
||||
STR_ALREADY_INSTALLED_MSG=Paket zaten kurulu
|
||||
STR_INSTALL_FROM_URL=URL'den Kur
|
||||
STR_CANNOT_READ_PKG_HDR_MSG=Paket başlık bilgisi okunamadı
|
||||
STR_FAVORITE_URLS=Favori URL'ler
|
||||
STR_SLOT=Yuva
|
||||
STR_EDIT=Düzenle
|
||||
STR_ONETIME_URL=Tek Seferlik URL
|
||||
STR_NOT_A_VALID_PACKAGE=Geçerli bir Paket değil
|
||||
STR_WAIT_FOR_INSTALL_MSG=Paketin kurulmasının tamamlanması bekleniyor
|
||||
STR_FAIL_INSTALL_TMP_PKG_MSG=Geçici paketin kurulumu başarısız. Lütfen geçici paketi manuel olarak silin
|
||||
STR_AUTO_DELETE_TMP_PKG=Kurulumdan sonra geçici indirilen paketi otomatik olarak sil
|
||||
STR_PROTOCOL_NOT_SUPPORTED=Protokol desteklenmiyor
|
||||
STR_COULD_NOT_RESOLVE_HOST=Ana bilgisayar adı çözülemedi
|
||||
STR_EXTRACT=Çıkart
|
||||
STR_EXTRACTING=Çıkartılıyor
|
||||
STR_FAILED_TO_EXTRACT=Çıkartma başarısız oldu
|
||||
STR_EXTRACT_LOCATION=Çıkartılacak Konum
|
||||
STR_COMPRESS=Sıkıştır
|
||||
STR_ZIP_FILE_PATH=Zip Dosya Adı
|
||||
STR_COMPRESSING=Sıkıştırılıyor
|
||||
STR_ERROR_CREATE_ZIP=Zip oluşturulurken hata oluştu
|
||||
STR_UNSUPPORTED_FILE_FORMAT=Desteklenmeyen sıkıştırılmış dosya formatı
|
||||
STR_CUT=Kes
|
||||
STR_COPY=Kopyala
|
||||
STR_PASTE=Yapıştır
|
||||
STR_MOVING=Taşınıyor
|
||||
STR_COPYING=Kopyalanıyor
|
||||
STR_FAIL_MOVE_MSG=Dosya taşınamadı
|
||||
STR_FAIL_COPY_MSG=Dosya kopyalanamadı
|
||||
STR_CANT_MOVE_TO_SUBDIR_MSG=Ana dizin alt dizinine taşınamaz
|
||||
STR_CANT_COPY_TO_SUBDIR_MSG=Ana dizin alt dizinine kopyalanamaz
|
||||
STR_UNSUPPORTED_OPERATION_MSG=Desteklenmeyen işlem
|
||||
STR_HTTP_PORT=Http Portu
|
||||
STR_REINSTALL_CONFIRM_MSG=İçerik zaten kurulu. Kuruluma devam etmek istiyor musunuz?
|
||||
STR_REMOTE_NOT_SUPPORT_MSG=Korunan sunucular için uzak paket kurulumu desteklenmiyor.
|
||||
STR_CANNOT_CONNECT_REMOTE_MSG=Uzak HTTP Sunucusuna bağlanılamıyor.
|
||||
STR_DOWNLOAD_INSTALL_MSG=Uzak Paket Kurulumu mümkün değil. Paketi indirip kurmak ister misiniz?
|
||||
STR_CHECKING_REMOTE_SERVER_MSG=Uzak Paket Kurulumu için uzak sunucu kontrol ediliyor.
|
||||
STR_FILES=Dosyalar
|
||||
STR_EDITOR=Düzenleyici
|
||||
STR_SAVE=Kaydet
|
||||
STR_MAX_EDIT_FILE_SIZE_MSG=Boyutu şu büyüklükten büyük dosyalar düzenlenemez
|
||||
STR_DELETE_LINE=Seçili Satırı Sil
|
||||
STR_INSERT_LINE=Seçili Satırın Altına Ekle
|
||||
STR_MODIFIED=Değiştirildi
|
||||
STR_FAIL_GET_TOKEN_MSG=Erişim token'ı alınamadı
|
||||
STR_GET_TOKEN_SUCCESS_MSG=Giriş Başarılı. Tarayıcıyı kapatıp uygulamaya dönebilirsiniz
|
||||
STR_NEW_FILE=Yeni Dosya
|
||||
STR_SETTINGS=Ayarlar
|
||||
STR_GLOBAL=Genel
|
||||
STR_COPY_LINE=Seçili satırı kopyala
|
||||
STR_PASTE_LINE=Seçili satıra yapıştır
|
||||
STR_SHOW_HIDDEN_FILES=Gizli dosyaları göster
|
||||
STR_SET_DEFAULT_DIRECTORY=Varsayılan Klasörü Ayarla
|
||||
STR_SET_DEFAULT_DIRECTORY_MSG=varsayılan dizin olarak ayarlandı
|
||||
STR_NFS_EXP_PATH_MISSING_MSG=URL'de NFS dışa aktarma yolu eksik
|
||||
STR_FAIL_INIT_NFS_CONTEXT=NFS bağlamı başlatılamadı
|
||||
STR_FAIL_MOUNT_NFS_MSG=NFS paylaşımı bağlanamadı
|
||||
STR_VIEW_IMAGE=Görüntüyü Görüntüle
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
STR_CONNECTION_SETTINGS=Cài đặt kết nối
|
||||
STR_SITE=Vị trí
|
||||
STR_LOCAL=Thiết bị
|
||||
STR_REMOTE=Máy đích
|
||||
STR_MESSAGES=Tin nhắn
|
||||
STR_UPDATE_SOFTWARE=Cập nhật phần mềm
|
||||
STR_CONNECT=Kết nối
|
||||
STR_DISCONNECT=Ngắt kết nối
|
||||
STR_SEARCH=Tìm kiếm
|
||||
STR_REFRESH=Làm mới
|
||||
STR_SERVER=Máy chủ
|
||||
STR_USERNAME=Tên đăng nhập
|
||||
STR_PASSWORD=Mật khẩu
|
||||
STR_PORT=Cổng
|
||||
STR_PASV=Pasv
|
||||
STR_DIRECTORY=Thư mục
|
||||
STR_FILTER=Bộ lọc
|
||||
STR_YES=Đồng ý
|
||||
STR_NO=Không
|
||||
STR_CANCEL=Hủy bỏ
|
||||
STR_CONTINUE=Tiếp tục
|
||||
STR_CLOSE=Đóng
|
||||
STR_FOLDER=Thư mục
|
||||
STR_FILE=Tập tin
|
||||
STR_TYPE=Loại
|
||||
STR_NAME=Tên
|
||||
STR_SIZE=Kích thước
|
||||
STR_DATE=Ngày tháng
|
||||
STR_NEW_FOLDER=Thư mục mới
|
||||
STR_RENAME=Đổi tên
|
||||
STR_DELETE=Xóa
|
||||
STR_UPLOAD=Tải lên
|
||||
STR_DOWNLOAD=Tải xuống
|
||||
STR_SELECT_ALL=Chọn tất cả
|
||||
STR_CLEAR_ALL=Bỏ chọn tất cả
|
||||
STR_UPLOADING=Đang tải lên
|
||||
STR_DOWNLOADING=Đang tải xuống
|
||||
STR_OVERWRITE=Ghi đè
|
||||
STR_DONT_OVERWRITE=Không ghi đè
|
||||
STR_ASK_FOR_CONFIRM=Hỏi xác nhận
|
||||
STR_DONT_ASK_CONFIRM=Không hỏi xác nhận
|
||||
STR_ALLWAYS_USE_OPTION=Luôn dùng tùy chọn này và không hỏi lại
|
||||
STR_ACTIONS=Hành động
|
||||
STR_CONFIRM=Xác nhận
|
||||
STR_OVERWRITE_OPTIONS=Tùy chọn ghi đè
|
||||
STR_PROPERTIES=Thuộc tính
|
||||
STR_PROGRESS=Tiến trình
|
||||
STR_UPDATES=Cập nhật
|
||||
STR_DEL_CONFIRM_MSG=Bạn có chắc chắn muốn xóa (những) tập tin / thư mục này không?
|
||||
STR_CANCEL_ACTION_MSG=Hủy bỏ. Chờ hành động cuối cùng hoàn tất.Canceling.
|
||||
STR_FAIL_UPLOAD_MSG=Không thể tải file lên
|
||||
STR_FAIL_DOWNLOAD_MSG=Không thể tải file
|
||||
STR_FAIL_READ_LOCAL_DIR_MSG=Không đọc được nội dung của thư mục hoặc thư mục không tồn tại.
|
||||
STR_CONNECTION_CLOSE_ERR_MSG=426 Kết nối đã đóng.
|
||||
STR_REMOTE_TERM_CONN_MSG=426 Máy chủ đã ngắt kết nối.
|
||||
STR_FAIL_LOGIN_MSG=300 Đăng nhập thất bại. Vui lòng kiểm tra lại tên đăng nhập hoặc mật khẩu.
|
||||
STR_FAIL_TIMEOUT_MSG=426 Thất bại. Quá thời gian kết nối.
|
||||
STR_FAIL_DEL_DIR_MSG=Không thể xóa thư mục
|
||||
STR_DELETING=Đang xóa
|
||||
STR_FAIL_DEL_FILE_MSG=Không thể xóa tập tin
|
||||
STR_DELETED=Đã xóa
|
||||
STR_LINK=Liên kết
|
||||
STR_SHARE=Chia sẻ
|
||||
STR_FAILED=310 Lỗi
|
||||
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 Không thể tạo file trên máy này
|
||||
STR_INSTALL=Cài đặt
|
||||
STR_INSTALLING=Đang cài đặt
|
||||
STR_INSTALL_SUCCESS=Thành công
|
||||
STR_INSTALL_FAILED=Thất bại
|
||||
STR_INSTALL_SKIPPED=Bỏ qua
|
||||
STR_CHECK_HTTP_MSG=Đang kiểm tra kết nối tới máy chủ HTTP
|
||||
STR_FAILED_HTTP_CHECK=Không thể kết nối tới máy chủ HTTP
|
||||
STR_REMOTE_NOT_HTTP=Máy đích không phải máy chủ HTTP
|
||||
STR_INSTALL_FROM_DATA_MSG=Package không có trong thư mục /data hoặc /mnt/usbX
|
||||
STR_ALREADY_INSTALLED_MSG=Package đã được cài đặt
|
||||
STR_INSTALL_FROM_URL=Cài từ địa chỉ URL
|
||||
STR_CANNOT_READ_PKG_HDR_MSG=Không thể đọc được thông tin header của package
|
||||
STR_FAVORITE_URLS=URLs yêu thích
|
||||
STR_SLOT=Vị trí
|
||||
STR_EDIT=Sửa
|
||||
STR_ONETIME_URL=Url một lần
|
||||
STR_NOT_A_VALID_PACKAGE=Package không đúng
|
||||
STR_WAIT_FOR_INSTALL_MSG=Đợi Package kết thúc cài đặt
|
||||
STR_FAIL_INSTALL_TMP_PKG_MSG=Không thể cài file pkg. Vui lòng xóa tmp pkg thủ công
|
||||
STR_AUTO_DELETE_TMP_PKG=Tự động xóa file pkg được tải về tạm thời sau khi cài xong
|
||||
STR_PROTOCOL_NOT_SUPPORTED=Protocol không được hỗ trợ
|
||||
STR_COULD_NOT_RESOLVE_HOST=Không thể phân giải tên máy chủ
|
||||
STR_EXTRACT=Giải nén
|
||||
STR_EXTRACTING=Đang giải nén
|
||||
STR_FAILED_TO_EXTRACT=Giải nén thất bại
|
||||
STR_EXTRACT_LOCATION=Vị trí giải nén
|
||||
STR_COMPRESS=Nén
|
||||
STR_ZIP_FILE_PATH=Tên file Zip
|
||||
STR_COMPRESSING=Đang nén
|
||||
STR_ERROR_CREATE_ZIP=Lỗi khi tạo file zip
|
||||
STR_UNSUPPORTED_FILE_FORMAT=Phần mở rộng file không được hỗ trợ
|
||||
STR_CUT=Cắt
|
||||
STR_COPY=Sao chép
|
||||
STR_PASTE=Dán
|
||||
STR_MOVING=Đang di chuyển
|
||||
STR_COPYING=Đang copy
|
||||
STR_FAIL_MOVE_MSG=Không thể di chuyển file
|
||||
STR_FAIL_COPY_MSG=Không thể sao chép file
|
||||
STR_CANT_MOVE_TO_SUBDIR_MSG=Không thể di chuyển thư mục cha vào bên trong thư mục con
|
||||
STR_CANT_COPY_TO_SUBDIR_MSG=Không thể sao chép thư mục cha vào bên trong thư mục con
|
||||
STR_UNSUPPORTED_OPERATION_MSG=Hành động không được hỗ trợ
|
||||
STR_HTTP_PORT=Cổng Http
|
||||
STR_REINSTALL_CONFIRM_MSG=Nội dung đã được cài đặt. Bạn có muốn tiếp tục cài đặt không?
|
||||
STR_REMOTE_NOT_SUPPORT_MSG=Cài đặt gói từ xa không được hỗ trợ cho các máy chủ được bảo vệ.
|
||||
STR_CANNOT_CONNECT_REMOTE_MSG=Máy chủ HTTP đích không thể truy cập được.
|
||||
STR_DOWNLOAD_INSTALL_MSG=Không thể cài đặt package từ xa. Bạn có muốn tải package xuống và cài đặt không?
|
||||
STR_CHECKING_REMOTE_SERVER_MSG=Đang kiểm tra máy chủ đích để cài đặt package từ xa.
|
||||
STR_FILES=Tập tin
|
||||
STR_EDITOR=Trình soạn thảo
|
||||
STR_SAVE=Lưu
|
||||
STR_MAX_EDIT_FILE_SIZE_MSG=Không thể chỉnh sửa các tập tin lớn hơn
|
||||
STR_DELETE_LINE=Xóa dòng đã chọn
|
||||
STR_INSERT_LINE=Chèn bên dưới dòng đã chọn
|
||||
STR_MODIFIED=Đã sửa đổi
|
||||
STR_FAIL_GET_TOKEN_MSG=Không thể lấy được access token từ
|
||||
STR_GET_TOKEN_SUCCESS_MSG=Đăng nhập thành công. Bạn có thể đóng trình duyệt và quay lại ứng dụng
|
||||
STR_NEW_FILE=Tập tin mới
|
||||
STR_SETTINGS=Cài đặt
|
||||
STR_GLOBAL=Toàn cục
|
||||
STR_COPY_LINE=Sao chép dòng đã chọn
|
||||
STR_PASTE_LINE=Dán vào dòng đã chọn
|
||||
STR_SHOW_HIDDEN_FILES=Hiển thị các tập tin ẩn
|
||||
STR_SET_DEFAULT_DIRECTORY=Đặt thư mục mặc định
|
||||
STR_SET_DEFAULT_DIRECTORY_MSG=đã được thiết lập làm thư mục mặc định
|
||||
STR_NFS_EXP_PATH_MISSING_MSG=Đường dẫn NFS bị thiếu trong URL
|
||||
STR_FAIL_INIT_NFS_CONTEXT=Không khởi tạo được ngữ cảnh NFS
|
||||
STR_FAIL_MOUNT_NFS_MSG=Không thể mount NFS share
|
||||
STR_PROMOTING=Promoting
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 165 KiB |
+79
-8
@@ -1,6 +1,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <json-c/json.h>
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <minizip/unzip.h>
|
||||
@@ -10,6 +11,9 @@
|
||||
#include "clients/smbclient.h"
|
||||
#include "clients/webdav.h"
|
||||
#include "clients/apache.h"
|
||||
#include "clients/archiveorg.h"
|
||||
#include "clients/github.h"
|
||||
#include "clients/myrient.h"
|
||||
#include "clients/nginx.h"
|
||||
#include "clients/npxserve.h"
|
||||
#include "clients/nfsclient.h"
|
||||
@@ -17,6 +21,7 @@
|
||||
#include "clients/rclone.h"
|
||||
#include "clients/sftpclient.h"
|
||||
#include "filehost/filehost.h"
|
||||
#include "server/http_server.h"
|
||||
#include "common.h"
|
||||
#include "fs.h"
|
||||
#include "config.h"
|
||||
@@ -1106,7 +1111,7 @@ namespace Actions
|
||||
}
|
||||
}
|
||||
|
||||
void *InstallUrlPkgThread(void *argp)
|
||||
void *InstallLocalUrlPkgThread(void *argp)
|
||||
{
|
||||
bytes_transfered = 0;
|
||||
sceRtcGetCurrentTick(&prev_tick);
|
||||
@@ -1117,10 +1122,10 @@ namespace Actions
|
||||
OrbisTick tick;
|
||||
sceRtcGetCurrentClockLocalTime(&now);
|
||||
sceRtcGetTick(&now, &tick);
|
||||
sprintf(filename, "%s/%lu.pkg", DATA_PATH, tick.mytick);
|
||||
sprintf(filename, "%s/%lu.pkg", TMP_FOLDER_PATH, tick.mytick);
|
||||
|
||||
std::string full_url = std::string(install_pkg_url.url);
|
||||
FileHost *filehost = FileHost::getFileHost(full_url);
|
||||
FileHost *filehost = FileHost::getFileHost(full_url, install_pkg_url.enable_alldebrid, install_pkg_url.enable_realdebrid);
|
||||
if (!filehost->IsValidUrl())
|
||||
{
|
||||
sprintf(status_message, "%s", lang_strings[STR_FAIL_TO_OBTAIN_GG_DL_MSG]);
|
||||
@@ -1143,7 +1148,7 @@ namespace Actions
|
||||
std::string host = full_url.substr(0, path_pos);
|
||||
std::string path = full_url.substr(path_pos);
|
||||
|
||||
WebDAVClient tmp_client;
|
||||
BaseClient tmp_client;
|
||||
tmp_client.Connect(host.c_str(), install_pkg_url.username, install_pkg_url.password);
|
||||
|
||||
sprintf(activity_message, "%s URL to %s", lang_strings[STR_DOWNLOADING], filename);
|
||||
@@ -1151,9 +1156,9 @@ namespace Actions
|
||||
memset(&header, 0, s);
|
||||
|
||||
int ret = tmp_client.Size(path, &bytes_to_download);
|
||||
if (!ret)
|
||||
if (ret == 0)
|
||||
{
|
||||
sprintf(status_message, "%s - %s", lang_strings[STR_FAILED], lang_strings[STR_CANNOT_READ_PKG_HDR_MSG]);
|
||||
sprintf(status_message, "%s", tmp_client.LastResponse());
|
||||
tmp_client.Quit();
|
||||
activity_inprogess = false;
|
||||
Windows::SetModalMode(false);
|
||||
@@ -1161,7 +1166,7 @@ namespace Actions
|
||||
}
|
||||
|
||||
file_transfering = 1;
|
||||
int is_performed = tmp_client.Get(path, filename);
|
||||
int is_performed = tmp_client.Get(filename, path);
|
||||
|
||||
if (is_performed == 0)
|
||||
{
|
||||
@@ -1214,10 +1219,70 @@ namespace Actions
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *InstallRpiUrlPkgThread(void *argp)
|
||||
{
|
||||
json_object *params = json_object_new_object();
|
||||
json_object_object_add(params, "url", json_object_new_string(install_pkg_url.url));
|
||||
json_object_object_add(params, "use_alldebrid", json_object_new_boolean(install_pkg_url.enable_alldebrid));
|
||||
json_object_object_add(params, "use_realdebrid", json_object_new_boolean(install_pkg_url.enable_realdebrid));
|
||||
json_object_object_add(params, "use_disk_cache", json_object_new_boolean(install_pkg_url.enable_disk_cache));
|
||||
|
||||
const char *params_str = json_object_to_json_string(params);
|
||||
|
||||
char host[128];
|
||||
sprintf(host, "http://127.0.0.1:%d", http_server_port);
|
||||
|
||||
httplib::Client tmp_client(host);
|
||||
tmp_client.set_keep_alive(true);
|
||||
tmp_client.set_follow_location(true);
|
||||
tmp_client.set_connection_timeout(30);
|
||||
tmp_client.set_read_timeout(30);
|
||||
tmp_client.enable_server_certificate_verification(false);
|
||||
|
||||
auto res = tmp_client.Post("/__local__/install_url", params_str, strlen(params_str), "application/json");
|
||||
if (res != nullptr && HTTP_SUCCESS(res->status))
|
||||
{
|
||||
json_object *jobj = json_tokener_parse(res->body.c_str());
|
||||
if (jobj != nullptr)
|
||||
{
|
||||
json_object *result = json_object_object_get(jobj, "result");
|
||||
if (result != nullptr)
|
||||
{
|
||||
bool success = json_object_get_boolean(json_object_object_get(result, "success"));
|
||||
if (!success)
|
||||
{
|
||||
const char* error_message = json_object_get_string(json_object_object_get(result, "error"));
|
||||
sprintf(status_message, "%s", error_message);
|
||||
activity_inprogess = false;
|
||||
Windows::SetModalMode(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
activity_inprogess = false;
|
||||
Windows::SetModalMode(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
activity_inprogess = false;
|
||||
Windows::SetModalMode(false);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InstallUrlPkg()
|
||||
{
|
||||
int res;
|
||||
sprintf(status_message, "%s", "");
|
||||
int res = pthread_create(&bk_activity_thid, NULL, InstallUrlPkgThread, NULL);
|
||||
|
||||
if (!install_pkg_url.enable_rpi)
|
||||
res = pthread_create(&bk_activity_thid, NULL, InstallLocalUrlPkgThread, NULL);
|
||||
else
|
||||
res = pthread_create(&bk_activity_thid, NULL, InstallRpiUrlPkgThread, NULL);
|
||||
|
||||
if (res != 0)
|
||||
{
|
||||
activity_inprogess = false;
|
||||
@@ -1246,6 +1311,12 @@ namespace Actions
|
||||
remoteclient = new NpxServeClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_RCLONE) == 0)
|
||||
remoteclient = new RCloneClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_ARCHIVEORG) == 0)
|
||||
remoteclient = new ArchiveOrgClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_MYRIENT) == 0)
|
||||
remoteclient = new MyrientClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_GITHUB) == 0)
|
||||
remoteclient = new GithubClient();
|
||||
}
|
||||
else if (strncmp(remote_settings->server, "webdavs://", 10) == 0 || strncmp(remote_settings->server, "webdav://", 9) == 0)
|
||||
{
|
||||
|
||||
+2
-1
@@ -99,7 +99,8 @@ namespace Actions
|
||||
void InstallRemotePkgs();
|
||||
void *InstallLocalPkgsThread(void *argp);
|
||||
void InstallLocalPkgs();
|
||||
void *InstallUrlPkgThread(void *argp);
|
||||
void *InstallLocalUrlPkgThread(void *argp);
|
||||
void *InstallRpiUrlPkgThread(void *argp);
|
||||
void InstallUrlPkg();
|
||||
void *KeepAliveThread(void *argp);
|
||||
void *ExtractZipThread(void *argp);
|
||||
|
||||
+23
-10
@@ -128,18 +128,31 @@ std::vector<DirEntry> ApacheClient::ListDir(const std::string &path)
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string.compare("td") == 0)
|
||||
{
|
||||
value = lxb_dom_node_text_content(node, &value_len);
|
||||
// get the child <a> element
|
||||
lxb_dom_node_t *a_node = NextChildElement(lxb_dom_interface_element(node));
|
||||
if (a_node == nullptr) continue;
|
||||
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(a_node), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
tmp_string = Util::Rtrim(tmp_string, "/");
|
||||
sprintf(entry.name, "%s", tmp_string.c_str());
|
||||
sprintf(entry.directory, "%s", path.c_str());
|
||||
if (path.length() > 0 && path[path.length() - 1] == '/')
|
||||
if (tmp_string.compare("a") == 0)
|
||||
{
|
||||
sprintf(entry.path, "%s%s", path.c_str(), entry.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(entry.path, "%s/%s", path.c_str(), entry.name);
|
||||
value = lxb_dom_element_get_attribute(lxb_dom_interface_element(a_node), (const lxb_char_t *)"href", 4, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
tmp_string = Util::Rtrim(tmp_string, "/");
|
||||
tmp_string = BaseClient::UnEscape(tmp_string);
|
||||
if (tmp_string.compare("..") != 0)
|
||||
{
|
||||
sprintf(entry.directory, "%s", path.c_str());
|
||||
sprintf(entry.name, "%s", tmp_string.c_str());
|
||||
if (path.length() > 0 && path[path.length() - 1] == '/')
|
||||
{
|
||||
sprintf(entry.path, "%s%s", path.c_str(), entry.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(entry.path, "%s/%s", path.c_str(), entry.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else continue; // not valid record
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <lexbor/dom/interfaces/node.h>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/archiveorg.h"
|
||||
#include "lang.h"
|
||||
#include "util.h"
|
||||
#include "system.h"
|
||||
#include "windows.h"
|
||||
|
||||
using httplib::Client;
|
||||
using httplib::Headers;
|
||||
using httplib::Result;
|
||||
|
||||
struct InsensitiveCompare
|
||||
{
|
||||
bool operator()(const std::string &a, const std::string &b) const
|
||||
{
|
||||
return strcasecmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
static std::map<std::string, int> month_map = {{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4}, {"May", 5}, {"Jun", 6}, {"Jul", 7}, {"Aug", 8}, {"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}};
|
||||
static std::set<std::string, InsensitiveCompare> ignore_cookie_keys = {"path", "expires", "max-age", "domain", "secure"};
|
||||
|
||||
std::string ArchiveOrgClient::GenerateRandomId(const int len)
|
||||
{
|
||||
static const char alphanum[] = "0123456789abcdef";
|
||||
std::string tmp_s;
|
||||
tmp_s.reserve(len);
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)];
|
||||
}
|
||||
|
||||
return tmp_s;
|
||||
}
|
||||
|
||||
int ArchiveOrgClient::Connect(const std::string &url, const std::string &username, const std::string &password)
|
||||
{
|
||||
this->host_url = url;
|
||||
size_t scheme_pos = url.find("://");
|
||||
size_t root_pos = url.find("/", scheme_pos + 3);
|
||||
if (root_pos != std::string::npos)
|
||||
{
|
||||
this->host_url = url.substr(0, root_pos);
|
||||
this->base_path = url.substr(root_pos);
|
||||
}
|
||||
client = new httplib::Client(this->host_url);
|
||||
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->cookies = {
|
||||
{"donation-identifier", GenerateRandomId(32)},
|
||||
{"test-cookie", "1"},
|
||||
{"abtest-identifier", GenerateRandomId(32)}
|
||||
};
|
||||
|
||||
if (username.length() > 0)
|
||||
return Login(username, password);
|
||||
else if (Ping())
|
||||
this->connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ArchiveOrgClient::Login(const std::string &username, const std::string &password)
|
||||
{
|
||||
std::string url = std::string("/account/login");
|
||||
Headers headers = {{ "User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0"}};
|
||||
SetCookies(headers);
|
||||
|
||||
MultipartFormDataItems items = {
|
||||
{"username", username, "", ""},
|
||||
{"password", password, "", ""},
|
||||
{"remember", "true", "", ""},
|
||||
{"referer", "https://archive.org/", "", ""},
|
||||
{"login", "true", "", ""},
|
||||
{"submit_by_js", "true", "", ""}};
|
||||
|
||||
if (auto res = client->Post(url, headers, items))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
if (res->has_header("Set-Cookie"))
|
||||
{
|
||||
int cookies_count = res->get_header_value_count("Set-Cookie");
|
||||
|
||||
for (int i = 0; i < cookies_count; i++)
|
||||
{
|
||||
std::string cookie_str = res->get_header_value("Set-Cookie", i);
|
||||
|
||||
std::vector<std::string> cookies = Util::Split(cookie_str, ";");
|
||||
for (std::vector<std::string>::iterator it = cookies.begin(); it != cookies.end();)
|
||||
{
|
||||
std::vector<std::string> cookie = Util::Split(*it, "=");
|
||||
std::string key = Util::Trim(cookie[0], " ");
|
||||
if (ignore_cookie_keys.find(key) == ignore_cookie_keys.end())
|
||||
{
|
||||
if (cookie.size() > 1)
|
||||
this->cookies[key] = Util::Trim(cookie[1], " ");
|
||||
else
|
||||
this->cookies[key] = "";
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
this->connected = true;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DirEntry> ArchiveOrgClient::ListDir(const std::string &path)
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
DirEntry entry;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
Headers headers;
|
||||
SetCookies(headers);
|
||||
|
||||
std::string encoded_path = httplib::detail::encode_url(GetFullPath(path) + "/");
|
||||
if (auto res = client->Get(encoded_path, headers))
|
||||
{
|
||||
lxb_status_t status;
|
||||
lxb_dom_attr_t *attr;
|
||||
lxb_dom_element_t *table_element, *tr_element, *td_element;
|
||||
lxb_html_document_t *document;
|
||||
lxb_dom_collection_t *table_collection;
|
||||
lxb_dom_collection_t *tr_collection;
|
||||
lxb_dom_collection_t *td_collection;
|
||||
std::string tmp_string;
|
||||
const lxb_char_t *value;
|
||||
size_t value_len;
|
||||
|
||||
document = lxb_html_document_create();
|
||||
status = lxb_html_document_parse(document, (lxb_char_t *)res->body.c_str(), res->body.length());
|
||||
if (status != LXB_STATUS_OK)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
table_collection = lxb_dom_collection_make(&document->dom_document, 1);
|
||||
if (table_collection == NULL)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
tr_collection = lxb_dom_collection_make(&document->dom_document, 128);
|
||||
if (tr_collection == NULL)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
|
||||
table_collection, (const lxb_char_t *)"table", 5);
|
||||
if (status != LXB_STATUS_OK)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (lxb_dom_collection_length(table_collection) < 1)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lxb_dom_collection_length(table_collection); i++)
|
||||
{
|
||||
table_element = lxb_dom_collection_element(table_collection, i);
|
||||
value = lxb_dom_element_class(table_element, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string.compare("directory-listing-table") == 0)
|
||||
break;
|
||||
table_element = nullptr;
|
||||
}
|
||||
|
||||
if (table_element == nullptr)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
status = lxb_dom_elements_by_tag_name(table_element,
|
||||
tr_collection, (const lxb_char_t *)"tr", 2);
|
||||
if (status != LXB_STATUS_OK && lxb_dom_collection_length(tr_collection) < 2)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// skip row 0 , since it has the previous folder header
|
||||
for (size_t i = 2; i < lxb_dom_collection_length(tr_collection); i++)
|
||||
{
|
||||
DirEntry entry;
|
||||
std::string title, aclass;
|
||||
memset(&entry.modified, 0, sizeof(DateTime));
|
||||
|
||||
tr_element = lxb_dom_collection_element(tr_collection, i);
|
||||
|
||||
td_collection = lxb_dom_collection_make(&document->dom_document, 5);
|
||||
status = lxb_dom_elements_by_tag_name(tr_element,
|
||||
td_collection, (const lxb_char_t *)"td", 2);
|
||||
if (status != LXB_STATUS_OK || lxb_dom_collection_length(td_collection) < 3)
|
||||
{
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// td0 contains the <a> tag
|
||||
td_element = lxb_dom_collection_element(td_collection, 0);
|
||||
lxb_dom_node_t *a_node = NextChildElement(td_element);
|
||||
// there is no a_node in protected links
|
||||
if (a_node == nullptr)
|
||||
{
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(a_node), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string.compare("a") != 0)
|
||||
{
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
value = lxb_dom_element_get_attribute(lxb_dom_interface_element(a_node), (const lxb_char_t *)"href", 4, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string[tmp_string.length()-1] == '/')
|
||||
tmp_string = tmp_string.substr(0, tmp_string.length()-1);
|
||||
tmp_string = BaseClient::UnEscape(tmp_string);
|
||||
sprintf(entry.name, "%s", tmp_string.c_str());
|
||||
sprintf(entry.directory, "%s", path.c_str());
|
||||
if (path.length() > 0 && path[path.length() - 1] == '/')
|
||||
{
|
||||
sprintf(entry.path, "%s%s", path.c_str(), entry.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(entry.path, "%s/%s", path.c_str(), entry.name);
|
||||
}
|
||||
|
||||
// next td contains the date
|
||||
td_element = lxb_dom_collection_element(td_collection, 1);
|
||||
value = lxb_dom_node_text_content(NextChildTextNode(td_element), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
std::vector<std::string> date_time = Util::Split(tmp_string, " ");
|
||||
|
||||
if (date_time.size() > 1)
|
||||
{
|
||||
std::vector<std::string> adate = Util::Split(date_time[0], "-");
|
||||
if (adate.size() == 3)
|
||||
{
|
||||
entry.modified.day = atoi(adate[0].c_str());
|
||||
entry.modified.month = month_map[adate[1]];
|
||||
entry.modified.year = atoi(adate[2].c_str());
|
||||
}
|
||||
|
||||
std::vector<std::string> atime = Util::Split(date_time[1], ":");
|
||||
if (atime.size() == 2)
|
||||
{
|
||||
entry.modified.hours = atoi(atime[0].c_str());
|
||||
entry.modified.minutes = atoi(atime[1].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// next td contains file size, if fize size is "-", then it's a directory
|
||||
td_element = lxb_dom_collection_element(td_collection, 2);
|
||||
value = lxb_dom_node_text_content(NextChildTextNode(td_element), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
|
||||
if (tmp_string.compare("-") == 0)
|
||||
{
|
||||
entry.isDir = true;
|
||||
entry.selectable = true;
|
||||
entry.file_size = 0;
|
||||
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.isDir = false;
|
||||
entry.selectable = true;
|
||||
uint64_t multiplier = 0;
|
||||
std::string size_formatted = tmp_string.substr(0, tmp_string.size()-1);
|
||||
Util::ReplaceAll(size_formatted, ",", "");
|
||||
float fsize = std::stof(size_formatted);
|
||||
switch (tmp_string[tmp_string.size()-1]) {
|
||||
case 'B':
|
||||
multiplier = 1;
|
||||
break;
|
||||
case 'K':
|
||||
multiplier = 1024;
|
||||
break;
|
||||
case 'M':
|
||||
multiplier = 1048576;
|
||||
break;
|
||||
case 'G':
|
||||
multiplier = 1073741824;
|
||||
break;
|
||||
default:
|
||||
multiplier = 1;
|
||||
}
|
||||
entry.file_size = fsize * multiplier;
|
||||
DirEntry::SetDisplaySize(&entry);
|
||||
}
|
||||
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
out.push_back(entry);
|
||||
}
|
||||
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
|
||||
return out;
|
||||
}
|
||||
|
||||
finish:
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef EZ_ARCHIVEORG_H
|
||||
#define EZ_ARCHIVEORG_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "common.h"
|
||||
|
||||
class ArchiveOrgClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
int Connect(const std::string &url, const std::string &username, const std::string &password);
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
|
||||
private:
|
||||
int Login(const std::string &username, const std::string &password);
|
||||
std::string GenerateRandomId(const int len);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -20,6 +20,26 @@ BaseClient::~BaseClient()
|
||||
delete client;
|
||||
};
|
||||
|
||||
int BaseClient::SetCookies(Headers &headers)
|
||||
{
|
||||
if (this->cookies.size() > 0)
|
||||
{
|
||||
std::string cookie;
|
||||
for (std::map<std::string, std::string>::iterator it = this->cookies.begin(); it != this->cookies.end();)
|
||||
{
|
||||
cookie.append(it->first).append("=").append(it->second);
|
||||
if (std::next(it, 1) != this->cookies.end())
|
||||
{
|
||||
cookie.append("; ");
|
||||
}
|
||||
++it;
|
||||
}
|
||||
headers.emplace("Cookie", cookie);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BaseClient::Connect(const std::string &url, const std::string &username, const std::string &password)
|
||||
{
|
||||
this->host_url = url;
|
||||
@@ -81,7 +101,10 @@ int BaseClient::Rmdir(const std::string &path, bool recursive)
|
||||
|
||||
int BaseClient::Size(const std::string &path, int64_t *size)
|
||||
{
|
||||
if (auto res = client->Head(GetFullPath(path)))
|
||||
Headers headers;
|
||||
SetCookies(headers);
|
||||
|
||||
if (auto res = client->Head(GetFullPath(path), headers))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
@@ -90,6 +113,33 @@ int BaseClient::Size(const std::string &path, int64_t *size)
|
||||
*size = atoll(content_length.c_str());
|
||||
return 1;
|
||||
}
|
||||
else if (res->status == 405)// Server doesn't support HEAD request. Try get range with 0 bytes and grab size from the response header
|
||||
// example: Content-Range: bytes 0-10/4372785
|
||||
{
|
||||
Headers headers = {{"Range", "bytes=0-1"}};
|
||||
SetCookies(headers);
|
||||
|
||||
if (auto range_res = client->Get(GetFullPath(path), headers))
|
||||
{
|
||||
if (HTTP_SUCCESS(range_res->status))
|
||||
{
|
||||
if (range_res->has_header("Content-Range"))
|
||||
{
|
||||
std::string range = range_res->get_header_value("Content-Range");
|
||||
std::vector<std::string> range_parts = Util::Split(range, "/");
|
||||
if (range_parts.size() == 2)
|
||||
{
|
||||
*size = atoll(range_parts[1].c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(this->response, "%d - %s", res->status, http_status_message(res->status));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -103,8 +153,10 @@ int BaseClient::Get(const std::string &outputfile, const std::string &path, uint
|
||||
std::ofstream file_stream(outputfile, std::ios::binary);
|
||||
bytes_transfered = 0;
|
||||
sceRtcGetCurrentTick(&prev_tick);
|
||||
Headers headers;
|
||||
SetCookies(headers);
|
||||
|
||||
if (auto res = client->Get(GetFullPath(path),
|
||||
if (auto res = client->Get(GetFullPath(path), headers,
|
||||
[&](const char *data, size_t data_length)
|
||||
{
|
||||
file_stream.write(data, data_length);
|
||||
@@ -124,7 +176,10 @@ int BaseClient::Get(const std::string &outputfile, const std::string &path, uint
|
||||
|
||||
int BaseClient::Get(SplitFile *split_file, const std::string &path, uint64_t offset)
|
||||
{
|
||||
if (auto res = client->Get(GetFullPath(path),
|
||||
Headers headers;
|
||||
SetCookies(headers);
|
||||
|
||||
if (auto res = client->Get(GetFullPath(path), headers,
|
||||
[&](const char *data, size_t data_length)
|
||||
{
|
||||
if (!split_file->IsClosed())
|
||||
@@ -150,6 +205,8 @@ int BaseClient::GetRange(const std::string &path, DataSink &sink, uint64_t size,
|
||||
char range_header[64];
|
||||
sprintf(range_header, "bytes=%lu-%lu", offset, offset + size - 1);
|
||||
Headers headers = {{"Range", range_header}};
|
||||
SetCookies(headers);
|
||||
|
||||
size_t bytes_read = 0;
|
||||
if (auto res = client->Get(GetFullPath(path), headers,
|
||||
[&](const char *data, size_t data_length)
|
||||
@@ -173,6 +230,8 @@ int BaseClient::GetRange(const std::string &path, void *buffer, uint64_t size, u
|
||||
char range_header[64];
|
||||
sprintf(range_header, "bytes=%lu-%lu", offset, offset + size - 1);
|
||||
Headers headers = {{"Range", range_header}};
|
||||
SetCookies(headers);
|
||||
|
||||
size_t bytes_read = 0;
|
||||
std::vector<char> body;
|
||||
if (auto res = client->Get(GetFullPath(path), headers,
|
||||
@@ -232,6 +291,8 @@ int BaseClient::Head(const std::string &path, void *buffer, uint64_t len)
|
||||
char range_header[64];
|
||||
sprintf(range_header, "bytes=%lu-%lu", 0L, len - 1);
|
||||
Headers headers = {{"Range", range_header}};
|
||||
SetCookies(headers);
|
||||
|
||||
size_t bytes_read = 0;
|
||||
std::vector<char> body;
|
||||
if (auto res = client->Get(GetFullPath(path), headers,
|
||||
|
||||
@@ -49,11 +49,14 @@ public:
|
||||
static std::string UnEscape(const std::string &url);
|
||||
|
||||
protected:
|
||||
int SetCookies(httplib::Headers &headers);
|
||||
|
||||
httplib::Client *client;
|
||||
std::string base_path;
|
||||
std::string host_url;
|
||||
char response[512];
|
||||
bool connected = false;
|
||||
std::map<std::string, std::string> cookies;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -24,8 +24,6 @@
|
||||
#define FTP_CLIENT_READ 1
|
||||
#define FTP_CLIENT_WRITE 2
|
||||
|
||||
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
|
||||
|
||||
FtpClient::FtpClient()
|
||||
{
|
||||
mp_ftphandle = static_cast<ftphandle *>(calloc(1, sizeof(ftphandle)));
|
||||
@@ -125,7 +123,7 @@ int FtpClient::Connect(const std::string &url, const std::string &user, const st
|
||||
}
|
||||
mp_ftphandle->handle = sControl;
|
||||
|
||||
if (ReadResponse('2', mp_ftphandle) == 0)
|
||||
if (ReadResponse("2", mp_ftphandle) == 0)
|
||||
{
|
||||
close(mp_ftphandle->handle);
|
||||
mp_ftphandle->handle = 0;
|
||||
@@ -142,7 +140,7 @@ int FtpClient::Connect(const std::string &url, const std::string &user, const st
|
||||
cmd = "USER anonymous";
|
||||
}
|
||||
|
||||
if (!FtpSendCmd(cmd, '3', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "3", mp_ftphandle))
|
||||
{
|
||||
if (mp_ftphandle->ctrl != NULL)
|
||||
return 1;
|
||||
@@ -161,7 +159,7 @@ int FtpClient::Connect(const std::string &url, const std::string &user, const st
|
||||
|
||||
cmd = "PASS " + pass;
|
||||
int ret;
|
||||
if ((ret = FtpSendCmd(cmd, '2', mp_ftphandle)))
|
||||
if ((ret = FtpSendCmd(cmd, "2", mp_ftphandle)))
|
||||
{
|
||||
mp_ftphandle->is_connected = true;
|
||||
}
|
||||
@@ -179,7 +177,7 @@ int FtpClient::Connect(const std::string &url, const std::string &user, const st
|
||||
*
|
||||
* return 1 if proper response received, 0 otherwise
|
||||
*/
|
||||
int FtpClient::FtpSendCmd(const std::string &cmd, char expected_resp, ftphandle *nControl)
|
||||
int FtpClient::FtpSendCmd(const std::string &cmd, const std::string &expected_resp, ftphandle *nControl)
|
||||
{
|
||||
char buf[512];
|
||||
int x;
|
||||
@@ -205,7 +203,7 @@ int FtpClient::FtpSendCmd(const std::string &cmd, char expected_resp, ftphandle
|
||||
* return 0 if first char doesn't match
|
||||
* return 1 if first char matches
|
||||
*/
|
||||
int FtpClient::ReadResponse(char c, ftphandle *nControl)
|
||||
int FtpClient::ReadResponse(const std::string &c, ftphandle *nControl)
|
||||
{
|
||||
char match[5];
|
||||
|
||||
@@ -228,7 +226,7 @@ int FtpClient::ReadResponse(char c, ftphandle *nControl)
|
||||
} while (strncmp(nControl->response, match, 4));
|
||||
}
|
||||
|
||||
if (nControl->response[0] == c)
|
||||
if (c.find(nControl->response[0]) != std::string::npos)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -368,7 +366,7 @@ int FtpClient::FtpAccess(const std::string &path, accesstype type, transfermode
|
||||
return 0;
|
||||
}
|
||||
sprintf(buf, "TYPE %c", mode);
|
||||
if (!FtpSendCmd(buf, '2', nControl))
|
||||
if (!FtpSendCmd(buf, "2", nControl))
|
||||
return 0;
|
||||
|
||||
switch (type)
|
||||
@@ -477,7 +475,7 @@ int FtpClient::FtpAcceptConnection(ftphandle *nData, ftphandle *nControl)
|
||||
{
|
||||
close(nData->handle);
|
||||
nData->handle = 0;
|
||||
ReadResponse('2', nControl);
|
||||
ReadResponse("2", nControl);
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
@@ -521,7 +519,7 @@ int FtpClient::FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode
|
||||
|
||||
memset(&sin, 0, l);
|
||||
sin.in.sin_family = AF_INET;
|
||||
if (!FtpSendCmd("PASV", '2', nControl))
|
||||
if (!FtpSendCmd("PASV", "2", nControl))
|
||||
return -1;
|
||||
cp = strchr(nControl->response, '(');
|
||||
if (cp == NULL)
|
||||
@@ -542,7 +540,7 @@ int FtpClient::FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode
|
||||
{
|
||||
char buf[512];
|
||||
sprintf(buf, "REST %lld", mp_ftphandle->offset);
|
||||
if (!FtpSendCmd(buf, '3', nControl))
|
||||
if (!FtpSendCmd(buf, "3", nControl))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -592,7 +590,7 @@ int FtpClient::FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ReadResponse('1', nControl))
|
||||
if (!ReadResponse("1", nControl))
|
||||
{
|
||||
close(sData);
|
||||
return -1;
|
||||
@@ -717,7 +715,7 @@ int FtpClient::FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode
|
||||
(unsigned char)sin.sa.sa_data[5],
|
||||
(unsigned char)sin.sa.sa_data[0],
|
||||
(unsigned char)sin.sa.sa_data[1]);
|
||||
if (!FtpSendCmd(buf, '2', nControl))
|
||||
if (!FtpSendCmd(buf, "2", nControl))
|
||||
{
|
||||
close(sData);
|
||||
return -1;
|
||||
@@ -727,7 +725,7 @@ int FtpClient::FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode
|
||||
{
|
||||
char buf[512];
|
||||
sprintf(buf, "REST %lld", mp_ftphandle->offset);
|
||||
if (!FtpSendCmd(buf, '3', nControl))
|
||||
if (!FtpSendCmd(buf, "3", nControl))
|
||||
{
|
||||
close(sData);
|
||||
return 0;
|
||||
@@ -747,7 +745,7 @@ int FtpClient::FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!FtpSendCmd(cmd, '1', nControl))
|
||||
if (!FtpSendCmd(cmd, "1", nControl))
|
||||
{
|
||||
FtpClose(*nData);
|
||||
*nData = NULL;
|
||||
@@ -1045,7 +1043,7 @@ int FtpClient::FtpClose(ftphandle *nData)
|
||||
ctrl = nData->ctrl;
|
||||
free(nData);
|
||||
if (ctrl)
|
||||
return ReadResponse('2', ctrl);
|
||||
return ReadResponse("2", ctrl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1061,7 +1059,7 @@ int FtpClient::Quit()
|
||||
strcpy(mp_ftphandle->response, "error: no anwser from server\n");
|
||||
return 0;
|
||||
}
|
||||
FtpSendCmd("QUIT", '2', mp_ftphandle);
|
||||
FtpSendCmd("QUIT", "2", mp_ftphandle);
|
||||
shutdown(mp_ftphandle->handle, SHUT_WR);
|
||||
struct linger lng = {1, 0};
|
||||
setsockopt(mp_ftphandle->handle, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng));
|
||||
@@ -1105,7 +1103,7 @@ int FtpClient::RawRead(void *buf, int max, ftphandle *handle)
|
||||
int FtpClient::Site(const std::string &cmd)
|
||||
{
|
||||
std::string tmp = "SITE " + cmd;
|
||||
if (!FtpSendCmd(tmp, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(tmp, "2", mp_ftphandle))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1118,7 +1116,7 @@ int FtpClient::Site(const std::string &cmd)
|
||||
|
||||
int FtpClient::Raw(const std::string &cmd)
|
||||
{
|
||||
if (!FtpSendCmd(cmd, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "2", mp_ftphandle))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1137,7 +1135,7 @@ int FtpClient::SysType(char *buf, int max)
|
||||
int l = max;
|
||||
char *b = buf;
|
||||
char *s;
|
||||
if (!FtpSendCmd("SYST", '2', mp_ftphandle))
|
||||
if (!FtpSendCmd("SYST", "2", mp_ftphandle))
|
||||
return 0;
|
||||
s = &mp_ftphandle->response[4];
|
||||
while ((--l) && (*s != ' '))
|
||||
@@ -1154,7 +1152,7 @@ int FtpClient::SysType(char *buf, int max)
|
||||
int FtpClient::Mkdir(const std::string &path)
|
||||
{
|
||||
std::string cmd = "MKD " + path;
|
||||
if (!FtpSendCmd(cmd, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "2", mp_ftphandle))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1167,7 +1165,7 @@ int FtpClient::Mkdir(const std::string &path)
|
||||
int FtpClient::Chdir(const std::string &path)
|
||||
{
|
||||
std::string cmd = "CWD " + path;
|
||||
if (!FtpSendCmd(cmd, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "2", mp_ftphandle))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1179,7 +1177,7 @@ int FtpClient::Chdir(const std::string &path)
|
||||
*/
|
||||
int FtpClient::Cdup()
|
||||
{
|
||||
if (!FtpSendCmd("CDUP", '2', mp_ftphandle))
|
||||
if (!FtpSendCmd("CDUP", "2", mp_ftphandle))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1191,7 +1189,7 @@ int FtpClient::Cdup()
|
||||
*/
|
||||
bool FtpClient::Noop()
|
||||
{
|
||||
if (!FtpSendCmd("NOOP", '2', mp_ftphandle))
|
||||
if (!FtpSendCmd("NOOP", "25", mp_ftphandle))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1209,7 +1207,7 @@ bool FtpClient::Ping()
|
||||
int FtpClient::Rmdir(const std::string &path)
|
||||
{
|
||||
std::string cmd = "RMD " + path;
|
||||
if (!FtpSendCmd(cmd, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "2", mp_ftphandle))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1272,11 +1270,11 @@ int FtpClient::Size(const std::string &path, int64_t *size)
|
||||
return 0;
|
||||
|
||||
sprintf(cmd, "TYPE %c", FtpClient::transfermode::image);
|
||||
if (!FtpSendCmd(cmd, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "2", mp_ftphandle))
|
||||
return 0;
|
||||
|
||||
sprintf(cmd, "SIZE %s", path.c_str());
|
||||
if (!FtpSendCmd(cmd, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "2", mp_ftphandle))
|
||||
rv = 0;
|
||||
else
|
||||
{
|
||||
@@ -1408,10 +1406,10 @@ int FtpClient::Put(const std::string &inputfile, const std::string &path, uint64
|
||||
int FtpClient::Rename(const std::string &src, const std::string &dst)
|
||||
{
|
||||
std::string cmd = "RNFR " + src;
|
||||
if (!FtpSendCmd(cmd, '3', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "3", mp_ftphandle))
|
||||
return 0;
|
||||
cmd = "RNTO " + dst;
|
||||
if (!FtpSendCmd(cmd, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "2", mp_ftphandle))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@@ -1420,7 +1418,7 @@ int FtpClient::Rename(const std::string &src, const std::string &dst)
|
||||
int FtpClient::Delete(const std::string &path)
|
||||
{
|
||||
std::string cmd = "DELE " + path;
|
||||
if (!FtpSendCmd(cmd, '2', mp_ftphandle))
|
||||
if (!FtpSendCmd(cmd, "2", mp_ftphandle))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -114,12 +114,12 @@ private:
|
||||
char server[128];
|
||||
int server_port;
|
||||
|
||||
int FtpSendCmd(const std::string &cmd, char expected_resp, ftphandle *nControl);
|
||||
int FtpSendCmd(const std::string &cmd, const std::string &expected_resp, ftphandle *nControl);
|
||||
ftphandle *RawOpen(const std::string &path, accesstype type, transfermode mode);
|
||||
int RawClose(ftphandle *handle);
|
||||
int RawWrite(void *buf, int len, ftphandle *handle);
|
||||
int RawRead(void *buf, int max, ftphandle *handle);
|
||||
int ReadResponse(char c, ftphandle *nControl);
|
||||
int ReadResponse(const std::string &c, ftphandle *nControl);
|
||||
int Readline(char *buf, int max, ftphandle *nControl);
|
||||
int Writeline(char *buf, int len, ftphandle *nData);
|
||||
void ClearHandle();
|
||||
|
||||
+174
-13
@@ -431,7 +431,6 @@ int GDriveClient::Update(const std::string &inputfile, const std::string &path)
|
||||
sceRtcGetCurrentTick(&prev_tick);
|
||||
|
||||
std::ifstream file_stream(inputfile, std::ios::binary);
|
||||
|
||||
std::string id = GetValue(path_id_map, path);
|
||||
std::string drive_id = GetDriveId(path);
|
||||
|
||||
@@ -442,6 +441,7 @@ int GDriveClient::Update(const std::string &inputfile, const std::string &path)
|
||||
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))
|
||||
@@ -457,8 +457,8 @@ int GDriveClient::Update(const std::string &inputfile, const std::string &path)
|
||||
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);
|
||||
uint64_t count = 0;
|
||||
uint64_t bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
do
|
||||
{
|
||||
file_stream.read(buf, bytes_to_transfer);
|
||||
@@ -471,7 +471,84 @@ int GDriveClient::Update(const std::string &inputfile, const std::string &path)
|
||||
},
|
||||
"application/octet-stream"))
|
||||
{
|
||||
// success
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 1;
|
||||
}
|
||||
else if (res->status == 503)
|
||||
{
|
||||
// retry interrupted uploads
|
||||
int retries = 5;
|
||||
while (res->status == 503 && retries > 0)
|
||||
{
|
||||
// Send empty PUT request to get resume position
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("Content-Range", "*/*"));
|
||||
auto resume_res = client->Put(upload_uri, headers, "", 0, "application/octet-stream");
|
||||
retries--;
|
||||
|
||||
if (HTTP_SUCCESS(resume_res->status))
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 1;
|
||||
}
|
||||
else if (resume_res->status == 308)
|
||||
{
|
||||
std::string range_val = resume_res->get_header_value("Range");
|
||||
uint64_t resume_offset = std::stol(Util::Split(Util::Split(range_val, "=")[1], "-")[1]);
|
||||
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("Content-Length", std::to_string(bytes_to_download-resume_offset)));
|
||||
std::string range_value = "bytes " + std::to_string(resume_offset + 1) + "_" + std::to_string(bytes_to_download-1);
|
||||
headers.insert(std::make_pair("Content-Range", range_value));
|
||||
file_stream.seekg(resume_offset+1);
|
||||
|
||||
|
||||
if (res = client->Put(upload_uri, bytes_to_download-resume_offset,
|
||||
[&file_stream, &buf](size_t offset, size_t length, DataSink &sink)
|
||||
{
|
||||
uint64_t count = 0;
|
||||
uint64_t bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
do
|
||||
{
|
||||
file_stream.read(buf, bytes_to_transfer);
|
||||
if (sink.write(buf, bytes_to_transfer))
|
||||
{
|
||||
count += bytes_to_transfer;
|
||||
bytes_transfered += bytes_to_transfer;
|
||||
bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (count < length);
|
||||
return true;
|
||||
},
|
||||
"application/octet-stream"))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// pause 5s before retrying
|
||||
sceKernelUsleep(5000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -505,7 +582,6 @@ int GDriveClient::Put(const std::string &inputfile, const std::string &path, uin
|
||||
sceRtcGetCurrentTick(&prev_tick);
|
||||
|
||||
std::ifstream file_stream(inputfile, std::ios::binary);
|
||||
|
||||
size_t path_pos = path.find_last_of("/");
|
||||
std::string parent_dir;
|
||||
if (path_pos == 0)
|
||||
@@ -528,7 +604,9 @@ int GDriveClient::Put(const std::string &inputfile, const std::string &path, uin
|
||||
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"))
|
||||
|
||||
httplib::Result res;
|
||||
if (res = client->Post(url, headers, post_data.c_str(), post_data.length(), "application/json"))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
@@ -543,21 +621,104 @@ int GDriveClient::Put(const std::string &inputfile, const std::string &path, uin
|
||||
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);
|
||||
uint64_t count = 0;
|
||||
uint64_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);
|
||||
if (sink.write(buf, bytes_to_transfer))
|
||||
{
|
||||
count += bytes_to_transfer;
|
||||
bytes_transfered += bytes_to_transfer;
|
||||
bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (count < length);
|
||||
return true;
|
||||
},
|
||||
"application/octet-stream"))
|
||||
{
|
||||
// success
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 1;
|
||||
}
|
||||
else if (res->status == 503)
|
||||
{
|
||||
// retry interrupted uploads
|
||||
int retries = 5;
|
||||
while (res->status == 503)
|
||||
{
|
||||
// Send empty PUT request to get resume position
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("Content-Range", "*/*"));
|
||||
retries--;
|
||||
|
||||
auto resume_res = client->Put(upload_uri, headers, "", 0, "application/octet-stream");
|
||||
|
||||
if (HTTP_SUCCESS(resume_res->status))
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 1;
|
||||
}
|
||||
else if (resume_res->status == 308)
|
||||
{
|
||||
std::string range_val = resume_res->get_header_value("Range");
|
||||
uint64_t resume_offset = std::stol(Util::Split(Util::Split(range_val, "=")[1], "-")[1]);
|
||||
|
||||
Headers headers;
|
||||
headers.insert(std::make_pair("Content-Length", std::to_string(bytes_to_download-resume_offset)));
|
||||
std::string range_value = "bytes " + std::to_string(resume_offset + 1) + "_" + std::to_string(bytes_to_download-1);
|
||||
headers.insert(std::make_pair("Content-Range", range_value));
|
||||
file_stream.seekg(resume_offset+1);
|
||||
|
||||
if (res = client->Put(upload_uri, bytes_to_download-resume_offset,
|
||||
[&file_stream, &buf](size_t offset, size_t length, DataSink &sink)
|
||||
{
|
||||
uint64_t count = 0;
|
||||
uint64_t bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
do
|
||||
{
|
||||
file_stream.read(buf, bytes_to_transfer);
|
||||
if (sink.write(buf, bytes_to_transfer))
|
||||
{
|
||||
count += bytes_to_transfer;
|
||||
bytes_transfered += bytes_to_transfer;
|
||||
bytes_to_transfer = MIN(GOOGLE_BUF_SIZE, length - count);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (count < length);
|
||||
return true;
|
||||
},
|
||||
"application/octet-stream"))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] buf;
|
||||
file_stream.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// pause 5s before retrying
|
||||
sceKernelUsleep(5000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
#include <json-c/json.h>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/github.h"
|
||||
#include "lang.h"
|
||||
#include "util.h"
|
||||
#include "windows.h"
|
||||
|
||||
using httplib::Client;
|
||||
using httplib::Headers;
|
||||
using httplib::Result;
|
||||
|
||||
int GithubClient::Connect(const std::string &url, const std::string &username, const std::string &password)
|
||||
{
|
||||
if (url.find("https://github.com") == std::string::npos)
|
||||
return 0;
|
||||
|
||||
this->host_url = "https://api.github.com";
|
||||
this->base_path = "/repos" + url.substr(18);
|
||||
Util::Rtrim(this->base_path, "/");
|
||||
this->base_path += "/releases";
|
||||
|
||||
client = new httplib::Client(this->host_url);
|
||||
if (username.length() > 0)
|
||||
client->set_basic_auth(username, password);
|
||||
client->set_follow_location(true);
|
||||
client->set_connection_timeout(10);
|
||||
client->set_read_timeout(30);
|
||||
client->enable_server_certificate_verification(false);
|
||||
m_client.Connect("https://github.com", username, password);
|
||||
|
||||
if (Ping())
|
||||
this->connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<DirEntry> GithubClient::ListDir(const std::string &path)
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
DirEntry entry;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
|
||||
if (!ParseReleases())
|
||||
return out;
|
||||
|
||||
if (path.compare("/") == 0) // return releases as folders
|
||||
{
|
||||
for (std::vector<GitRelease>::iterator release = m_releases.begin(); release != m_releases.end();)
|
||||
{
|
||||
DirEntry entry;
|
||||
entry.isDir = true;
|
||||
entry.selectable = true;
|
||||
entry.file_size = 0;
|
||||
snprintf(entry.directory, 512, "%s", "/");
|
||||
snprintf(entry.name, 256, "%s", release->name.c_str());
|
||||
snprintf(entry.path, 768, "/%s", release->name.c_str());
|
||||
snprintf(entry.display_size, 48, "%s", lang_strings[STR_FOLDER]);
|
||||
entry.modified = release->modified;
|
||||
|
||||
out.push_back(entry);
|
||||
release++;
|
||||
}
|
||||
}
|
||||
else // return assets in the releases matching the path
|
||||
{
|
||||
std::string tag_name = path.substr(1);
|
||||
std::map<std::string, GitAsset> assets = m_assets[tag_name];
|
||||
for (std::map<std::string, GitAsset>::iterator asset = assets.begin(); asset != assets.end();)
|
||||
{
|
||||
DirEntry entry;
|
||||
memset(&entry, 0, sizeof(DirEntry));
|
||||
entry.isDir = false;
|
||||
entry.selectable = true;
|
||||
snprintf(entry.directory, 512, "%s", path.c_str());
|
||||
snprintf(entry.name, 256, "%s", asset->second.name.c_str());
|
||||
snprintf(entry.path, 768, "%s/%s", path.c_str(), asset->second.name.c_str());
|
||||
entry.file_size = asset->second.size;
|
||||
entry.modified = asset->second.modified;
|
||||
DirEntry::SetDisplaySize(&entry);
|
||||
|
||||
out.push_back(entry);
|
||||
asset++;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int GithubClient::Size(const std::string &path, int64_t *size)
|
||||
{
|
||||
if (!ParseReleases())
|
||||
return 0;
|
||||
|
||||
std::vector<std::string> path_parts = Util::Split(path, "/");
|
||||
|
||||
if (path_parts.size() != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*size = m_assets[path_parts[0]][path_parts[1]].size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GithubClient::Head(const std::string &path, void *buffer, uint64_t len)
|
||||
{
|
||||
if (!ParseReleases())
|
||||
return 0;
|
||||
|
||||
std::vector<std::string> path_parts = Util::Split(path, "/");
|
||||
|
||||
if (path_parts.size() != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_client.Head(m_assets[path_parts[0]][path_parts[1]].url, buffer, len);
|
||||
}
|
||||
|
||||
int GithubClient::Get(const std::string &outputfile, const std::string &path, uint64_t offset)
|
||||
{
|
||||
if (!ParseReleases())
|
||||
return 0;
|
||||
|
||||
std::vector<std::string> path_parts = Util::Split(path, "/");
|
||||
|
||||
if (path_parts.size() != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_client.Get(outputfile, m_assets[path_parts[0]][path_parts[1]].url, offset);
|
||||
}
|
||||
|
||||
int GithubClient::Get(SplitFile *split_file, const std::string &path, uint64_t offset)
|
||||
{
|
||||
if (!ParseReleases())
|
||||
return 0;
|
||||
|
||||
std::vector<std::string> path_parts = Util::Split(path, "/");
|
||||
|
||||
if (path_parts.size() != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_client.Get(split_file, m_assets[path_parts[0]][path_parts[1]].url, offset);
|
||||
}
|
||||
|
||||
int GithubClient::GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset)
|
||||
{
|
||||
if (!ParseReleases())
|
||||
return 0;
|
||||
|
||||
std::vector<std::string> path_parts = Util::Split(path, "/");
|
||||
|
||||
if (path_parts.size() != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_client.GetRange(m_assets[path_parts[0]][path_parts[1]].url, buffer, size, offset);
|
||||
}
|
||||
|
||||
int GithubClient::GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset)
|
||||
{
|
||||
if (!ParseReleases())
|
||||
return 0;
|
||||
|
||||
std::vector<std::string> path_parts = Util::Split(path, "/");
|
||||
|
||||
if (path_parts.size() != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_client.GetRange(m_assets[path_parts[0]][path_parts[1]].url, sink, size, offset);
|
||||
}
|
||||
|
||||
bool GithubClient::ParseReleases()
|
||||
{
|
||||
if (!releases_parsed)
|
||||
{
|
||||
if (auto res = client->Get(this->base_path + "?per_page=100&page=1"))
|
||||
{
|
||||
if (HTTP_SUCCESS(res->status))
|
||||
{
|
||||
json_object *jobj = json_tokener_parse(res->body.c_str());
|
||||
struct array_list *areleases = json_object_get_array(jobj);
|
||||
|
||||
for (size_t release_idx = 0; release_idx < areleases->length; ++release_idx)
|
||||
{
|
||||
GitRelease release_entry;
|
||||
|
||||
json_object *release = (json_object *)array_list_get_idx(areleases, release_idx);
|
||||
release_entry.name = std::string(json_object_get_string(json_object_object_get(release, "tag_name")));
|
||||
std::string date_time = std::string(json_object_get_string(json_object_object_get(release, "published_at")));
|
||||
|
||||
auto date_time_array = Util::Split(date_time, "T");
|
||||
auto date_array = Util::Split(date_time_array[0], "-");
|
||||
auto time_array = Util::Split(date_time_array[1], ":");
|
||||
release_entry.modified.year = std::atoi(date_array[0].c_str());
|
||||
release_entry.modified.month = std::atoi(date_array[1].c_str());
|
||||
release_entry.modified.day = std::atoi(date_array[2].c_str());
|
||||
release_entry.modified.hours = std::atoi(time_array[0].c_str());
|
||||
release_entry.modified.minutes = std::atoi(time_array[1].c_str());
|
||||
release_entry.modified.seconds = std::atoi(time_array[2].substr(0,2).c_str());
|
||||
|
||||
json_object *obj_assets = json_object_object_get(release, "assets");
|
||||
if (json_object_get_type(obj_assets) == json_type_array)
|
||||
{
|
||||
struct array_list *aassets = json_object_get_array(obj_assets);
|
||||
std::map<std::string, GitAsset> assets;
|
||||
|
||||
for (size_t asset_idx = 0; asset_idx < aassets->length; ++asset_idx)
|
||||
{
|
||||
GitAsset asset_entry;
|
||||
|
||||
json_object *asset = (json_object *)array_list_get_idx(aassets, asset_idx);
|
||||
asset_entry.name = std::string(json_object_get_string(json_object_object_get(asset, "name")));
|
||||
asset_entry.size = json_object_get_uint64(json_object_object_get(asset, "size"));
|
||||
std::string date_time = std::string(json_object_get_string(json_object_object_get(asset, "updated_at")));
|
||||
asset_entry.url = std::string(json_object_get_string(json_object_object_get(asset, "browser_download_url")));
|
||||
Util::ReplaceAll(asset_entry.url, "https://github.com", "");
|
||||
|
||||
auto date_time_array = Util::Split(date_time, "T");
|
||||
auto date_array = Util::Split(date_time_array[0], "-");
|
||||
auto time_array = Util::Split(date_time_array[1], ":");
|
||||
asset_entry.modified.year = std::atoi(date_array[0].c_str());
|
||||
asset_entry.modified.month = std::atoi(date_array[1].c_str());
|
||||
asset_entry.modified.day = std::atoi(date_array[2].c_str());
|
||||
asset_entry.modified.hours = std::atoi(time_array[0].c_str());
|
||||
asset_entry.modified.minutes = std::atoi(time_array[1].c_str());
|
||||
asset_entry.modified.seconds = std::atoi(time_array[2].substr(0,2).c_str());
|
||||
|
||||
assets.insert(std::make_pair(asset_entry.name, asset_entry));
|
||||
}
|
||||
|
||||
m_assets.insert(std::make_pair(release_entry.name, assets));
|
||||
}
|
||||
|
||||
m_releases.push_back(release_entry);
|
||||
}
|
||||
|
||||
releases_parsed = true;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef EZ_GITHUB_H
|
||||
#define EZ_GITHUB_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "common.h"
|
||||
|
||||
class GithubClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
int Connect(const std::string &url, const std::string &username, const std::string &password);
|
||||
std::vector<DirEntry> ListDir(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 Get(SplitFile *split_file, const std::string &path, uint64_t offset=0);
|
||||
int GetRange(const std::string &path, void *buffer, uint64_t size, uint64_t offset);
|
||||
int GetRange(const std::string &path, DataSink &sink, uint64_t size, uint64_t offset);
|
||||
int Head(const std::string &path, void *buffer, uint64_t len);
|
||||
|
||||
private:
|
||||
struct GitAsset
|
||||
{
|
||||
std::string name;
|
||||
std::string url;
|
||||
DateTime modified;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
struct GitRelease
|
||||
{
|
||||
std::string name;
|
||||
DateTime modified;
|
||||
};
|
||||
|
||||
std::vector<GitRelease> m_releases;
|
||||
std::map<std::string, std::map<std::string, GitAsset>> m_assets;
|
||||
bool releases_parsed = false;
|
||||
BaseClient m_client;
|
||||
|
||||
bool ParseReleases();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,241 @@
|
||||
#include <lexbor/html/parser.h>
|
||||
#include <lexbor/dom/interfaces/element.h>
|
||||
#include <lexbor/dom/interfaces/node.h>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include "common.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/myrient.h"
|
||||
#include "lang.h"
|
||||
#include "util.h"
|
||||
#include "system.h"
|
||||
#include "windows.h"
|
||||
|
||||
using httplib::Client;
|
||||
using httplib::Headers;
|
||||
using httplib::Result;
|
||||
|
||||
static std::map<std::string, int> month_map = {{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4}, {"May", 5}, {"Jun", 6}, {"Jul", 7}, {"Aug", 8}, {"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}};
|
||||
|
||||
std::vector<DirEntry> MyrientClient::ListDir(const std::string &path)
|
||||
{
|
||||
std::vector<DirEntry> out;
|
||||
DirEntry entry;
|
||||
Util::SetupPreviousFolder(path, &entry);
|
||||
out.push_back(entry);
|
||||
|
||||
std::string encoded_path = httplib::detail::encode_url(GetFullPath(path) + "/");
|
||||
if (auto res = client->Get(encoded_path))
|
||||
{
|
||||
lxb_status_t status;
|
||||
lxb_dom_attr_t *attr;
|
||||
lxb_dom_element_t *table_element, *tr_element, *td_element;
|
||||
lxb_html_document_t *document;
|
||||
lxb_dom_collection_t *table_collection;
|
||||
lxb_dom_collection_t *tr_collection;
|
||||
lxb_dom_collection_t *td_collection;
|
||||
std::string tmp_string;
|
||||
const lxb_char_t *value;
|
||||
size_t value_len;
|
||||
|
||||
document = lxb_html_document_create();
|
||||
status = lxb_html_document_parse(document, (lxb_char_t *)res->body.c_str(), res->body.length());
|
||||
if (status != LXB_STATUS_OK)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
table_collection = lxb_dom_collection_make(&document->dom_document, 1);
|
||||
if (table_collection == NULL)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
tr_collection = lxb_dom_collection_make(&document->dom_document, 128);
|
||||
if (tr_collection == NULL)
|
||||
{
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
status = lxb_dom_elements_by_tag_name(lxb_dom_interface_element(document->body),
|
||||
table_collection, (const lxb_char_t *)"table", 5);
|
||||
if (status != LXB_STATUS_OK)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (lxb_dom_collection_length(table_collection) < 1)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lxb_dom_collection_length(table_collection); i++)
|
||||
{
|
||||
table_element = lxb_dom_collection_element(table_collection, i);
|
||||
value = lxb_dom_element_id(table_element, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string.compare("list") == 0)
|
||||
break;
|
||||
table_element = nullptr;
|
||||
}
|
||||
|
||||
if (table_element == nullptr)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
status = lxb_dom_elements_by_tag_name(table_element,
|
||||
tr_collection, (const lxb_char_t *)"tr", 2);
|
||||
if (status != LXB_STATUS_OK && lxb_dom_collection_length(tr_collection) < 2)
|
||||
{
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// skip row 0 , since it has the previous folder header
|
||||
for (size_t i = 2; i < lxb_dom_collection_length(tr_collection); i++)
|
||||
{
|
||||
DirEntry entry;
|
||||
std::string title, aclass;
|
||||
memset(&entry.modified, 0, sizeof(DateTime));
|
||||
|
||||
tr_element = lxb_dom_collection_element(tr_collection, i);
|
||||
|
||||
td_collection = lxb_dom_collection_make(&document->dom_document, 5);
|
||||
status = lxb_dom_elements_by_tag_name(tr_element,
|
||||
td_collection, (const lxb_char_t *)"td", 2);
|
||||
if (status != LXB_STATUS_OK || lxb_dom_collection_length(td_collection) < 3)
|
||||
{
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// td0 contains the <a> tag
|
||||
td_element = lxb_dom_collection_element(td_collection, 0);
|
||||
lxb_dom_node_t *a_node = NextChildElement(td_element);
|
||||
value = lxb_dom_element_local_name(lxb_dom_interface_element(a_node), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string.compare("a") != 0)
|
||||
{
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
goto finish;
|
||||
}
|
||||
value = lxb_dom_element_get_attribute(lxb_dom_interface_element(a_node), (const lxb_char_t *)"href", 4, &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
if (tmp_string[tmp_string.length()-1] == '/')
|
||||
tmp_string = tmp_string.substr(0, tmp_string.length()-1);
|
||||
tmp_string = BaseClient::UnEscape(tmp_string);
|
||||
sprintf(entry.name, "%s", tmp_string.c_str());
|
||||
sprintf(entry.directory, "%s", path.c_str());
|
||||
if (path.length() > 0 && path[path.length() - 1] == '/')
|
||||
{
|
||||
sprintf(entry.path, "%s%s", path.c_str(), entry.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(entry.path, "%s/%s", path.c_str(), entry.name);
|
||||
}
|
||||
|
||||
// next td contains file size, if fize size is "-", then it's a directory
|
||||
td_element = lxb_dom_collection_element(td_collection, 1);
|
||||
value = lxb_dom_node_text_content(NextChildTextNode(td_element), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
|
||||
if (tmp_string.compare("-") == 0)
|
||||
{
|
||||
entry.isDir = true;
|
||||
entry.selectable = true;
|
||||
entry.file_size = 0;
|
||||
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.isDir = false;
|
||||
entry.selectable = true;
|
||||
uint64_t multiplier = 1;
|
||||
std::vector<std::string> fsize_parts = Util::Split(tmp_string, " ");
|
||||
|
||||
float fsize = std::stof(fsize_parts[0]);
|
||||
|
||||
if (fsize_parts.size() > 1)
|
||||
{
|
||||
switch (fsize_parts[1][0])
|
||||
{
|
||||
case 'K':
|
||||
multiplier = 1024;
|
||||
break;
|
||||
case 'M':
|
||||
multiplier = 1048576;
|
||||
break;
|
||||
case 'G':
|
||||
multiplier = 1073741824;
|
||||
break;
|
||||
default:
|
||||
multiplier = 1;
|
||||
}
|
||||
}
|
||||
entry.file_size = fsize * multiplier;
|
||||
DirEntry::SetDisplaySize(&entry);
|
||||
}
|
||||
|
||||
// next td contains the date
|
||||
td_element = lxb_dom_collection_element(td_collection, 2);
|
||||
value = lxb_dom_node_text_content(NextChildTextNode(td_element), &value_len);
|
||||
tmp_string = std::string((const char *)value, value_len);
|
||||
std::vector<std::string> date_time = Util::Split(tmp_string, " ");
|
||||
|
||||
if (date_time.size() > 1)
|
||||
{
|
||||
std::vector<std::string> adate = Util::Split(date_time[0], "-");
|
||||
if (adate.size() == 3)
|
||||
{
|
||||
entry.modified.day = atoi(adate[0].c_str());
|
||||
entry.modified.month = month_map[adate[1]];
|
||||
entry.modified.year = atoi(adate[2].c_str());
|
||||
}
|
||||
|
||||
std::vector<std::string> atime = Util::Split(date_time[1], ":");
|
||||
if (atime.size() == 2)
|
||||
{
|
||||
entry.modified.hours = atoi(atime[0].c_str());
|
||||
entry.modified.minutes = atoi(atime[1].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
lxb_dom_collection_destroy(td_collection, true);
|
||||
out.push_back(entry);
|
||||
}
|
||||
|
||||
lxb_dom_collection_destroy(tr_collection, true);
|
||||
lxb_dom_collection_destroy(table_collection, true);
|
||||
lxb_html_document_destroy(document);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(this->response, "%s", httplib::to_string(res.error()).c_str());
|
||||
return out;
|
||||
}
|
||||
|
||||
finish:
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef EZ_MYRIENT_H
|
||||
#define EZ_MYRIENT_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "http/httplib.h"
|
||||
#include "clients/remote_client.h"
|
||||
#include "clients/baseclient.h"
|
||||
#include "common.h"
|
||||
|
||||
class MyrientClient : public BaseClient
|
||||
{
|
||||
public:
|
||||
std::vector<DirEntry> ListDir(const std::string &path);
|
||||
};
|
||||
|
||||
#endif
|
||||
+8
-4
@@ -152,14 +152,18 @@ namespace CONFIG
|
||||
FS::MkDirs(DATA_PATH);
|
||||
}
|
||||
|
||||
memset(&install_pkg_url, 0, sizeof(install_pkg_url));
|
||||
install_pkg_url.enable_rpi = true;
|
||||
|
||||
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"};
|
||||
"Site 11", "Site 12", "Site 13", "Site 14", "Site 15", "Site 16", "Site 17", "Site 18", "Site 19", "Site 20",
|
||||
"Site 21", "Site 22", "Site 23", "Site 24", "Site 25", "Site 26", "Site 27", "Site 28", "Site 29", "Site 30"};
|
||||
|
||||
langs = { "Default", "Arabic", "Catalan", "Croatian", "Dutch", "English", "Euskera", "French", "Galego", "German", "Greek",
|
||||
"Hungarian", "Indonesian", "Italiano", "Japanese", "Korean", "Polish", "Portuguese_BR", "Russian", "Romanian", "Ryukyuan", "Spanish", "Turkish",
|
||||
"Simplified Chinese", "Traditional Chinese", "Thai", "Ukrainian"};
|
||||
"Hungarian", "Indonesian", "Italiano", "Japanese", "Korean", "Norwegian", "Polish", "Portuguese_BR", "Russian",
|
||||
"Romanian", "Ryukyuan", "Spanish", "Turkish", "Simplified Chinese", "Traditional Chinese", "Thai", "Ukrainian", "Vietnamese"};
|
||||
|
||||
http_servers = {HTTP_SERVER_APACHE, HTTP_SERVER_MS_IIS, HTTP_SERVER_NGINX, HTTP_SERVER_NPX_SERVE, HTTP_SERVER_RCLONE};
|
||||
http_servers = {HTTP_SERVER_APACHE, HTTP_SERVER_MS_IIS, HTTP_SERVER_NGINX, HTTP_SERVER_NPX_SERVE, HTTP_SERVER_RCLONE, HTTP_SERVER_ARCHIVEORG, HTTP_SERVER_MYRIENT, HTTP_SERVER_GITHUB};
|
||||
text_file_extensions = { ".txt", ".ini", ".log", ".json", ".xml", ".html", ".xhtml", ".conf", ".config" };
|
||||
image_file_extensions = { ".bmp", ".jpg", ".jpeg", ".png", ".webp" };
|
||||
|
||||
|
||||
@@ -82,6 +82,9 @@
|
||||
#define HTTP_SERVER_NGINX "Nginx"
|
||||
#define HTTP_SERVER_NPX_SERVE "Serve"
|
||||
#define HTTP_SERVER_RCLONE "RClone"
|
||||
#define HTTP_SERVER_ARCHIVEORG "Archive.org"
|
||||
#define HTTP_SERVER_MYRIENT "Myrient"
|
||||
#define HTTP_SERVER_GITHUB "Github"
|
||||
|
||||
#define MAX_EDIT_FILE_SIZE 32768
|
||||
|
||||
@@ -119,6 +122,10 @@ struct PackageUrlInfo
|
||||
char url[512];
|
||||
char username[33];
|
||||
char password[25];
|
||||
bool enable_alldebrid;
|
||||
bool enable_realdebrid;
|
||||
bool enable_disk_cache;
|
||||
bool enable_rpi;
|
||||
};
|
||||
|
||||
extern std::vector<std::string> sites;
|
||||
|
||||
+980
-480
File diff suppressed because it is too large
Load Diff
+403
-83
File diff suppressed because it is too large
Load Diff
@@ -84,6 +84,8 @@
|
||||
#define BUTTON_RIGHT 0x00000020
|
||||
#define BUTTON_UP 0x00000040
|
||||
#define BUTTON_DOWN 0x00000080
|
||||
#define BUTTON_C 0x00000100
|
||||
#define BUTTON_D 0x00000200
|
||||
|
||||
static uint32_t previous_down = 0;
|
||||
static int repeat_count = 0;
|
||||
@@ -531,8 +533,15 @@ static void ImGui_ImplSDL2_UpdateGamepads()
|
||||
down |= BUTTON_DOWN;
|
||||
else if (SDL_GameControllerGetAxis(game_controller, SDL_CONTROLLER_AXIS_LEFTY) < -ANALOG_THRESHOLD)
|
||||
down |= BUTTON_UP;
|
||||
else if (SDL_GameControllerGetAxis(game_controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) > ANALOG_THRESHOLD)
|
||||
down |= BUTTON_C;
|
||||
else if (SDL_GameControllerGetAxis(game_controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > ANALOG_THRESHOLD)
|
||||
down |= BUTTON_D;
|
||||
|
||||
uint32_t pressed = down & ~previous_down;
|
||||
io.AddKeyEvent(ImGuiKey_C, (pressed & BUTTON_C) != 0);
|
||||
io.AddKeyEvent(ImGuiKey_D, (pressed & BUTTON_D) != 0);
|
||||
|
||||
if (previous_down == down)
|
||||
{
|
||||
uint64_t delay = 300;
|
||||
|
||||
@@ -202,7 +202,8 @@ namespace INSTALLER
|
||||
std::string getRemoteUrl(const std::string path, bool encodeUrl)
|
||||
{
|
||||
if (strlen(remote_settings->username) == 0 && strlen(remote_settings->password) == 0 &&
|
||||
(remoteclient->clientType() == CLIENT_TYPE_WEBDAV || remoteclient->clientType() == CLIENT_TYPE_HTTP_SERVER))
|
||||
(remoteclient->clientType() == CLIENT_TYPE_WEBDAV ||
|
||||
(remoteclient->clientType() == CLIENT_TYPE_HTTP_SERVER && strcmp(remote_settings->http_server_type, HTTP_SERVER_GITHUB) != 0)))
|
||||
{
|
||||
std::string full_url = WebDAVClient::GetHttpUrl(remote_settings->server + path);
|
||||
size_t scheme_pos = full_url.find("://");
|
||||
|
||||
+7
-1
@@ -172,8 +172,11 @@ char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
|
||||
"Temp Directory", // STR_TEMP_DIRECTORY
|
||||
"Real-Debrid", // STR_REALDEBRID
|
||||
"Package install is running in the background. Don't close the app while install is in progress", // STR_BACKGROUND_INSTALL_INPROGRESS
|
||||
"Enable disk caching. Can improve package install speed in cases where connection to remote is slow", // STR_ENABLE_DISC_CACHE_MSG
|
||||
"Enable disk caching. Can improve package install speed in cases where connection to remote is slow, but breaks resuming of install", // STR_ENABLE_DISC_CACHE_MSG
|
||||
"DC", // STR_ENABLE_DISK_CACHE
|
||||
"Install Via AllDebrid", // STR_ENABLE_ALLDEBRID_MSG
|
||||
"Install Via RealDebrid", // STR_ENABLE_REALDEBRID_MSG
|
||||
"Enable Disk Cache", // STR_ENABLE_DISKCACHE_DESC
|
||||
};
|
||||
|
||||
bool needs_extended_font = false;
|
||||
@@ -255,6 +258,9 @@ namespace Lang
|
||||
case ORBIS_SYSTEM_PARAM_LANG_ROMANIAN:
|
||||
sprintf(langFile, "%s", "/app0/assets/langs/Romanian.ini");
|
||||
break;
|
||||
case ORBIS_SYSTEM_PARAM_LANG_NORWEGIAN:
|
||||
sprintf(langFile, "%s", "/app0/assets/langs/Norwegian.ini");
|
||||
break;
|
||||
default:
|
||||
sprintf(langFile, "%s", "/app0/assets/langs/English.ini");
|
||||
break;
|
||||
|
||||
+5
-2
@@ -167,7 +167,10 @@
|
||||
FUNC(STR_REALDEBRID) \
|
||||
FUNC(STR_BACKGROUND_INSTALL_INPROGRESS) \
|
||||
FUNC(STR_ENABLE_DISC_CACHE_MSG) \
|
||||
FUNC(STR_ENABLE_DISK_CACHE)
|
||||
FUNC(STR_ENABLE_DISK_CACHE) \
|
||||
FUNC(STR_ENABLE_ALLDEBRID_MSG) \
|
||||
FUNC(STR_ENABLE_REALDEBRID_MSG) \
|
||||
FUNC(STR_ENABLE_DISKCACHE_DESC)
|
||||
|
||||
#define GET_VALUE(x) x,
|
||||
#define GET_STRING(x) #x,
|
||||
@@ -177,7 +180,7 @@ enum
|
||||
FOREACH_STR(GET_VALUE)
|
||||
};
|
||||
|
||||
#define LANG_STRINGS_NUM 164
|
||||
#define LANG_STRINGS_NUM 167
|
||||
#define LANG_ID_SIZE 64
|
||||
#define LANG_STR_SIZE 384
|
||||
extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE];
|
||||
|
||||
+10
-8
@@ -139,41 +139,43 @@ void InitImgui()
|
||||
sceSystemServiceParamGetInt( ORBIS_SYSTEM_SERVICE_PARAM_ID_LANG, &lang_idx );
|
||||
|
||||
lang = Util::Trim(lang, " ");
|
||||
if (lang.compare("Korean") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_KOREAN))
|
||||
bool use_system_lang = lang.empty() || lang.compare("Default") == 0;
|
||||
|
||||
if (lang.compare("Korean") == 0 || (use_system_lang && lang_idx == ORBIS_SYSTEM_PARAM_LANG_KOREAN))
|
||||
{
|
||||
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, io.Fonts->GetGlyphRangesKorean());
|
||||
}
|
||||
else if (lang.compare("Simplified Chinese") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_CHINESE_S))
|
||||
else if (lang.compare("Simplified Chinese") == 0 || (use_system_lang && lang_idx == ORBIS_SYSTEM_PARAM_LANG_CHINESE_S))
|
||||
{
|
||||
ImFontConfig config;
|
||||
config.OversampleH = 1;
|
||||
config.OversampleV = 1;
|
||||
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, &config, io.Fonts->GetGlyphRangesChineseFull());
|
||||
}
|
||||
else if (lang.compare("Traditional Chinese") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_CHINESE_T))
|
||||
else if (lang.compare("Traditional Chinese") == 0 || (use_system_lang && lang_idx == ORBIS_SYSTEM_PARAM_LANG_CHINESE_T))
|
||||
{
|
||||
ImFontConfig config;
|
||||
config.OversampleH = 1;
|
||||
config.OversampleV = 1;
|
||||
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, &config, io.Fonts->GetGlyphRangesChineseFull());
|
||||
}
|
||||
else if (lang.compare("Japanese") == 0 || lang.compare("Ryukyuan") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_JAPANESE))
|
||||
else if (lang.compare("Japanese") == 0 || lang.compare("Ryukyuan") == 0 || (use_system_lang && lang_idx == ORBIS_SYSTEM_PARAM_LANG_JAPANESE))
|
||||
{
|
||||
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
}
|
||||
else if (lang.compare("Thai") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_THAI))
|
||||
else if (lang.compare("Thai") == 0 || (use_system_lang && lang_idx == ORBIS_SYSTEM_PARAM_LANG_THAI))
|
||||
{
|
||||
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, io.Fonts->GetGlyphRangesThai());
|
||||
}
|
||||
else if (lang.compare("Vietnamese") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_VIETNAMESE))
|
||||
else if (lang.compare("Vietnamese") == 0 || (use_system_lang && lang_idx == ORBIS_SYSTEM_PARAM_LANG_VIETNAMESE))
|
||||
{
|
||||
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, io.Fonts->GetGlyphRangesVietnamese());
|
||||
}
|
||||
else if (lang.compare("Greek") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_GREEK))
|
||||
else if (lang.compare("Greek") == 0 || (use_system_lang && lang_idx == ORBIS_SYSTEM_PARAM_LANG_GREEK))
|
||||
{
|
||||
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, io.Fonts->GetGlyphRangesGreek());
|
||||
}
|
||||
else if (lang.compare("Arabic") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_ARABIC))
|
||||
else if (lang.compare("Arabic") == 0 || (use_system_lang && lang_idx == ORBIS_SYSTEM_PARAM_LANG_ARABIC))
|
||||
{
|
||||
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, arabic);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
#include "clients/nfsclient.h"
|
||||
#include "clients/webdav.h"
|
||||
#include "clients/apache.h"
|
||||
#include "clients/archiveorg.h"
|
||||
#include "clients/github.h"
|
||||
#include "clients/iis.h"
|
||||
#include "clients/myrient.h"
|
||||
#include "clients/nginx.h"
|
||||
#include "clients/npxserve.h"
|
||||
#include "clients/rclone.h"
|
||||
@@ -249,6 +252,12 @@ namespace HttpServer
|
||||
tmp_client = new NpxServeClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_RCLONE) == 0)
|
||||
tmp_client = new RCloneClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_ARCHIVEORG) == 0)
|
||||
tmp_client = new ArchiveOrgClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_MYRIENT) == 0)
|
||||
tmp_client = new MyrientClient();
|
||||
else if (strcmp(remote_settings->http_server_type, HTTP_SERVER_GITHUB) == 0)
|
||||
tmp_client = new GithubClient();
|
||||
}
|
||||
|
||||
if (tmp_client->clientType() != CLIENT_TYPE_GOOGLE)
|
||||
@@ -1174,6 +1183,12 @@ namespace HttpServer
|
||||
|
||||
SplitPkgInstallData *pkg_data = INSTALLER::GetSplitPkgInstallData(hash);
|
||||
|
||||
if (pkg_data == nullptr)
|
||||
{
|
||||
failed(res, 500, "Cannot resume split_inst");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method == "HEAD")
|
||||
{
|
||||
res.status = 204;
|
||||
@@ -1283,7 +1298,7 @@ namespace HttpServer
|
||||
failed(res, 200, lang_strings[STR_CANT_EXTRACT_URL_MSG]);
|
||||
activity_inprogess = false;
|
||||
file_transfering = false;
|
||||
Windows::SetModalMode(true);
|
||||
Windows::SetModalMode(false);
|
||||
return;
|
||||
}
|
||||
delete(filehost);
|
||||
@@ -1296,6 +1311,15 @@ namespace HttpServer
|
||||
|
||||
BaseClient *baseclient = new BaseClient();
|
||||
baseclient->Connect(host, "", "");
|
||||
|
||||
if (!baseclient->FileExists(path))
|
||||
{
|
||||
failed(res, 200, baseclient->LastResponse());
|
||||
activity_inprogess = false;
|
||||
file_transfering = false;
|
||||
Windows::SetModalMode(false);
|
||||
return;
|
||||
}
|
||||
baseclient->Head(path, &header, sizeof(pkg_header));
|
||||
|
||||
if (BE32(header.pkg_magic) == 0x7F434E54)
|
||||
@@ -1313,7 +1337,7 @@ namespace HttpServer
|
||||
failed(res, 200, lang_strings[STR_FAIL_INSTALL_FROM_URL_MSG]);
|
||||
activity_inprogess = false;
|
||||
file_transfering = false;
|
||||
Windows::SetModalMode(true);
|
||||
Windows::SetModalMode(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1343,7 +1367,6 @@ namespace HttpServer
|
||||
failed(res, 200, lang_strings[STR_FAIL_INSTALL_FROM_URL_MSG]);
|
||||
activity_inprogess = false;
|
||||
file_transfering = false;
|
||||
free(install_data);
|
||||
Windows::SetModalMode(false);
|
||||
return;
|
||||
}
|
||||
|
||||
+123
-43
@@ -327,11 +327,13 @@ namespace Windows
|
||||
if (ImGui::BeginCombo("##Site", display_site, ImGuiComboFlags_PopupAlignLeft | ImGuiComboFlags_HeightLargest | ImGuiComboFlags_NoArrowButton))
|
||||
{
|
||||
static char site_id[64];
|
||||
static char site_display[512];
|
||||
for (int n = 0; n < sites.size(); n++)
|
||||
{
|
||||
const bool is_selected = strcmp(sites[n].c_str(), last_site) == 0;
|
||||
sprintf(site_id, "%s %d", lang_strings[STR_SITE], n + 1);
|
||||
if (ImGui::Selectable(site_id, is_selected))
|
||||
sprintf(site_display, "%s %d %s", lang_strings[STR_SITE], n + 1, site_settings[sites[n]].server);
|
||||
if (ImGui::Selectable(site_display, is_selected))
|
||||
{
|
||||
sprintf(last_site, "%s", sites[n].c_str());
|
||||
sprintf(display_site, "%s", site_id);
|
||||
@@ -437,42 +439,45 @@ namespace Windows
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_RPI]);
|
||||
ImGui::SameLine();
|
||||
if (strcmp(remote_settings->http_server_type, HTTP_SERVER_GITHUB) != 0)
|
||||
{
|
||||
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, 70));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_RPI_FTP_SMB_MSG]);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
if (ImGui::Checkbox("###enable_rpi", &remote_settings->enable_rpi))
|
||||
{
|
||||
CONFIG::SaveConfig();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(450, 110));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_RPI_FTP_SMB_MSG]);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_DISK_CACHE]);
|
||||
ImGui::SameLine();
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||
ImGui::TextColored(colors[ImGuiCol_ButtonHovered], "%s:", lang_strings[STR_ENABLE_DISK_CACHE]);
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Checkbox("###enable_disk_cache", &remote_settings->enable_disk_cache))
|
||||
{
|
||||
CONFIG::SaveConfig();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(450, 70));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 440);
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_DISC_CACHE_MSG]);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
if (ImGui::Checkbox("###enable_disk_cache", &remote_settings->enable_disk_cache))
|
||||
{
|
||||
CONFIG::SaveConfig();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(550, 110));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 540);
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_DISC_CACHE_MSG]);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
@@ -876,6 +881,23 @@ namespace Windows
|
||||
ImGui::Columns(1);
|
||||
ImGui::EndChild();
|
||||
EndGroupPanel();
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_C) && !paused)
|
||||
{
|
||||
if (selected_browser & LOCAL_BROWSER)
|
||||
{
|
||||
selected_local_file = local_files[0];
|
||||
selected_action = ACTION_CHANGE_LOCAL_DIRECTORY;
|
||||
}
|
||||
else if (selected_browser & REMOTE_BROWSER)
|
||||
{
|
||||
if (remoteclient != nullptr && remote_files.size() > 0)
|
||||
{
|
||||
selected_remote_file = remote_files[0];
|
||||
selected_action = ACTION_CHANGE_REMOTE_DIRECTORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StatusPanel()
|
||||
@@ -1479,7 +1501,52 @@ namespace Windows
|
||||
{
|
||||
ImVec2 cur_pos = ImGui::GetCursorPos();
|
||||
char id[128];
|
||||
if (ImGui::Button(lang_strings[STR_ONETIME_URL], ImVec2(535, 0)))
|
||||
|
||||
ImGui::Checkbox("##enable_alldebrid_install_uril", &install_pkg_url.enable_alldebrid);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_ALLDEBRID_MSG]);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX()+40);
|
||||
ImGui::Checkbox("##enable_realdebrid_install_uril", &install_pkg_url.enable_realdebrid);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_REALDEBRID_MSG]);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX()+40);
|
||||
ImGui::Checkbox("##enable_rpi_install_url", &install_pkg_url.enable_rpi);
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(550, 110));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 540);
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_RPI_WEBDAV_MSG]);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_RPI]);
|
||||
|
||||
if (install_pkg_url.enable_rpi)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX()+40);
|
||||
ImGui::Checkbox("##enable_diskcache_install_uril", &install_pkg_url.enable_disk_cache);
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(550, 110));
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 540);
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_DISC_CACHE_MSG]);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", lang_strings[STR_ENABLE_DISKCACHE_DESC]);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button(lang_strings[STR_ONETIME_URL], ImVec2(1070, 0)))
|
||||
{
|
||||
ResetImeCallbacks();
|
||||
sprintf(install_pkg_url.url, "%s", "");
|
||||
@@ -1493,14 +1560,6 @@ namespace Windows
|
||||
SetModalMode(false);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
sprintf(id, "%s##favoriteurl", lang_strings[STR_CANCEL]);
|
||||
if (ImGui::Button(id, ImVec2(535, 0)))
|
||||
{
|
||||
select_url_inprogress = false;
|
||||
SetModalMode(false);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
for (int j = 0; j < MAX_FAVORITE_URLS; j++)
|
||||
@@ -1548,6 +1607,13 @@ namespace Windows
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_GamepadFaceRight, false))
|
||||
{
|
||||
select_url_inprogress = false;
|
||||
SetModalMode(false);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
@@ -2576,6 +2642,20 @@ namespace Windows
|
||||
if (ime_result == IME_DIALOG_RESULT_FINISHED)
|
||||
{
|
||||
CONFIG::SetClientType(remote_settings);
|
||||
if (strncasecmp(remote_settings->server, "https://archive.org/", 20) == 0)
|
||||
{
|
||||
sprintf(remote_settings->http_server_type, "%s", HTTP_SERVER_ARCHIVEORG);
|
||||
}
|
||||
else if (strncasecmp(remote_settings->server, "https://myrient.erista.me/", 26) == 0)
|
||||
{
|
||||
sprintf(remote_settings->http_server_type, "%s", HTTP_SERVER_MYRIENT);
|
||||
}
|
||||
else if (strncasecmp(remote_settings->server, "https://github.com/", 19) == 0)
|
||||
{
|
||||
snprintf(remote_settings->http_server_type, 24, "%s", HTTP_SERVER_GITHUB);
|
||||
remote_settings->enable_rpi = false;
|
||||
remote_settings->enable_disk_cache = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user