initial commit

This commit is contained in:
Chee Yee
2023-02-05 03:41:36 -08:00
parent a1b55623fa
commit eb936fab31
108 changed files with 72285 additions and 0 deletions
+2
View File
@@ -9,3 +9,5 @@ install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
.vscode
build
+79
View File
@@ -0,0 +1,79 @@
cmake_minimum_required(VERSION 3.0)
project(ps4_remote_client)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDONT_HAVE_STRUPR")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
include_directories(
source
source/webdav
source/pugixml
)
add_executable(ps4_remote_client
source/pugixml/pugixml.cpp
source/webdav/callback.cpp
source/webdav/client.cpp
source/webdav/fsinfo.cpp
source/webdav/header.cpp
source/webdav/request.cpp
source/webdav/urn.cpp
source/actions.cpp
source/config.cpp
source/fs.cpp
source/ftpclient.cpp
source/gui.cpp
source/getentropy.c
source/ime_dialog.cpp
source/inifile.c
source/installer.cpp
source/lang.cpp
source/main.cpp
source/orbis_jbc.c
source/rtc.cpp
source/smbclient.cpp
source/windows.cpp
source/webdavclient.cpp
source/imgui_draw.cpp
source/imgui_impl_sdl.cpp
source/imgui_impl_sdlrenderer.cpp
source/imgui_tables.cpp
source/imgui_widgets.cpp
source/imgui.cpp
)
add_self(ps4_remote_client)
add_pkg(ps4_remote_client ${CMAKE_SOURCE_DIR}/data "RMTC00001" "PS4 Remote Client" "01.00" 32 0)
target_link_libraries(ps4_remote_client
c
c++
png
z
pthread
SDL2
samplerate
jbc
crypto
ssl
curl
lexbor
smb2
kernel
SceShellCoreUtil
SceSysmodule
SceSystemService
ScePigletv2VSH
ScePrecompiledShaders
SceRtc
SceUserService
ScePad
SceAudioOut
SceSysUtil
SceImeDialog
SceNet
SceBgft
SceAppInstUtil
)
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+75
View File
@@ -0,0 +1,75 @@
STR_CONNECTION_SETTINGS=إعداد الاتصال
STR_SITE=الموقع
STR_LOCAL=محلي
STR_REMOTE=بعيد
STR_MESSAGES=الرسائل
STR_UPDATE_SOFTWARE=تحديث التطبيق
STR_CONNECT_WEBDAV=توصيل
STR_DISCONNECT_WEBDAV=قطع الاتصال
STR_SEARCH=بحث
STR_REFRESH=تحديث
STR_SERVER=الخادم
STR_USERNAME=اسم المستخدم
STR_PASSWORD=كلمة المرور
STR_PORT=المنفذ
STR_PASV=متجاوز
STR_DIRECTORY=المسار
STR_FILTER=الفلتر
STR_YES=نعم
STR_NO=لا
STR_CANCEL=إلغاء
STR_CONTINUE=استمرار
STR_CLOSE=اغلاق
STR_FOLDER=المجلد
STR_FILE=الملف
STR_TYPE=النوع
STR_NAME=الاسم
STR_SIZE=الحجم
STR_DATE=التاريخ
STR_NEW_FOLDER=مجلد جديد
STR_RENAME=أعادة تسمية
STR_DELETE=حذف
STR_UPLOAD=رفع
STR_DOWNLOAD=تحميل
STR_SELECT_ALL=تحديد الكل
STR_CLEAR_ALL=تجاهل الكل
STR_UPLOADING=قيد الرفع
STR_DOWNLOADING=قيد التحميل
STR_OVERWRITE=الكتابة فوق
STR_DONT_OVERWRITE=لاتكتب فوق
STR_ASK_FOR_CONFIRM=أسال لتأكيد
STR_DONT_ASK_CONFIRM=لاتسأل لتأكيد
STR_ALLWAYS_USE_OPTION=استخدم هذا الاختيار بشكل دائم ولاتسأل مجددا
STR_ACTIONS=الإجراءات
STR_CONFIRM=تأكيد
STR_OVERWRITE_OPTIONS=خيارات الاستبدال او الكتابة فوق
STR_PROPERTIES=الخصائص
STR_PROGRESS=التقدم
STR_UPDATES=التحديثات
STR_DEL_CONFIRM_MSG=هل انت متأكد من اجراء حذف حذف الملف او المجلد?
STR_CANCEL_ACTION_MSG=قيد الإلغاء. بأنتظار الاتصال الاخير ليتم إلغائه
STR_FAIL_UPLOAD_MSG=فشل في رفع الملف
STR_FAIL_DOWNLOAD_MSG=فشل في تحميل الملف
STR_FAIL_READ_LOCAL_DIR_MSG=فشل في قراءة محتويات المسار او المجلد غير متوفر.
STR_CONNECTION_CLOSE_ERR_MSG=٤٢٦ أغلق الاتصال.
STR_REMOTE_TERM_CONN_MSG=٤٢٦ الخادم البعيد قطع الإتصال.
STR_FAIL_LOGIN_MSG=٣٠٠ فشل تسجيل الدخول. الرجاء التاكد من اسم المستخدم وكلمة المرور.
STR_FAIL_TIMEOUT_MSG=٤٢٦ فشل. انتهى الاتصال.
STR_FAIL_DEL_DIR_MSG=فشل في حذف المسار
STR_DELETING=قيد الحذف
STR_FAIL_DEL_FILE_MSG=فشل في حذف الملف
STR_DELETED=تم الحذف
STR_LINK=ربط
STR_SHARE=مشاركة
STR_FAILED=٣١٠ فشل
STR_FAIL_CREATE_LOCAL_FILE_MSG= فشل في انشاء الملف في المحلي ٣١٠
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=الحزمة مثبتة مسبقا
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Configuració de connexió
STR_SITE=Lloc
STR_LOCAL=Local
STR_REMOTE=Remot
STR_MESSAGES=Missatges
STR_UPDATE_SOFTWARE=Actualització de programari
STR_CONNECT_WEBDAV=Connectar
STR_DISCONNECT_WEBDAV=Desconnectar
STR_SEARCH=Cercar
STR_REFRESH=Refrescar
STR_SERVER=Servidor
STR_USERNAME=Nom d'usuari
STR_PASSWORD=Mot de pas
STR_PORT=Port
STR_PASV=Passiu
STR_DIRECTORY=Directori
STR_FILTER=Filtre
STR_YES=
STR_NO=No
STR_CANCEL=Cancel·lar
STR_CONTINUE=Continuar
STR_CLOSE=Tancar
STR_FOLDER=Carpeta
STR_FILE=Arxiu
STR_TYPE=Tipus
STR_NAME=Nom
STR_SIZE=Mida
STR_DATE=Data
STR_NEW_FOLDER=Nova carpeta
STR_RENAME=Reanomenar
STR_DELETE=Esborrar
STR_UPLOAD=Pujar
STR_DOWNLOAD=Descarregar
STR_SELECT_ALL=Seleccionar tot
STR_CLEAR_ALL=Netejar tot
STR_UPLOADING=Pujant
STR_DOWNLOADING=Descarregant
STR_OVERWRITE=Sobreescriure
STR_DONT_OVERWRITE=No sobreescriguis
STR_ASK_FOR_CONFIRM=Demana confirmació
STR_DONT_ASK_CONFIRM=No demanis confirmació
STR_ALLWAYS_USE_OPTION=Empra sempre aquesta opció i no tornis a preguntar
STR_ACTIONS=Accions
STR_CONFIRM=Confirmar
STR_OVERWRITE_OPTIONS=Opcions de sobreescritura
STR_PROPERTIES=Propietats
STR_PROGRESS=Progrés
STR_UPDATES=Actualitzacions
STR_DEL_CONFIRM_MSG=Realment vols esborrar aquest fitxer(s)/carpeta(s)?
STR_CANCEL_ACTION_MSG=Cancel·lant. Esperant a que es completi la última acció.
STR_FAIL_UPLOAD_MSG=Errada al pujar fitxer.
STR_FAIL_DOWNLOAD_MSG=Errada al descarregar fitxer.
STR_FAIL_READ_LOCAL_DIR_MSG=Errada al llegir els continguts del directori o el directori no existeix.
STR_CONNECTION_CLOSE_ERR_MSG=426 Connexió tancada.
STR_REMOTE_TERM_CONN_MSG=426 El servidor remot ha tancat la connexió.
STR_FAIL_LOGIN_MSG=300 Inici de sessió fallit. Si us plau, comproba el nom d'usuari i mot de pas.
STR_FAIL_TIMEOUT_MSG=426 Fallit. S'ha superat el temps màxim d'espera de connexió.
STR_FAIL_DEL_DIR_MSG=Errada a l'esborrar la carpeta.
STR_DELETING=Esborrant.
STR_FAIL_DEL_FILE_MSG=Error a l'esborrar el fitxer.
STR_DELETED=Esborrat.
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Postavke spajanja
STR_SITE=Stranica
STR_LOCAL=Lokalno
STR_REMOTE=Daljinsko
STR_MESSAGES=Poruke
STR_UPDATE_SOFTWARE=Ažuriranje softvera
STR_CONNECT_WEBDAV=Spajanje
STR_DISCONNECT_WEBDAV=Odspajanje
STR_SEARCH=Pretražiti
STR_REFRESH=Osvježiti
STR_SERVER=Server
STR_USERNAME=Korisničko ime
STR_PASSWORD=Šifra
STR_PORT=Port
STR_PASV=Pasv
STR_DIRECTORY=Direktorij
STR_FILTER=Filter
STR_YES=Da
STR_NO=Ne
STR_CANCEL=Odustani
STR_CONTINUE=Nastavi
STR_CLOSE=Zatvori
STR_FOLDER=Mapa
STR_FILE=Datoteka
STR_TYPE=Tip
STR_NAME=Ime
STR_SIZE=Veličina
STR_DATE=Datum
STR_NEW_FOLDER=Nova mapa
STR_RENAME=Preimenovati
STR_DELETE=Izbrisati
STR_UPLOAD=Učitati
STR_DOWNLOAD=Skinuti
STR_SELECT_ALL=Izabrati sve
STR_CLEAR_ALL=Pobrisati sve
STR_UPLOADING=Učitavanje
STR_DOWNLOADING=Skidanje
STR_OVERWRITE=Prebrisati
STR_DONT_OVERWRITE=Nemoj prebrisati
STR_ASK_FOR_CONFIRM=Pitati za dopuštenje
STR_DONT_ASK_CONFIRM=Nemoj pitati za dopuštenje
STR_ALLWAYS_USE_OPTION=Uvijek koristiti ovu opciju i ne pitaj me više
STR_ACTIONS=Akcija
STR_CONFIRM=Potvrdi
STR_OVERWRITE_OPTIONS=Prebrisati opcije
STR_PROPERTIES=Svojstva
STR_PROGRESS=Napredak
STR_UPDATES=Ažuriranja
STR_DEL_CONFIRM_MSG=Dali ste sigurni da želite izbrisati ovu/e mapu/e, datoteku/e?
STR_CANCEL_ACTION_MSG=Odustajanje. Čekanje da završi zadnji zadatak
STR_FAIL_UPLOAD_MSG=Neuspješno učitavanje podataka
STR_FAIL_DOWNLOAD_MSG=Neuspješno skidanje podataka
STR_FAIL_READ_LOCAL_DIR_MSG=Neuspješno čitanje sadržaja ova datoteka ili mapa ne postoji
STR_CONNECTION_CLOSE_ERR_MSG=426 Koneckija zatvorena
STR_REMOTE_TERM_CONN_MSG=426 Daljinski server je prekinio konekciju
STR_FAIL_LOGIN_MSG=300 Neuspjelo ulogiranje. Provjerite svoje korisničko ime i šifru.
STR_FAIL_TIMEOUT_MSG=426 Neuspjelo. Konekcijska pauza
STR_FAIL_DEL_DIR_MSG=Neuspješno brisanje mape
STR_DELETING=Brisanje
STR_FAIL_DEL_FILE_MSG=Neuspješno brisanje datoteke
STR_DELETED=Obrisano
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Verbindingsinstellingen
STR_SITE=Site
STR_LOCAL=Lokaal
STR_REMOTE=Extern
STR_MESSAGES=Berichten
STR_UPDATE_SOFTWARE=Update Software
STR_CONNECT_WEBDAV=Verbind met
STR_DISCONNECT_WEBDAV=Verbreek verbinding met
STR_SEARCH=Zoek
STR_REFRESH=Vernieuw
STR_SERVER=Server
STR_USERNAME=Gebruikersnaam
STR_PASSWORD=Wachtwoord
STR_PORT=Poort
STR_PASV=Pasv
STR_DIRECTORY=Locatie
STR_FILTER=Filter
STR_YES=Ja
STR_NO=Nee
STR_CANCEL=Annuleren
STR_CONTINUE=Ga door
STR_CLOSE=Sluit
STR_FOLDER=Map
STR_FILE=Bestand
STR_TYPE=Type
STR_NAME=Naam
STR_SIZE=Grootte
STR_DATE=Datum
STR_NEW_FOLDER=Nieuwe Map
STR_RENAME=Hernoemen
STR_DELETE=Verwijderen
STR_UPLOAD=Upload
STR_DOWNLOAD=Download
STR_SELECT_ALL=Alles selecteren
STR_CLEAR_ALL=Alles wissen
STR_UPLOADING=Uploaden
STR_DOWNLOADING=Downloaden
STR_OVERWRITE=Overschrijven
STR_DONT_OVERWRITE=Niet Overschrijven
STR_ASK_FOR_CONFIRM=Vraag om bevestiging
STR_DONT_ASK_CONFIRM=Vraag niet om bevestiging
STR_ALLWAYS_USE_OPTION=Gebruik altijd deze optie en niet opnieuw vragen
STR_ACTIONS=Acties
STR_CONFIRM=Bevestig
STR_OVERWRITE_OPTIONS=Opties Overschrijven
STR_PROPERTIES=Eigenschappen
STR_PROGRESS=Voortgang
STR_UPDATES=Updates
STR_DEL_CONFIRM_MSG=Ben je zeker dat je dit(deze) bestand(en) of map(pen) wilt verwijderen?
STR_CANCEL_ACTION_MSG=Annuleren. Wachten tot de laatste actie voltooid is.
STR_FAIL_UPLOAD_MSG=Uploaden van bestand mislukt
STR_FAIL_DOWNLOAD_MSG=Downloaden van bestand mislukt
STR_FAIL_READ_LOCAL_DIR_MSG=Lezen van inhoud mislukt, map is onbekend
STR_CONNECTION_CLOSE_ERR_MSG=426 Verbinding verbroken.
STR_REMOTE_TERM_CONN_MSG=426 Externe server heeft de verbinding verbroken.
STR_FAIL_LOGIN_MSG=300 Inloggen mislukt. Controleer je gebruikersnaam of wachtwoord.
STR_FAIL_TIMEOUT_MSG=426 Mislukt. Verbinding time-out.
STR_FAIL_DEL_DIR_MSG=Verwijderen van map mislukt.
STR_DELETING=Verwijderen
STR_FAIL_DEL_FILE_MSG=Verwijderen van bestand mislukt.
STR_DELETED=Verwijderd
+88
View File
@@ -0,0 +1,88 @@
STR_CONNECTION_SETTINGS=Connection Settings
STR_SITE=Site
STR_LOCAL=Local
STR_REMOTE=Remote
STR_MESSAGES=Messages
STR_UPDATE_SOFTWARE=Update Software
STR_CONNECT_WEBDAV=Connect
STR_DISCONNECT_WEBDAV=Disconnect
STR_SEARCH=Search
STR_REFRESH=Refresh
STR_SERVER=Server
STR_USERNAME=Username
STR_PASSWORD=Password
STR_PORT=Port
STR_PASV=Pasv
STR_DIRECTORY=Directory
STR_FILTER=Filter
STR_YES=Yes
STR_NO=No
STR_CANCEL=Cancel
STR_CONTINUE=Continue
STR_CLOSE=Close
STR_FOLDER=Folder
STR_FILE=File
STR_TYPE=Type
STR_NAME=Name
STR_SIZE=Size
STR_DATE=Date
STR_NEW_FOLDER=New Folder
STR_RENAME=Rename
STR_DELETE=Delete
STR_UPLOAD=Upload
STR_DOWNLOAD=Download
STR_SELECT_ALL=Select All
STR_CLEAR_ALL=Clear All
STR_UPLOADING=Uploading
STR_DOWNLOADING=Downloading
STR_OVERWRITE=Overwrite
STR_DONT_OVERWRITE=Don't Overwrite
STR_ASK_FOR_CONFIRM=Ask for Confirmation
STR_DONT_ASK_CONFIRM=Don't Ask for Confirmation
STR_ALLWAYS_USE_OPTION=Always use this option and don't ask again
STR_ACTIONS=Actions
STR_CONFIRM=Confirm
STR_OVERWRITE_OPTIONS=Overwrite Options
STR_PROPERTIES=Properties
STR_PROGRESS=Progress
STR_UPDATES=Updates
STR_DEL_CONFIRM_MSG=Are you sure you want to delete this file(s)/folder(s)?
STR_CANCEL_ACTION_MSG=Canceling. Waiting for last action to complete
STR_FAIL_UPLOAD_MSG=Failed to upload file
STR_FAIL_DOWNLOAD_MSG=Failed to download file
STR_FAIL_READ_LOCAL_DIR_MSG=Failed to read contents of directory or folder does not exist.
STR_CONNECTION_CLOSE_ERR_MSG=426 Connection closed.
STR_REMOTE_TERM_CONN_MSG=426 Remote Server has terminated the connection.
STR_FAIL_LOGIN_MSG=300 Failed Login. Please check your username or password.
STR_FAIL_TIMEOUT_MSG=426 Failed. Connection timeout.
STR_FAIL_DEL_DIR_MSG=Failed to delete directory
STR_DELETING=Deleting
STR_FAIL_DEL_FILE_MSG=Failed to delete file
STR_DELETED=Deleted
STR_LINK=Link
STR_SHARE=Share
STR_FAILED=310 Failed
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 Failed to create file on local
STR_INSTALL=Install
STR_INSTALLING=Installing
STR_INSTALL_SUCCESS=Success
STR_INSTALL_FAILED=Failed
STR_INSTALL_SKIPPED=Skipped
STR_CHECK_HTTP_MSG=Checking connection to remote HTTP Server
STR_FAILED_HTTP_CHECK=Failed connecting to HTTP Server
STR_REMOTE_NOT_HTTP=Remote is not a HTTP Server
STR_INSTALL_FROM_DATA_MSG=Package not in the /data or /mnt/usbX folder
STR_ALREADY_INSTALLED_MSG=Package is already installed
STR_INSTALL_FROM_URL=Install from URL
STR_CANNOT_READ_PKG_HDR_MSG=Could not read package header info
STR_FAVORITE_URLS=Favorite URLs
STR_SLOT=Slot
STR_EDIT=Edit
STR_ONETIME_URL=One Time Url
STR_NOT_A_VALID_PACKAGE=Not a valid Package
STR_WAIT_FOR_INSTALL_MSG=Waiting for Package to finish installing
STR_FAIL_INSTALL_TMP_PKG_MSG=Failed to install pkg file. Please delete the tmp pkg manually
STR_FAIL_TO_OBTAIN_GG_DL_MSG=Failed to obtain google download URL
STR_AUTO_DELETE_TMP_PKG=Auto delete temporary downloaded pkg file after install
STR_PROTOCOL_NOT_SUPPORTED=Protocol not supported
STR_COULD_NOT_RESOLVE_HOST=Could not resolve hostname
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Konexio ezarpenak
STR_SITE=Gunea
STR_LOCAL=Lekuko
STR_REMOTE=Urrunekoa
STR_MESSAGES=Mezuak
STR_UPDATE_SOFTWARE=Eguneratu Softwarea
STR_CONNECT_WEBDAV=Konektatu
STR_DISCONNECT_WEBDAV=Deskonektatu
STR_SEARCH=Bilatu
STR_REFRESH=Freskatu
STR_SERVER=Zerbitzaria
STR_USERNAME=Erabiltzaile izena
STR_PASSWORD=Pasahitza
STR_PORT=Portua
STR_PASV=Pasiboa
STR_DIRECTORY=Direktorioa
STR_FILTER=Iragazkia
STR_YES=Bai
STR_NO=Ez
STR_CANCEL=Utzi
STR_CONTINUE=Jarraitu
STR_CLOSE=Itxi
STR_FOLDER=Karpeta
STR_FILE=Fitxategia
STR_TYPE=Mota
STR_NAME=Izena
STR_SIZE=Tamaina
STR_DATE=Data
STR_NEW_FOLDER=Karpeta berria
STR_RENAME=Aldatu izena
STR_DELETE=Ezabatu
STR_UPLOAD=Kargatu
STR_DOWNLOAD=Deskargatu
STR_SELECT_ALL=Hautatu guztiak
STR_CLEAR_ALL=Garbitu guztiak
STR_UPLOADING=Kargatzen
STR_DOWNLOADING=Deskargatzen
STR_OVERWRITE=Gainidatzi
STR_DONT_OVERWRITE=Ez gainidatzi
STR_ASK_FOR_CONFIRM=Baieztapena eskatu
STR_DONT_ASK_CONFIRM=Ez eskatu baieztapena
STR_ALLWAYS_USE_OPTION=Erabili beti aukera hau eta ez galdetu berriro
STR_ACTIONS=Ekintzak
STR_CONFIRM=Berretsi
STR_OVERWRITE_OPTIONS=Gainidatzi aukerak
STR_PROPERTIES=Propietateak
STR_PROGRESS=Aurrerapena
STR_UPDATES=Eguneraketak
STR_DEL_CONFIRM_MSG=Ziur fitxategi/karpeta hau(k) ezabatu nahi duzula?
STR_CANCEL_ACTION_MSG=Bertan behera uzten. Azken ekintza amaitzeko zain
STR_FAIL_UPLOAD_MSG=Ezin izan da fitxategia kargatu
STR_FAIL_DOWNLOAD_MSG=Ezin izan da deskargatu fitxategia
STR_FAIL_READ_LOCAL_DIR_MSG=Ezin izan da direktorioa edo karpetaren edukia irakurtzean existitzen.
STR_CONNECTION_CLOSE_ERR_MSG=426 Konexioa itxita.
STR_REMOTE_TERM_CONN_MSG=426 Urruneko zerbitzariak konexioa amaitu du.
STR_FAIL_LOGIN_MSG=300 Ezin izan da saioa hasi. Mesedez, egiaztatu zure erabiltzaile-izena edo pasahitza.
STR_FAIL_TIMEOUT_MSG=426 Huts egin. Konexioaren denbora-muga.
STR_FAIL_DEL_DIR_MSG=Ezin izan da ezabatu direktorioa
STR_DELETING=Ezabatzen
STR_FAIL_DEL_FILE_MSG=Ezin izan da fitxategia ezabatu
STR_DELETED=Ezabatu da
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Paramètres de connexion
STR_SITE=Site
STR_LOCAL=Local
STR_REMOTE=A distance
STR_MESSAGES=Messages
STR_UPDATE_SOFTWARE=Mise à jour logicielle
STR_CONNECT_WEBDAV=Connexion
STR_DISCONNECT_WEBDAV=Déconnexion
STR_SEARCH=Rechercher
STR_REFRESH=Rafraîchir
STR_SERVER=Serveur
STR_USERNAME=Identifiant
STR_PASSWORD=Mot de passe
STR_PORT=Port
STR_PASV=Pasv
STR_DIRECTORY=Répertoire
STR_FILTER=Filtre
STR_YES=Oui
STR_NO=Non
STR_CANCEL=Annuler
STR_CONTINUE=Continuer
STR_CLOSE=Fermer
STR_FOLDER=Dossier
STR_FILE=Fichier
STR_TYPE=Type
STR_NAME=Nom
STR_SIZE=Taille
STR_DATE=Date
STR_NEW_FOLDER=Nouveau dossier
STR_RENAME=Renommer
STR_DELETE=Supprimer
STR_UPLOAD=Uploader
STR_DOWNLOAD=Télécharger
STR_SELECT_ALL=Tout sélectionner
STR_CLEAR_ALL=Tout vider
STR_UPLOADING=En cours d'upload
STR_DOWNLOADING=En cours de téléchargement
STR_OVERWRITE=Remplacer
STR_DONT_OVERWRITE=Ne pas remplacer
STR_ASK_FOR_CONFIRM=Demander confirmation
STR_DONT_ASK_CONFIRM=Ne pas demander confirmation
STR_ALLWAYS_USE_OPTION=Toujours utiliser cette option et ne plus jamais me demander
STR_ACTIONS=Actions
STR_CONFIRM=Confirmer
STR_OVERWRITE_OPTIONS=Remplacer les options
STR_PROPERTIES=Propriétés
STR_PROGRESS=Etat d'avancement
STR_UPDATES=Mises à jour
STR_DEL_CONFIRM_MSG=Êtes vous sûr de vouloir supprimer ce(s) fichier(s)/dossier(s) ?
STR_CANCEL_ACTION_MSG=En cours d'annulation. En attente de la fin de la dernière action.
STR_FAIL_UPLOAD_MSG=Echec de l'upload du fichier
STR_FAIL_DOWNLOAD_MSG=Echec du téléchargement du fichier
STR_FAIL_READ_LOCAL_DIR_MSG=Echec de la lecture du contenu du dossier/le dossier n'existe pas.
STR_CONNECTION_CLOSE_ERR_MSG=426 Connexion interrompue
STR_REMOTE_TERM_CONN_MSG=426 Le serveur à distance à interrompu la connexion
STR_FAIL_LOGIN_MSG=300 Echec d'identification. Merci de vérifier votre identifiant et votre mot de passe
STR_FAIL_TIMEOUT_MSG=426 Echec. La connection a mis trop de temps à répondre
STR_FAIL_DEL_DIR_MSG=Echec de la suppression du dossier
STR_DELETING=En cours de suppression
STR_FAIL_DEL_FILE_MSG=Echec de la suppression du fichier
STR_DELETED=Supprimé
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Axustes de conexión
STR_SITE=Sitio
STR_LOCAL=Local
STR_REMOTE=Remoto
STR_MESSAGES=Mensaxes
STR_UPDATE_SOFTWARE=Actualizar Software
STR_CONNECT_WEBDAV=Conectar
STR_DISCONNECT_WEBDAV=Desconectar
STR_SEARCH=Busca
STR_REFRESH=Actualizar
STR_SERVER=Servidor
STR_USERNAME=Nome de usuario
STR_PASSWORD=Contrasinal
STR_PORT=Porto
STR_PASV=Pasivo
STR_DIRECTORY=Directorio
STR_FILTER=Filtro
STR_YES=Si
STR_NO=Non
STR_CANCEL=Cancelar
STR_CONTINUE=Continuar
STR_CLOSE=Pechar
STR_FOLDER=Carpeta
STR_FILE=Arquivo
STR_TYPE=Tipo
STR_NAME=Nome
STR_SIZE=Tamaño
STR_DATE=Data
STR_NEW_FOLDER=Nova carpeta
STR_RENAME=Renomear
STR_DELETE=Eliminar
STR_UPLOAD=Cargar
STR_DOWNLOAD=Descargar
STR_SELECT_ALL=Seleccionar todo
STR_CLEAR_ALL=Limpar todo
STR_UPLOADING=Cargando
STR_DOWNLOADING=Descargando
STR_OVERWRITE=Sobrescribir
STR_DONT_OVERWRITE=Non sobrescribir
STR_ASK_FOR_CONFIRM=Pedir confirmación
STR_DONT_ASK_CONFIRM=Non pidas confirmación
STR_ALLWAYS_USE_OPTION=Use sempre esta opción e non volva preguntar
STR_ACTIONS=Accións
STR_CONFIRM=Confirmar
STR_OVERWRITE_OPTIONS=Opcións de sobrescritura
STR_PROPERTIES=Propiedades
STR_PROGRESS=Progreso
STR_UPDATES=Actualizacións
STR_DEL_CONFIRM_MSG=Estás seguro de que queres eliminar este(s) ficheiro(s)/cartafol(s)?
STR_CANCEL_ACTION_MSG=Cancelando. Agardando a que se complete a última acción.
STR_FAIL_UPLOAD_MSG=Produciuse un erro ao cargar o ficheiro.
STR_FAIL_DOWNLOAD_MSG=Produciuse un erro ao descargar o ficheiro.
STR_FAIL_READ_LOCAL_DIR_MSG=Non se puido ler o contido do directorio ou cartafol non existe.
STR_CONNECTION_CLOSE_ERR_MSG=426 Conexión pechada.
STR_REMOTE_TERM_CONN_MSG=426 O servidor remoto rematou a conexión.
STR_FAIL_LOGIN_MSG=300 Fallou o inicio de sesión. Comproba o teu nome de usuario ou contrasinal.
STR_FAIL_TIMEOUT_MSG=426 Fallou. Superouse o tempo de espera da conexión.
STR_FAIL_DEL_DIR_MSG=Produciuse un erro ao eliminar o directorio.
STR_DELETING=Eliminando...
STR_FAIL_DEL_FILE_MSG=Produciuse un erro ao eliminar o ficheiro.
STR_DELETED=Eliminado.
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Verbindungseinstellungen
STR_SITE=Site
STR_LOCAL=Lokal
STR_REMOTE=Remote
STR_MESSAGES=Nachrichten
STR_UPDATE_SOFTWARE=Software aktualisieren
STR_CONNECT_WEBDAV=Verbinde
STR_DISCONNECT_WEBDAV=Trenne
STR_SEARCH=Suchen
STR_REFRESH=Aktualisieren
STR_SERVER=Server
STR_USERNAME=Benutzername
STR_PASSWORD=Passwort
STR_PORT=Port
STR_PASV=Pasv
STR_DIRECTORY=Verzeichnis
STR_FILTER=Filter
STR_YES=Ja
STR_NO=Nein
STR_CANCEL=Abbrechen
STR_CONTINUE=Fortfahren
STR_CLOSE=Schließen
STR_FOLDER=Ordner
STR_FILE=Datei
STR_TYPE=Typ
STR_NAME=Name
STR_SIZE=Größe
STR_DATE=Datum
STR_NEW_FOLDER=Neuer Ordner
STR_RENAME=Umbenennen
STR_DELETE=Löschen
STR_UPLOAD=Hochladen
STR_DOWNLOAD=Herunterladen
STR_SELECT_ALL=Alles auswählen
STR_CLEAR_ALL=Alles abwählen
STR_UPLOADING=Hochladen
STR_DOWNLOADING=Herunterladen
STR_OVERWRITE=Überschreiben
STR_DONT_OVERWRITE=Nicht Überschreiben
STR_ASK_FOR_CONFIRM=Nach einer Bestätigung fragen
STR_DONT_ASK_CONFIRM=Nicht nach einer Bestätigung fragen
STR_ALLWAYS_USE_OPTION=Immer diese Option verwenden und nicht mehr nachfragen
STR_ACTIONS=Aktionen
STR_CONFIRM=Bestätigen
STR_OVERWRITE_OPTIONS=Optionen für das Überschreiben
STR_PROPERTIES=Eigenschaften
STR_PROGRESS=Fortschritt
STR_UPDATES=Updates
STR_DEL_CONFIRM_MSG=Sind Sie sicher, dass Sie diese Datei(en)/Ordner löschen wollen?
STR_CANCEL_ACTION_MSG=Abbruch. Warte auf Abschluss der letzten Aktion
STR_FAIL_UPLOAD_MSG=Dateiupload gescheitert
STR_FAIL_DOWNLOAD_MSG=Dateidownload gescheitert
STR_FAIL_READ_LOCAL_DIR_MSG=Inhalt des Verzeichnisses konnte nicht gelesen werden oder der Ordner existiert nicht.
STR_CONNECTION_CLOSE_ERR_MSG=426 Verbindung getrennt.
STR_REMOTE_TERM_CONN_MSG=426 Remote Server hat die die Verbindung getrennt.
STR_FAIL_LOGIN_MSG=300 Login fehlgeschlagen. Bitte Passwort und Benutzernamen überprüfen.
STR_FAIL_TIMEOUT_MSG=426 Fehler. Verbindung abgelaufen.
STR_FAIL_DEL_DIR_MSG=Verzeichnis konnte nicht gelöscht werden
STR_DELETING=Löschen
STR_FAIL_DEL_FILE_MSG=Datei konnte nicht gelöscht werden
STR_DELETED=Gelöscht
+75
View File
@@ -0,0 +1,75 @@
STR_CONNECTION_SETTINGS=Ρυθμίσεις Σύνδεσης
STR_SITE=Τοποθεσία
STR_LOCAL=Τοπικό
STR_REMOTE=Remote
STR_MESSAGES=Απομακρυσμένο
STR_UPDATE_SOFTWARE=Ενημέρωση Λογισμικού
STR_CONNECT_WEBDAV=Σύνδεση
STR_DISCONNECT_WEBDAV=Αποσύνδεση
STR_SEARCH=Αναζήτηση
STR_REFRESH=Ανανέωση
STR_SERVER=Διακομιστής
STR_USERNAME=Όνομα Χρήστη
STR_PASSWORD=Κωδικός Πρόσβασης
STR_PORT=Θύρα
STR_PASV=Παθητ.Λειτ.
STR_DIRECTORY=Κατάλογος
STR_FILTER=Φίλτρο
STR_YES=Ναί
STR_NO=Όχι
STR_CANCEL=Ακύρωση
STR_CONTINUE=Συνεχίστε
STR_CLOSE=Κλείσιμο
STR_FOLDER=Φάκελος
STR_FILE=Αρχείο
STR_TYPE=Τύπος
STR_NAME=Όνομα
STR_SIZE=Μέγεθος
STR_DATE=Ημερομηνία
STR_NEW_FOLDER=Νέος Φάκελος
STR_RENAME=Μετονομασία
STR_DELETE=Διαγραφή
STR_UPLOAD=Ανέβασμα
STR_DOWNLOAD=Λήψη
STR_SELECT_ALL=Επιλογή Όλων
STR_CLEAR_ALL=Εκκαθάριση Όλων
STR_UPLOADING=Μεταφόρτωση
STR_DOWNLOADING=Κατεβαίνει
STR_OVERWRITE=Αντικατάσταση
STR_DONT_OVERWRITE=Μην Αντικαταστήσετε
STR_ASK_FOR_CONFIRM=Ρωτήστε για επιβεβαίωση
STR_DONT_ASK_CONFIRM=Μη Ρωτάτε για επιβεβαίωση
STR_ALLWAYS_USE_OPTION=Χρησιμοποιήστε πάντα αυτή την επιλογή και μην ξαναρωτήσετε
STR_ACTIONS=Ενέργειες
STR_CONFIRM=Επιβεβαίωση
STR_OVERWRITE_OPTIONS=Επιλογές Αντικατάστασης
STR_PROPERTIES=Ιδιότητες
STR_PROGRESS=Πρόοδος
STR_UPDATES=Ενημερώσεις
STR_DEL_CONFIRM_MSG=Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό(-α) το(-α) αρχείο(-α)/φάκελο(-ους);
STR_CANCEL_ACTION_MSG=Ακύρωση. Αναμονή για την ολοκλήρωση της τελευταίας ενέργειας
STR_FAIL_UPLOAD_MSG=Απέτυχε το ανέβασμα Αρχείου
STR_FAIL_DOWNLOAD_MSG=Αποτυχία λήψης αρχείου
STR_FAIL_READ_LOCAL_DIR_MSG=Απέτυχε να διαβάσει τα περιεχόμενα του καταλόγου ή ο φάκελος δεν υπάρχει.
STR_CONNECTION_CLOSE_ERR_MSG=426 Η σύνδεση έκλεισε.
STR_REMOTE_TERM_CONN_MSG=426 Ο απομακρυσμένος διακομιστής τερμάτισε τη σύνδεση.
STR_FAIL_LOGIN_MSG=300 Αποτυχημένη σύνδεση. Παρακαλούμε ελέγξτε το όνομα χρήστη ή τον κωδικό πρόσβασής σας.
STR_FAIL_TIMEOUT_MSG=426 Απέτυχε. Η σύνδεση έχει διακοπεί.
STR_FAIL_DEL_DIR_MSG=Απέτυχε η διαγραφή καταλόγου
STR_DELETING=Διαγραφή
STR_FAIL_DEL_FILE_MSG=Αποτυχία διαγραφής αρχείου
STR_DELETED=Διαγράφηκε(-αν)
STR_LINK=Σύνδεσμος
STR_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=Το Package δεν βρίσκεται στο φάκελο /data ή /mnt/usbX
STR_ALREADY_INSTALLED_MSG=Το Package είναι ήδη εγκατεστημένο
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Kapcsolati beállítások
STR_SITE=Site
STR_LOCAL=Helyi
STR_REMOTE=Távoli
STR_MESSAGES=Üzenetek
STR_UPDATE_SOFTWARE=Szoftver frissítés
STR_CONNECT_WEBDAV=Kapcsolódás
STR_DISCONNECT_WEBDAV=Szétkapcsol
STR_SEARCH=Keres
STR_REFRESH=Frissít
STR_SERVER=Szerver
STR_USERNAME=Felhasználónév
STR_PASSWORD=Jelszó
STR_PORT=Port
STR_PASV=Pasv
STR_DIRECTORY=Útvonal
STR_FILTER=Szűrés
STR_YES=Igen
STR_NO=Nem
STR_CANCEL=Kilép
STR_CONTINUE=Folytatás
STR_CLOSE=Bezár
STR_FOLDER=Mappa
STR_FILE=Fájl
STR_TYPE=Típus
STR_NAME=Fájlnév
STR_SIZE=Méret
STR_DATE=Dátum
STR_NEW_FOLDER=Új Mappa
STR_RENAME=Átnevez
STR_DELETE=Töröl
STR_UPLOAD=Feltölt
STR_DOWNLOAD=Letölt
STR_SELECT_ALL=Mind kijelöl
STR_CLEAR_ALL=Kijelölést megszüntet
STR_UPLOADING=Feltöltés
STR_DOWNLOADING=Letöltés
STR_OVERWRITE=Felülír
STR_DONT_OVERWRITE=Ne írja felül
STR_ASK_FOR_CONFIRM=Kérjen megerősítést
STR_DONT_ASK_CONFIRM=Ne kérjen megerősítést
STR_ALLWAYS_USE_OPTION=Mindig ezt a beállítást használja és ne kérdezze úja
STR_ACTIONS=Műveletek
STR_CONFIRM=Megerősít
STR_OVERWRITE_OPTIONS=Felülírási beállítások
STR_PROPERTIES=Tulajdonságok
STR_PROGRESS=Folyamat
STR_UPDATES=Frissítések
STR_DEL_CONFIRM_MSG=Biztos benne, hogy törli a mappá(ka)t vagy a fájl(oka)t?
STR_CANCEL_ACTION_MSG=Kilépés. Várakozás az utolsó művelet befejezésére
STR_FAIL_UPLOAD_MSG=Sikertelen feltöltés
STR_FAIL_DOWNLOAD_MSG=Sikertelen letöltés
STR_FAIL_READ_LOCAL_DIR_MSG=Az útvonal nem érhető el vagy a mappa nem létezik.
STR_CONNECTION_CLOSE_ERR_MSG=426 Kapcsolat megszakadt.
STR_REMOTE_TERM_CONN_MSG=426 Távoli szerver megszakította a kapcsolatot.
STR_FAIL_LOGIN_MSG=300 Sikertelen belépés. Kérem, ellenőrizze a felhasználónevet és a jelszót.
STR_FAIL_TIMEOUT_MSG=426 Hiba. Kapcsolat időtúllépés.
STR_FAIL_DEL_DIR_MSG=Nem sikerült a mappát törölni
STR_DELETING=Törlés
STR_FAIL_DEL_FILE_MSG=A fájl törlése sikertelen
STR_DELETED=Törölve
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Pengaturan Koneksi
STR_SITE=Situs
STR_LOCAL=Lokal
STR_REMOTE=Remote
STR_MESSAGES=Pesan
STR_UPDATE_SOFTWARE=Perbarui Software
STR_CONNECT_WEBDAV=Hubungkan
STR_DISCONNECT_WEBDAV=Putuskan
STR_SEARCH=Cari
STR_REFRESH=Refresh
STR_SERVER=Server
STR_USERNAME=Nama Pengguna
STR_PASSWORD=Kata Sandi
STR_PORT=Port
STR_PASV=Pasv
STR_DIRECTORY=Direktori
STR_FILTER=Filter
STR_YES=Iya
STR_NO=Tidak
STR_CANCEL=Batal
STR_CONTINUE=Lanjut
STR_CLOSE=Tutup
STR_FOLDER=Folder
STR_FILE=File
STR_TYPE=Jenis
STR_NAME=Nama
STR_SIZE=Ukuran
STR_DATE=Tanggal
STR_NEW_FOLDER=Folder Baru
STR_RENAME=Ganti Nama
STR_DELETE=Hapus
STR_UPLOAD=Unggah
STR_DOWNLOAD=Unduh
STR_SELECT_ALL=Pilih Semua
STR_CLEAR_ALL=Lepaskan Semua
STR_UPLOADING=Mengunggah
STR_DOWNLOADING=Mengunduh
STR_OVERWRITE=Overwrite
STR_DONT_OVERWRITE=Jangan Overwrite
STR_ASK_FOR_CONFIRM=Minta untuk Konfirmasi
STR_DONT_ASK_CONFIRM=Jangan minta untuk Konfirmasi
STR_ALLWAYS_USE_OPTION=Selalu gunakan opsi ini dan jangan tanya lagi
STR_ACTIONS=Aksi
STR_CONFIRM=Setuju
STR_OVERWRITE_OPTIONS=Opsi Overwrite
STR_PROPERTIES=Perincian
STR_PROGRESS=Progres
STR_UPDATES=Pembaruan
STR_DEL_CONFIRM_MSG=Apakah kamu mau menghapus file/folder ini?
STR_CANCEL_ACTION_MSG=Membatalkan. Menunggu aksi terakhir untuk selesai
STR_FAIL_UPLOAD_MSG=Pengunggahan file gagal
STR_FAIL_DOWNLOAD_MSG=Pengunduhan file gagal
STR_FAIL_READ_LOCAL_DIR_MSG=Isi direktori gagal dibaca atau folder tidak ada.
STR_CONNECTION_CLOSE_ERR_MSG=426 Koneksi ditutup.
STR_REMOTE_TERM_CONN_MSG=426 Server Remote telah menutupkan koneksi.
STR_FAIL_LOGIN_MSG=300 Login gagal. Tolong perhatikan nama pengguna dan kata sandi.
STR_FAIL_TIMEOUT_MSG=426 Gagal. Waktu koneksi habis/timeout.
STR_FAIL_DEL_DIR_MSG=Direktori gagal dihapus
STR_DELETING=Menghapus
STR_FAIL_DEL_FILE_MSG=File gagal dihapus
STR_DELETED=Dihapus
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Impostazioni di rete
STR_SITE=Sito
STR_LOCAL=Locale
STR_REMOTE=Remoto
STR_MESSAGES=Messaggi
STR_UPDATE_SOFTWARE=Aggiornamento di sistema
STR_CONNECT_WEBDAV=Connesione
STR_DISCONNECT_WEBDAV=Disconnetti da
STR_SEARCH=Cerca
STR_REFRESH=Aggiorna
STR_SERVER=Server
STR_USERNAME=Nome utente
STR_PASSWORD=Password
STR_PORT=Porta
STR_PASV=Pasv
STR_DIRECTORY=Percorso
STR_FILTER=Filtro
STR_YES=
STR_NO=No
STR_CANCEL=Annulla
STR_CONTINUE=Conferma
STR_CLOSE=Chiudi
STR_FOLDER=Cartella
STR_FILE=File
STR_TYPE=Tipo
STR_NAME=Nome
STR_SIZE=Dimensione
STR_DATE=Data
STR_NEW_FOLDER=Nuova cartella
STR_RENAME=Rinomina
STR_DELETE=Elimina
STR_UPLOAD=Carica
STR_DOWNLOAD=Scarica
STR_SELECT_ALL=Seleziona tutto
STR_CLEAR_ALL=Elimina tutto
STR_UPLOADING=Caricando
STR_DOWNLOADING=Scaricando
STR_OVERWRITE=Socrascrivi
STR_DONT_OVERWRITE=Non sovrascrivere
STR_ASK_FOR_CONFIRM=Chiedere conferma
STR_DONT_ASK_CONFIRM=Non chiedere conferma
STR_ALLWAYS_USE_OPTION=Usa sempre questa opzione e non chiedere in seguito
STR_ACTIONS=Opzioni
STR_CONFIRM=Conferma
STR_OVERWRITE_OPTIONS=Sovrascrivere impostazioni
STR_PROPERTIES=Proprietà
STR_PROGRESS=Stato
STR_UPDATES=Aggiornamenti
STR_DEL_CONFIRM_MSG=Sei sicuro di voler eliminare questo(i) file o cartella(e)?
STR_CANCEL_ACTION_MSG=Annulamento. Attendo il completamento dell'ultima operazione eseguita.
STR_FAIL_UPLOAD_MSG=Caricamento fallito
STR_FAIL_DOWNLOAD_MSG=Scaricamento fallito
STR_FAIL_READ_LOCAL_DIR_MSG=Non è stato possibile leggere il contenuto del percorso o la cartella non esiste.
STR_CONNECTION_CLOSE_ERR_MSG=426 Connessione chiusa.
STR_REMOTE_TERM_CONN_MSG=426 Errore. Il server remoto ha terminato la connessione.
STR_FAIL_LOGIN_MSG=300 Login Fallito. Controllare Nome utente o password.
STR_FAIL_TIMEOUT_MSG=426 Errore. La connessione ha richiesto troppo tempo.
STR_FAIL_DEL_DIR_MSG=Impossibile eliminare il percorso
STR_DELETING=Eliminazione
STR_FAIL_DEL_FILE_MSG=Impossibile eliminare il file
STR_DELETED=Eliminato
+75
View File
@@ -0,0 +1,75 @@
STR_CONNECTION_SETTINGS=接続の設定
STR_SITE=サイト
STR_LOCAL=ローカル
STR_REMOTE=リモート
STR_MESSAGES=メッセージ
STR_UPDATE_SOFTWARE=ソフトウェアの更新
STR_CONNECT_WEBDAV=に接続
STR_DISCONNECT_WEBDAV=を切断
STR_SEARCH=検索
STR_REFRESH=更新
STR_SERVER=サーバー
STR_USERNAME=ユーザー名
STR_PASSWORD=パスワード
STR_PORT=ポート
STR_PASV=Pasv
STR_DIRECTORY=ディレクトリ
STR_FILTER=フィルター
STR_YES=はい
STR_NO=いいえ
STR_CANCEL=キャンセル
STR_CONTINUE=続ける
STR_CLOSE=閉じる
STR_FOLDER=フォルダー
STR_FILE=ファイル
STR_TYPE=タイプ
STR_NAME=名前
STR_SIZE=サイズ
STR_DATE=日付
STR_NEW_FOLDER=新しいフォルダー
STR_RENAME=名前を変更
STR_DELETE=消去
STR_UPLOAD=アップロード
STR_DOWNLOAD=ダウンロード
STR_SELECT_ALL=全て選択
STR_CLEAR_ALL=全てクリア
STR_UPLOADING=アップロード
STR_DOWNLOADING=ダウンロード
STR_OVERWRITE=上書き
STR_DONT_OVERWRITE=上書きしない
STR_ASK_FOR_CONFIRM=確認を求める
STR_DONT_ASK_CONFIRM=確認を求めない
STR_ALLWAYS_USE_OPTION=常にこのオプションを使用し、二度と尋ねない
STR_ACTIONS=アクション
STR_CONFIRM=確認
STR_OVERWRITE_OPTIONS=上書きオプション
STR_PROPERTIES=プロパティ
STR_PROGRESS=進捗
STR_UPDATES=更新
STR_DEL_CONFIRM_MSG=このファイル/フォルダを削除してもよろしいですか?
STR_CANCEL_ACTION_MSG=キャンセルします。 最後のアクションが完了するのを待っています
STR_FAIL_UPLOAD_MSG=ファイルのアップロードに失敗しました
STR_FAIL_DOWNLOAD_MSG=ファイルのダウンロードに失敗しました
STR_FAIL_READ_LOCAL_DIR_MSG=ディレクトリまたはフォルダの内容の読み取りに失敗しましたが存在しません。
STR_CONNECTION_CLOSE_ERR_MSG=426 接続が閉じられました。
STR_REMOTE_TERM_CONN_MSG=426 リモートサーバーが接続を終了しました。
STR_FAIL_LOGIN_MSG=300 ログインに失敗しました。 ユーザー名またはパスワードを確認してください。
STR_FAIL_TIMEOUT_MSG=426 失敗した。 接続タイムアウト。
STR_FAIL_DEL_DIR_MSG=ディレクトリの削除に失敗しました
STR_DELETING=削除
STR_FAIL_DEL_FILE_MSG=ファイルの削除に失敗しました
STR_DELETED=削除
STR_LINK=リンク
STR_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=パッケージは既にインストールされています
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=접속 설정
STR_SITE=사이트
STR_LOCAL=로컬
STR_REMOTE=리모트
STR_MESSAGES=메시지
STR_UPDATE_SOFTWARE=소프트웨어 업데이트
STR_CONNECT_WEBDAV=접속
STR_DISCONNECT_WEBDAV=끊기
STR_SEARCH=검색
STR_REFRESH=새로고침
STR_SERVER=서버
STR_USERNAME=사용자
STR_PASSWORD=비밀번호
STR_PORT=포트
STR_PASV=수동형
STR_DIRECTORY=디렉토리
STR_FILTER=필터
STR_YES=
STR_NO=아니오
STR_CANCEL=취소
STR_CONTINUE=계속
STR_CLOSE=닫기
STR_FOLDER=폴더
STR_FILE=파일
STR_TYPE=종류
STR_NAME=이름
STR_SIZE=크기
STR_DATE=일시
STR_NEW_FOLDER=새 폴더
STR_RENAME=이름 변경
STR_DELETE=삭제
STR_UPLOAD=업로드
STR_DOWNLOAD=다운로드
STR_SELECT_ALL=전체 선택
STR_CLEAR_ALL=전체 삭제
STR_UPLOADING=업로드 중
STR_DOWNLOADING=다운로드 중
STR_OVERWRITE=덮어쓰기
STR_DONT_OVERWRITE=덮어쓰기 금지
STR_ASK_FOR_CONFIRM=수락여부를 질문
STR_DONT_ASK_CONFIRM=수락여부를 묻지 않음
STR_ALLWAYS_USE_OPTION=두번다시 묻지 않고 항상 이 설정을 사용
STR_ACTIONS=실행
STR_CONFIRM=확인
STR_OVERWRITE_OPTIONS=덮어쓰기 옵션
STR_PROPERTIES=속성
STR_PROGRESS=진행
STR_UPDATES=업데이트
STR_DEL_CONFIRM_MSG=이 파일(들) 또는 폴더(들)를 삭제하시겠습니까?
STR_CANCEL_ACTION_MSG=취소되었습니다. 마지막 실행이 완료될 때 까지 대기하여 주십시오.
STR_FAIL_UPLOAD_MSG=파일 업로드에 실패하였습니다.
STR_FAIL_DOWNLOAD_MSG=파일 다운로드에 실패하였습니다.
STR_FAIL_READ_LOCAL_DIR_MSG=디렉토리의 내용을 읽을 수 없거나 폴더가 존재하지 않습니다.
STR_CONNECTION_CLOSE_ERR_MSG=426 접속 종료.
STR_REMOTE_TERM_CONN_MSG=426 원격 서버의 접속이 종료되었습니다.
STR_FAIL_LOGIN_MSG=300 로그인에 실패하였습니다. 사용자명과 패스워드를 체크하여 주십시오.
STR_FAIL_TIMEOUT_MSG=426 실패. 접속시간 초과.
STR_FAIL_DEL_DIR_MSG=디렉토리 삭제에 실패하였습니다.
STR_DELETING=삭제 중
STR_FAIL_DEL_FILE_MSG=파일 삭제에 실패하였습니다.
STR_DELETED=삭제됨
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Ustawienia połączenia
STR_SITE=Strona
STR_LOCAL=Lokalny
STR_REMOTE=Zdalny
STR_MESSAGES=Wiadomości
STR_UPDATE_SOFTWARE=Aktualizuj aplikację
STR_CONNECT_WEBDAV=Połącz
STR_DISCONNECT_WEBDAV=Rozłącz
STR_SEARCH=Szukaj
STR_REFRESH=Odśwież
STR_SERVER=Serwer
STR_USERNAME=Użytkownik
STR_PASSWORD=Hasło
STR_PORT=Port
STR_PASV=Pasywny
STR_DIRECTORY=Katalog
STR_FILTER=Filtr
STR_YES=Tak
STR_NO=Nie
STR_CANCEL=Anuluj
STR_CONTINUE=Kontynuuj
STR_CLOSE=Zamknij
STR_FOLDER=Folder
STR_FILE=Plik
STR_TYPE=Typ
STR_NAME=Nazwa
STR_SIZE=Rozmiar
STR_DATE=Data
STR_NEW_FOLDER=Nowy folder
STR_RENAME=Zmień nazwę
STR_DELETE=Usuń
STR_UPLOAD=Wyślij
STR_DOWNLOAD=Pobierz
STR_SELECT_ALL=Zaznacz wszystko
STR_CLEAR_ALL=Wyczyść zaznaczenie
STR_UPLOADING=Wysyłanie
STR_DOWNLOADING=Pobieranie
STR_OVERWRITE=Nadpisz
STR_DONT_OVERWRITE=Nie nadpisuj
STR_ASK_FOR_CONFIRM=Pytaj o potwierdzenie
STR_DONT_ASK_CONFIRM=Nie pytaj o potwierdzenie
STR_ALLWAYS_USE_OPTION=Zawsze używaj tej opcji i nie pytaj ponownie
STR_ACTIONS=Akcje
STR_CONFIRM=Potwierdź
STR_OVERWRITE_OPTIONS=Nadpisz Opcje
STR_PROPERTIES=Właściwości
STR_PROGRESS=Postęp
STR_UPDATES=Aktualizacje
STR_DEL_CONFIRM_MSG=Czy na pewno usunąć wybrane plik(i)/folder(y)?
STR_CANCEL_ACTION_MSG=Anulowanie. Oczekiwanie na zakończenie ostatniej operacji
STR_FAIL_UPLOAD_MSG=Niepowodzenie wysłania pliku
STR_FAIL_DOWNLOAD_MSG=Niepowodzenie pobierania pliku
STR_FAIL_READ_LOCAL_DIR_MSG=Nie udało się odczytać listy plików w katalogu lub katalog nie istnieje.
STR_CONNECTION_CLOSE_ERR_MSG=426 Połączenie zamknięte.
STR_REMOTE_TERM_CONN_MSG=426 Serwer zdalny zakończył połączenie.
STR_FAIL_LOGIN_MSG=300 Nieudane logowanie. Sprawdź nazwę użytkownika i/lub hasło.
STR_FAIL_TIMEOUT_MSG=426 Przekroczono limit czasu oczekiwania na połączenie.
STR_FAIL_DEL_DIR_MSG=Niepowodzenie usuwania katalogu
STR_DELETING=Usuwanie
STR_FAIL_DEL_FILE_MSG=Niepowodzenie usuwania pliku
STR_DELETED=Usunięto
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Configurações de Conexão
STR_SITE=Site
STR_LOCAL=Local
STR_REMOTE=Remoto
STR_MESSAGES=Mensagens
STR_UPDATE_SOFTWARE=Atualizar Software
STR_CONNECT_WEBDAV=Conectar
STR_DISCONNECT_WEBDAV=Desconectar
STR_SEARCH=Pesquisar
STR_REFRESH=Recarregar
STR_SERVER=Servidor
STR_USERNAME=Usuário
STR_PASSWORD=Senha
STR_PORT=Porta
STR_PASV=Salvar
STR_DIRECTORY=Diretório
STR_FILTER=Filtro
STR_YES=Sim
STR_NO=Não
STR_CANCEL=Cancelar
STR_CONTINUE=Continuar
STR_CLOSE=Fechar
STR_FOLDER=Pasta
STR_FILE=Arquivo
STR_TYPE=Tipo
STR_NAME=Nome
STR_SIZE=Tamanho
STR_DATE=Data
STR_NEW_FOLDER=Nova pasta
STR_RENAME=Renomear
STR_DELETE=Deletar
STR_UPLOAD=Carregar
STR_DOWNLOAD=Baixar
STR_SELECT_ALL=Selecionar tudo
STR_CLEAR_ALL=Apagar tudo
STR_UPLOADING=Carregando
STR_DOWNLOADING=Baixando
STR_OVERWRITE=Sobrescrever
STR_DONT_OVERWRITE=Não sobrescrever
STR_ASK_FOR_CONFIRM=Perguntar novamente
STR_DONT_ASK_CONFIRM=Não perguntar novamente
STR_ALLWAYS_USE_OPTION=Usar sempre esta opção e não perguntar novamente
STR_ACTIONS=Ações
STR_CONFIRM=Confirmar
STR_OVERWRITE_OPTIONS=Sobrescrever opções
STR_PROPERTIES=Propriedades
STR_PROGRESS=Progresso
STR_UPDATES=Atualizações
STR_DEL_CONFIRM_MSG=Tem certeza que deseja deletar este(a) arquivo(s)/pasta(s)?
STR_CANCEL_ACTION_MSG=Cancelando. Aguardando a conclusão da última ação
STR_FAIL_UPLOAD_MSG=Falha em carregar o arquivo
STR_FAIL_DOWNLOAD_MSG=Falha em baixar o arquivo
STR_FAIL_READ_LOCAL_DIR_MSG=Falha ao ler o conteúdo do diretório ou pasta não existe.
STR_CONNECTION_CLOSE_ERR_MSG=426 Conexão encerrada.
STR_REMOTE_TERM_CONN_MSG=426 O servidor remoto encerrou a conexão.
STR_FAIL_LOGIN_MSG=300 Falha no login. Favor checar o usuário e senha.
STR_FAIL_TIMEOUT_MSG=426 Falha. Tempo limite de conexão atingido.
STR_FAIL_DEL_DIR_MSG=Falha ao excluir o diretório
STR_DELETING=Excluindo
STR_FAIL_DEL_FILE_MSG=Falha ao excluir o arquivo
STR_DELETED=Excluido
+86
View File
@@ -0,0 +1,86 @@
STR_CONNECTION_SETTINGS=Setări de conecțiune
STR_SITE=Site
STR_LOCAL=Local
STR_REMOTE=Distant
STR_MESSAGES=Mesaje
STR_UPDATE_SOFTWARE=Update de aplicație
STR_CONNECT_WEBDAV=Conecteazăte
STR_DISCONNECT_WEBDAV=Deconecteazăte
STR_SEARCH=Caută
STR_REFRESH=Reîncarca
STR_SERVER=Servere
STR_USERNAME=Nume de utilizator
STR_PASSWORD=Parola
STR_PORT=Portul
STR_PASV=Pasv-ul
STR_DIRECTORY=Directorul
STR_FILTER=Filtru
STR_YES=Da
STR_NO=Nu
STR_CANCEL=Anulează
STR_CONTINUE=Continuă
STR_CLOSE=Închide
STR_FOLDER=Dosar
STR_FILE=Fișier
STR_TYPE=Tip
STR_NAME=Nume
STR_SIZE=Mărime
STR_DATE=Data
STR_NEW_FOLDER=Nou dosar
STR_RENAME=Renumește
STR_DELETE=Șterge
STR_UPLOAD=Încarcă
STR_DOWNLOAD=Descarcă
STR_SELECT_ALL=Selectează tot
STR_CLEAR_ALL=Șterge tot
STR_UPLOADING=Încarcă
STR_DOWNLOADING=Descarcă
STR_OVERWRITE=Suprascrie
STR_DONT_OVERWRITE=Nu suprascrie
STR_ASK_FOR_CONFIRM=Întreabă pentru confirmare
STR_DONT_ASK_CONFIRM=Nu întreba pentru confirmare
STR_ALLWAYS_USE_OPTION=Mereu să folosești această opțiune și să nu mă m-ai întrebi
STR_ACTIONS=Acțiuni
STR_CONFIRM=Confirmă
STR_OVERWRITE_OPTIONS=Suprascrie opțiunile
STR_PROPERTIES=Proprietăți
STR_PROGRESS=Progres
STR_UPDATES=Updateturi
STR_DEL_CONFIRM_MSG=Ești sigur că vrei să ștergi aceast fișier(e)/dosar(e)?
STR_CANCEL_ACTION_MSG=Anulînd. Așteptînd pentru ultima acțiune să fie completată
STR_FAIL_UPLOAD_MSG=Fișierul a eșuat să fie încărcat
STR_FAIL_DOWNLOAD_MSG=Fișierul a eșuat să fie descărcat
STR_FAIL_READ_LOCAL_DIR_MSG=A eșuat să citească conținutul directorului sau dosarului care nu există
STR_CONNECTION_CLOSE_ERR_MSG=426 Conecțiune închisă
STR_REMOTE_TERM_CONN_MSG=426 Servărul distant ți-a terminat conecțiunea.
STR_FAIL_LOGIN_MSG=300 Autentificarea eșuata. Te rog sa verifici numele de utilizator și parola.
STR_FAIL_TIMEOUT_MSG=426 Eșuat. Conecțiune terminată
STR_FAIL_DEL_DIR_MSG=A eșuat sa se ștearga directorul
STR_DELETING=Ștergînd
STR_FAIL_DEL_FILE_MSG=A eșuat ștersul fișierului
STR_DELETED=Șters
STR_LINK=Link
STR_SHARE=Înpărtășește
STR_FAILED=310 Eșuat
STR_FAIL_CREATE_LOCAL_FILE_MSG=310 A eșuat să se creeze fișierul pe local
STR_INSTALL=Instalat
STR_INSTALLING=Instalează
STR_INSTALL_SUCCESS=Succes
STR_INSTALL_FAILED=Eșuat
STR_INSTALL_SKIPPED=Sărit
STR_CHECK_HTTP_MSG=Vericînd conecțiunea la servărul distant HTTP
STR_FAILED_HTTP_CHECK=Eșuat conecțiunea la servărul HTTP
STR_REMOTE_NOT_HTTP=Servărul distant nu este de tip HTTP
STR_INSTALL_FROM_DATA_MSG=Pachetul nu se află in /data sau fișierul /mnt/usbX
STR_ALREADY_INSTALLED_MSG=Pachetul este deja instalat
STR_INSTALL_FROM_URL=Instalează din URL
STR_CANNOT_READ_PKG_HDR_MSG=Nu sa putut citit antetul de info al pachetului
STR_FAVORITE_URLS=URL-urile favorite
STR_SLOT=Slot
STR_EDIT=Editează
STR_ONETIME_URL=Un Url pentru o singură dată
STR_NOT_A_VALID_PACKAGE=Nu este un pachet valid
STR_WAIT_FOR_INSTALL_MSG=Așteptînd pachetul să se termine de instalat
STR_FAIL_INSTALL_TMP_PKG_MSG=A eșuat instalarea fișierului pkg. Te rog șterge pkg temporar manual
STR_FAIL_TO_OBTAIN_GG_DL_MSG=A eșuat obținerea URL-ului de instalare de la google
STR_AUTO_DELETE_TMP_PKG=Auto șterge fișierele temporare pkg instalate dupa instalare
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Настройка Связей
STR_SITE=Сайт
STR_LOCAL=Локальная
STR_REMOTE=Дистанционная
STR_MESSAGES=Сообщения
STR_UPDATE_SOFTWARE=Обновить Программу
STR_CONNECT_WEBDAV=Подключить
STR_DISCONNECT_WEBDAV=Отключить
STR_SEARCH=Найти
STR_REFRESH=Обновить
STR_SERVER=Сервер
STR_USERNAME=Пользователь
STR_PASSWORD=Пароль
STR_PORT=Порт
STR_PASV=Пассивный
STR_DIRECTORY=Директория
STR_FILTER=Фильтр
STR_YES=Да
STR_NO=Нет
STR_CANCEL=Отменить
STR_CONTINUE=Продолжить
STR_CLOSE=Закрыть
STR_FOLDER=Папка
STR_FILE=Файл
STR_TYPE=Тип
STR_NAME=Название
STR_SIZE=Размер
STR_DATE=Дата
STR_NEW_FOLDER=Новая Папка
STR_RENAME=Переименовать
STR_DELETE=Удалить
STR_UPLOAD=Отправить
STR_DOWNLOAD=Получить
STR_SELECT_ALL=Выбрать Все
STR_CLEAR_ALL=Отменить Все
STR_UPLOADING=Получаются
STR_DOWNLOADING=Отправляются
STR_OVERWRITE=Переписать
STR_DONT_OVERWRITE=Не Переписывать
STR_ASK_FOR_CONFIRM=Спросить Подтверждение
STR_DONT_ASK_CONFIRM=Не Спрашивать Подтверждение
STR_ALLWAYS_USE_OPTION=Всегда используйте эту опцию, и больше не спрашивайте
STR_ACTIONS=Действия
STR_CONFIRM=Подтвердить
STR_OVERWRITE_OPTIONS=Переписать Опции
STR_PROPERTIES=Свойства
STR_PROGRESS=Прогресс
STR_UPDATES=Обновления
STR_DEL_CONFIRM_MSG=Уверены, что хотите удалить эти файлы/папки?
STR_CANCEL_ACTION_MSG=Отмена. Ожидаем завершения последнего действия
STR_FAIL_UPLOAD_MSG=Отправление файла неуспешно
STR_FAIL_DOWNLOAD_MSG=Загрузка файла неуспешна
STR_FAIL_READ_LOCAL_DIR_MSG=Чтение содержимых файла или папки неуспешно, или папка не существует
STR_CONNECTION_CLOSE_ERR_MSG=426 Соединениние Закрыто.
STR_REMOTE_TERM_CONN_MSG=426 Дистанционный Сервер Закрыл Соединение.
STR_FAIL_LOGIN_MSG=300 Неуспешный Логин. Пожалуйста проверьте ваше имя пользователя или пароль.
STR_FAIL_TIMEOUT_MSG=426 Неуспешно. Время соединения вышло.
STR_FAIL_DEL_DIR_MSG=Удаление папки неуспешно
STR_DELETING=Удаляются
STR_FAIL_DEL_FILE_MSG=Удаление файла неуспешно
STR_DELETED=Удалено
+75
View File
@@ -0,0 +1,75 @@
STR_CONNECTION_SETTINGS=接続ぬ設定
STR_SITE=サイト
STR_LOCAL=ローカル
STR_REMOTE=リモート
STR_MESSAGES=メッセージ
STR_UPDATE_SOFTWARE=ソフトウェアぬ更新
STR_CONNECT_WEBDAV=んかい接続
STR_DISCONNECT_WEBDAV=切断
STR_SEARCH=検索
STR_REFRESH=更新
STR_SERVER=サーバー
STR_USERNAME=ユーザー名
STR_PASSWORD=パスワード
STR_PORT=ポート
STR_PASV=Pasv
STR_DIRECTORY=ディレクトリ
STR_FILTER=フィルター
STR_YES=はい
STR_NO=うぅーうぅー
STR_CANCEL=キャンセル
STR_CONTINUE=続きーん
STR_CLOSE=くーいん
STR_FOLDER=フォルダー
STR_FILE=ファイル
STR_TYPE=タイプ
STR_NAME=なめー
STR_SIZE=サイズ
STR_DATE=日付
STR_NEW_FOLDER=みーさるフォルダー
STR_RENAME=なめー変更
STR_DELETE=消去
STR_UPLOAD=アップロード
STR_DOWNLOAD=ダウンロード
STR_SELECT_ALL=まじり選択
STR_CLEAR_ALL=まじりクリア
STR_UPLOADING=アップロード
STR_DOWNLOADING=ダウンロード
STR_OVERWRITE=上書き
STR_DONT_OVERWRITE=上書きさん
STR_ASK_FOR_CONFIRM=確認むとぅみーん
STR_DONT_ASK_CONFIRM=確認むとぅみらん
STR_ALLWAYS_USE_OPTION=常にくぬオプション使用しー、二度とぅたんにらん
STR_ACTIONS=アクション
STR_CONFIRM=確認
STR_OVERWRITE_OPTIONS=上書きオプション
STR_PROPERTIES=プロパティ
STR_PROGRESS=進捗
STR_UPDATES=更新
STR_DEL_CONFIRM_MSG=くぬファイル/フォルダ削除しんゆたさいびーが?
STR_CANCEL_ACTION_MSG=キャンセルさびーん。 最後ぬアクションぬしーうわいし待っちょーいびーん
STR_FAIL_UPLOAD_MSG=ファイルぬアップロードんかいしーやんじゃびたん
STR_FAIL_DOWNLOAD_MSG=ファイルぬダウンロードんかいしーやんじゃびたん
STR_FAIL_READ_LOCAL_DIR_MSG=ディレクトリあらんでぃフォルダぬ内容ぬ読み取りんかいしーやんじゃびたんしが存在さびらん。
STR_CONNECTION_CLOSE_ERR_MSG=426 接続ぬくーららりやびたん。
STR_REMOTE_TERM_CONN_MSG=426 リモートサーバーぬ接続終了さびたん。
STR_FAIL_LOGIN_MSG=300 ログインんかいしーやんじゃびたん。 ユーザー名あらんでぃパスワード確認しくぃみそーれー。
STR_FAIL_TIMEOUT_MSG=426 しーやんたん。 接続タイムアウト。
STR_FAIL_DEL_DIR_MSG=ディレクトリぬ削除んかいしーやんじゃびたん
STR_DELETING=削除
STR_FAIL_DEL_FILE_MSG=ファイルぬ削除んかいしーやんじゃびたん
STR_DELETED=削除
STR_LINK=リンク
STR_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=パッケージェーしでぃにインストールさりとーいびーん
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=连接设置
STR_SITE=地点
STR_LOCAL=当地的
STR_REMOTE=偏僻的
STR_MESSAGES=留言
STR_UPDATE_SOFTWARE=更新软件
STR_CONNECT_WEBDAV=连接
STR_DISCONNECT_WEBDAV=断开
STR_SEARCH=搜索
STR_REFRESH=刷新
STR_SERVER=服务器
STR_USERNAME=用户名
STR_PASSWORD=密码
STR_PORT=港口
STR_PASV=帕夫
STR_DIRECTORY=目录
STR_FILTER=筛选
STR_YES=是的
STR_NO=
STR_CANCEL=取消
STR_CONTINUE=继续
STR_CLOSE=关闭
STR_FOLDER=文件夹
STR_FILE=文件
STR_TYPE=类型
STR_NAME=姓名
STR_SIZE=尺寸
STR_DATE=日期
STR_NEW_FOLDER=新建文件夹
STR_RENAME=改名
STR_DELETE=删除
STR_UPLOAD=上传
STR_DOWNLOAD=下载
STR_SELECT_ALL=全选
STR_CLEAR_ALL=全部清除
STR_UPLOADING=上传
STR_DOWNLOADING=下载
STR_OVERWRITE=覆盖
STR_DONT_OVERWRITE=不要覆盖
STR_ASK_FOR_CONFIRM=要求确认
STR_DONT_ASK_CONFIRM=不要要求确认
STR_ALLWAYS_USE_OPTION=始终使用此选项,不再询问
STR_ACTIONS=行动
STR_CONFIRM=确认
STR_OVERWRITE_OPTIONS=覆盖选项
STR_PROPERTIES=特性
STR_PROGRESS=进步
STR_UPDATES=更新
STR_DEL_CONFIRM_MSG=您确定要删除此文件/文件夹吗?
STR_CANCEL_ACTION_MSG=取消。 等待最后一个动作完成
STR_FAIL_UPLOAD_MSG=上传文件失败
STR_FAIL_DOWNLOAD_MSG=下载文件失败
STR_FAIL_READ_LOCAL_DIR_MSG=读取目录内容失败或文件夹不存在。
STR_CONNECTION_CLOSE_ERR_MSG=426 连接已关闭。
STR_REMOTE_TERM_CONN_MSG=426 远程服务器已终止连接。
STR_FAIL_LOGIN_MSG=300 登录失败。 请检查您的用户名或密码。
STR_FAIL_TIMEOUT_MSG=426 失败。 连接超时。
STR_FAIL_DEL_DIR_MSG=删除目录失败
STR_DELETING=删除
STR_FAIL_DEL_FILE_MSG=删除文件失败
STR_DELETED=已删除
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=Ajustes de conexión
STR_SITE=Sitio
STR_LOCAL=Local
STR_REMOTE=Remoto
STR_MESSAGES=Mensajes
STR_UPDATE_SOFTWARE=Actualizar software
STR_CONNECT_WEBDAV=Conectar
STR_DISCONNECT_WEBDAV=Desconectar
STR_SEARCH=Buscar
STR_REFRESH=Actualizar
STR_SERVER=Servidor
STR_USERNAME=Usuario
STR_PASSWORD=Contraseña
STR_PORT=Puerto
STR_PASV=Pasv
STR_DIRECTORY=Directorio
STR_FILTER=Filtro
STR_YES=
STR_NO=No
STR_CANCEL=Cancelar
STR_CONTINUE=Continuar
STR_CLOSE=Cerrar
STR_FOLDER=Carpeta
STR_FILE=Archivo
STR_TYPE=Tipo
STR_NAME=Nombre
STR_SIZE=Tamaño
STR_DATE=Fecha
STR_NEW_FOLDER=Nueva carpeta
STR_RENAME=Cambiar nombre
STR_DELETE=Eliminar
STR_UPLOAD=Enviar
STR_DOWNLOAD=Descargar
STR_SELECT_ALL=Seleccionar todo
STR_CLEAR_ALL=Deseleccionar todo
STR_UPLOADING=Enviando
STR_DOWNLOADING=Descargando
STR_OVERWRITE=Sobrescribir
STR_DONT_OVERWRITE=No sobrescribir
STR_ASK_FOR_CONFIRM=Pedir confirmación
STR_DONT_ASK_CONFIRM=No pedir confirmación
STR_ALLWAYS_USE_OPTION=Usar siempre esta opción y no volver a preguntar
STR_ACTIONS=Acciones
STR_CONFIRM=Confirmación
STR_OVERWRITE_OPTIONS=Opciones de sobrescritura
STR_PROPERTIES=Propiedades
STR_PROGRESS=Progreso
STR_UPDATES=Actualizaciones
STR_DEL_CONFIRM_MSG=¿Seguro que deseas eliminar este(estos) archivo(s) o carpeta(s)?
STR_CANCEL_ACTION_MSG=Cancelando. Esperando a finalizar la última acción
STR_FAIL_UPLOAD_MSG=Error al enviar el archivo
STR_FAIL_DOWNLOAD_MSG=Error al descargar el archivo
STR_FAIL_READ_LOCAL_DIR_MSG=Error al leer los contenidos del directorio o la carpeta no existe.
STR_CONNECTION_CLOSE_ERR_MSG=426: conexión cerrada.
STR_REMOTE_TERM_CONN_MSG=426: el servidor remoto ha cerrado la conexión.
STR_FAIL_LOGIN_MSG=300: error al iniciar sesión. Comprueba tu nombre de usuario y contraseña.
STR_FAIL_TIMEOUT_MSG=426: error se agotó el tiempo de espera.
STR_FAIL_DEL_DIR_MSG=Error al eliminar el directorio
STR_DELETING=Eliminando
STR_FAIL_DEL_FILE_MSG=Error al eliminar el archivo
STR_DELETED=Eliminado
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=การตั้งค่าการเชื่อมต่อ
STR_SITE=เวปไซต์
STR_LOCAL=ภายใน
STR_REMOTE=ระยะไกล
STR_MESSAGES=ข้อความ
STR_UPDATE_SOFTWARE=อัปเดตซอฟต์แวร์
STR_CONNECT_WEBDAV=เชื่อมต่อ
STR_DISCONNECT_WEBDAV=ยกเลิกการเชื่อมต่อ
STR_SEARCH=ค้นหา
STR_REFRESH=รีเฟรช
STR_SERVER=เซิร์ฟเวอร์
STR_USERNAME=ชื่อผู้ใช้
STR_PASSWORD=รหัสผ่าน
STR_PORT=พอร์ต
STR_PASV=Pasv
STR_DIRECTORY=ไดเรกทอรี
STR_FILTER=ฟิลเตอร์
STR_YES=ใช่
STR_NO=ไม่
STR_CANCEL=ยกเลิก
STR_CONTINUE=ดำเนินการต่อ
STR_CLOSE=ปิด
STR_FOLDER=โฟลเดอร์
STR_FILE=ไฟล์
STR_TYPE=ประเภท
STR_NAME=ชื่อ
STR_SIZE=ขนาด
STR_DATE=วันที่
STR_NEW_FOLDER=โฟลเดอร์ใหม่
STR_RENAME=เปลี่ยนชื่อ
STR_DELETE=ลบ
STR_UPLOAD=อัปโหลด
STR_DOWNLOAD=ดาวน์โหลด
STR_SELECT_ALL=เลือกทั้งหมด
STR_CLEAR_ALL=ล้างทั้งหมด
STR_UPLOADING=กำลังอัปโหลด
STR_DOWNLOADING=กำลังดาวน์โหลด
STR_OVERWRITE=เขียนทับ
STR_DONT_OVERWRITE=ไม่เขียนทับ
STR_ASK_FOR_CONFIRM=ไม่ต้องยืนยัน
STR_DONT_ASK_CONFIRM=ต้องยืนยัน
STR_ALLWAYS_USE_OPTION=ใช้ตัวเลือกนี้อยู่เสมอและไม่แสดงอีก
STR_ACTIONS=การดำเนินการ
STR_CONFIRM=ยืนยัน
STR_OVERWRITE_OPTIONS=ตัวเลือกเขียนทับ
STR_PROPERTIES=คุณสมบัติ
STR_PROGRESS=ความคืบหน้า
STR_UPDATES=อัปเดต
STR_DEL_CONFIRM_MSG=คุณแน่ใจหรือว่าต้องการลบไฟล์/โฟลเดอร์นี้?
STR_CANCEL_ACTION_MSG=ยกเลิก กำลังรอการดำเนินการสุดท้าย
STR_FAIL_UPLOAD_MSG=อัปโหลดไฟล์ล้มเหลว
STR_FAIL_DOWNLOAD_MSG=ดาวน์โหลดไฟล์ล้มเหลว
STR_FAIL_READ_LOCAL_DIR_MSG=ไม่สามารถอ่านเนื้อหาของไดเรกทอรีหรือโฟลเดอร์นี้ได้ หรือโฟลเดอร์ไม่มีอยู่
STR_CONNECTION_CLOSE_ERR_MSG=426 การเชื่อมต่อถูกปิด
STR_REMOTE_TERM_CONN_MSG=426 เซิร์ฟเวอร์ระยะไกลได้ยุติการเชื่อมต่อ
STR_FAIL_LOGIN_MSG=300 การเข้าสู่ระบบล้มเหลว กรุณาตรวจสอบชื่อผู้ใช้หรือรหัสผ่านของคุณ
STR_FAIL_TIMEOUT_MSG=426 ล้มเหลว หมดเวลาการเชื่อมต่อ
STR_FAIL_DEL_DIR_MSG=ไม่สามารถลบไดเรกทอรี
STR_DELETING=กำลังลบ
STR_FAIL_DEL_FILE_MSG=ไม่สามารถลบไฟล์
STR_DELETED=ลบแล้ว
+61
View File
@@ -0,0 +1,61 @@
STR_CONNECTION_SETTINGS=連接設定
STR_SITE=主機
STR_LOCAL=本地
STR_REMOTE=遠端
STR_MESSAGES=狀態
STR_UPDATE_SOFTWARE=更新版本
STR_CONNECT_WEBDAV=連接
STR_DISCONNECT_WEBDAV=中斷
STR_SEARCH=搜尋
STR_REFRESH=重新整理
STR_SERVER=伺服器
STR_USERNAME=使用者
STR_PASSWORD=密碼
STR_PORT=連接埠
STR_PASV=Pasv
STR_DIRECTORY=路徑
STR_FILTER=篩選
STR_YES=
STR_NO=
STR_CANCEL=取消
STR_CONTINUE=繼續
STR_CLOSE=關閉
STR_FOLDER=資料夾
STR_FILE=檔案
STR_TYPE=類型
STR_NAME=名稱
STR_SIZE=大小
STR_DATE=日期
STR_NEW_FOLDER=新建資料夾
STR_RENAME=更名
STR_DELETE=刪除
STR_UPLOAD=上傳
STR_DOWNLOAD=下載
STR_SELECT_ALL=全選
STR_CLEAR_ALL=全部清除
STR_UPLOADING=上傳
STR_DOWNLOADING=下載
STR_OVERWRITE=覆蓋
STR_DONT_OVERWRITE=不要覆蓋
STR_ASK_FOR_CONFIRM=詢問確認
STR_DONT_ASK_CONFIRM=無須再次確認
STR_ALLWAYS_USE_OPTION=預設使用此設定,不再詢問
STR_ACTIONS=操作
STR_CONFIRM=確認
STR_OVERWRITE_OPTIONS=覆蓋選項
STR_PROPERTIES=屬性
STR_PROGRESS=進程
STR_UPDATES=更新
STR_DEL_CONFIRM_MSG=確認要刪除此檔案/資料夾嗎?
STR_CANCEL_ACTION_MSG=取消,等待最後一個動作完成
STR_FAIL_UPLOAD_MSG=上傳檔案失敗
STR_FAIL_DOWNLOAD_MSG=下載檔案失敗
STR_FAIL_READ_LOCAL_DIR_MSG=讀取資料夾失敗或資料夾不存在。
STR_CONNECTION_CLOSE_ERR_MSG=426 連線已關閉。
STR_REMOTE_TERM_CONN_MSG=426 遠端伺服器已終止連線。
STR_FAIL_LOGIN_MSG=300 連線失敗。請檢查使用者名稱或密碼。
STR_FAIL_TIMEOUT_MSG=426 連線失敗。連線逾時。
STR_FAIL_DEL_DIR_MSG=刪除資料夾失敗
STR_DELETING=正在刪除
STR_FAIL_DEL_FILE_MSG=刪除檔案失敗
STR_DELETED=已刪除
+75
View File
@@ -0,0 +1,75 @@
STR_CONNECTION_SETTINGS=Bağlantı Ayarları
STR_SITE=Site
STR_LOCAL=Yerel
STR_REMOTE=Uzaktan
STR_MESSAGES=Mesajlar
STR_UPDATE_SOFTWARE=Yazılımı Güncelle
STR_CONNECT_WEBDAV=Bağlan
STR_DISCONNECT_WEBDAV=Bağlantıyı kes
STR_SEARCH=Ara
STR_REFRESH=Yenile
STR_SERVER=Sunucu
STR_USERNAME=Kullanıcı Adı
STR_PASSWORD=Şifre
STR_PORT=Port
STR_PASV=Pasv
STR_DIRECTORY=Dizin
STR_FILTER=Filtre
STR_YES=Evet
STR_NO=Hayır
STR_CANCEL=İptal
STR_CONTINUE=Devam
STR_CLOSE=Kapat
STR_FOLDER=Klasör
STR_FILE=Dosya
STR_TYPE=Tip
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_DOWNLOAD=İndir
STR_SELECT_ALL=Tümünü Seç
STR_CLEAR_ALL=Tümünü Temizle
STR_UPLOADING=Karşıya 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_CONFIRM=Onayla
STR_OVERWRITE_OPTIONS=Ayarların üzerine yaz
STR_PROPERTIES=Özellikler
STR_PROGRESS=Durum
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_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_DELETING=Siliniyor
STR_FAIL_DEL_FILE_MSG=Dosya silme başarısız
STR_DELETED=Silindi
STR_LINK=Link
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_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_ALREADY_INSTALLED_MSG=Paket zaten kurulu
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

+1030
View File
File diff suppressed because it is too large Load Diff
+87
View File
@@ -0,0 +1,87 @@
#ifndef ACTIONS_H
#define ACTIONS_H
#include <pthread.h>
#include "common.h"
#define CONFIRM_NONE -1
#define CONFIRM_WAIT 0
#define CONFIRM_YES 1
#define CONFIRM_NO 2
enum ACTIONS
{
ACTION_NONE = 0,
ACTION_UPLOAD,
ACTION_DOWNLOAD,
ACTION_DELETE_LOCAL,
ACTION_DELETE_REMOTE,
ACTION_RENAME_LOCAL,
ACTION_RENAME_REMOTE,
ACTION_NEW_LOCAL_FOLDER,
ACTION_NEW_REMOTE_FOLDER,
ACTION_CHANGE_LOCAL_DIRECTORY,
ACTION_CHANGE_REMOTE_DIRECTORY,
ACTION_APPLY_LOCAL_FILTER,
ACTION_APPLY_REMOTE_FILTER,
ACTION_REFRESH_LOCAL_FILES,
ACTION_REFRESH_REMOTE_FILES,
ACTION_SHOW_LOCAL_PROPERTIES,
ACTION_SHOW_REMOTE_PROPERTIES,
ACTION_LOCAL_SELECT_ALL,
ACTION_REMOTE_SELECT_ALL,
ACTION_LOCAL_CLEAR_ALL,
ACTION_REMOTE_CLEAR_ALL,
ACTION_CONNECT_WEBDAV,
ACTION_DISCONNECT_WEBDAV,
ACTION_DISCONNECT_WEBDAV_AND_EXIT,
ACTION_INSTALL_REMOTE_PKG,
ACTION_INSTALL_LOCAL_PKG,
ACTION_INSTALL_URL_PKG
};
enum OverWriteType
{
OVERWRITE_NONE = 0,
OVERWRITE_PROMPT,
OVERWRITE_ALL
};
static pthread_t bk_activity_thid;
static pthread_t ftp_keep_alive_thid;
namespace Actions
{
void RefreshLocalFiles(bool apply_filter);
void RefreshRemoteFiles(bool apply_filter);
void HandleChangeLocalDirectory(const DirEntry entry);
void HandleChangeRemoteDirectory(const DirEntry entry);
void HandleRefreshLocalFiles();
void HandleRefreshRemoteFiles();
void CreateNewLocalFolder(char *new_folder);
void CreateNewRemoteFolder(char *new_folder);
void RenameLocalFolder(const char *old_path, const char *new_path);
void RenameRemoteFolder(const char *old_path, const char *new_path);
void *DeleteSelectedLocalFilesThread(void *argp);
void DeleteSelectedLocalFiles();
void *DeleteSelectedRemotesFilesThread(void *argp);
void DeleteSelectedRemotesFiles();
void *UploadFilesThread(void *argp);
void UploadFiles();
void *DownloadFilesThread(void *argp);
void DownloadFiles();
void ConnectWebDav();
void DisconnectWebDav();
void SelectAllLocalFiles();
void SelectAllRemoteFiles();
void *InstallRemotePkgsThread(void *argp);
void InstallRemotePkgs();
void *InstallLocalPkgsThread(void *argp);
void InstallLocalPkgs();
void *InstallUrlPkgThread(void *argp);
void InstallUrlPkg();
void *KeepAliveThread(void *argp);
}
#endif
+64
View File
@@ -0,0 +1,64 @@
#ifndef COMMON_H
#define COMMON_H
#include <string>
#include <vector>
#include <string.h>
typedef struct
{
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t dayOfWeek;
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
uint32_t microsecond;
} DateTime;
struct DirEntry
{
char directory[512];
char name[256];
char display_size[48];
char display_date[32];
char path[768];
uint64_t file_size;
bool isDir;
bool isLink;
DateTime modified;
friend bool operator<(DirEntry const &a, DirEntry const &b)
{
return strcmp(a.name, b.name) < 0;
}
static int DirEntryComparator(const void *v1, const void *v2)
{
const DirEntry *p1 = (DirEntry *)v1;
const DirEntry *p2 = (DirEntry *)v2;
if (strcasecmp(p1->name, "..") == 0)
return -1;
if (strcasecmp(p2->name, "..") == 0)
return 1;
if (p1->isDir && !p2->isDir)
{
return -1;
}
else if (!p1->isDir && p2->isDir)
{
return 1;
}
return strcasecmp(p1->name, p2->name);
}
static void Sort(std::vector<DirEntry> &list)
{
qsort(&list[0], list.size(), sizeof(DirEntry), DirEntryComparator);
}
};
#endif
+160
View File
@@ -0,0 +1,160 @@
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <stdlib.h>
#include "config.h"
#include "fs.h"
#include "lang.h"
extern "C"
{
#include "inifile.h"
}
bool swap_xo;
WebDavSettings *webdav_settings;
char local_directory[255];
char remote_directory[255];
char app_ver[6];
char last_site[32];
char display_site[32];
char language[128];
std::vector<std::string> sites;
std::map<std::string, WebDavSettings> site_settings;
char install_pkg_url[512];
char favorite_urls[MAX_FAVORITE_URLS][512];
bool auto_delete_tmp_pkg;
RemoteClient *webdavclient;
namespace CONFIG
{
void LoadConfig()
{
if (!FS::FolderExists(DATA_PATH))
{
FS::MkDirs(DATA_PATH);
}
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"};
OpenIniFile(CONFIG_INI_FILE);
// Load global config
sprintf(language, "%s", ReadString(CONFIG_GLOBAL, CONFIG_LANGUAGE, ""));
WriteString(CONFIG_GLOBAL, CONFIG_LANGUAGE, language);
sprintf(local_directory, "%s", ReadString(CONFIG_GLOBAL, CONFIG_LOCAL_DIRECTORY, "/"));
WriteString(CONFIG_GLOBAL, CONFIG_LOCAL_DIRECTORY, local_directory);
sprintf(remote_directory, "%s", ReadString(CONFIG_GLOBAL, CONFIG_REMOTE_DIRECTORY, "/"));
WriteString(CONFIG_GLOBAL, CONFIG_REMOTE_DIRECTORY, remote_directory);
auto_delete_tmp_pkg = ReadBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, true);
WriteBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, auto_delete_tmp_pkg);
for (int i = 0; i < sites.size(); i++)
{
WebDavSettings setting;
sprintf(setting.site_name, "%s", sites[i].c_str());
sprintf(setting.server, "%s", ReadString(sites[i].c_str(), CONFIG_WEBDAV_SERVER_IP, ""));
WriteString(sites[i].c_str(), CONFIG_WEBDAV_SERVER_IP, setting.server);
sprintf(setting.username, "%s", ReadString(sites[i].c_str(), CONFIG_WEBDAV_SERVER_USER, ""));
WriteString(sites[i].c_str(), CONFIG_WEBDAV_SERVER_USER, setting.username);
sprintf(setting.password, "%s", ReadString(sites[i].c_str(), CONFIG_WEBDAV_SERVER_PASSWORD, ""));
WriteString(sites[i].c_str(), CONFIG_WEBDAV_SERVER_PASSWORD, setting.password);
site_settings.insert(std::make_pair(sites[i], setting));
}
sprintf(last_site, "%s", ReadString(CONFIG_GLOBAL, CONFIG_LAST_SITE, sites[0].c_str()));
WriteString(CONFIG_GLOBAL, CONFIG_LAST_SITE, last_site);
webdav_settings = &site_settings[std::string(last_site)];
for (int i = 0; i < MAX_FAVORITE_URLS; i++)
{
const char *index = std::to_string(i).c_str();
sprintf(favorite_urls[i], "%s", ReadString(CONFIG_FAVORITE_URLS, index, ""));
WriteString(CONFIG_FAVORITE_URLS, index, favorite_urls[i]);
}
WriteIniFile(CONFIG_INI_FILE);
CloseIniFile();
}
void SaveConfig()
{
OpenIniFile(CONFIG_INI_FILE);
WriteString(last_site, CONFIG_WEBDAV_SERVER_IP, webdav_settings->server);
WriteString(last_site, CONFIG_WEBDAV_SERVER_USER, webdav_settings->username);
WriteString(last_site, CONFIG_WEBDAV_SERVER_PASSWORD, webdav_settings->password);
WriteString(CONFIG_GLOBAL, CONFIG_LAST_SITE, last_site);
WriteBool(CONFIG_GLOBAL, CONFIG_AUTO_DELETE_TMP_PKG, auto_delete_tmp_pkg);
WriteIniFile(CONFIG_INI_FILE);
CloseIniFile();
}
void SaveFavoriteUrl(int index, char *url)
{
OpenIniFile(CONFIG_INI_FILE);
const char *idx = std::to_string(index).c_str();
WriteString(CONFIG_FAVORITE_URLS, idx, url);
WriteIniFile(CONFIG_INI_FILE);
CloseIniFile();
}
void ParseMultiValueString(const char *prefix_list, std::vector<std::string> &prefixes, bool toLower)
{
std::string prefix = "";
int length = strlen(prefix_list);
for (int i = 0; i < length; i++)
{
char c = prefix_list[i];
if (c != ' ' && c != '\t' && c != ',')
{
if (toLower)
{
prefix += std::tolower(c);
}
else
{
prefix += c;
}
}
if (c == ',' || i == length - 1)
{
prefixes.push_back(prefix);
prefix = "";
}
}
}
std::string GetMultiValueString(std::vector<std::string> &multi_values)
{
std::string vts = std::string("");
if (multi_values.size() > 0)
{
for (int i = 0; i < multi_values.size() - 1; i++)
{
vts.append(multi_values[i]).append(",");
}
vts.append(multi_values[multi_values.size() - 1]);
}
return vts;
}
void RemoveFromMultiValues(std::vector<std::string> &multi_values, std::string value)
{
auto itr = std::find(multi_values.begin(), multi_values.end(), value);
if (itr != multi_values.end())
multi_values.erase(itr);
}
}
+68
View File
@@ -0,0 +1,68 @@
#ifndef LAUNCHER_CONFIG_H
#define LAUNCHER_CONFIG_H
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include "remote_client.h"
#define APP_ID "ps4-remote-client"
#define DATA_PATH "/data/" APP_ID
#define CONFIG_INI_FILE DATA_PATH "/config.ini"
#define COOKIE_FILE DATA_PATH "/cookies.txt"
#define CONFIG_GLOBAL "Global"
#define CONFIG_WEBDAV_SERVER_NAME "webdav_server_name"
#define CONFIG_WEBDAV_SERVER_IP "webdav_server_ip"
#define CONFIG_WEBDAV_SERVER_PORT "webdav_server_port"
#define CONFIG_WEBDAV_SERVER_USER "webdav_server_user"
#define CONFIG_WEBDAV_SERVER_PASSWORD "webdav_server_password"
#define CONFIG_WEBDAV_SERVER_SHARE "webdav_server_share"
#define CONFIG_WEBDAV_SERVER_HTTP_PORT "webdav_server_http_port"
#define CONFIG_FAVORITE_URLS "favorite_urls"
#define MAX_FAVORITE_URLS 30
#define CONFIG_LAST_SITE "last_site"
#define CONFIG_AUTO_DELETE_TMP_PKG "auto_delete_tmp_pkg"
#define CONFIG_LOCAL_DIRECTORY "local_directory"
#define CONFIG_REMOTE_DIRECTORY "remote_directory"
#define CONFIG_LANGUAGE "language"
struct WebDavSettings
{
char site_name[32];
char server[256];
char username[33];
char password[25];
};
extern std::vector<std::string> sites;
extern std::map<std::string, WebDavSettings> site_settings;
extern char local_directory[255];
extern char remote_directory[255];
extern char app_ver[6];
extern char last_site[32];
extern char display_site[32];
extern char language[128];
extern WebDavSettings *webdav_settings;
extern RemoteClient *webdavclient;
extern char install_pkg_url[512];
extern char favorite_urls[MAX_FAVORITE_URLS][512];
extern bool auto_delete_tmp_pkg;
namespace CONFIG
{
void LoadConfig();
void SaveConfig();
void SaveFavoriteUrl(int index, char *url);
void RemoveFromMultiValues(std::vector<std::string> &multi_values, std::string value);
void ParseMultiValueString(const char *prefix_list, std::vector<std::string> &prefixes, bool toLower);
std::string GetMultiValueString(std::vector<std::string> &multi_values);
}
#endif
+435
View File
@@ -0,0 +1,435 @@
#include "fs.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <dirent.h>
#include <filesystem>
#include <stdio.h>
#include <unistd.h>
#include "util.h"
#include "lang.h"
#include "rtc.h"
#include "windows.h"
namespace FS
{
int hasEndSlash(const char *path)
{
return path[strlen(path) - 1] == '/';
}
void MkDirs(const std::string &ppath, bool prev)
{
std::string path = ppath;
if (!prev)
{
path.push_back('/');
}
auto ptr = path.begin();
while (true)
{
ptr = std::find(ptr, path.end(), '/');
if (ptr == path.end())
break;
char last = *ptr;
*ptr = 0;
int err = mkdir(path.c_str(), 0777);
*ptr = last;
++ptr;
}
}
void Rm(const std::string &file)
{
remove(file.c_str());
}
void RmDir(const std::string &path)
{
remove(path.c_str());
}
int64_t GetSize(const std::string &path)
{
struct stat file_stat = {0};
int err = stat(path.c_str(), &file_stat);
if (err < 0)
{
return -1;
}
return file_stat.st_size;
}
bool FileExists(const std::string &path)
{
struct stat file_stat = {0};
return (stat(path.c_str(), std::addressof(file_stat)) == 0 && S_ISREG(file_stat.st_mode));
}
bool FolderExists(const std::string &path)
{
struct stat dir_stat = {0};
return (stat(path.c_str(), &dir_stat) == 0);
}
void Rename(const std::string &from, const std::string &to)
{
int res = rename(from.c_str(), to.c_str());
}
FILE *Create(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "w");
return fd;
}
FILE *OpenRW(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "w+");
return fd;
}
FILE *OpenRead(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "rb");
return fd;
}
FILE *Append(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "a");
return fd;
}
int64_t Seek(FILE *f, uint64_t offset)
{
auto const pos = fseek(f, offset, SEEK_SET);
return pos;
}
int Read(FILE *f, void *buffer, uint32_t size)
{
const auto read = fread(buffer, 1, size, f);
return read;
}
int Write(FILE *f, const void *buffer, uint32_t size)
{
int write = fwrite(buffer, size, 1, f);
return write;
}
void Close(FILE *fd)
{
int err = fclose(fd);
}
std::vector<char> Load(const std::string &path)
{
FILE *fd = fopen(path.c_str(), "r");
if (fd == nullptr)
return std::vector<char>(0);
const auto size = fseek(fd, 0, SEEK_END);
fseek(fd, 0, SEEK_SET);
std::vector<char> data(size);
const auto read = fread(data.data(), data.size(), 1, fd);
fclose(fd);
if (read < 0)
return std::vector<char>(0);
data.resize(read);
return data;
}
void Save(const std::string &path, const void *data, uint32_t size)
{
FILE *fd = fopen(path.c_str(), "w+");
if (fd == nullptr)
return;
const char *data8 = static_cast<const char *>(data);
while (size != 0)
{
int written = fwrite(data8, size, 1, fd);
fclose(fd);
if (written <= 0)
return;
data8 += written;
size -= written;
}
}
std::vector<DirEntry> ListDir(const std::string &ppath, int *err)
{
std::vector<DirEntry> out;
DirEntry entry;
std::string path = ppath;
memset(&entry, 0, sizeof(DirEntry));
sprintf(entry.directory, "%s", path.c_str());
sprintf(entry.name, "..");
sprintf(entry.display_size, "%s",lang_strings[STR_FOLDER]);
sprintf(entry.path, "%s", path.c_str());
entry.file_size = 0;
entry.isDir = true;
out.push_back(entry);
DIR *fd = opendir(path.c_str());
*err = 0;
if (fd == NULL)
{
*err = 1;
return out;
}
while (true)
{
struct dirent *dirent;
DirEntry entry;
dirent = readdir(fd);
if (dirent == NULL)
{
closedir(fd);
return out;
}
else
{
if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
{
continue;
}
snprintf(entry.directory, 512, "%s", path.c_str());
snprintf(entry.name, 256, "%s", dirent->d_name);
if (hasEndSlash(path.c_str()))
{
sprintf(entry.path, "%s%s", path.c_str(), dirent->d_name);
}
else
{
sprintf(entry.path, "%s/%s", path.c_str(), dirent->d_name);
}
struct stat file_stat = {0};
stat(entry.path, &file_stat);
struct tm tm = *localtime(&file_stat.st_mtim.tv_sec);
OrbisDateTime gmt;
OrbisDateTime lt;
gmt.day = tm.tm_mday;
gmt.month = tm.tm_mon + 1;
gmt.year = tm.tm_year + 1900;
gmt.hour = tm.tm_hour;
gmt.minute = tm.tm_min;
gmt.second = tm.tm_sec;
convertUtcToLocalTime(&gmt, &lt);
entry.modified.day = lt.day;
entry.modified.month = lt.month;
entry.modified.year = lt.year;
entry.modified.hours = lt.hour;
entry.modified.minutes = lt.minute;
entry.modified.seconds = lt.second;
entry.file_size = file_stat.st_size;
if (dirent->d_type & DT_DIR)
{
entry.isDir = true;
entry.file_size = 0;
sprintf(entry.display_size, "%s",lang_strings[STR_FOLDER]);
}
else
{
if (entry.file_size < 1024)
{
sprintf(entry.display_size, "%luB", entry.file_size);
}
else if (entry.file_size < 1024 * 1024)
{
sprintf(entry.display_size, "%.2fKB", entry.file_size * 1.0f / 1024);
}
else if (entry.file_size < 1024 * 1024 * 1024)
{
sprintf(entry.display_size, "%.2fMB", entry.file_size * 1.0f / (1024 * 1024));
}
else
{
sprintf(entry.display_size, "%.2fGB", entry.file_size * 1.0f / (1024 * 1024 * 1024));
}
entry.isDir = false;
}
out.push_back(entry);
}
}
closedir(fd);
return out;
}
std::vector<std::string> ListFiles(const std::string &path)
{
DIR *fd = opendir(path.c_str());
if (fd == NULL)
return std::vector<std::string>(0);
std::vector<std::string> out;
while (true)
{
struct dirent *dirent;
dirent = readdir(fd);
if (dirent == NULL)
{
closedir(fd);
return out;
}
if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
{
continue;
}
if (dirent->d_type & DT_DIR)
{
std::vector<std::string> files = FS::ListFiles(path + "/" + dirent->d_name);
for (std::vector<std::string>::iterator it = files.begin(); it != files.end();)
{
out.push_back(std::string(dirent->d_name) + "/" + *it);
++it;
}
}
else
{
out.push_back(dirent->d_name);
}
}
closedir(fd);
return out;
}
int RmRecursive(const std::string &path)
{
if (stop_activity)
return 1;
DIR *dfd = opendir(path.c_str());
if (dfd != NULL)
{
struct dirent *dir = NULL;
do
{
dir = readdir(dfd);
if (dir == NULL || strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0)
{
continue;
}
char new_path[512];
snprintf(new_path, 512, "%s%s%s", path.c_str(), hasEndSlash(path.c_str()) ? "" : "/", dir->d_name);
if (dir->d_type & DT_DIR)
{
int ret = RmRecursive(new_path);
if (ret <= 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], new_path);
closedir(dfd);
return ret;
}
}
else
{
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_DELETING], new_path);
int ret = remove(new_path);
if (ret < 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_FILE_MSG], new_path);
closedir(dfd);
return ret;
}
}
} while (dir != NULL && !stop_activity);
closedir(dfd);
if (stop_activity)
return 0;
int ret = rmdir(path.c_str());
if (ret < 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], path.c_str());
return ret;
}
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_DELETED], path.c_str());
}
else
{
int ret = remove(path.c_str());
if (ret < 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_FILE_MSG], path.c_str());
return ret;
}
snprintf(activity_message, 1024, "%s %s", lang_strings[STR_DELETED], path.c_str());
}
return 1;
}
int DirEntryComparator(const void *v1, const void *v2)
{
const DirEntry *p1 = (DirEntry *)v1;
const DirEntry *p2 = (DirEntry *)v2;
if (strcasecmp(p1->name, "..") == 0)
return -1;
if (strcasecmp(p2->name, "..") == 0)
return 1;
if (p1->isDir && !p2->isDir)
{
return -1;
}
else if (!p1->isDir && p2->isDir)
{
return 1;
}
return strcasecmp(p1->name, p2->name);
}
void Sort(std::vector<DirEntry> &list)
{
qsort(&list[0], list.size(), sizeof(DirEntry), DirEntryComparator);
}
std::string GetPath(const std::string &ppath1, const std::string &ppath2)
{
std::string path1 = ppath1;
std::string path2 = ppath2;
path2 = Util::Rtrim(Util::Trim(path2, " "), "/");
return path1 + "/" + path2;
}
int Head(const std::string &path, void* buffer, uint16_t len)
{
FILE *file = OpenRead(path);
int ret = Read(file, buffer, len);
if (ret != len)
{
Close(file);
return 0;
}
Close(file);
return 1;
}
}
+62
View File
@@ -0,0 +1,62 @@
#ifndef LAUNCHER_FS_H
#define LAUNCHER_FS_H
#pragma once
#include <string.h>
#include <string>
#include <vector>
#include <cstdint>
#include "common.h"
#define MAX_PATH_LENGTH 1024
namespace FS
{
std::string GetPath(const std::string &path1, const std::string &path2);
void MkDirs(const std::string &path, bool prev = false);
void Rm(const std::string &file);
void RmDir(const std::string &path);
int RmRecursive(const std::string &path);
int64_t GetSize(const std::string &path);
bool FileExists(const std::string &path);
bool FolderExists(const std::string &path);
void Rename(const std::string &from, const std::string &to);
// creates file (if it exists, truncates size to 0)
FILE *Create(const std::string &path);
// open existing file in read/write, fails if file does not exist
FILE *OpenRW(const std::string &path);
// open existing file in read/write, fails if file does not exist
FILE *OpenRead(const std::string &path);
// open file for writing, next write will append data to end of it
FILE *Append(const std::string &path);
void Close(FILE *f);
int64_t Seek(FILE *f, uint64_t offset);
int Read(FILE *f, void *buffer, uint32_t size);
int Write(FILE *f, const void *buffer, uint32_t size);
std::vector<char> Load(const std::string &path);
void Save(const std::string &path, const void *data, uint32_t size);
std::vector<std::string> ListFiles(const std::string &path);
std::vector<DirEntry> ListDir(const std::string &path, int *err);
void Sort(std::vector<DirEntry> &list);
int hasEndSlash(const char *path);
int Head(const std::string &path, void* buffer, uint16_t len);
}
#endif
+1692
View File
File diff suppressed because it is too large Load Diff
+127
View File
@@ -0,0 +1,127 @@
#ifndef FTPCLIENT_H
#define FTPCLIENT_H
#include <sys/socket.h>
#include <arpa/inet.h>
#include <time.h>
#include <string>
#include <vector>
#include "remote_client.h"
#define FTP_CLIENT_MAX_FILENAME_LEN 128
typedef int (*FtpCallbackXfer)(int64_t xfered, void *arg);
struct ftphandle
{
char *cput, *cget;
int handle;
int cavail, cleft;
char *buf;
int dir;
ftphandle *ctrl;
int cmode;
int64_t xfered;
int64_t xfered1;
int64_t cbbytes;
char response[512];
int64_t offset;
bool correctpasv;
FtpCallbackXfer xfercb;
void *cbarg;
bool is_connected;
};
class FtpClient : public RemoteClient
{
public:
enum accesstype
{
dir = 1,
dirverbose,
dirmlsd,
fileread,
filewrite,
filereadappend,
filewriteappend
};
enum transfermode
{
ascii = 'A',
image = 'I'
};
enum connmode
{
pasv = 1,
port
};
enum attributes
{
directory = 1,
readonly = 2
};
FtpClient();
~FtpClient();
int Connect(const std::string &url, const std::string &user, const std::string &pass);
void SetConnmode(connmode mode);
int Site(const std::string &cmd);
int Raw(const std::string &cmd);
int SysType(char *buf, int max);
int Mkdir(const std::string &path);
int Chdir(const std::string &path);
int Cdup();
int Rmdir(const std::string &path);
int Rmdir(const std::string &path, bool recursive);
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset = 0);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset = 0);
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
std::vector<DirEntry> ListDir(const std::string &path);
void SetCallbackXferFunction(FtpCallbackXfer pointer);
void SetCallbackArg(void *arg);
void SetCallbackBytes(int64_t bytes);
bool Noop();
bool Ping();
bool FileExists(const std::string &path);
bool IsConnected();
char *LastResponse();
long GetIdleTime();
int Quit();
std::string GetPath(std::string path1, std::string path2);
ClientType clientType();
private:
ftphandle *mp_ftphandle;
struct tm cur_time;
timeval tick;
char server[128];
int server_port;
int FtpSendCmd(const std::string &cmd, char 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 Readline(char *buf, int max, ftphandle *nControl);
int Writeline(char *buf, int len, ftphandle *nData);
void ClearHandle();
int FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, std::string &cmd);
int FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, std::string &cmd);
int FtpAcceptConnection(ftphandle *nData, ftphandle *nControl);
int CorrectPasvResponse(int *v);
int FtpAccess(const std::string &path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData);
int FtpXfer(const std::string &localfile, const std::string &path, ftphandle *nControl, accesstype type, transfermode mode);
int FtpWrite(void *buf, int len, ftphandle *nData);
int FtpRead(void *buf, int max, ftphandle *nData);
int FtpClose(ftphandle *nData);
int ParseDirEntry(char *line, DirEntry *dirEntry);
int ParseMLSDDirEntry(char *line, DirEntry *dirEntry);
};
#endif
+32
View File
@@ -0,0 +1,32 @@
#include <unistd.h>
#include <sys/random.h>
#include <pthread.h>
#include <errno.h>
int getentropy(void *buffer, size_t len)
{
int cs, ret = 0;
char *pos = buffer;
if (len > 256) {
errno = EIO;
return -1;
}
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
while (len) {
ret = getrandom(pos, len, 0);
if (ret < 0) {
if (errno == EINTR) continue;
else break;
}
pos += ret;
len -= ret;
ret = 0;
}
pthread_setcancelstate(cs, 0);
return ret;
}
+46
View File
@@ -0,0 +1,46 @@
#include "imgui.h"
#include <stdio.h>
#include "windows.h"
#include "gui.h"
#include "SDL2/SDL.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_sdlrenderer.h"
bool done = false;
int gui_mode = GUI_MODE_BROWSER;
namespace GUI
{
int RenderLoop(SDL_Renderer *renderer)
{
Windows::Init();
while (!done)
{
if (gui_mode == GUI_MODE_BROWSER)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
}
ImGui_ImplSDLRenderer_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
Windows::HandleWindowInput();
Windows::MainWindow();
Windows::ExecuteActions();
ImGui::Render();
ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
SDL_RenderPresent(renderer);
}
else if (gui_mode == GUI_MODE_IME)
{
Windows::HandleImeInput();
}
}
return 0;
}
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef LAUNCHER_GUI_H
#define LAUNCHER_GUI_H
#include <string>
#include "SDL2/SDL.h"
#define GUI_MODE_BROWSER 0
#define GUI_MODE_IME 1
extern bool done;
extern int gui_mode;
namespace GUI
{
int RenderLoop(SDL_Renderer *renderer);
}
#endif
+125
View File
@@ -0,0 +1,125 @@
//-----------------------------------------------------------------------------
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
//-----------------------------------------------------------------------------
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
//-----------------------------------------------------------------------------
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
//-----------------------------------------------------------------------------
#pragma once
//---- Define assertion handler. Defaults to calling assert().
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport )
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
//---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Include imgui_user.h at the end of imgui.h as a convenience
//#define IMGUI_INCLUDE_IMGUI_USER_H
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
//#define IMGUI_USE_STB_SPRINTF
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE
//---- Use stb_truetype to build and rasterize the font atlas (default)
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
//#define IMGUI_ENABLE_STB_TRUETYPE
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
/*
#define IM_VEC2_CLASS_EXTRA \
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
//#define ImDrawIdx unsigned int
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
//struct ImDrawList;
//struct ImDrawCmd;
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
//#define ImDrawCallback MyImDrawCallback
//---- Debug Tools: Macro to break in Debugger
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
//#define IM_DEBUG_BREAK IM_ASSERT(0)
//#define IM_DEBUG_BREAK __debugbreak()
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
// This adds a small runtime cost which is why it is not enabled by default.
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
//---- Debug Tools: Enable slower asserts
//#define IMGUI_DEBUG_PARANOID
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
/*
namespace ImGui
{
void MyFunction(const char* name, const MyMatrix44& v);
}
*/
+191
View File
@@ -0,0 +1,191 @@
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdarg.h>
#include <orbis/UserService.h>
#include "ime_dialog.h"
static int ime_dialog_running = 0;
static uint16_t inputTextBuffer[512+1];
static uint8_t storebuffer[512];
static char initial_ime_text[512];
static int max_text_length;
static void utf16_to_utf8(const uint16_t *src, uint8_t *dst)
{
int i;
for (i = 0; src[i]; i++)
{
if ((src[i] & 0xFF80) == 0)
{
*(dst++) = src[i] & 0xFF;
}
else if ((src[i] & 0xF800) == 0)
{
*(dst++) = ((src[i] >> 6) & 0xFF) | 0xC0;
*(dst++) = (src[i] & 0x3F) | 0x80;
}
else if ((src[i] & 0xFC00) == 0xD800 && (src[i + 1] & 0xFC00) == 0xDC00)
{
*(dst++) = (((src[i] + 64) >> 8) & 0x3) | 0xF0;
*(dst++) = (((src[i] >> 2) + 16) & 0x3F) | 0x80;
*(dst++) = ((src[i] >> 4) & 0x30) | 0x80 | ((src[i + 1] << 2) & 0xF);
*(dst++) = (src[i + 1] & 0x3F) | 0x80;
i += 1;
}
else
{
*(dst++) = ((src[i] >> 12) & 0xF) | 0xE0;
*(dst++) = ((src[i] >> 6) & 0x3F) | 0x80;
*(dst++) = (src[i] & 0x3F) | 0x80;
}
}
*dst = '\0';
}
static void utf8_to_utf16(const uint8_t *src, uint16_t *dst)
{
int i;
for (i = 0; src[i];)
{
if ((src[i] & 0xE0) == 0xE0)
{
*(dst++) = ((src[i] & 0x0F) << 12) | ((src[i + 1] & 0x3F) << 6) | (src[i + 2] & 0x3F);
i += 3;
}
else if ((src[i] & 0xC0) == 0xC0)
{
*(dst++) = ((src[i] & 0x1F) << 6) | (src[i + 1] & 0x3F);
i += 2;
}
else
{
*(dst++) = src[i];
i += 1;
}
}
*dst = '\0';
}
namespace Dialog
{
int initImeDialog(const char *Title, const char *initialTextBuffer, int max_text_length, OrbisImeType type, float posx, float posy)
{
if (ime_dialog_running)
return IME_DIALOG_ALREADY_RUNNING;
uint16_t title[100];
if ((initialTextBuffer && strlen(initialTextBuffer) > 511) || (Title && strlen(Title) > 99))
{
ime_dialog_running = 0;
return -1;
}
memset(&inputTextBuffer[0], 0, sizeof(inputTextBuffer));
memset(&storebuffer[0], 0, sizeof(storebuffer));
memset(&initial_ime_text[0], 0, sizeof(initial_ime_text));
if (initialTextBuffer)
{
snprintf(initial_ime_text, 511, "%s", initialTextBuffer);
}
// converts the multibyte string src to a wide-character string starting at dest.
utf8_to_utf16((uint8_t *)initialTextBuffer, inputTextBuffer);
utf8_to_utf16((uint8_t *)Title, title);
OrbisImeDialogSetting param;
memset(&param, 0, sizeof(OrbisImeDialogSetting));
int UserID = 0;
sceUserServiceGetInitialUser(&UserID);
param.supportedLanguages = 0;
param.maxTextLength = max_text_length;
param.inputTextBuffer = reinterpret_cast<wchar_t*>(inputTextBuffer);
param.title = reinterpret_cast<wchar_t*>(title);
param.userId = UserID;
param.type = type;
param.posx = posx;
param.posy = posy;
param.enterLabel = ORBIS_BUTTON_LABEL_DEFAULT;
int res = sceImeDialogInit(&param, NULL);
if (res >= 0)
{
ime_dialog_running = 1;
}
return res;
}
int isImeDialogRunning()
{
return ime_dialog_running;
}
uint8_t *getImeDialogInputText()
{
return storebuffer;
}
uint16_t *getImeDialogInputText16()
{
return inputTextBuffer;
}
const char *getImeDialogInitialText()
{
return initial_ime_text;
}
int updateImeDialog()
{
if (!ime_dialog_running)
return IME_DIALOG_RESULT_NONE;
int status;
while (1)
{
status = sceImeDialogGetStatus();
if (status == ORBIS_DIALOG_STATUS_STOPPED)
{
OrbisDialogResult result;
memset(&result, 0, sizeof(OrbisDialogResult));
sceImeDialogGetResult(&result);
if (result.endstatus == ORBIS_DIALOG_CANCEL)
{
status = IME_DIALOG_RESULT_CANCELED;
goto Finished;
}
if (result.endstatus == ORBIS_DIALOG_OK)
{
utf16_to_utf8(inputTextBuffer, storebuffer);
status = IME_DIALOG_RESULT_FINISHED;
goto Finished;
}
}
if (status == ORBIS_DIALOG_STATUS_NONE)
{
status = IME_DIALOG_RESULT_NONE;
goto Finished;
}
}
Finished:
sceImeDialogTerm();
ime_dialog_running = 0;
return status;
}
} // namespace Dialog
+43
View File
@@ -0,0 +1,43 @@
/*
VitaShell
Copyright (C) 2015-2018, TheFloW
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __IME_DIALOG_H__
#define __IME_DIALOG_H__
#define IME_DIALOG_RESULT_NONE 0
#define IME_DIALOG_RESULT_RUNNING 1
#define IME_DIALOG_RESULT_FINISHED 2
#define IME_DIALOG_RESULT_CANCELED 3
#define IME_DIALOG_ALREADY_RUNNING -1
#include <orbis/ImeDialog.h>
typedef void (*ime_callback_t)(int ime_result);
namespace Dialog
{
int initImeDialog(const char *Title, const char *initialTextBuffer, int max_text_length, OrbisImeType type, float posx, float posy);
uint8_t *getImeDialogInputText();
uint16_t *getImeDialogInputText16();
const char *getImeDialogInitialText();
int isImeDialogRunning();
int updateImeDialog();
}
#endif
+13718
View File
File diff suppressed because it is too large Load Diff
+3082
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+630
View File
@@ -0,0 +1,630 @@
// dear imgui: Platform Backend for SDL2
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
// (Prefer SDL 2.0.5+ for full feature support.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2022-09-26: Inputs: Disable SDL 2.0.22 new "auto capture" (SDL_HINT_MOUSE_AUTO_CAPTURE) which prevents drag and drop across windows for multi-viewport support + don't capture when drag and dropping. (#5710)
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
// 2022-03-22: Inputs: Fix mouse position issues when dragging outside of boundaries. SDL_CaptureMouse() erroneously still gives out LEAVE events when hovering OS decorations.
// 2022-03-22: Inputs: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2).
// 2022-02-04: Added SDL_Renderer* parameter to ImGui_ImplSDL2_InitForSDLRenderer(), so we can use SDL_GetRendererOutputSize() instead of SDL_GL_GetDrawableSize() when bound to a SDL_Renderer.
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
// 2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates.
// 2022-01-12: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API.
// 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted.
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)
// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950)
// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
// 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
// 2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
// 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
// 2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
// 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
#include "imgui.h"
#include "imgui_impl_sdl.h"
// SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__)
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1
#else
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
#endif
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
#define ANALOG_THRESHOLD 20000
#define BUTTON_LEFT 0x00000010
#define BUTTON_RIGHT 0x00000020
#define BUTTON_UP 0x00000040
#define BUTTON_DOWN 0x00000080
static uint32_t previous_down = 0;
static int repeat_count = 0;
static int repeat_delay = 70;
static uint64_t previous_time = 0;
// Disabled controller buttons
bool disabled_buttons[21] = {false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false};
// SDL Data
struct ImGui_ImplSDL2_Data
{
SDL_Window* Window;
SDL_Renderer* Renderer;
Uint64 Time;
int MouseButtonsDown;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
int PendingMouseLeaveFrame;
char* ClipboardTextData;
bool MouseCanUseGlobalState;
ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;
}
// Functions
static const char* ImGui_ImplSDL2_GetClipboardText(void*)
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
bd->ClipboardTextData = SDL_GetClipboardText();
return bd->ClipboardTextData;
}
static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
{
SDL_SetClipboardText(text);
}
static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode)
{
switch (keycode)
{
case SDLK_TAB: return ImGuiKey_Tab;
case SDLK_LEFT: return ImGuiKey_LeftArrow;
case SDLK_RIGHT: return ImGuiKey_RightArrow;
case SDLK_UP: return ImGuiKey_UpArrow;
case SDLK_DOWN: return ImGuiKey_DownArrow;
case SDLK_PAGEUP: return ImGuiKey_PageUp;
case SDLK_PAGEDOWN: return ImGuiKey_PageDown;
case SDLK_HOME: return ImGuiKey_Home;
case SDLK_END: return ImGuiKey_End;
case SDLK_INSERT: return ImGuiKey_Insert;
case SDLK_DELETE: return ImGuiKey_Delete;
case SDLK_BACKSPACE: return ImGuiKey_Backspace;
case SDLK_SPACE: return ImGuiKey_Space;
case SDLK_RETURN: return ImGuiKey_Enter;
case SDLK_ESCAPE: return ImGuiKey_Escape;
case SDLK_QUOTE: return ImGuiKey_Apostrophe;
case SDLK_COMMA: return ImGuiKey_Comma;
case SDLK_MINUS: return ImGuiKey_Minus;
case SDLK_PERIOD: return ImGuiKey_Period;
case SDLK_SLASH: return ImGuiKey_Slash;
case SDLK_SEMICOLON: return ImGuiKey_Semicolon;
case SDLK_EQUALS: return ImGuiKey_Equal;
case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket;
case SDLK_BACKSLASH: return ImGuiKey_Backslash;
case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket;
case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent;
case SDLK_CAPSLOCK: return ImGuiKey_CapsLock;
case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock;
case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock;
case SDLK_PRINTSCREEN: return ImGuiKey_PrintScreen;
case SDLK_PAUSE: return ImGuiKey_Pause;
case SDLK_KP_0: return ImGuiKey_Keypad0;
case SDLK_KP_1: return ImGuiKey_Keypad1;
case SDLK_KP_2: return ImGuiKey_Keypad2;
case SDLK_KP_3: return ImGuiKey_Keypad3;
case SDLK_KP_4: return ImGuiKey_Keypad4;
case SDLK_KP_5: return ImGuiKey_Keypad5;
case SDLK_KP_6: return ImGuiKey_Keypad6;
case SDLK_KP_7: return ImGuiKey_Keypad7;
case SDLK_KP_8: return ImGuiKey_Keypad8;
case SDLK_KP_9: return ImGuiKey_Keypad9;
case SDLK_KP_PERIOD: return ImGuiKey_KeypadDecimal;
case SDLK_KP_DIVIDE: return ImGuiKey_KeypadDivide;
case SDLK_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
case SDLK_KP_MINUS: return ImGuiKey_KeypadSubtract;
case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd;
case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter;
case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual;
case SDLK_LCTRL: return ImGuiKey_LeftCtrl;
case SDLK_LSHIFT: return ImGuiKey_LeftShift;
case SDLK_LALT: return ImGuiKey_LeftAlt;
case SDLK_LGUI: return ImGuiKey_LeftSuper;
case SDLK_RCTRL: return ImGuiKey_RightCtrl;
case SDLK_RSHIFT: return ImGuiKey_RightShift;
case SDLK_RALT: return ImGuiKey_RightAlt;
case SDLK_RGUI: return ImGuiKey_RightSuper;
case SDLK_APPLICATION: return ImGuiKey_Menu;
case SDLK_0: return ImGuiKey_0;
case SDLK_1: return ImGuiKey_1;
case SDLK_2: return ImGuiKey_2;
case SDLK_3: return ImGuiKey_3;
case SDLK_4: return ImGuiKey_4;
case SDLK_5: return ImGuiKey_5;
case SDLK_6: return ImGuiKey_6;
case SDLK_7: return ImGuiKey_7;
case SDLK_8: return ImGuiKey_8;
case SDLK_9: return ImGuiKey_9;
case SDLK_a: return ImGuiKey_A;
case SDLK_b: return ImGuiKey_B;
case SDLK_c: return ImGuiKey_C;
case SDLK_d: return ImGuiKey_D;
case SDLK_e: return ImGuiKey_E;
case SDLK_f: return ImGuiKey_F;
case SDLK_g: return ImGuiKey_G;
case SDLK_h: return ImGuiKey_H;
case SDLK_i: return ImGuiKey_I;
case SDLK_j: return ImGuiKey_J;
case SDLK_k: return ImGuiKey_K;
case SDLK_l: return ImGuiKey_L;
case SDLK_m: return ImGuiKey_M;
case SDLK_n: return ImGuiKey_N;
case SDLK_o: return ImGuiKey_O;
case SDLK_p: return ImGuiKey_P;
case SDLK_q: return ImGuiKey_Q;
case SDLK_r: return ImGuiKey_R;
case SDLK_s: return ImGuiKey_S;
case SDLK_t: return ImGuiKey_T;
case SDLK_u: return ImGuiKey_U;
case SDLK_v: return ImGuiKey_V;
case SDLK_w: return ImGuiKey_W;
case SDLK_x: return ImGuiKey_X;
case SDLK_y: return ImGuiKey_Y;
case SDLK_z: return ImGuiKey_Z;
case SDLK_F1: return ImGuiKey_F1;
case SDLK_F2: return ImGuiKey_F2;
case SDLK_F3: return ImGuiKey_F3;
case SDLK_F4: return ImGuiKey_F4;
case SDLK_F5: return ImGuiKey_F5;
case SDLK_F6: return ImGuiKey_F6;
case SDLK_F7: return ImGuiKey_F7;
case SDLK_F8: return ImGuiKey_F8;
case SDLK_F9: return ImGuiKey_F9;
case SDLK_F10: return ImGuiKey_F10;
case SDLK_F11: return ImGuiKey_F11;
case SDLK_F12: return ImGuiKey_F12;
}
return ImGuiKey_None;
}
static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
{
ImGuiIO& io = ImGui::GetIO();
io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & KMOD_CTRL) != 0);
io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & KMOD_SHIFT) != 0);
io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & KMOD_ALT) != 0);
io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & KMOD_GUI) != 0);
}
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
switch (event->type)
{
case SDL_MOUSEMOTION:
{
io.AddMousePosEvent((float)event->motion.x, (float)event->motion.y);
return true;
}
case SDL_MOUSEWHEEL:
{
float wheel_x = (event->wheel.x > 0) ? 1.0f : (event->wheel.x < 0) ? -1.0f : 0.0f;
float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f;
io.AddMouseWheelEvent(wheel_x, wheel_y);
return true;
}
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
int mouse_button = -1;
if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; }
if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; }
if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; }
if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; }
if (mouse_button == -1)
break;
io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN));
bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
return true;
}
case SDL_TEXTINPUT:
{
io.AddInputCharactersUTF8(event->text.text);
return true;
}
case SDL_KEYDOWN:
case SDL_KEYUP:
{
ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod);
ImGuiKey key = ImGui_ImplSDL2_KeycodeToImGuiKey(event->key.keysym.sym);
io.AddKeyEvent(key, (event->type == SDL_KEYDOWN));
io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
return true;
}
case SDL_WINDOWEVENT:
{
// - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right.
// - However we won't get a correct LEAVE event for a captured window.
// - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late,
// causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why
// we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details.
Uint8 window_event = event->window.event;
if (window_event == SDL_WINDOWEVENT_ENTER)
bd->PendingMouseLeaveFrame = 0;
if (window_event == SDL_WINDOWEVENT_LEAVE)
bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1;
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true);
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
io.AddFocusEvent(false);
return true;
}
}
return false;
}
void ImGui_ImplSDL2_DisableButton(int button , bool disabled)
{
if (button < 0 || button > 15)
return;
disabled_buttons[button] = disabled;
}
static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
// Check and store if we are on a SDL backend that supports global mouse position
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
bool mouse_can_use_global_state = false;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
const char* sdl_backend = SDL_GetCurrentVideoDriver();
const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)
if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)
mouse_can_use_global_state = true;
#endif
// Setup backend capabilities flags
ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = "imgui_impl_sdl";
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
bd->Window = window;
bd->Renderer = renderer;
bd->MouseCanUseGlobalState = mouse_can_use_global_state;
io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
io.ClipboardUserData = NULL;
// Load mouse cursors
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
// Set platform dependent data in viewport
#ifdef _WIN32
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(window, &info))
ImGui::GetMainViewport()->PlatformHandleRaw = (void*)info.info.win.window;
#else
(void)window;
#endif
// From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
// you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
#ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
#endif
// From 2.0.22: Disable auto-capture, this is preventing drag and drop across multiple windows (see #5710)
#ifdef SDL_HINT_MOUSE_AUTO_CAPTURE
SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0");
#endif
return true;
}
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
{
IM_UNUSED(sdl_gl_context); // Viewport branch will need this.
return ImGui_ImplSDL2_Init(window, NULL);
}
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
{
#if !SDL_HAS_VULKAN
IM_ASSERT(0 && "Unsupported");
#endif
return ImGui_ImplSDL2_Init(window, NULL);
}
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
{
#if !defined(_WIN32)
IM_ASSERT(0 && "Unsupported");
#endif
return ImGui_ImplSDL2_Init(window, NULL);
}
bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
{
return ImGui_ImplSDL2_Init(window, NULL);
}
bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer)
{
return ImGui_ImplSDL2_Init(window, renderer);
}
void ImGui_ImplSDL2_Shutdown()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
IM_ASSERT(bd != NULL && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
SDL_FreeCursor(bd->MouseCursors[cursor_n]);
io.BackendPlatformName = NULL;
io.BackendPlatformUserData = NULL;
IM_DELETE(bd);
}
static void ImGui_ImplSDL2_UpdateMouseData()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
ImGuiIO& io = ImGui::GetIO();
// We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
SDL_CaptureMouse((bd->MouseButtonsDown != 0 && ImGui::GetDragDropPayload() == NULL) ? SDL_TRUE : SDL_FALSE);
SDL_Window* focused_window = SDL_GetKeyboardFocus();
const bool is_app_focused = (bd->Window == focused_window);
#else
const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
#endif
if (is_app_focused)
{
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if (io.WantSetMousePos)
SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);
// (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured)
if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0)
{
int window_x, window_y, mouse_x_global, mouse_y_global;
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
SDL_GetWindowPosition(bd->Window, &window_x, &window_y);
io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
}
}
}
static void ImGui_ImplSDL2_UpdateMouseCursor()
{
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return;
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
{
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
SDL_ShowCursor(SDL_FALSE);
}
else
{
// Show OS mouse cursor
SDL_SetCursor(bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
SDL_ShowCursor(SDL_TRUE);
}
}
static void ImGui_ImplSDL2_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
return;
// Get gamepad
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
if (!game_controller)
return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
uint64_t current_time = SDL_GetTicks64();
// Simulate analog left stick as d-pad
uint32_t down = 0;
if (SDL_GameControllerGetAxis(game_controller, SDL_CONTROLLER_AXIS_LEFTX) < -ANALOG_THRESHOLD)
down |= BUTTON_LEFT;
else if (SDL_GameControllerGetAxis(game_controller, SDL_CONTROLLER_AXIS_LEFTX) > ANALOG_THRESHOLD)
down |= BUTTON_RIGHT;
else if (SDL_GameControllerGetAxis(game_controller, SDL_CONTROLLER_AXIS_LEFTY) > ANALOG_THRESHOLD)
down |= BUTTON_DOWN;
else if (SDL_GameControllerGetAxis(game_controller, SDL_CONTROLLER_AXIS_LEFTY) < -ANALOG_THRESHOLD)
down |= BUTTON_UP;
uint32_t pressed = down & ~previous_down;
if (previous_down == down)
{
uint64_t delay = 300;
if (repeat_count > 0)
delay = repeat_delay;
if (current_time - previous_time > delay)
{
pressed = down;
previous_time = current_time;
repeat_count++;
}
}
else
{
previous_time = current_time;
repeat_count = 0;
}
if (pressed & BUTTON_LEFT)
io.AddKeyEvent(ImGuiKey_GamepadDpadLeft, true);
if (pressed & BUTTON_RIGHT)
io.AddKeyEvent(ImGuiKey_GamepadDpadRight, true);
if (pressed & BUTTON_UP)
io.AddKeyEvent(ImGuiKey_GamepadDpadUp, true);
if (pressed & BUTTON_DOWN)
io.AddKeyEvent(ImGuiKey_GamepadDpadDown, true);
previous_down = down;
// Update gamepad inputs
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_NO) { if (!disabled_buttons[BUTTON_NO]) io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); }
#define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); }
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767);
MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK);
MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767);
#undef MAP_BUTTON
#undef MAP_ANALOG
}
void ImGui_ImplSDL2_NewFrame()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDL2_Init()?");
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
int w, h;
int display_w, display_h;
SDL_GetWindowSize(bd->Window, &w, &h);
if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED)
w = h = 0;
if (bd->Renderer != NULL)
SDL_GetRendererOutputSize(bd->Renderer, &display_w, &display_h);
else
SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
static Uint64 frequency = SDL_GetPerformanceFrequency();
Uint64 current_time = SDL_GetPerformanceCounter();
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time;
if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
{
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
bd->PendingMouseLeaveFrame = 0;
}
ImGui_ImplSDL2_UpdateMouseData();
ImGui_ImplSDL2_UpdateMouseCursor();
// Update game controllers (if enabled and available)
ImGui_ImplSDL2_UpdateGamepads();
}
+37
View File
@@ -0,0 +1,37 @@
// dear imgui: Platform Backend for SDL2
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
struct SDL_Window;
struct SDL_Renderer;
typedef union SDL_Event SDL_Event;
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer);
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
IMGUI_IMPL_API void ImGui_ImplSDL2_DisableButton(int button , bool disabled);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter
#endif
+252
View File
@@ -0,0 +1,252 @@
// dear imgui: Renderer Backend for SDL_Renderer
// (Requires: SDL 2.0.17+)
// Important to understand: SDL_Renderer is an _optional_ component of SDL.
// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
// If your application will want to render any non trivial amount of graphics other than UI,
// please be aware that SDL_Renderer offers a limited graphic API to the end-user and it might
// be difficult to step out of those boundaries.
// However, we understand it is a convenient choice to get an app started easily.
// Implemented features:
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// Missing features:
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// 2021-12-21: Update SDL_RenderGeometryRaw() format to work with SDL 2.0.19.
// 2021-12-03: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2021-10-06: Backup and restore modified ClipRect/Viewport.
// 2021-09-21: Initial version.
#include "imgui.h"
#include "imgui_impl_sdlrenderer.h"
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t
#else
#include <stdint.h> // intptr_t
#endif
// SDL
#include <SDL2/SDL.h>
#if !SDL_VERSION_ATLEAST(2,0,17)
#error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function
#endif
// SDL_Renderer data
struct ImGui_ImplSDLRenderer_Data
{
SDL_Renderer* SDLRenderer;
SDL_Texture* FontTexture;
ImGui_ImplSDLRenderer_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplSDLRenderer_Data* ImGui_ImplSDLRenderer_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
}
// Functions
bool ImGui_ImplSDLRenderer_Init(SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
IM_ASSERT(renderer != NULL && "SDL_Renderer not initialized!");
// Setup backend capabilities flags
ImGui_ImplSDLRenderer_Data* bd = IM_NEW(ImGui_ImplSDLRenderer_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_sdlrenderer";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
bd->SDLRenderer = renderer;
return true;
}
void ImGui_ImplSDLRenderer_Shutdown()
{
ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplSDLRenderer_DestroyDeviceObjects();
io.BackendRendererName = NULL;
io.BackendRendererUserData = NULL;
IM_DELETE(bd);
}
static void ImGui_ImplSDLRenderer_SetupRenderState()
{
ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
// Clear out any viewports and cliprect set by the user
// FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
SDL_RenderSetViewport(bd->SDLRenderer, NULL);
SDL_RenderSetClipRect(bd->SDLRenderer, NULL);
}
void ImGui_ImplSDLRenderer_NewFrame()
{
ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDLRenderer_Init()?");
if (!bd->FontTexture)
ImGui_ImplSDLRenderer_CreateDeviceObjects();
}
void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
{
ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
// If there's a scale factor set by the user, use that instead
// If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass
// to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here.
float rsx = 1.0f;
float rsy = 1.0f;
SDL_RenderGetScale(bd->SDLRenderer, &rsx, &rsy);
ImVec2 render_scale;
render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f;
render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f;
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * render_scale.x);
int fb_height = (int)(draw_data->DisplaySize.y * render_scale.y);
if (fb_width == 0 || fb_height == 0)
return;
// Backup SDL_Renderer state that will be modified to restore it afterwards
struct BackupSDLRendererState
{
SDL_Rect Viewport;
bool ClipEnabled;
SDL_Rect ClipRect;
};
BackupSDLRendererState old = {};
old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer) == SDL_TRUE;
SDL_RenderGetViewport(bd->SDLRenderer, &old.Viewport);
SDL_RenderGetClipRect(bd->SDLRenderer, &old.ClipRect);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = render_scale;
// Render command lists
ImGui_ImplSDLRenderer_SetupRenderState();
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplSDLRenderer_SetupRenderState();
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
SDL_RenderSetClipRect(bd->SDLRenderer, &r);
const float* xy = (const float*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, pos));
const float* uv = (const float*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, uv));
#if SDL_VERSION_ATLEAST(2,0,19)
const SDL_Color* color = (const SDL_Color*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col)); // SDL 2.0.19+
#else
const int* color = (const int*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col)); // SDL 2.0.17 and 2.0.18
#endif
// Bind texture, Draw
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
SDL_RenderGeometryRaw(bd->SDLRenderer, tex,
xy, (int)sizeof(ImDrawVert),
color, (int)sizeof(ImDrawVert),
uv, (int)sizeof(ImDrawVert),
cmd_list->VtxBuffer.Size - pcmd->VtxOffset,
idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx));
}
}
}
// Restore modified SDL_Renderer state
SDL_RenderSetViewport(bd->SDLRenderer, &old.Viewport);
SDL_RenderSetClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : NULL);
}
// Called by Init/NewFrame/Shutdown
bool ImGui_ImplSDLRenderer_CreateFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
// Build texture atlas
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
// Upload texture to graphics system
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*) pixels, width, height, 32, 4 * width, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
bd->FontTexture = SDL_CreateTextureFromSurface(bd->SDLRenderer, surface);
if (bd->FontTexture == NULL)
{
SDL_Log("error creating texture");
return false;
}
SDL_UpdateTexture(bd->FontTexture, NULL, pixels, 4 * width);
SDL_SetTextureBlendMode(bd->FontTexture, SDL_BLENDMODE_BLEND);
SDL_SetTextureScaleMode(bd->FontTexture, SDL_ScaleModeLinear);
SDL_FreeSurface(surface);
// Store our identifier
io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
return true;
}
void ImGui_ImplSDLRenderer_DestroyFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
if (bd->FontTexture)
{
io.Fonts->SetTexID(0);
SDL_DestroyTexture(bd->FontTexture);
bd->FontTexture = NULL;
}
}
bool ImGui_ImplSDLRenderer_CreateDeviceObjects()
{
return ImGui_ImplSDLRenderer_CreateFontsTexture();
}
void ImGui_ImplSDLRenderer_DestroyDeviceObjects()
{
ImGui_ImplSDLRenderer_DestroyFontsTexture();
}
+29
View File
@@ -0,0 +1,29 @@
// dear imgui: Renderer Backend for SDL_Renderer
// (Requires: SDL 2.0.17+)
// Important to understand: SDL_Renderer is an _optional_ component of SDL.
// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
// If your application will want to render any non trivial amount of graphics other than UI,
// please be aware that SDL_Renderer offers a limited graphic API to the end-user and it might
// be difficult to step out of those boundaries.
// However, we understand it is a convenient choice to get an app started easily.
// Implemented features:
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
struct SDL_Renderer;
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_Init(SDL_Renderer* renderer);
IMGUI_IMPL_API void ImGui_ImplSDLRenderer_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer_NewFrame();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data);
// Called by Init/NewFrame/Shutdown
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_CreateFontsTexture();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer_DestroyFontsTexture();
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer_DestroyDeviceObjects();
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+627
View File
@@ -0,0 +1,627 @@
// [DEAR IMGUI]
// This is a slightly modified version of stb_rect_pack.h 1.01.
// Grep for [DEAR IMGUI] to find the changes.
//
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
//
// Has only had a few tests run, may have issues.
//
// More docs to come.
//
// No memory allocations; uses qsort() and assert() from stdlib.
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
//
// This library currently uses the Skyline Bottom-Left algorithm.
//
// Please note: better rectangle packers are welcome! Please
// implement them to the same API, but with a different init
// function.
//
// Credits
//
// Library
// Sean Barrett
// Minor features
// Martins Mozeiko
// github:IntellectualKitty
//
// Bugfixes / warning fixes
// Jeremy Jaussaud
// Fabian Giesen
//
// Version history:
//
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
// 0.09 (2016-08-27) fix compiler warnings
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
// 0.05: added STBRP_ASSERT to allow replacing assert
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
// 0.01: initial release
//
// LICENSE
//
// See end of file for license information.
//////////////////////////////////////////////////////////////////////////////
//
// INCLUDE SECTION
//
#ifndef STB_INCLUDE_STB_RECT_PACK_H
#define STB_INCLUDE_STB_RECT_PACK_H
#define STB_RECT_PACK_VERSION 1
#ifdef STBRP_STATIC
#define STBRP_DEF static
#else
#define STBRP_DEF extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
typedef int stbrp_coord;
#define STBRP__MAXVAL 0x7fffffff
// Mostly for internal use, but this is the maximum supported coordinate value.
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
// 'stbrp_rect' defined below, stored in the array 'rects', and there
// are 'num_rects' many of them.
//
// Rectangles which are successfully packed have the 'was_packed' flag
// set to a non-zero value and 'x' and 'y' store the minimum location
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
// if you imagine y increasing downwards). Rectangles which do not fit
// have the 'was_packed' flag set to 0.
//
// You should not try to access the 'rects' array from another thread
// while this function is running, as the function temporarily reorders
// the array while it executes.
//
// To pack into another rectangle, you need to call stbrp_init_target
// again. To continue packing into the same rectangle, you can call
// this function again. Calling this multiple times with multiple rect
// arrays will probably produce worse packing results than calling it
// a single time with the full rectangle array, but the option is
// available.
//
// The function returns 1 if all of the rectangles were successfully
// packed and 0 otherwise.
struct stbrp_rect
{
// reserved for your use:
int id;
// input:
stbrp_coord w, h;
// output:
stbrp_coord x, y;
int was_packed; // non-zero if valid packing
}; // 16 bytes, nominally
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
// Initialize a rectangle packer to:
// pack a rectangle that is 'width' by 'height' in dimensions
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
//
// You must call this function every time you start packing into a new target.
//
// There is no "shutdown" function. The 'nodes' memory must stay valid for
// the following stbrp_pack_rects() call (or calls), but can be freed after
// the call (or calls) finish.
//
// Note: to guarantee best results, either:
// 1. make sure 'num_nodes' >= 'width'
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
//
// If you don't do either of the above things, widths will be quantized to multiples
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
//
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
// may run out of temporary storage and be unable to pack some rectangles.
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
// Optionally call this function after init but before doing any packing to
// change the handling of the out-of-temp-memory scenario, described above.
// If you call init again, this will be reset to the default (false).
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
// Optionally select which packing heuristic the library should use. Different
// heuristics will produce better/worse results for different data sets.
// If you call init again, this will be reset to the default.
enum
{
STBRP_HEURISTIC_Skyline_default=0,
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
STBRP_HEURISTIC_Skyline_BF_sortHeight
};
//////////////////////////////////////////////////////////////////////////////
//
// the details of the following structures don't matter to you, but they must
// be visible so you can handle the memory allocations for them
struct stbrp_node
{
stbrp_coord x,y;
stbrp_node *next;
};
struct stbrp_context
{
int width;
int height;
int align;
int init_mode;
int heuristic;
int num_nodes;
stbrp_node *active_head;
stbrp_node *free_head;
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
};
#ifdef __cplusplus
}
#endif
#endif
//////////////////////////////////////////////////////////////////////////////
//
// IMPLEMENTATION SECTION
//
#ifdef STB_RECT_PACK_IMPLEMENTATION
#ifndef STBRP_SORT
#include <stdlib.h>
#define STBRP_SORT qsort
#endif
#ifndef STBRP_ASSERT
#include <assert.h>
#define STBRP_ASSERT assert
#endif
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
{
STBRP__INIT_skyline = 1
};
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
{
switch (context->init_mode) {
case STBRP__INIT_skyline:
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
context->heuristic = heuristic;
break;
default:
STBRP_ASSERT(0);
}
}
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
{
if (allow_out_of_mem)
// if it's ok to run out of memory, then don't bother aligning them;
// this gives better packing, but may fail due to OOM (even though
// the rectangles easily fit). @TODO a smarter approach would be to only
// quantize once we've hit OOM, then we could get rid of this parameter.
context->align = 1;
else {
// if it's not ok to run out of memory, then quantize the widths
// so that num_nodes is always enough nodes.
//
// I.e. num_nodes * align >= width
// align >= width / num_nodes
// align = ceil(width/num_nodes)
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
}
}
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
nodes[i].next = NULL;
context->init_mode = STBRP__INIT_skyline;
context->heuristic = STBRP_HEURISTIC_Skyline_default;
context->free_head = &nodes[0];
context->active_head = &context->extra[0];
context->width = width;
context->height = height;
context->num_nodes = num_nodes;
stbrp_setup_allow_out_of_mem(context, 0);
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
context->extra[0].x = 0;
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
context->extra[1].y = (1<<30);
context->extra[1].next = NULL;
}
// find minimum y position if it starts at x1
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
{
stbrp_node *node = first;
int x1 = x0 + width;
int min_y, visited_width, waste_area;
STBRP__NOTUSED(c);
STBRP_ASSERT(first->x <= x0);
#if 0
// skip in case we're past the node
while (node->next->x <= x0)
++node;
#else
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
#endif
STBRP_ASSERT(node->x <= x0);
min_y = 0;
waste_area = 0;
visited_width = 0;
while (node->x < x1) {
if (node->y > min_y) {
// raise min_y higher.
// we've accounted for all waste up to min_y,
// but we'll now add more waste for everything we've visted
waste_area += visited_width * (node->y - min_y);
min_y = node->y;
// the first time through, visited_width might be reduced
if (node->x < x0)
visited_width += node->next->x - x0;
else
visited_width += node->next->x - node->x;
} else {
// add waste area
int under_width = node->next->x - node->x;
if (under_width + visited_width > width)
under_width = width - visited_width;
waste_area += under_width * (min_y - node->y);
visited_width += under_width;
}
node = node->next;
}
*pwaste = waste_area;
return min_y;
}
typedef struct
{
int x,y;
stbrp_node **prev_link;
} stbrp__findresult;
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
{
int best_waste = (1<<30), best_x, best_y = (1 << 30);
stbrp__findresult fr;
stbrp_node **prev, *node, *tail, **best = NULL;
// align to multiple of c->align
width = (width + c->align - 1);
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
// if it can't possibly fit, bail immediately
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
int y,waste;
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
// bottom left
if (y < best_y) {
best_y = y;
best = prev;
}
} else {
// best-fit
if (y + height <= c->height) {
// can only use it if it first vertically
if (y < best_y || (y == best_y && waste < best_waste)) {
best_y = y;
best_waste = waste;
best = prev;
}
}
}
prev = &node->next;
node = node->next;
}
best_x = (best == NULL) ? 0 : (*best)->x;
// if doing best-fit (BF), we also have to try aligning right edge to each node position
//
// e.g, if fitting
//
// ____________________
// |____________________|
//
// into
//
// | |
// | ____________|
// |____________|
//
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
//
// This makes BF take about 2x the time
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
tail = c->active_head;
node = c->active_head;
prev = &c->active_head;
// find first node that's admissible
while (tail->x < width)
tail = tail->next;
while (tail) {
int xpos = tail->x - width;
int y,waste;
STBRP_ASSERT(xpos >= 0);
// find the left position that matches this
while (node->next->x <= xpos) {
prev = &node->next;
node = node->next;
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height <= c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
best_y = y;
best_waste = waste;
best = prev;
}
}
}
tail = tail->next;
}
}
fr.prev_link = best;
fr.x = best_x;
fr.y = best_y;
return fr;
}
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
{
// find best position according to heuristic
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
stbrp_node *node, *cur;
// bail if:
// 1. it failed
// 2. the best node doesn't fit (we don't always check this)
// 3. we're out of memory
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
res.prev_link = NULL;
return res;
}
// on success, create new node
node = context->free_head;
node->x = (stbrp_coord) res.x;
node->y = (stbrp_coord) (res.y + height);
context->free_head = node->next;
// insert the new node into the right starting point, and
// let 'cur' point to the remaining nodes needing to be
// stiched back in
cur = *res.prev_link;
if (cur->x < res.x) {
// preserve the existing one, so start testing with the next one
stbrp_node *next = cur->next;
cur->next = node;
cur = next;
} else {
*res.prev_link = node;
}
// from here, traverse cur and free the nodes, until we get to one
// that shouldn't be freed
while (cur->next && cur->next->x <= res.x + width) {
stbrp_node *next = cur->next;
// move the current node to the free list
cur->next = context->free_head;
context->free_head = cur;
cur = next;
}
// stitch the list back in
node->next = cur;
if (cur->x < res.x + width)
cur->x = (stbrp_coord) (res.x + width);
#ifdef _DEBUG
cur = context->active_head;
while (cur->x < context->width) {
STBRP_ASSERT(cur->x < cur->next->x);
cur = cur->next;
}
STBRP_ASSERT(cur->next == NULL);
{
int count=0;
cur = context->active_head;
while (cur) {
cur = cur->next;
++count;
}
cur = context->free_head;
while (cur) {
cur = cur->next;
++count;
}
STBRP_ASSERT(count == context->num_nodes+2);
}
#endif
return res;
}
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
if (p->h > q->h)
return -1;
if (p->h < q->h)
return 1;
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
// we use the 'was_packed' field internally to allow sorting/unsorting
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = i;
}
// sort according to heuristic
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) {
if (rects[i].w == 0 || rects[i].h == 0) {
rects[i].x = rects[i].y = 0; // empty rect needs no space
} else {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
}
}
}
// unsort
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
// set was_packed flags and all_rects_packed status
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
if (!rects[i].was_packed)
all_rects_packed = 0;
}
// return the all_rects_packed status
return all_rects_packed;
}
#endif
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+686
View File
@@ -0,0 +1,686 @@
/************************************************************************
Filename : IniFile.C
Version : 0.51
Author(s) : Carsten Breuer
--[ Description ]-------------------------------------------------------
This file contains a complete interface to read and write ini files
like windows do it. It's also avaiable as a C++ class.
--[ History ] ----------------------------------------------------------
0.10: Original file by Carsten Breuer. First beta version.
0.20: Some bugs resolved and some suggestions from
jim hall (freedos.org) implemented.
0.30: Some stuff for unix added. They dont know strupr.
Thanks to Dieter Engelbrecht (dieter@wintop.net).
0.40: Bug at WriteString fixed.
0.50: Problem with file pointer solved
0.51: We better do smaller steps now. I have reformated to tab4. Sorry
New function DeletepKey added. Thanks for the guy who post this.
--[ How to compile ]----------------------------------------------------
This file was developed under DJGPP and Rhide. If you are familiar with
Borland C++ 3.1, you will feel like at home ;-)).
Both tools are free software.
Downloads at: http://www.delorie.com/djgpp
--[ Where to get help/information ]-------------------------------------
The author : C.Breuer@OpenWin.de
--[ License ] ----------------------------------------------------------
LGPL (Free for private and comercial use)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
------------------------------------------------------------------------
Copyright (c) 2000 Carsten Breuer
/************************************************************************/
/* defines for, or consts and inline functions for C++ */
/* global includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* local includes */
#include "inifile.h"
/* Global Variables */
struct ENTRY *Entry = NULL;
struct ENTRY *CurEntry = NULL;
char Result[4096] =
{""};
FILE *IniFile;
/* Private functions declarations */
void AddpKey(struct ENTRY *Entry, cchr *pKey, cchr *Value);
void FreeMem(void *Ptr);
void FreeAllMem(void);
bool FindpKey(cchr *Section, cchr *pKey, EFIND *List);
bool AddSectionAndpKey(cchr *Section, cchr *pKey, cchr *Value);
struct ENTRY *MakeNewEntry(void);
/*=========================================================================
strupr -de-
-------------------------------------------------------------------------
Job : String to Uppercase 22.03.2001 Dieter Engelbrecht dieter@wintop.net
/*========================================================================*/
#ifdef DONT_HAVE_STRUPR
/* DONT_HAVE_STRUPR is set when INI_REMOVE_CR is defined */
void strupr(char *str)
{
// We dont check the ptr because the original also dont do it.
while (*str != 0)
{
if (islower(*str))
{
*str = toupper(*str);
}
str++;
}
}
#endif
/*=========================================================================
OpenIniFile
-------------------------------------------------------------------------
Job : Opens an ini file or creates a new one if the requested file
doesnt exists.
Att : Be sure to call CloseIniFile to free all mem allocated during
operation!
/*========================================================================*/
bool OpenIniFile(cchr *FileName)
{
char Str[5120];
char *pStr;
struct ENTRY *pEntry;
FreeAllMem();
if (FileName == NULL)
{
return FALSE;
}
if ((IniFile = fopen(FileName, "r")) == NULL)
{
return FALSE;
}
while (fgets(Str, 5120, IniFile) != NULL)
{
pStr = strchr(Str, '\n');
if (pStr != NULL)
{
*pStr = 0;
}
pEntry = MakeNewEntry();
if (pEntry == NULL)
{
return FALSE;
}
#ifdef INI_REMOVE_CR
Len = strlen(Str);
if (Len > 0)
{
if (Str[Len - 1] == '\r')
{
Str[Len - 1] = '\0';
}
}
#endif
pEntry->Text = (char *)malloc(strlen(Str) + 1);
if (pEntry->Text == NULL)
{
FreeAllMem();
return FALSE;
}
strcpy(pEntry->Text, Str);
pStr = strchr(Str, ';');
if (pStr != NULL)
{
*pStr = 0;
} /* Cut all comments */
if ((strstr(Str, "[") > 0) && (strstr(Str, "]") > 0)) /* Is Section */
{
pEntry->Type = tpSECTION;
}
else
{
if (strstr(Str, "=") > 0)
{
pEntry->Type = tpKEYVALUE;
}
else
{
pEntry->Type = tpCOMMENT;
}
}
CurEntry = pEntry;
}
fclose(IniFile);
IniFile = NULL;
return TRUE;
}
/*=========================================================================
CloseIniFile
-------------------------------------------------------------------------
Job : Frees the memory and closes the ini file without any
modifications. If you want to write the file use
WriteIniFile instead.
/*========================================================================*/
void CloseIniFile(void)
{
FreeAllMem();
if (IniFile != NULL)
{
fclose(IniFile);
IniFile = NULL;
}
}
/*=========================================================================
WriteIniFile
-------------------------------------------------------------------------
Job : Writes the iniFile to the disk and close it. Frees all memory
allocated by WriteIniFile;
/*========================================================================*/
bool WriteIniFile(const char *FileName)
{
struct ENTRY *pEntry = Entry;
IniFile = NULL;
if (IniFile != NULL)
{
fclose(IniFile);
}
if ((IniFile = fopen(FileName, "wb")) == NULL)
{
FreeAllMem();
return FALSE;
}
while (pEntry != NULL)
{
if (pEntry->Type != tpNULL)
{
fprintf(IniFile, "%s\n", pEntry->Text);
pEntry = pEntry->pNext;
}
}
fclose(IniFile);
IniFile = NULL;
return TRUE;
}
/*=========================================================================
WriteString : Writes a string to the ini file
*========================================================================*/
void WriteString(cchr *Section, cchr *pKey, cchr *Value)
{
EFIND List;
char Str[5120];
if (ArePtrValid(Section, pKey, Value) == FALSE)
{
return;
}
if (FindpKey(Section, pKey, &List) == TRUE)
{
sprintf(Str, "%s=%s%s", List.KeyText, Value, List.Comment);
FreeMem(List.pKey->Text);
List.pKey->Text = (char *)malloc(strlen(Str) + 1);
strcpy(List.pKey->Text, Str);
}
else
{
if ((List.pSec != NULL) && (List.pKey == NULL)) /* section exist, pKey not */
{
AddpKey(List.pSec, pKey, Value);
}
else
{
AddSectionAndpKey(Section, pKey, Value);
}
}
}
/*=========================================================================
WriteBool : Writes a boolean to the ini file
*========================================================================*/
void WriteBool(cchr *Section, cchr *pKey, bool Value)
{
char Val[2] = {'0', 0};
if (Value != 0)
{
Val[0] = '1';
}
WriteString(Section, pKey, Val);
}
/*=========================================================================
WriteInt : Writes an integer to the ini file
*========================================================================*/
void WriteInt(cchr *Section, cchr *pKey, int Value)
{
char Val[12]; /* 32bit maximum + sign + \0 */
sprintf(Val, "%d", Value);
WriteString(Section, pKey, Val);
}
/*=========================================================================
WriteDouble : Writes a double to the ini file
*========================================================================*/
void WriteDouble(cchr *Section, cchr *pKey, double Value)
{
char Val[32]; /* DDDDDDDDDDDDDDD+E308\0 */
sprintf(Val, "%1.10lE", Value);
WriteString(Section, pKey, Val);
}
/*=========================================================================
ReadString : Reads a string from the ini file
*========================================================================*/
const char *
ReadString(cchr *Section, cchr *pKey, cchr *Default)
{
EFIND List;
if (ArePtrValid(Section, pKey, Default) == FALSE)
{
return Default;
}
if (FindpKey(Section, pKey, &List) == TRUE)
{
strcpy(Result, List.ValText);
return Result;
}
return Default;
}
/*=========================================================================
ReadBool : Reads a boolean from the ini file
*========================================================================*/
bool ReadBool(cchr *Section, cchr *pKey, bool Default)
{
char Val[2] = {"0"};
if (Default != 0)
{
Val[0] = '1';
}
return (atoi(ReadString(Section, pKey, Val)) ? 1 : 0); /* Only 0 or 1 allowed */
}
/*=========================================================================
ReadInt : Reads a integer from the ini file
*========================================================================*/
int ReadInt(cchr *Section, cchr *pKey, int Default)
{
char Val[12];
sprintf(Val, "%d", Default);
return (atoi(ReadString(Section, pKey, Val)));
}
/*=========================================================================
ReadDouble : Reads a double from the ini file
*========================================================================*/
double
ReadDouble(cchr *Section, cchr *pKey, double Default)
{
double Val;
sprintf(Result, "%1.10lE", Default);
sscanf(ReadString(Section, pKey, Result), "%lE", &Val);
return Val;
}
/*=========================================================================
DeleteKey : Deletes a pKey from the ini file.
*========================================================================*/
bool DeleteKey(cchr *Section, cchr *pKey)
{
EFIND List;
struct ENTRY *pPrev;
struct ENTRY *pNext;
if (FindpKey(Section, pKey, &List) == TRUE)
{
pPrev = List.pKey->pPrev;
pNext = List.pKey->pNext;
if (pPrev)
{
pPrev->pNext = pNext;
}
if (pNext)
{
pNext->pPrev = pPrev;
}
FreeMem(List.pKey->Text);
FreeMem(List.pKey);
return TRUE;
}
return FALSE;
}
/* Here we start with our helper functions */
/*=========================================================================
FreeMem : Frees a pointer. It is set to NULL by Free AllMem
*========================================================================*/
void FreeMem(void *Ptr)
{
if (Ptr != NULL)
{
free(Ptr);
}
}
/*=========================================================================
FreeAllMem : Frees all allocated memory and set the pointer to NULL.
Thats IMO one of the most important issues relating
to pointers :
A pointer is valid or NULL.
*========================================================================*/
void FreeAllMem(void)
{
struct ENTRY *pEntry;
struct ENTRY *pNextEntry;
pEntry = Entry;
while (1)
{
if (pEntry == NULL)
{
break;
}
pNextEntry = pEntry->pNext;
FreeMem(pEntry->Text); /* Frees the pointer if not NULL */
FreeMem(pEntry);
pEntry = pNextEntry;
}
Entry = NULL;
CurEntry = NULL;
}
/*=========================================================================
FindSection : Searches the chained list for a section. The section
must be given without the brackets!
Return Value: NULL at an error or a pointer to the ENTRY structure
if succeed.
*========================================================================*/
struct ENTRY *
FindSection(cchr *Section)
{
char Sec[130];
char iSec[130];
struct ENTRY *pEntry;
sprintf(Sec, "[%s]", Section);
strupr(Sec);
pEntry = Entry; /* Get a pointer to the first Entry */
while (pEntry != NULL)
{
if (pEntry->Type == tpSECTION)
{
strcpy(iSec, pEntry->Text);
strupr(iSec);
if (strcmp(Sec, iSec) == 0)
{
return pEntry;
}
}
pEntry = pEntry->pNext;
}
return NULL;
}
/*=========================================================================
FindpKey : Searches the chained list for a pKey under a given section
Return Value: NULL at an error or a pointer to the ENTRY structure
if succeed.
*========================================================================*/
bool FindpKey(cchr *Section, cchr *pKey, EFIND *List)
{
char Search[130];
char Found[130];
char Text[5120];
char *pText;
struct ENTRY *pEntry;
List->pSec = NULL;
List->pKey = NULL;
pEntry = FindSection(Section);
if (pEntry == NULL)
{
return FALSE;
}
List->pSec = pEntry;
List->KeyText[0] = 0;
List->ValText[0] = 0;
List->Comment[0] = 0;
pEntry = pEntry->pNext;
if (pEntry == NULL)
{
return FALSE;
}
sprintf(Search, "%s", pKey);
strupr(Search);
while (pEntry != NULL)
{
if ((pEntry->Type == tpSECTION) || /* Stop after next section or EOF */
(pEntry->Type == tpNULL))
{
return FALSE;
}
if (pEntry->Type == tpKEYVALUE)
{
strcpy(Text, pEntry->Text);
pText = strchr(Text, ';');
if (pText != NULL)
{
strcpy(List->Comment, Text);
*pText = 0;
}
pText = strchr(Text, '=');
if (pText != NULL)
{
*pText = 0;
strcpy(List->KeyText, Text);
strcpy(Found, Text);
*pText = '=';
strupr(Found);
/* printf ("%s,%s\n", Search, Found); */
if (strcmp(Found, Search) == 0)
{
strcpy(List->ValText, pText + 1);
List->pKey = pEntry;
return TRUE;
}
}
}
pEntry = pEntry->pNext;
}
return FALSE;
}
/*=========================================================================
AddItem : Adds an item (pKey or section) to the chaines list
*========================================================================*/
bool AddItem(char Type, cchr *Text)
{
struct ENTRY *pEntry = MakeNewEntry();
if (pEntry == NULL)
{
return FALSE;
}
pEntry->Type = Type;
pEntry->Text = (char *)malloc(strlen(Text) + 1);
if (pEntry->Text == NULL)
{
free(pEntry);
return FALSE;
}
strcpy(pEntry->Text, Text);
pEntry->pNext = NULL;
if (CurEntry != NULL)
{
CurEntry->pNext = pEntry;
}
CurEntry = pEntry;
return TRUE;
}
/*=========================================================================
AddItemAt : Adds an item at a selected position. This means, that the
chained list will be broken at the selected position and
that the new item will be Inserted.
Before : A.Next = &B
After : A.Next = &NewItem, NewItem.Next = &B
*========================================================================*/
bool AddItemAt(struct ENTRY *EntryAt, char Mode, cchr *Text)
{
struct ENTRY *pNewEntry;
if (EntryAt == NULL)
{
return FALSE;
}
pNewEntry = (struct ENTRY *)malloc(sizeof(ENTRY));
if (pNewEntry == NULL)
{
return FALSE;
}
pNewEntry->Text = (char *)malloc(strlen(Text) + 1);
if (pNewEntry->Text == NULL)
{
free(pNewEntry);
return FALSE;
}
strcpy(pNewEntry->Text, Text);
if (EntryAt->pNext == NULL) /* No following nodes. */
{
EntryAt->pNext = pNewEntry;
pNewEntry->pNext = NULL;
}
else
{
pNewEntry->pNext = EntryAt->pNext;
EntryAt->pNext = pNewEntry;
}
pNewEntry->pPrev = EntryAt;
pNewEntry->Type = Mode;
return TRUE;
}
/*=========================================================================
AddSectionAndpKey : Adds a section and then a pKey to the chained list
*========================================================================*/
bool AddSectionAndpKey(cchr *Section, cchr *pKey, cchr *Value)
{
char Text[5120];
sprintf(Text, "[%s]", Section);
if (AddItem(tpSECTION, Text) == FALSE)
{
return FALSE;
}
sprintf(Text, "%s=%s", pKey, Value);
return AddItem(tpKEYVALUE, Text);
}
/*=========================================================================
AddpKey : Adds a pKey to the chained list
*========================================================================*/
void AddpKey(struct ENTRY *SecEntry, cchr *pKey, cchr *Value)
{
char Text[5120];
sprintf(Text, "%s=%s", pKey, Value);
AddItemAt(SecEntry, tpKEYVALUE, Text);
}
/*=========================================================================
MakeNewEntry : Allocates the memory for a new entry. This is only
the new empty structure, that must be filled from
function like AddItem etc.
Info : This is only a internal function. You dont have to call
it from outside.
*==========================================================================*/
struct ENTRY *
MakeNewEntry(void)
{
struct ENTRY *pEntry;
pEntry = (struct ENTRY *)malloc(sizeof(ENTRY));
if (pEntry == NULL)
{
FreeAllMem();
return NULL;
}
if (Entry == NULL)
{
Entry = pEntry;
}
pEntry->Type = tpNULL;
pEntry->pPrev = CurEntry;
pEntry->pNext = NULL;
pEntry->Text = NULL;
if (CurEntry != NULL)
{
CurEntry->pNext = pEntry;
}
return pEntry;
}
/*=========================================================================
GetSectionCount : Get the number of sections
*========================================================================*/
int GetSectionCount()
{
struct ENTRY *pEntry = Entry;
int count = 0;
while (pEntry != NULL)
{
if (pEntry->Type == tpSECTION)
{
count++;
}
pEntry = pEntry->pNext;
}
return count;
}
/*=========================================================================
GetSections : Retrieve the sections
*========================================================================*/
void GetSections(char *sections[])
{
struct ENTRY *pEntry = Entry;
int i = 0;
while (pEntry != NULL)
{
if (pEntry->Type == tpSECTION)
{
sprintf(sections[i], pEntry->Text);
i++;
}
pEntry = pEntry->pNext;
}
}
+72
View File
@@ -0,0 +1,72 @@
/************************************************************************
T h e O p e n W i n d o w s P r o j e c t
------------------------------------------------------------------------
Filename : IniFile.h
Author(s) : Carsten Breuer
------------------------------------------------------------------------
Copyright (c) 2000 by Carsten Breuer (C.Breuer@openwin.de)
/************************************************************************/
#ifndef INIFILE_H
#define INIFILE_H
#ifndef CCHR_H
#define CCHR_H
typedef const char cchr;
#endif
#ifndef __cplusplus
typedef char bool;
#define true 1
#define TRUE 1
#define false 0
#define FALSE 0
#endif
#define tpNULL 0
#define tpSECTION 1
#define tpKEYVALUE 2
#define tpCOMMENT 3
typedef struct ENTRY
{
char Type;
char *Text;
struct ENTRY *pPrev;
struct ENTRY *pNext;
} ENTRY;
typedef struct
{
struct ENTRY *pSec;
struct ENTRY *pKey;
char KeyText[128];
char ValText[4096];
char Comment[32];
} EFIND;
/* Macros */
#define ArePtrValid(Sec, Key, Val) ((Sec != NULL) && (Key != NULL) && (Val != NULL))
/* Connectors of this file (Prototypes) */
bool OpenIniFile(cchr *FileName);
bool ReadBool(cchr *Section, cchr *Key, bool Default);
int ReadInt(cchr *Section, cchr *Key, int Default);
double ReadDouble(cchr *Section, cchr *Key, double Default);
cchr *ReadString(cchr *Section, cchr *Key, cchr *Default);
void WriteBool(cchr *Section, cchr *Key, bool Value);
void WriteInt(cchr *Section, cchr *Key, int Value);
void WriteDouble(cchr *Section, cchr *Key, double Value);
void WriteString(cchr *Section, cchr *Key, cchr *Value);
bool DeleteKey(cchr *Section, cchr *Key);
void CloseIniFile();
bool WriteIniFile(cchr *FileName);
int GetSectionCount();
void GetSections(char *sections[]);
#endif
+268
View File
@@ -0,0 +1,268 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <orbis/libkernel.h>
#include <orbis/Bgft.h>
#include <orbis/AppInstUtil.h>
#include <orbis/UserService.h>
#include <curl/curl.h>
#include <request.hpp>
#include <urn.hpp>
#include "installer.h"
#include "util.h"
#include "config.h"
#include "windows.h"
#include "lang.h"
#include "rtc.h"
#include "fs.h"
#define BGFT_HEAP_SIZE (1 * 1024 * 1024)
static OrbisBgftInitParams s_bgft_init_params;
static bool s_bgft_initialized = false;
namespace INSTALLER
{
int Init(void)
{
int ret;
if (s_bgft_initialized)
{
goto done;
}
memset(&s_bgft_init_params, 0, sizeof(s_bgft_init_params));
{
s_bgft_init_params.heapSize = BGFT_HEAP_SIZE;
s_bgft_init_params.heap = (uint8_t *)malloc(s_bgft_init_params.heapSize);
if (!s_bgft_init_params.heap)
{
goto err;
}
memset(s_bgft_init_params.heap, 0, s_bgft_init_params.heapSize);
}
ret = sceBgftServiceIntInit(&s_bgft_init_params);
if (ret)
{
goto err_bgft_heap_free;
}
s_bgft_initialized = true;
done:
return 0;
err_bgft_heap_free:
if (s_bgft_init_params.heap)
{
free(s_bgft_init_params.heap);
s_bgft_init_params.heap = NULL;
}
memset(&s_bgft_init_params, 0, sizeof(s_bgft_init_params));
err:
s_bgft_initialized = false;
return -1;
}
void Exit(void)
{
int ret;
if (!s_bgft_initialized)
{
return;
}
ret = sceBgftServiceIntTerm();
if (s_bgft_init_params.heap)
{
free(s_bgft_init_params.heap);
s_bgft_init_params.heap = NULL;
}
memset(&s_bgft_init_params, 0, sizeof(s_bgft_init_params));
s_bgft_initialized = false;
}
int InstallRemotePkg(const char *filename, pkg_header *header)
{
std::string full_url = webdav_settings->server + std::string(filename);
size_t scheme_pos = full_url.find("://");
size_t root_pos = full_url.find("/", scheme_pos+3);
std::string host = full_url.substr(0, root_pos);
std::string path = full_url.substr(root_pos);
WebDAV::Urn::Path uri(path);
CURL *curl = curl_easy_init();
path = uri.quote(curl);
curl_easy_cleanup(curl);
char url[2000];
sprintf(url, "%s%s", host.c_str(), path.c_str());
int ret;
std::string cid = std::string((char *)header->pkg_content_id);
cid = cid.substr(cid.find_first_of("-") + 1, 9);
int user_id;
ret = sceUserServiceGetForegroundUser(&user_id);
const char *package_type;
uint32_t content_type = BE32(header->pkg_content_type);
uint32_t flags = BE32(header->pkg_content_flags);
bool is_patch = false;
switch (content_type)
{
case PKG_CONTENT_TYPE_GD:
package_type = "PS4GD";
break;
case PKG_CONTENT_TYPE_AC:
package_type = "PS4AC";
break;
case PKG_CONTENT_TYPE_AL:
package_type = "PS4AL";
break;
case PKG_CONTENT_TYPE_DP:
package_type = "PS4DP";
break;
default:
package_type = NULL;
return 0;
break;
}
if (flags & PKG_CONTENT_FLAGS_FIRST_PATCH ||
flags & PKG_CONTENT_FLAGS_SUBSEQUENT_PATCH ||
flags & PKG_CONTENT_FLAGS_DELTA_PATCH ||
flags & PKG_CONTENT_FLAGS_CUMULATIVE_PATCH)
{
is_patch = true;
}
OrbisBgftDownloadParam params;
memset(&params, 0, sizeof(params));
{
params.userId = user_id;
params.entitlementType = 5;
params.id = (char *)header->pkg_content_id;
params.contentUrl = url;
params.contentName = cid.c_str();
params.iconPath = "";
params.playgoScenarioId = "0";
params.option = ORBIS_BGFT_TASK_OPT_DISABLE_CDN_QUERY_PARAM;
params.packageType = package_type;
params.packageSubType = "";
params.packageSize = BE64(header->pkg_size);
}
int task_id = -1;
if (!is_patch)
ret = sceBgftServiceIntDownloadRegisterTask(&params, &task_id);
else
ret = sceBgftServiceIntDebugDownloadRegisterPkg(&params, &task_id);
if (ret)
{
goto err;
}
ret = sceBgftServiceDownloadStartTask(task_id);
if (ret)
{
goto err;
}
Util::Notify("%s queued", cid.c_str());
return 1;
err:
return 0;
}
int InstallLocalPkg(const char *filename, pkg_header *header, bool remove_after_install)
{
int ret;
if (strncmp(filename, "/data/", 6) != 0 &&
strncmp(filename, "/user/data/", 11) != 0 &&
strncmp(filename, "/mnt/usb", 8) != 0)
return -1;
char filepath[1024];
snprintf(filepath, 1023, "%s", filename);
if (strncmp(filename, "/data/", 6) == 0)
snprintf(filepath, 1023, "/user%s", filename);
char titleId[18];
memset(titleId, 0, sizeof(titleId));
int is_app = -1;
ret = sceAppInstUtilGetTitleIdFromPkg(filename, titleId, &is_app);
if (ret)
{
return 0;
}
OrbisBgftTaskProgress progress_info;
int prog = 0;
OrbisBgftDownloadParamEx download_params;
memset(&download_params, 0, sizeof(download_params));
{
download_params.params.entitlementType = 5;
download_params.params.id = (char *)header->pkg_content_id;
download_params.params.contentUrl = filepath;
download_params.params.contentName = (char *)header->pkg_content_id;;
download_params.params.iconPath = "";
download_params.params.playgoScenarioId = "0";
download_params.params.option = ORBIS_BGFT_TASK_OPT_FORCE_UPDATE;
download_params.slot = 0;
}
int task_id = -1;
ret = sceBgftServiceIntDownloadRegisterTaskByStorageEx(&download_params, &task_id);
if (ret)
{
if (ret == 0x80990088)
return -2;
goto err;
}
ret = sceBgftServiceDownloadStartTask(task_id);
if (ret)
{
goto err;
}
if (!remove_after_install)
{
Util::Notify("%s queued", titleId);
return 1;
}
sprintf(activity_message, "%s", lang_strings[STR_WAIT_FOR_INSTALL_MSG]);
bytes_to_download = 1;
bytes_transfered = 0;
while (prog < 99)
{
memset(&progress_info, 0, sizeof(progress_info));
ret = sceBgftServiceDownloadGetProgress(task_id, &progress_info);
if (ret || (progress_info.transferred > 0 && progress_info.errorResult != 0))
return -3;
prog = (uint32_t)(((float)progress_info.transferred / progress_info.length) * 100.f);
bytes_to_download = progress_info.length;
bytes_transfered = progress_info.transferred;
}
if (auto_delete_tmp_pkg)
FS::Rm(filename);
return 1;
err:
return 0;
}
}
+115
View File
@@ -0,0 +1,115 @@
#pragma once
#define SWAP16(x) \
((uint16_t)( \
(((uint16_t)(x) & UINT16_C(0x00FF)) << 8) | \
(((uint16_t)(x) & UINT16_C(0xFF00)) >> 8) \
))
#define SWAP32(x) \
((uint32_t)( \
(((uint32_t)(x) & UINT32_C(0x000000FF)) << 24) | \
(((uint32_t)(x) & UINT32_C(0x0000FF00)) << 8) | \
(((uint32_t)(x) & UINT32_C(0x00FF0000)) >> 8) | \
(((uint32_t)(x) & UINT32_C(0xFF000000)) >> 24) \
))
#define SWAP64(x) \
((uint64_t)( \
(uint64_t)(((uint64_t)(x) & UINT64_C(0x00000000000000FF)) << 56) | \
(uint64_t)(((uint64_t)(x) & UINT64_C(0x000000000000FF00)) << 40) | \
(uint64_t)(((uint64_t)(x) & UINT64_C(0x0000000000FF0000)) << 24) | \
(uint64_t)(((uint64_t)(x) & UINT64_C(0x00000000FF000000)) << 8) | \
(uint64_t)(((uint64_t)(x) & UINT64_C(0x000000FF00000000)) >> 8) | \
(uint64_t)(((uint64_t)(x) & UINT64_C(0x0000FF0000000000)) >> 24) | \
(uint64_t)(((uint64_t)(x) & UINT64_C(0x00FF000000000000)) >> 40) | \
(uint64_t)(((uint64_t)(x) & UINT64_C(0xFF00000000000000)) >> 56) \
))
#define LE16(x) (x)
#define LE32(x) (x)
#define LE64(x) (x)
#define BE16(x) SWAP16(x)
#define BE32(x) SWAP32(x)
#define BE64(x) SWAP64(x)
#define PKG_MAGIC 0x7F434E54
#define PKG_CONTENT_FLAGS_FIRST_PATCH 0x00100000
#define PKG_CONTENT_FLAGS_PATCHGO 0x00200000
#define PKG_CONTENT_FLAGS_REMASTER 0x00400000
#define PKG_CONTENT_FLAGS_PS_CLOUD 0x00800000
#define PKG_CONTENT_FLAGS_GD_AC 0x02000000
#define PKG_CONTENT_FLAGS_NON_GAME 0x04000000
#define PKG_CONTENT_FLAGS_0x8000000 0x08000000 /* has data? */
#define PKG_CONTENT_FLAGS_SUBSEQUENT_PATCH 0x40000000
#define PKG_CONTENT_FLAGS_DELTA_PATCH 0x41000000
#define PKG_CONTENT_FLAGS_CUMULATIVE_PATCH 0x60000000
typedef struct
{
uint32_t pkg_magic; // 0x000 - 0x7F434E54
uint32_t pkg_type; // 0x004
uint32_t pkg_0x008; // 0x008 - unknown field
uint32_t pkg_file_count; // 0x00C
uint32_t pkg_entry_count; // 0x010
uint16_t pkg_sc_entry_count; // 0x014
uint16_t pkg_entry_count_2; // 0x016 - same as pkg_entry_count
uint32_t pkg_table_offset; // 0x018 - file table offset
uint32_t pkg_entry_data_size; // 0x01C
uint64_t pkg_body_offset; // 0x020 - offset of PKG entries
uint64_t pkg_body_size; // 0x028 - length of all PKG entries
uint64_t pkg_content_offset; // 0x030
uint64_t pkg_content_size; // 0x038
unsigned char pkg_content_id[0x24]; // 0x040 - packages' content ID as a 36-byte string
unsigned char pkg_padding[0xC]; // 0x064 - padding
uint32_t pkg_drm_type; // 0x070 - DRM type
uint32_t pkg_content_type; // 0x074 - Content type
uint32_t pkg_content_flags; // 0x078 - Content flags
uint32_t pkg_promote_size; // 0x07C
uint32_t pkg_version_date; // 0x080
uint32_t pkg_version_hash; // 0x084
uint32_t pkg_0x088; // 0x088
uint32_t pkg_0x08C; // 0x08C
uint32_t pkg_0x090; // 0x090
uint32_t pkg_0x094; // 0x094
uint32_t pkg_iro_tag; // 0x098
uint32_t pkg_drm_type_version; // 0x09C
unsigned char digest_entries1[0x20]; // 0x100 - sha256 digest for main entry 1
unsigned char digest_entries2[0x20]; // 0x120 - sha256 digest for main entry 2
unsigned char digest_table_digest[0x20]; // 0x140 - sha256 digest for digest table
unsigned char digest_body_digest[0x20]; // 0x160 - sha256 digest for main table
uint32_t pfs_image_count; // 0x404 - count of PFS images
uint64_t pfs_image_flags; // 0x408 - PFS flags
uint64_t pfs_image_offset; // 0x410 - offset to start of external PFS image
uint64_t pfs_image_size; // 0x418 - size of external PFS image
uint64_t mount_image_offset; // 0x420
uint64_t mount_image_size; // 0x428
uint64_t pkg_size; // 0x430
uint32_t pfs_signed_size; // 0x438
uint32_t pfs_cache_size; // 0x43C
unsigned char pfs_image_digest[0x20]; // 0x440
unsigned char pfs_signed_digest[0x20]; // 0x460
uint64_t pfs_split_size_nth_0; // 0x480
uint64_t pfs_split_size_nth_1; // 0x488
unsigned char pkg_digest[0x20]; // 0xFE0
} pkg_header;
enum pkg_content_type {
PKG_CONTENT_TYPE_GD = 0x1A, /* pkg_ps4_app, pkg_ps4_patch, pkg_ps4_remaster */
PKG_CONTENT_TYPE_AC = 0x1B, /* pkg_ps4_ac_data, pkg_ps4_sf_theme, pkg_ps4_theme */
PKG_CONTENT_TYPE_AL = 0x1C, /* pkg_ps4_ac_nodata */
PKG_CONTENT_TYPE_DP = 0x1E, /* pkg_ps4_delta_patch */
};
namespace INSTALLER
{
int Init(void);
void Exit(void);
int InstallRemotePkg(const char *filename, pkg_header *header);
int InstallLocalPkg(const char *filename, pkg_header *header, bool remove_after_install=false);
}
+218
View File
@@ -0,0 +1,218 @@
#include <orbis/SystemService.h>
#include "string.h"
#include "stdio.h"
#include "config.h"
#include "util.h"
#include "lang.h"
char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE] = {
FOREACH_STR(GET_STRING)};
// This is properly populated so that emulator won't crash if an user launches it without language INI files.
char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE] = {
"Connection Settings", // STR_CONNECTION_SETTINGS
"Site", // STR_SITE
"Local", // STR_LOCAL
"Remote", // STR_REMOTE
"Messages", // STR_MESSAGES
"Update Software", // STR_UPDATE_SOFTWARE
"Connect", // STR_CONNECT_WEBDAV
"Disconnect", // STR_DISCONNECT_WEBDAV
"Search", // STR_SEARCH
"Refresh", // STR_REFRESH
"Server", // STR_SERVER
"Username", // STR_USERNAME
"Password", // STR_PASSWORD
"Port", // STR_PORT
"Pasv", // STR_PASV
"Directory", // STR_DIRECTORY
"Filter", // STR_FILTER
"Yes", // STR_YES
"No", // STR_NO
"Cancel", // STR_CANCEL
"Continue", // STR_CONTINUE
"Close", // STR_CLOSE
"Folder", // STR_FOLDER
"File", // STR_FILE
"Type", // STR_TYPE
"Name", // STR_NAME
"Size", // STR_SIZE
"Date", // STR_DATE
"New Folder", // STR_NEW_FOLDER
"Rename", // STR_RENAME
"Delete", // STR_DELETE
"Upload", // STR_UPLOAD
"Download", // STR_DOWNLOAD
"Select All", // STR_SELECT_ALL
"Clear All", // STR_CLEAR_ALL
"Uploading", // STR_UPLOADING
"Downloading", // STR_DOWNLOADING
"Overwrite", // STR_OVERWRITE
"Don't Overwrite", // STR_DONT_OVERWRITE
"Ask for Confirmation", // STR_ASK_FOR_CONFIRM
"Don't Ask for Confirmation", // STR_DONT_ASK_CONFIRM
"Always use this option and don't ask again", // STR_ALLWAYS_USE_OPTION
"Actions", // STR_ACTIONS
"Confirm", // STR_CONFIRM
"Overwrite Options", // STR_OVERWRITE_OPTIONS
"Properties", // STR_PROPERTIES
"Progress", // STR_PROGRESS
"Updates", // STR_UPDATES
"Are you sure you want to delete this file(s)/folder(s)?", // STR_DEL_CONFIRM_MSG
"Canceling. Waiting for last action to complete", // STR_CANCEL_ACTION_MSG
"Failed to upload file", // STR_FAIL_UPLOAD_MSG
"Failed to download file", // STR_FAIL_DOWNLOAD_MSG
"Failed to read contents of directory or folder does not exist.", // STR_FAIL_READ_LOCAL_DIR_MSG
"426 Connection closed.", // STR_CONNECTION_CLOSE_ERR_MSG
"426 Remote Server has terminated the connection.", // STR_REMOTE_TERM_CONN_MSG
"300 Failed Login. Please check your username or password.", // STR_FAIL_LOGIN_MSG
"426 Failed. Connection timeout.", // STR_FAIL_TIMEOUT_MSG
"Failed to delete directory", // STR_FAIL_DEL_DIR_MSG
"Deleting", // STR_DELETING
"Failed to delete file", // STR_FAIL_DEL_FILE_MSG
"Deleted", // STR_DELETED
"Link", // STR_LINK
"Share", // STR_SHARE
"310 Failed", // STR_FAILED
"310 Failed to create file on local", // STR_FAIL_CREATE_LOCAL_FILE_MSG
"Install", // STR_INSTALL
"Installing", // STR_INSTALLING
"Success", // STR_INSTALL_SUCCESS
"Failed", // STR_INSTALL_FAILED
"Skipped", // STR_INSTALL_SKIPPED
"Checking connection to remote HTTP Server", // STR_CHECK_HTTP_MSG
"Failed connecting to HTTP Server", // STR_FAILED_HTTP_CHECK
"Remote is not a HTTP Server", // STR_REMOTE_NOT_HTTP
"Package not in the /data or /mnt/usbX folder", // STR_INSTALL_FROM_DATA_MSG
"Package is already installed", // STR_ALREADY_INSTALLED_MSG
"Install from URL", // STR_INSTALL_FROM_URL
"Could not read package header info", // STR_CANNOT_READ_PKG_HDR_MSG
"Favorite URLs", // STR_FAVORITE_URLS
"Slot", // STR_SLOT
"Edit", // STR_EDIT
"One Time Url", // STR_ONETIME_URL
"Not a valid Package", // STR_NOT_A_VALID_PACKAGE
"Waiting for Package to finish installing", // STR_WAIT_FOR_INSTALL_MSG
"Failed to install pkg file. Please delete the tmp pkg manually", // STR_FAIL_INSTALL_TMP_PKG_MSG
"Failed to obtain google download URL", // STR_FAIL_TO_OBTAIN_GG_DL_MSG
"Auto delete temporary downloaded pkg file after install", // STR_AUTO_DELETE_TMP_PKG
"Protocol not supported", // STR_PROTOCOL_NOT_SUPPORTED
"Could not resolve hostname" // STR_COULD_NOT_RESOLVE_HOST
};
bool needs_extended_font = false;
namespace Lang
{
void SetTranslation(int32_t lang_idx)
{
char langFile[LANG_STR_SIZE * 2];
char identifier[LANG_ID_SIZE], buffer[LANG_STR_SIZE];
std::string lang = std::string(language);
lang = Util::Trim(lang, " ");
if (lang.size() > 0)
{
sprintf(langFile, "/app0/assets/langs/%s.ini", lang.c_str());
}
else
{
switch (lang_idx)
{
case ORBIS_SYSTEM_PARAM_LANG_ITALIAN:
sprintf(langFile, "%s", "/app0/assets/langs/Italiano.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_SPANISH:
case ORBIS_SYSTEM_PARAM_LANG_SPANISH_LA:
sprintf(langFile, "%s", "/app0/assets/langs/Spanish.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_GERMAN:
sprintf(langFile, "%s", "/app0/assets/langs/German.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_PORTUGUESE_PT:
case ORBIS_SYSTEM_PARAM_LANG_PORTUGUESE_BR:
sprintf(langFile, "%s", "/app0/assets/langs/Portuguese_BR.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_RUSSIAN:
sprintf(langFile, "%s", "/app0/assets/langs/Russian.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_DUTCH:
sprintf(langFile, "%s", "/app0/assets/langs/Dutch.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_FRENCH:
case ORBIS_SYSTEM_PARAM_LANG_FRENCH_CA:
sprintf(langFile, "%s", "/app0/assets/langs/French.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_POLISH:
sprintf(langFile, "%s", "/app0/assets/langs/Polish.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_JAPANESE:
sprintf(langFile, "%s", "/app0/assets/langs/Japanese.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_KOREAN:
sprintf(langFile, "%s", "/app0/assets/langs/Korean.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_CHINESE_S:
sprintf(langFile, "%s", "/app0/assets/langs/Simplified Chinese.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_CHINESE_T:
sprintf(langFile, "%s", "/app0/assets/langs/Traditional Chinese.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_INDONESIAN:
sprintf(langFile, "%s", "/app0/assets/langs/Indonesian.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_HUNGARIAN:
sprintf(langFile, "%s", "/app0/assets/langs/Hungarian.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_GREEK:
sprintf(langFile, "%s", "/app0/assets/langs/Greek.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_VIETNAMESE:
sprintf(langFile, "%s", "/app0/assets/langs/Vietnamese.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_TURKISH:
sprintf(langFile, "%s", "/app0/assets/langs/Turkish.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_ARABIC:
sprintf(langFile, "%s", "/app0/assets/langs/Arabic.ini");
break;
case ORBIS_SYSTEM_PARAM_LANG_ROMANIAN:
sprintf(langFile, "%s", "/app0/assets/langs/Romanian.ini");
break;
default:
sprintf(langFile, "%s", "/app0/assets/langs/English.ini");
break;
}
}
FILE *config = fopen(langFile, "r");
if (config)
{
while (EOF != fscanf(config, "%[^=]=%[^\n]\n", identifier, buffer))
{
for (int i = 0; i < LANG_STRINGS_NUM; i++)
{
if (strcmp(lang_identifiers[i], identifier) == 0)
{
char *newline = nullptr, *p = buffer;
while ((newline = strstr(p, "\\n")) != NULL)
{
newline[0] = '\n';
int len = strlen(&newline[2]);
memmove(&newline[1], &newline[2], len);
newline[len + 1] = 0;
p++;
}
strcpy(lang_strings[i], buffer);
}
}
}
fclose(config);
}
char buf[12];
int num;
sscanf(last_site, "%[^ ] %d", buf, &num);
sprintf(display_site, "%s %d", lang_strings[STR_SITE], num);
}
}
+116
View File
@@ -0,0 +1,116 @@
#ifndef __LANG_H__
#define __LANG_H__
#include "config.h"
#define FOREACH_STR(FUNC) \
FUNC(STR_CONNECTION_SETTINGS) \
FUNC(STR_SITE) \
FUNC(STR_LOCAL) \
FUNC(STR_REMOTE) \
FUNC(STR_MESSAGES) \
FUNC(STR_UPDATE_SOFTWARE) \
FUNC(STR_CONNECT_WEBDAV) \
FUNC(STR_DISCONNECT_WEBDAV) \
FUNC(STR_SEARCH) \
FUNC(STR_REFRESH) \
FUNC(STR_SERVER) \
FUNC(STR_USERNAME) \
FUNC(STR_PASSWORD) \
FUNC(STR_PORT) \
FUNC(STR_PASV) \
FUNC(STR_DIRECTORY) \
FUNC(STR_FILTER) \
FUNC(STR_YES) \
FUNC(STR_NO) \
FUNC(STR_CANCEL) \
FUNC(STR_CONTINUE) \
FUNC(STR_CLOSE) \
FUNC(STR_FOLDER) \
FUNC(STR_FILE) \
FUNC(STR_TYPE) \
FUNC(STR_NAME) \
FUNC(STR_SIZE) \
FUNC(STR_DATE) \
FUNC(STR_NEW_FOLDER) \
FUNC(STR_RENAME) \
FUNC(STR_DELETE) \
FUNC(STR_UPLOAD) \
FUNC(STR_DOWNLOAD) \
FUNC(STR_SELECT_ALL) \
FUNC(STR_CLEAR_ALL) \
FUNC(STR_UPLOADING) \
FUNC(STR_DOWNLOADING) \
FUNC(STR_OVERWRITE) \
FUNC(STR_DONT_OVERWRITE) \
FUNC(STR_ASK_FOR_CONFIRM) \
FUNC(STR_DONT_ASK_CONFIRM) \
FUNC(STR_ALLWAYS_USE_OPTION) \
FUNC(STR_ACTIONS) \
FUNC(STR_CONFIRM) \
FUNC(STR_OVERWRITE_OPTIONS) \
FUNC(STR_PROPERTIES) \
FUNC(STR_PROGRESS) \
FUNC(STR_UPDATES) \
FUNC(STR_DEL_CONFIRM_MSG) \
FUNC(STR_CANCEL_ACTION_MSG) \
FUNC(STR_FAIL_UPLOAD_MSG) \
FUNC(STR_FAIL_DOWNLOAD_MSG) \
FUNC(STR_FAIL_READ_LOCAL_DIR_MSG) \
FUNC(STR_CONNECTION_CLOSE_ERR_MSG) \
FUNC(STR_REMOTE_TERM_CONN_MSG) \
FUNC(STR_FAIL_LOGIN_MSG) \
FUNC(STR_FAIL_TIMEOUT_MSG) \
FUNC(STR_FAIL_DEL_DIR_MSG) \
FUNC(STR_DELETING) \
FUNC(STR_FAIL_DEL_FILE_MSG) \
FUNC(STR_DELETED) \
FUNC(STR_LINK) \
FUNC(STR_SHARE) \
FUNC(STR_FAILED) \
FUNC(STR_FAIL_CREATE_LOCAL_FILE_MSG) \
FUNC(STR_INSTALL) \
FUNC(STR_INSTALLING) \
FUNC(STR_INSTALL_SUCCESS) \
FUNC(STR_INSTALL_FAILED) \
FUNC(STR_INSTALL_SKIPPED) \
FUNC(STR_CHECK_HTTP_MSG) \
FUNC(STR_FAILED_HTTP_CHECK) \
FUNC(STR_REMOTE_NOT_HTTP) \
FUNC(STR_INSTALL_FROM_DATA_MSG) \
FUNC(STR_ALREADY_INSTALLED_MSG) \
FUNC(STR_INSTALL_FROM_URL) \
FUNC(STR_CANNOT_READ_PKG_HDR_MSG) \
FUNC(STR_FAVORITE_URLS) \
FUNC(STR_SLOT) \
FUNC(STR_EDIT) \
FUNC(STR_ONETIME_URL) \
FUNC(STR_NOT_A_VALID_PACKAGE) \
FUNC(STR_WAIT_FOR_INSTALL_MSG) \
FUNC(STR_FAIL_INSTALL_TMP_PKG_MSG) \
FUNC(STR_FAIL_TO_OBTAIN_GG_DL_MSG) \
FUNC(STR_AUTO_DELETE_TMP_PKG) \
FUNC(STR_PROTOCOL_NOT_SUPPORTED) \
FUNC(STR_COULD_NOT_RESOLVE_HOST)
#define GET_VALUE(x) x,
#define GET_STRING(x) #x,
enum
{
FOREACH_STR(GET_VALUE)
};
#define LANG_STRINGS_NUM 88
#define LANG_ID_SIZE LANG_STRINGS_NUM
#define LANG_STR_SIZE 256
extern char lang_identifiers[LANG_STRINGS_NUM][LANG_ID_SIZE];
extern char lang_strings[LANG_STRINGS_NUM][LANG_STR_SIZE];
extern bool needs_extended_font;
namespace Lang
{
void SetTranslation(int32_t lang_idx);
}
#endif
+314
View File
@@ -0,0 +1,314 @@
#undef main
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <orbis/libkernel.h>
#include <orbis/Sysmodule.h>
#include <orbis/UserService.h>
#include <orbis/SystemService.h>
#include <orbis/Pad.h>
#include <orbis/AudioOut.h>
#include <orbis/Net.h>
// #include <dbglogger.h>
#include "imgui.h"
#include "SDL2/SDL.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_sdlrenderer.h"
#include "config.h"
#include "lang.h"
#include "gui.h"
#include "util.h"
#include "installer.h"
#include "rtc.h"
extern "C"
{
#include "orbis_jbc.h"
}
#define FRAME_WIDTH 1920
#define FRAME_HEIGHT 1080
#define NET_HEAP_SIZE (5 * 1024 * 1024)
// SDL window and software renderer
SDL_Window *window;
SDL_Renderer *renderer;
ImVec4 ColorFromBytes(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255)
{
return ImVec4((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f);
};
void InitImgui()
{
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
(void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
io.Fonts->Clear();
io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines;
static const ImWchar ranges[] = { // All languages with chinese included
0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x0100, 0x024F, // Latin Extended
0x0370, 0x03FF, // Greek
0x0400, 0x052F, // Cyrillic + Cyrillic Supplement
0x0590, 0x05FF, // Hebrew
0x1E00, 0x1EFF, // Latin Extended Additional
0x1F00, 0x1FFF, // Greek Extended
0x2000, 0x206F, // General Punctuation
0x2100, 0x214F, // Letterlike Symbols
0x2460, 0x24FF, // Enclosed Alphanumerics
0x2DE0, 0x2DFF, // Cyrillic Extended-A
0x2E80, 0x2EFF, // CJK Radicals Supplement
0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
0x31F0, 0x31FF, // Katakana Phonetic Extensions
0x3400, 0x4DBF, // CJK Rare
0x4E00, 0x9FFF, // CJK Ideograms
0xA640, 0xA69F, // Cyrillic Extended-B
0xF900, 0xFAFF, // CJK Compatibility Ideographs
0xFF00, 0xFFEF, // Half-width characters
0,
};
static const ImWchar arabic[] = { // Arabic
0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x0100, 0x024F, // Latin Extended
0x0400, 0x052F, // Cyrillic + Cyrillic Supplement
0x1E00, 0x1EFF, // Latin Extended Additional
0x2000, 0x206F, // General Punctuation
0x2100, 0x214F, // Letterlike Symbols
0x2460, 0x24FF, // Enclosed Alphanumerics
0x0600, 0x06FF, // Arabic
0x0750, 0x077F, // Arabic Supplement
0x0870, 0x089F, // Arabic Extended-B
0x08A0, 0x08FF, // Arabic Extended-A
0xFB50, 0xFDFF, // Arabic Presentation Forms-A
0xFE70, 0xFEFF, // Arabic Presentation Forms-B
0,
};
std::string lang = std::string(language);
int32_t lang_idx;
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))
{
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))
{
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
}
else if (lang.compare("Traditional Chinese") == 0 || (lang.empty() && lang_idx == ORBIS_SYSTEM_PARAM_LANG_CHINESE_T))
{
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());
}
else if (lang.compare("Japanese") == 0 || lang.compare("Ryukyuan") == 0 || (lang.empty() && 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))
{
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))
{
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))
{
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))
{
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto_ext.ttf", 26.0f, NULL, arabic);
}
else
{
io.Fonts->AddFontFromFileTTF("/app0/assets/fonts/Roboto.ttf", 26.0f, NULL, ranges);
}
Lang::SetTranslation(lang_idx);
auto &style = ImGui::GetStyle();
style.AntiAliasedLinesUseTex = false;
style.AntiAliasedLines = true;
style.AntiAliasedFill = true;
style.WindowRounding = 1.0f;
style.FrameRounding = 2.0f;
style.GrabRounding = 2.0f;
ImVec4* colors = style.Colors;
const ImVec4 bgColor = ColorFromBytes(37, 37, 38);
const ImVec4 bgColorBlur = ColorFromBytes(37, 37, 38, 170);
const ImVec4 lightBgColor = ColorFromBytes(82, 82, 85);
const ImVec4 veryLightBgColor = ColorFromBytes(90, 90, 95);
const ImVec4 titleColor = ColorFromBytes(10, 100, 142);
const ImVec4 panelColor = ColorFromBytes(51, 51, 55);
const ImVec4 panelHoverColor = ColorFromBytes(29, 151, 236);
const ImVec4 panelActiveColor = ColorFromBytes(0, 119, 200);
const ImVec4 textColor = ColorFromBytes(255, 255, 255);
const ImVec4 textDisabledColor = ColorFromBytes(151, 151, 151);
const ImVec4 borderColor = ColorFromBytes(78, 78, 78);
colors[ImGuiCol_Text] = textColor;
colors[ImGuiCol_TextDisabled] = textDisabledColor;
colors[ImGuiCol_TextSelectedBg] = panelActiveColor;
colors[ImGuiCol_WindowBg] = bgColor;
colors[ImGuiCol_ChildBg] = panelColor;
colors[ImGuiCol_PopupBg] = bgColor;
colors[ImGuiCol_Border] = borderColor;
colors[ImGuiCol_BorderShadow] = borderColor;
colors[ImGuiCol_FrameBg] = panelColor;
colors[ImGuiCol_FrameBgHovered] = panelHoverColor;
colors[ImGuiCol_FrameBgActive] = panelActiveColor;
colors[ImGuiCol_TitleBg] = titleColor;
colors[ImGuiCol_TitleBgActive] = titleColor;
colors[ImGuiCol_TitleBgCollapsed] = titleColor;
colors[ImGuiCol_MenuBarBg] = panelColor;
colors[ImGuiCol_ScrollbarBg] = panelColor;
colors[ImGuiCol_ScrollbarGrab] = lightBgColor;
colors[ImGuiCol_ScrollbarGrabHovered] = veryLightBgColor;
colors[ImGuiCol_ScrollbarGrabActive] = veryLightBgColor;
colors[ImGuiCol_CheckMark] = panelActiveColor;
colors[ImGuiCol_SliderGrab] = panelHoverColor;
colors[ImGuiCol_SliderGrabActive] = panelActiveColor;
colors[ImGuiCol_Button] = panelColor;
colors[ImGuiCol_ButtonHovered] = panelHoverColor;
colors[ImGuiCol_ButtonActive] = panelHoverColor;
colors[ImGuiCol_Header] = panelColor;
colors[ImGuiCol_HeaderHovered] = panelHoverColor;
colors[ImGuiCol_HeaderActive] = panelActiveColor;
colors[ImGuiCol_Separator] = borderColor;
colors[ImGuiCol_SeparatorHovered] = borderColor;
colors[ImGuiCol_SeparatorActive] = borderColor;
colors[ImGuiCol_ResizeGrip] = bgColor;
colors[ImGuiCol_ResizeGripHovered] = panelColor;
colors[ImGuiCol_ResizeGripActive] = lightBgColor;
colors[ImGuiCol_PlotLines] = panelActiveColor;
colors[ImGuiCol_PlotLinesHovered] = panelHoverColor;
colors[ImGuiCol_PlotHistogram] = panelActiveColor;
colors[ImGuiCol_PlotHistogramHovered] = panelHoverColor;
colors[ImGuiCol_ModalWindowDimBg] = bgColorBlur;
colors[ImGuiCol_DragDropTarget] = bgColor;
colors[ImGuiCol_NavHighlight] = bgColor;
colors[ImGuiCol_Tab] = bgColor;
colors[ImGuiCol_TabActive] = panelActiveColor;
colors[ImGuiCol_TabUnfocused] = bgColor;
colors[ImGuiCol_TabUnfocusedActive] = panelActiveColor;
colors[ImGuiCol_TabHovered] = panelHoverColor;
}
static void terminate()
{
INSTALLER::Exit();
terminate_jbc();
sceSystemServiceLoadExec("exit", NULL);
}
int main()
{
// dbglogger_init();
// dbglogger_log("If you see this you've set up dbglogger correctly.");
int rc;
// No buffering
setvbuf(stdout, NULL, _IONBF, 0);
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
return 0;
}
// load common modules
int ret = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_SYSTEM_SERVICE);
if (ret < 0)
{
return 0;
}
ret = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_USER_SERVICE);
if (ret < 0)
{
return 0;
}
ret = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_BGFT);
if (ret) {
return 0;
}
ret = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_APP_INST_UTIL);
if (ret) {
return 0;
}
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_PAD) < 0)
return 0;
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_AUDIOOUT) < 0 ||
sceAudioOutInit() != 0)
{
return 0;
}
if (sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_IME_DIALOG) < 0)
return 0;
if(sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_NET) < 0 || sceNetInit() != 0)
return 0;
sceNetPoolCreate("simple", NET_HEAP_SIZE, 0);
if (INSTALLER::Init() < 0)
return 0;
CONFIG::LoadConfig();
// Create a window context
window = SDL_CreateWindow("main", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, FRAME_WIDTH, FRAME_HEIGHT, 0);
if (window == NULL)
return 0;
renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL)
return 0;
InitImgui();
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer_Init(renderer);
ImGui_ImplSDLRenderer_CreateFontsTexture();
ImGui_ImplSDL2_DisableButton(SDL_CONTROLLER_BUTTON_X, true);
if (!initialize_jbc())
{
terminate();
}
if (load_rtc_module() != 0)
return 0;
atexit(terminate);
GUI::RenderLoop(renderer);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
ImGui::DestroyContext();
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <orbis/libkernel.h>
#include <libjbc.h>
// Variables for (un)jailbreaking
jbc_cred g_Cred;
jbc_cred g_RootCreds;
// Verify jailbreak
static int is_jailbroken()
{
FILE *s_FilePointer = fopen("/user/.jailbreak", "w");
if (!s_FilePointer)
return 0;
fclose(s_FilePointer);
remove("/user/.jailbreak");
return 1;
}
// Jailbreaks creds
static int jailbreak()
{
if (is_jailbroken())
{
return 1;
}
jbc_get_cred(&g_Cred);
g_RootCreds = g_Cred;
jbc_jailbreak_cred(&g_RootCreds);
jbc_set_cred(&g_RootCreds);
return (is_jailbroken());
}
// Initialize jailbreak
int initialize_jbc()
{
// Pop notification depending on jailbreak result
if (!jailbreak())
{
return 0;
}
return 1;
}
// Unload libjbc libraries
void terminate_jbc()
{
if (!is_jailbroken())
return;
// Restores original creds
jbc_set_cred(&g_Cred);
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef __ORBIS_JBC_H__
#define __ORBIS_JBC_H__
int initialize_jbc();
void terminate_jbc();
#endif
+77
View File
@@ -0,0 +1,77 @@
/**
* pugixml parser - version 1.13
* --------------------------------------------------------
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to enable compact mode
// #define PUGIXML_COMPACT
// Uncomment this to disable XPath
// #define PUGIXML_NO_XPATH
// Uncomment this to disable STL
// #define PUGIXML_NO_STL
// Uncomment this to disable exceptions
// #define PUGIXML_NO_EXCEPTIONS
// Set this to control attributes for public classes/functions, i.e.:
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
// Tune these constants to adjust memory-related behavior
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
// Tune this constant to adjust max nesting for XPath queries
// #define PUGIXML_XPATH_DEPTH_LIMIT 1024
// Uncomment this to switch to header-only version
// #define PUGIXML_HEADER_ONLY
// Uncomment this to enable long long support
// #define PUGIXML_HAS_LONG_LONG
#endif
/**
* Copyright (c) 2006-2022 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+36
View File
@@ -0,0 +1,36 @@
#ifndef REMOTECLIENT_H
#define REMOTECLIENT_H
#include <string>
#include <vector>
#include "common.h"
enum ClientType
{
CLIENT_TYPE_FTP, CLIENT_TYPE_SMB, CLIENT_TYPE_WEBDAV
};
class RemoteClient
{
public:
RemoteClient(){};
virtual ~RemoteClient(){};
virtual int Connect(const std::string &url, const std::string &username, const std::string &password) = 0;
virtual int Mkdir(const std::string &path) = 0;
virtual int Rmdir(const std::string &path, bool recursive) = 0;
virtual int Size(const std::string &path, int64_t *size) = 0;
virtual int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0) = 0;
virtual int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0) = 0;
virtual int Rename(const std::string &src, const std::string &dst) = 0;
virtual int Delete(const std::string &path) = 0;
virtual bool FileExists(const std::string &path) = 0;
virtual std::vector<DirEntry> ListDir(const std::string &path) = 0;
virtual std::string GetPath(std::string path1, std::string path2) = 0;
virtual bool IsConnected() = 0;
virtual bool Ping() = 0;
virtual const char *LastResponse() = 0;
virtual int Quit() = 0;
virtual ClientType clientType() = 0;
};
#endif
+70
View File
@@ -0,0 +1,70 @@
#include <stdlib.h>
#include <orbis/libkernel.h>
#include <orbis/Sysmodule.h>
#include "rtc.h"
int (*sceRtcGetTick)(const OrbisDateTime *inOrbisDateTime, OrbisTick *outTick);
int (*sceRtcSetTick)(OrbisDateTime *outOrbisDateTime, const OrbisTick *inputTick);
int (*sceRtcConvertLocalTimeToUtc)(const OrbisTick *local_time, OrbisTick *utc);
int (*sceRtcConvertUtcToLocalTime)(const OrbisTick *utc, OrbisTick *local_time);
int (*sceRtcGetCurrentClockLocalTime)(OrbisDateTime *time);
void convertUtcToLocalTime(const OrbisDateTime *utc, OrbisDateTime *local_time)
{
OrbisTick utc_tick;
OrbisTick local_tick;
sceRtcGetTick(utc, &utc_tick);
sceRtcConvertUtcToLocalTime(&utc_tick, &local_tick);
sceRtcSetTick(local_time, &local_tick);
}
void convertLocalTimeToUtc(const OrbisDateTime *local_time, OrbisDateTime *utc)
{
OrbisTick utc_tick;
OrbisTick local_tick;
sceRtcGetTick(local_time, &local_tick);
sceRtcConvertLocalTimeToUtc(&local_tick, &utc_tick);
sceRtcSetTick(utc, &utc_tick);
}
int load_rtc_module()
{
int rtc_handle = sceKernelLoadStartModule("/system/common/lib/libSceRtc.sprx", 0, NULL, 0, NULL, NULL);
if (rtc_handle == 0)
{
return -1;
}
sceKernelDlsym(rtc_handle, "sceRtcGetTick", (void **)&sceRtcGetTick);
if (sceRtcGetTick == NULL)
{
return -1;
}
sceKernelDlsym(rtc_handle, "sceRtcSetTick", (void **)&sceRtcSetTick);
if (sceRtcSetTick == NULL)
{
return -1;
}
sceKernelDlsym(rtc_handle, "sceRtcConvertLocalTimeToUtc", (void **)&sceRtcConvertLocalTimeToUtc);
if (sceRtcConvertLocalTimeToUtc == NULL)
{
return -1;
}
sceKernelDlsym(rtc_handle, "sceRtcConvertUtcToLocalTime", (void **)&sceRtcConvertUtcToLocalTime);
if (sceRtcConvertUtcToLocalTime == NULL)
{
return -1;
}
sceKernelDlsym(rtc_handle, "sceRtcGetCurrentClockLocalTime", (void **)&sceRtcGetCurrentClockLocalTime);
if (sceRtcGetCurrentClockLocalTime == NULL)
{
return -1;
}
return 0;
}
+33
View File
@@ -0,0 +1,33 @@
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OrbisTick {
uint64_t mytick;
} OrbisTick;
typedef struct OrbisDateTime {
unsigned short year;
unsigned short month;
unsigned short day;
unsigned short hour;
unsigned short minute;
unsigned short second;
unsigned int microsecond;
} OrbisDateTime;
extern int (*sceRtcGetTick)(const OrbisDateTime *inOrbisDateTime, OrbisTick *outTick);
extern int (*sceRtcSetTick)(OrbisDateTime *outOrbisDateTime, const OrbisTick *inputTick);
extern int (*sceRtcConvertLocalTimeToUtc)(const OrbisTick *local_time, OrbisTick *utc);
extern int (*sceRtcConvertUtcToLocalTime)(const OrbisTick *utc, OrbisTick *local_time);
extern int (*sceRtcGetCurrentClockLocalTime)(OrbisDateTime *time) ;
int load_rtc_module();
void convertUtcToLocalTime(const OrbisDateTime *utc, OrbisDateTime *local_time);
void convertLocalTimeToUtc(const OrbisDateTime *local_time, OrbisDateTime *utc);
#ifdef __cplusplus
}
#endif
+515
View File
@@ -0,0 +1,515 @@
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <cstring>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <orbis/Net.h>
#include "fs.h"
#include "lang.h"
#include "smbclient.h"
#include "windows.h"
#include "util.h"
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
SmbClient::SmbClient()
{
}
SmbClient::~SmbClient()
{
}
int SmbClient::Connect(const std::string &url, const std::string &user, const std::string &pass)
{
struct smb2_url *smb_url;
smb2 = smb2_init_context();
if (smb2 == NULL)
{
sprintf(response, "Failed to init SMB context");
return 0;
}
smb_url = smb2_parse_url(smb2, url.c_str());
if (pass.length() > 0)
smb2_set_password(smb2, pass.c_str());
smb2_set_security_mode(smb2, SMB2_NEGOTIATE_SIGNING_ENABLED);
smb2_set_timeout(smb2, 30);
if (smb2_connect_share(smb2, smb_url->server, smb_url->share, user.c_str()) < 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
smb2_destroy_url(smb_url);
max_read_size = smb2_get_max_read_size(smb2);
max_write_size = smb2_get_max_write_size(smb2);
connected = true;
return 1;
}
/*
* SmbLastResponse - return a pointer to the last response received
*/
const char *SmbClient::LastResponse()
{
return (const char *)response;
}
/*
* IsConnected - return true if connected to remote
*/
bool SmbClient::IsConnected()
{
return connected;
}
/*
* Ping - return true if connected to remote
*/
bool SmbClient::Ping()
{
connected = smb2_echo(smb2) == 0;
return connected;
}
/*
* SmbQuit - disconnect from remote
*
* return 1 if successful, 0 otherwise
*/
int SmbClient::Quit()
{
smb2_destroy_context(smb2);
smb2 = NULL;
connected = false;
return 1;
}
/*
* SmbMkdir - create a directory at server
*
* return 1 if successful, 0 otherwise
*/
int SmbClient::Mkdir(const std::string &ppath)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
if (smb2_mkdir(smb2, path.c_str()) != 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
return 1;
}
/*
* SmbRmdir - remove directory and all files under directory at remote
*
* return 1 if successful, 0 otherwise
*/
int SmbClient::_Rmdir(const std::string &ppath)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
if (smb2_rmdir(smb2, path.c_str()) != 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
return 1;
}
/*
* SmbRmdir - remove directory and all files under directory at remote
*
* return 1 if successful, 0 otherwise
*/
int SmbClient::Rmdir(const std::string &path, bool recursive)
{
if (stop_activity)
return 1;
std::vector<DirEntry> list = ListDir(path);
int ret;
for (int i = 0; i < list.size(); i++)
{
if (stop_activity)
return 1;
if (list[i].isDir && recursive)
{
if (strcmp(list[i].name, "..") == 0)
continue;
ret = Rmdir(list[i].path, recursive);
if (ret == 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], list[i].path);
return 0;
}
}
else
{
sprintf(activity_message, "%s %s\n", lang_strings[STR_DELETING], list[i].path);
ret = Delete(list[i].path);
if (ret == 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_FILE_MSG], list[i].path);
return 0;
}
}
}
ret = _Rmdir(path);
if (ret == 0)
{
sprintf(status_message, "%s %s", lang_strings[STR_FAIL_DEL_DIR_MSG], path.c_str());
return 0;
}
return 1;
}
/*
* SmbGet - issue a GET command and write received data to output
*
* return 1 if successful, 0 otherwise
*/
int SmbClient::Get(const std::string &outputfile, const std::string &ppath, uint64_t offset)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
if (!Size(path.c_str(), &bytes_to_download))
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
struct smb2fh* in = smb2_open(smb2, path.c_str(), O_RDONLY);
if (in == NULL)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
FILE* out = FS::Create(outputfile);
if (out == NULL)
{
sprintf(response, "%s", lang_strings[STR_FAILED]);
return 0;
}
uint8_t *buff = (uint8_t*)malloc(max_read_size);
int count = 0;
bytes_transfered = 0;
while ((count = smb2_read(smb2, in, buff, max_read_size)) > 0)
{
if (count < 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
FS::Close(out);
smb2_close(smb2, in);
free((void*)buff);
return 0;
}
FS::Write(out, buff, count);
bytes_transfered += count;
}
FS::Close(out);
smb2_close(smb2, in);
free((void*)buff);
return 1;
}
int SmbClient::Copy(const std::string &ppath, int socket_fd)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
if (!IsConnected())
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
struct smb2fh* in = smb2_open(smb2, path.c_str(), O_RDONLY);
if (in == NULL)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
uint8_t *buff = (uint8_t*)malloc(max_read_size);
int count = 0;
while ((count = smb2_read(smb2, in, buff, max_read_size)) > 0)
{
if (count < 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
smb2_close(smb2, in);
free((void*)buff);
return 0;
}
int ret = sceNetSend(socket_fd, buff, count, 0);
if (ret < 0)
{
break;
}
}
smb2_close(smb2, in);
free((void*)buff);
return 1;
}
bool SmbClient::FileExists(const std::string &ppath)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
smb2_stat_64 st;
int ret = smb2_stat(smb2, path.c_str(), &st);
if (ret != 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
return false;
}
return true;
}
/*
* SmbPut - issue a PUT command and send data from input
*
* return 1 if successful, 0 otherwise
*/
int SmbClient::Put(const std::string &inputfile, const std::string &ppath, uint64_t offset)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
bytes_to_download = FS::GetSize(inputfile);
if (bytes_to_download < 0)
{
sprintf(response, "%s", lang_strings[STR_FAILED]);
return 0;
}
FILE* in = FS::OpenRead(inputfile);
if (in == NULL)
{
sprintf(response, "%s", lang_strings[STR_FAILED]);
return 0;
}
struct smb2fh* out = smb2_open(smb2, path.c_str(), O_WRONLY | O_CREAT | O_TRUNC);
if (out == NULL)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
uint8_t* buff = (uint8_t*)malloc(max_write_size);
int count = 0;
bytes_transfered = 0;
while ((count = FS::Read(in, buff, max_write_size)) > 0)
{
if (count < 0)
{
sprintf(response, "%s", lang_strings[STR_FAILED]);
FS::Close(in);
smb2_close(smb2, out);
free(buff);
return 0;
}
smb2_write(smb2, out, buff, count);
bytes_transfered += count;
}
FS::Close(in);
smb2_close(smb2, out);
free(buff);
return 1;
}
int SmbClient::Rename(const std::string &src, const std::string &dst)
{
std::string path1 = std::string(src);
std::string path2 = std::string(dst);
path1 = Util::Trim(path1, "/");
path2 = Util::Trim(path2, "/");
if (smb2_rename(smb2, path1.c_str(), path2.c_str()) != 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
return 1;
}
int SmbClient::Delete(const std::string &ppath)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
if (smb2_unlink(smb2, path.c_str()) != 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
return 1;
}
int SmbClient::Size(const std::string &ppath, int64_t *size)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
smb2_stat_64 st;
if (smb2_stat(smb2, path.c_str(), &st) != 0)
{
sprintf(response, "%s", smb2_get_error(smb2));
return 0;
}
*size = st.smb2_size;
return 1;
}
std::vector<DirEntry> SmbClient::ListDir(const std::string &path)
{
std::vector<DirEntry> out;
DirEntry entry;
memset(&entry, 0, sizeof(DirEntry));
if (path.length() > 1 && path[path.length() - 1] == '/')
{
strlcpy(entry.directory, path.c_str(), path.length() - 1);
}
else
{
sprintf(entry.directory, "%s", path.c_str());
}
sprintf(entry.name, "..");
sprintf(entry.path, "%s", entry.directory);
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
entry.file_size = 0;
entry.isDir = true;
out.push_back(entry);
struct smb2dir *dir;
struct smb2dirent *ent;
std::string ppath = std::string(path);
dir = smb2_opendir(smb2, Util::Ltrim(ppath, "/").c_str());
if (dir == NULL)
{
sprintf(status_message, "%s - %s", lang_strings[STR_FAIL_READ_LOCAL_DIR_MSG], smb2_get_error(smb2));
return out;
}
while ((ent = smb2_readdir(smb2, dir)))
{
DirEntry entry;
memset(&entry, 0, sizeof(entry));
snprintf(entry.directory, 511, "%s", path.c_str());
snprintf(entry.name, 255, "%s", ent->name);
entry.file_size = ent->st.smb2_size;
if (path.length() > 0 && path[path.length() - 1] == '/')
{
sprintf(entry.path, "%s%s", path.c_str(), ent->name);
}
else
{
sprintf(entry.path, "%s/%s", path.c_str(), ent->name);
}
time_t t = (time_t)ent->st.smb2_mtime;
struct tm tm = *localtime(&t);
entry.modified.day = tm.tm_mday;
entry.modified.month = tm.tm_mon + 1;
entry.modified.year = tm.tm_year + 1900;
entry.modified.hours = tm.tm_hour;
entry.modified.minutes = tm.tm_min;
entry.modified.seconds = tm.tm_sec;
switch (ent->st.smb2_type)
{
case SMB2_TYPE_LINK:
entry.isLink = true;
entry.file_size = 0;
sprintf(entry.display_size, "%s", lang_strings[STR_LINK]);
break;
case SMB2_TYPE_FILE:
if (entry.file_size < 1024)
{
sprintf(entry.display_size, "%ldB", entry.file_size);
}
else if (entry.file_size < 1024 * 1024)
{
sprintf(entry.display_size, "%.2fKB", entry.file_size * 1.0f / 1024);
}
else if (entry.file_size < 1024 * 1024 * 1024)
{
sprintf(entry.display_size, "%.2fMB", entry.file_size * 1.0f / (1024 * 1024));
}
else
{
sprintf(entry.display_size, "%.2fGB", entry.file_size * 1.0f / (1024 * 1024 * 1024));
}
break;
case SMB2_TYPE_DIRECTORY:
entry.isDir = true;
entry.file_size = 0;
sprintf(entry.display_size, "%s", lang_strings[STR_FOLDER]);
break;
}
if (strcmp(entry.name, "..") != 0 && strcmp(entry.name, ".") != 0)
out.push_back(entry);
}
smb2_closedir(smb2, dir);
return out;
}
std::string SmbClient::GetPath(std::string ppath1, std::string ppath2)
{
std::string path1 = ppath1;
std::string path2 = ppath2;
path1 = Util::Rtrim(Util::Trim(path1, " "), "/");
path2 = Util::Rtrim(Util::Trim(path2, " "), "/");
path1 = path1 + "/" + path2;
return Util::Ltrim(path1, "/");
}
int SmbClient::Head(const std::string &ppath, void* buffer, uint16_t len)
{
std::string path = std::string(ppath);
path = Util::Trim(path, "/");
if (!Size(path.c_str(), &bytes_to_download))
{
return 0;
}
struct smb2fh* in = smb2_open(smb2, path.c_str(), O_RDONLY);
if (in == NULL)
{
return 0;
}
int count = smb2_read(smb2, in, (uint8_t*)buffer, len);
smb2_close(smb2, in);
if (count != len)
return 0;
return 1;
}
ClientType SmbClient::clientType()
{
return CLIENT_TYPE_SMB;
}
+49
View File
@@ -0,0 +1,49 @@
#ifndef SMBCLIENT_H
#define SMBCLIENT_H
#include <sys/socket.h>
#include <arpa/inet.h>
#include <time.h>
#include <string>
#include <vector>
#include <smb2/smb2.h>
#include <smb2/libsmb2.h>
#include "common.h"
#include "remote_client.h"
#define SMB_CLIENT_MAX_FILENAME_LEN 256
class SmbClient : public RemoteClient
{
public:
SmbClient();
~SmbClient();
int Connect(const std::string &url, const std::string &user, const std::string &pass);
int Mkdir(const std::string &path);
int Rmdir(const std::string &path, bool recursive);
int Size(const std::string &path, int64_t *size);
int Get(const std::string &outputfile, const std::string &path, uint64_t offset=0);
int Put(const std::string &inputfile, const std::string &path, uint64_t offset=0);
int Rename(const std::string &src, const std::string &dst);
int Delete(const std::string &path);
bool FileExists(const std::string &path);
int Copy(const std::string &path, int socket_fd);
std::vector<DirEntry> ListDir(const std::string &path);
bool IsConnected();
bool Ping();
const char *LastResponse();
int Quit();
std::string GetPath(std::string ppath1, std::string ppath2);
int Head(const std::string &path, void* buffer, uint16_t len);
ClientType clientType();
private:
int _Rmdir(const std::string &path);
struct smb2_context *smb2;
char response[1024];
bool connected = false;
uint32_t max_read_size = 0;
uint32_t max_write_size = 0;
};
#endif
+66
View File
@@ -0,0 +1,66 @@
#ifndef UTIL_H
#define UTIL_H
#include <string>
#include <vector>
#include <algorithm>
#include <stdarg.h>
#include <orbis/libkernel.h>
namespace Util
{
static inline std::string &Ltrim(std::string &str, std::string chars)
{
str.erase(0, str.find_first_not_of(chars));
return str;
}
static inline std::string &Rtrim(std::string &str, std::string chars)
{
str.erase(str.find_last_not_of(chars) + 1);
return str;
}
// trim from both ends (in place)
static inline std::string &Trim(std::string &str, std::string chars)
{
return Ltrim(Rtrim(str, chars), chars);
}
static inline void ReplaceAll(std::string &data, std::string toSearch, std::string replaceStr)
{
size_t pos = data.find(toSearch);
while (pos != std::string::npos)
{
data.replace(pos, toSearch.size(), replaceStr);
pos = data.find(toSearch, pos + replaceStr.size());
}
}
static inline std::string ToLower(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c)
{ return std::tolower(c); });
return s;
}
static inline void Notify(const char *fmt, ...)
{
OrbisNotificationRequest request;
va_list args;
va_start(args, fmt);
vsprintf(request.message, fmt, args);
va_end(args);
request.type = OrbisNotificationRequestType::NotificationRequest;
request.unk3 = 0;
request.useIconImageUri = 0;
request.targetId = -1;
sceKernelSendNotificationRequest(0, &request, sizeof(request), 0);
}
}
#endif
+109
View File
@@ -0,0 +1,109 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#include <algorithm>
#include <fstream>
#include <cstring>
#include "callback.hpp"
namespace WebDAV
{
namespace Callback
{
namespace Read
{
size_t stream(char* ptr, size_t item_size, size_t item_count, void* stream)
{
auto in_stream = reinterpret_cast<std::istream*>(stream);
auto read_bytes = static_cast<unsigned long long>(item_size * item_count);
auto position = static_cast<unsigned long long>(in_stream->tellg());
in_stream->seekg(0, std::ios::end);
auto size = static_cast<unsigned long long>(in_stream->tellg());
in_stream->seekg(position, std::ios::beg);
auto rest_bytes = size - position;
read_bytes = std::min<unsigned long long>(read_bytes, rest_bytes);
in_stream->read(ptr, read_bytes);
return read_bytes;
}
size_t buffer(char* ptr, size_t item_size, size_t item_count, void* buffer)
{
auto data = (Data*)buffer;
auto size = static_cast<unsigned long long>(item_size * item_count);
auto rest_bytes = data->size - data->position;
auto copied_bytes = std::min<unsigned long long>(size, rest_bytes);
memcpy(ptr, data->buffer, copied_bytes);
data->position += copied_bytes;
return copied_bytes;
}
} // namespace Read
namespace Write
{
size_t stream(char* ptr, size_t item_size, size_t item_count, void* stream)
{
auto out_stream = reinterpret_cast<std::ostream*>(stream);
size_t write_bytes = item_size * item_count;
out_stream->write(ptr, write_bytes);
return write_bytes;
}
size_t buffer(char* ptr, size_t item_size, size_t item_count, void* buffer)
{
auto data = reinterpret_cast<Data*>(buffer);
auto size = static_cast<unsigned long long>(item_size * item_count);
auto rest_bytes = data->size - data->position;
auto copied_bytes = std::min<unsigned long long>(size, rest_bytes);
memcpy(data->buffer, ptr, copied_bytes);
data->position += copied_bytes;
return copied_bytes;
}
} // namespace Write
namespace Append
{
size_t buffer(char* ptr, size_t item_size, size_t item_count, void* buffer)
{
auto data = reinterpret_cast<Data*>(buffer);
auto append_size = item_size * item_count;
auto new_buffer_size = data->size + append_size;
auto new_buffer = new char[new_buffer_size];
if (data->size != 0) memcpy(new_buffer, data->buffer, data->size);
memcpy(new_buffer + data->size, ptr, append_size);
delete[] data->buffer;
data->buffer = new_buffer;
data->size = new_buffer_size;
return append_size;
}
size_t stream(char* ptr, size_t item_size, size_t item_count, void* stream)
{
auto out_stream = reinterpret_cast<std::ostream*>(stream);
size_t write_bytes = item_size * item_count;
out_stream->seekp(0, std::ios::end);
out_stream->write(ptr, write_bytes);
return write_bytes;
}
} // namespace Append
} // namespace Callback
} // namespace WebDAV
+67
View File
@@ -0,0 +1,67 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#ifndef WEBDAV_CALLBACK_HPP
#define WEBDAV_CALLBACK_HPP
namespace WebDAV
{
struct Data
{
char* buffer;
unsigned long long position;
unsigned long long size;
void reset()
{
buffer = nullptr;
position = 0;
size = 0;
}
~Data()
{
delete[] buffer;
}
};
namespace Callback
{
namespace Read
{
size_t stream(char* data, size_t size, size_t count, void* stream);
size_t buffer(char* data, size_t size, size_t count, void* buffer);
}
namespace Write
{
size_t stream(char* data, size_t size, size_t count, void* stream);
size_t buffer(char* data, size_t size, size_t count, void* buffer);
}
namespace Append
{
size_t stream(char* data, size_t size, size_t count, void* stream);
size_t buffer(char* data, size_t size, size_t count, void* buffer);
}
}
} // namespace WebDAV
#endif
+975
View File
@@ -0,0 +1,975 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#include <client.hpp>
#include "callback.hpp"
#include "fsinfo.hpp"
#include "header.hpp"
#include "pugiext.hpp"
#include "request.hpp"
#include "urn.hpp"
#include "util.h"
#include <algorithm>
#include <thread>
namespace WebDAV
{
using Urn::Path;
using progress_funptr = int (*)(void *context, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata)
{
std::string header(reinterpret_cast<char *>(buffer), size * nitems);
dict_t *headers = (dict_t *)userdata;
size_t seperator = header.find_first_of(":");
if (seperator != std::string::npos)
{
std::string key = header.substr(0, seperator);
key = Util::Trim(key, " ");
key = Util::ToLower(key);
std::string value = header.substr(seperator + 1);
value = Util::Trim(value, " ");
headers->erase(key);
headers->insert(std::make_pair(key, value));
}
return (size * nitems);
}
dict_t
Client::options()
{
return dict_t{
{"webdav_hostname", this->webdav_hostname},
{"webdav_root", this->webdav_root},
{"webdav_username", this->webdav_username},
{"webdav_password", this->webdav_password},
{"proxy_hostname", this->proxy_hostname},
{"proxy_username", this->proxy_username},
{"proxy_password", this->proxy_password},
{"cert_path", this->cert_path},
{"key_path", this->key_path},
};
}
long
Client::status_code()
{
return this->http_code;
}
bool
Client::sync_download(
const std::string &remote_file,
const std::string &local_file,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
bool is_existed = this->check(remote_file);
if (!is_existed)
return false;
auto root_urn = Path(this->webdav_root, true);
auto file_urn = root_urn + remote_file;
std::ofstream file_stream(local_file, std::ios::binary);
Request request(this->options());
auto url = this->webdav_hostname + file_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "GET");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&file_stream));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Write::stream));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
if (progress != nullptr)
{
request.set(CURLOPT_XFERINFODATA, progress_data);
request.set(CURLOPT_XFERINFOFUNCTION, progress);
request.set(CURLOPT_NOPROGRESS, 0L);
}
bool is_performed = request.perform();
this->http_code = request.status_code();
if (callback != nullptr)
callback(is_performed);
return is_performed;
}
bool
Client::sync_download_to(
const std::string &remote_file,
char *&buffer_ptr,
unsigned long long &buffer_size,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
bool is_existed = this->check(remote_file);
if (!is_existed)
return false;
auto root_urn = Path(this->webdav_root, true);
auto file_urn = root_urn + remote_file;
Data data = {nullptr, 0, 0};
Request request(this->options());
auto url = this->webdav_hostname + file_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "GET");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
if (progress != nullptr)
{
request.set(CURLOPT_XFERINFODATA, progress_data);
request.set(CURLOPT_XFERINFOFUNCTION, progress);
request.set(CURLOPT_NOPROGRESS, 0L);
}
bool is_performed = request.perform();
this->http_code = request.status_code();
if (callback != nullptr)
callback(is_performed);
if (!is_performed)
return false;
buffer_ptr = data.buffer;
buffer_size = data.size;
data.reset();
return true;
}
bool
Client::sync_download_range_to(
const std::string &remote_file,
char *&buffer_ptr,
unsigned long long &buffer_size,
uint64_t range_from,
uint64_t range_to,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
bool is_existed = this->check(remote_file);
if (!is_existed)
return false;
auto root_urn = Path(this->webdav_root, true);
auto file_urn = root_urn + remote_file;
Data data = {nullptr, 0, 0};
Request request(this->options());
auto url = this->webdav_hostname + file_urn.quote(request.handle);
struct curl_slist *list = NULL;
char range_header[64];
sprintf(range_header, "Range: bytes=%lu-%lu", range_from, range_to);
list = curl_slist_append(list, range_header);
request.set(CURLOPT_CUSTOMREQUEST, "GET");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_HTTPHEADER, list);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
if (progress != nullptr)
{
request.set(CURLOPT_XFERINFODATA, progress_data);
request.set(CURLOPT_XFERINFOFUNCTION, progress);
request.set(CURLOPT_NOPROGRESS, 0L);
}
bool is_performed = request.perform();
this->http_code = request.status_code();
if (callback != nullptr)
callback(is_performed);
if (!is_performed)
return false;
buffer_ptr = data.buffer;
buffer_size = data.size;
data.reset();
return true;
}
bool
Client::sync_download_to(
const std::string &remote_file,
std::ostream &stream,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
bool is_existed = this->check(remote_file);
if (!is_existed)
return false;
auto root_urn = Path(this->webdav_root, true);
auto file_urn = root_urn + remote_file;
Request request(this->options());
auto url = this->webdav_hostname + file_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "GET");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HEADER, 0L);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&stream));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Write::stream));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
if (progress != nullptr)
{
request.set(CURLOPT_XFERINFODATA, progress_data);
request.set(CURLOPT_XFERINFOFUNCTION, progress);
request.set(CURLOPT_NOPROGRESS, 0L);
}
bool is_performed = request.perform();
this->http_code = request.status_code();
if (callback != nullptr)
callback(is_performed);
return is_performed;
}
bool
Client::sync_upload(
const std::string &remote_file,
const std::string &local_file,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
bool is_existed = FileInfo::exists(local_file);
if (!is_existed)
return false;
auto root_urn = Path(this->webdav_root, true);
auto file_urn = root_urn + remote_file;
std::ifstream file_stream(local_file, std::ios::binary);
auto size = FileInfo::size(local_file);
Request request(this->options());
auto url = this->webdav_hostname + file_urn.quote(request.handle);
Data response = {nullptr, 0, 0};
request.set(CURLOPT_UPLOAD, 1L);
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_READDATA, reinterpret_cast<size_t>(&file_stream));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Callback::Read::stream));
request.set(CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(size));
request.set(CURLOPT_BUFFERSIZE, static_cast<long>(Client::buffer_size));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&response));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
if (progress != nullptr)
{
request.set(CURLOPT_XFERINFODATA, progress_data);
request.set(CURLOPT_XFERINFOFUNCTION, progress);
request.set(CURLOPT_NOPROGRESS, 0L);
}
bool is_performed = request.perform();
this->http_code = request.status_code();
if (callback != nullptr)
callback(is_performed);
return is_performed;
}
bool
Client::sync_upload_from(
const std::string &remote_file,
char *buffer_ptr,
unsigned long long buffer_size,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
auto root_urn = Path(this->webdav_root, true);
auto file_urn = root_urn + remote_file;
Data data = {buffer_ptr, 0, buffer_size};
Request request(this->options());
auto url = this->webdav_hostname + file_urn.quote(request.handle);
Data response = {nullptr, 0, 0};
request.set(CURLOPT_UPLOAD, 1L);
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_READDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Callback::Read::buffer));
request.set(CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(buffer_size));
request.set(CURLOPT_BUFFERSIZE, static_cast<long>(Client::buffer_size));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&response));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
if (progress != nullptr)
{
request.set(CURLOPT_XFERINFODATA, progress_data);
request.set(CURLOPT_XFERINFOFUNCTION, progress);
request.set(CURLOPT_NOPROGRESS, 0L);
}
bool is_performed = request.perform();
this->http_code = request.status_code();
if (callback != nullptr)
callback(is_performed);
data.reset();
return is_performed;
}
bool
Client::sync_upload_from(
const std::string &remote_file,
std::istream &stream,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
auto root_urn = Path(this->webdav_root, true);
auto file_urn = root_urn + remote_file;
Request request(this->options());
auto url = this->webdav_hostname + file_urn.quote(request.handle);
stream.seekg(0, std::ios::end);
size_t stream_size = stream.tellg();
stream.seekg(0, std::ios::beg);
Data response = {nullptr, 0, 0};
request.set(CURLOPT_UPLOAD, 1L);
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_READDATA, reinterpret_cast<size_t>(&stream));
request.set(CURLOPT_READFUNCTION, reinterpret_cast<size_t>(Callback::Read::stream));
request.set(CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(stream_size));
request.set(CURLOPT_BUFFERSIZE, static_cast<long>(Client::buffer_size));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&response));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
if (progress != nullptr)
{
request.set(CURLOPT_XFERINFODATA, progress_data);
request.set(CURLOPT_XFERINFOFUNCTION, progress);
request.set(CURLOPT_NOPROGRESS, 0L);
}
bool is_performed = request.perform();
this->http_code = request.status_code();
if (callback != nullptr)
callback(is_performed);
return is_performed;
}
Client::Client(const dict_t &options)
{
this->webdav_hostname = get(options, "webdav_hostname");
this->webdav_root = get(options, "webdav_root");
this->webdav_username = get(options, "webdav_username");
this->webdav_password = get(options, "webdav_password");
this->proxy_hostname = get(options, "proxy_hostname");
this->proxy_username = get(options, "proxy_username");
this->proxy_password = get(options, "proxy_password");
this->cert_path = get(options, "cert_path");
this->key_path = get(options, "key_path");
auto check = get(options, "check_enabled");
if (check.length() > 0)
this->check_enabled = std::stoi(check);
else
this->check_enabled = 0;
}
unsigned long long
Client::free_size()
{
Header header =
{
"Accept: */*",
"Depth: 0",
"Content-Type: text/xml"};
pugi::xml_document document;
auto propfind = document.append_child("D:propfind");
propfind.append_attribute("xmlns:D") = "DAV:";
auto prop = propfind.append_child("D:prop");
prop.append_child("D:quokta-available-bytes");
prop.append_child("D:quota-used-bytes");
auto document_print = pugi::node_to_string(document);
size_t size = document_print.length() * sizeof((document_print.c_str())[0]);
Data data = {nullptr, 0, 0};
Request request(this->options());
request.set(CURLOPT_CUSTOMREQUEST, "PROPFIND");
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<struct curl_slist *>(header.handle));
request.set(CURLOPT_POSTFIELDS, document_print.c_str());
request.set(CURLOPT_POSTFIELDSIZE, static_cast<long>(size));
request.set(CURLOPT_HEADER, 0);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
auto is_performed = request.perform();
this->http_code = request.status_code();
if (!is_performed)
return 0;
document.load_buffer(data.buffer, static_cast<size_t>(data.size));
pugi::xml_node multistatus = document.select_node("*[local-name()='multistatus']").node();
pugi::xml_node response = multistatus.select_node("*[local-name()='response']").node();
pugi::xml_node propstat = response.select_node("*[local-name()='propstat']").node();
prop = propstat.select_node("*[local-name()='prop']").node();
pugi::xml_node quota_available_bytes = prop.select_node("*[local-name()='quota-available-bytes']").node();
std::string free_size_text = quota_available_bytes.first_child().value();
return std::stoll(free_size_text);
}
bool
Client::check(const std::string &remote_resource)
{
if (!this->check_enabled)
return true;
auto root_urn = Path(this->webdav_root, true);
auto resource_urn = root_urn + remote_resource;
Header header =
{
"Accept: */*",
"Depth: 0"};
Data data = {nullptr, 0, 0};
Request request(this->options());
auto url = this->webdav_hostname + resource_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "PROPFIND");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
return is_performed;
}
dict_t
Client::info(const std::string &remote_resource)
{
auto root_urn = Path(this->webdav_root, true);
auto target_urn = root_urn + remote_resource;
Header header =
{
"Accept: */*",
"Depth: 0"};
Data data = {nullptr, 0, 0};
Request request(this->options());
auto url = this->webdav_hostname + target_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "PROPFIND");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
if (!is_performed)
return dict_t{};
pugi::xml_document document;
document.load_buffer(data.buffer, static_cast<size_t>(data.size));
#ifdef WDC_VERBOSE
document.save(std::cout);
#endif
auto multistatus = document.select_node("*[local-name()='multistatus']").node();
auto responses = multistatus.select_nodes("*[local-name()='response']");
for (auto response : responses)
{
pugi::xml_node href = response.node().select_node("*[local-name()='href']").node();
std::string encode_file_name = href.first_child().value();
std::string resource_path = curl_unescape(encode_file_name.c_str(), static_cast<int>(encode_file_name.length()));
auto target_path = target_urn.path();
auto target_path_without_sep = target_urn.path();
if (!target_path_without_sep.empty() && target_path_without_sep.back() == '/')
target_path_without_sep.resize(target_path_without_sep.length() - 1);
auto resource_path_without_sep = resource_path.erase(resource_path.find_last_not_of('/') + 1);
size_t pos = resource_path_without_sep.find(this->webdav_hostname);
if (pos != std::string::npos)
resource_path_without_sep.erase(pos, this->webdav_hostname.length());
if (resource_path_without_sep == target_path_without_sep)
{
auto propstat = response.node().select_node("*[local-name()='propstat']").node();
auto prop = propstat.select_node("*[local-name()='prop']").node();
auto creation_date = prop.select_node("*[local-name()='creationdate']").node();
auto display_name = prop.select_node("*[local-name()='displayname']").node();
auto content_length = prop.select_node("*[local-name()='getcontentlength']").node();
auto modified_date = prop.select_node("*[local-name()='getlastmodified']").node();
auto resource_type = prop.select_node("*[local-name()='resourcetype']").node();
std::string name = target_urn.name();
dict_t information =
{
{"created", creation_date.first_child().value()},
{"name", Util::Rtrim(name, "/")},
{"size", content_length.first_child().value()},
{"modified", modified_date.first_child().value()},
{"type", resource_type.first_child().name()}};
return information;
}
}
return dict_t{};
}
bool
Client::head(const std::string &remote_resource, dict_t *headers)
{
auto root_urn = Path(this->webdav_root, true);
auto target_urn = root_urn + remote_resource;
Header header =
{"Accept: */*"};
Request request(this->options());
auto url = this->webdav_hostname + target_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "HEAD");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
request.set(CURLOPT_HEADERDATA, headers);
request.set(CURLOPT_HEADERFUNCTION, header_callback);
request.set(CURLOPT_NOBODY, 1L);
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
return is_performed;
}
bool
Client::is_directory(const std::string &remote_resource)
{
auto information = this->info(remote_resource);
auto resource_type = information["type"];
bool is_dir = resource_type == "d:collection" || resource_type == "D:collection";
return is_dir;
}
dict_items_t
Client::list(const std::string &remote_directory)
{
bool is_existed = this->check(remote_directory);
if (!is_existed)
return dict_items_t{};
auto target_urn = Path(this->webdav_root, true) + remote_directory;
target_urn = Path(target_urn.path(), true);
Header header =
{
"Accept: */*",
"Depth: 1"};
Data data = {nullptr, 0, 0};
Request request(this->options());
auto url = this->webdav_hostname + target_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "PROPFIND");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
request.set(CURLOPT_HEADER, 0);
request.set(CURLOPT_WRITEDATA, reinterpret_cast<size_t>(&data));
request.set(CURLOPT_WRITEFUNCTION, reinterpret_cast<size_t>(Callback::Append::buffer));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
if (!is_performed)
return dict_items_t{};
dict_items_t resources;
pugi::xml_document document;
document.load_buffer(data.buffer, static_cast<size_t>(data.size));
auto multistatus = document.select_node("*[local-name()='multistatus']").node();
auto responses = multistatus.select_nodes("*[local-name()='response']");
for (auto response : responses)
{
pugi::xml_node href = response.node().select_node("*[local-name()='href']").node();
std::string encode_file_name = href.first_child().value();
std::string resource_path = curl_unescape(encode_file_name.c_str(), static_cast<int>(encode_file_name.length()));
auto target_path = target_urn.path();
auto target_path_without_sep = target_urn.path();
if (!target_path_without_sep.empty() && target_path_without_sep.back() == '/')
target_path_without_sep.resize(target_path_without_sep.length() - 1);
auto resource_path_without_sep = resource_path.erase(resource_path.find_last_not_of('/') + 1);
size_t pos = resource_path_without_sep.find(this->webdav_hostname);
if (pos != std::string::npos)
resource_path_without_sep.erase(pos, this->webdav_hostname.length());
if (resource_path_without_sep == target_path_without_sep)
continue;
auto propstat = response.node().select_node("*[local-name()='propstat']").node();
auto prop = propstat.select_node("*[local-name()='prop']").node();
auto creation_date = prop.select_node("*[local-name()='creationdate']").node();
auto display_name = prop.select_node("*[local-name()='displayname']").node();
auto content_length = prop.select_node("*[local-name()='getcontentlength']").node();
auto modified_date = prop.select_node("*[local-name()='getlastmodified']").node();
auto resource_type = prop.select_node("*[local-name()='resourcetype']").node();
Path resource_urn(resource_path);
std::string name = resource_urn.name();
dict_t item = {
{"created", creation_date.first_child().value()},
{"name", Util::Rtrim(name, "/")},
{"size", content_length.first_child().value()},
{"modified", modified_date.first_child().value()},
{"type", resource_type.first_child().name()}};
resources.push_back(item);
}
return resources;
}
bool Client::download(
const std::string &remote_file,
const std::string &local_file,
progress_data_t progress_data,
progress_t progress)
{
return this->sync_download(remote_file, local_file, nullptr, progress_data, std::move(progress));
}
void
Client::async_download(
const std::string &remote_file,
const std::string &local_file,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
std::thread downloading([=]()
{ this->sync_download(remote_file, local_file, callback, progress_data, std::move(progress)); });
downloading.detach();
}
bool
Client::download_to(
const std::string &remote_file,
char *&buffer_ptr,
unsigned long long &buffer_size,
progress_data_t progress_data,
progress_t progress)
{
return this->sync_download_to(remote_file, buffer_ptr, buffer_size, nullptr, progress_data, std::move(progress));
}
bool
Client::download_range_to(
const std::string &remote_file,
char *&buffer_ptr,
unsigned long long &buffer_size,
uint64_t range_from,
uint64_t range_to,
progress_data_t progress_data,
progress_t progress)
{
return this->sync_download_range_to(remote_file, buffer_ptr, buffer_size, range_from, range_to, nullptr, progress_data, std::move(progress));
}
bool
Client::download_to(
const std::string &remote_file,
std::ostream &stream,
progress_data_t progress_data,
progress_t progress)
{
return this->sync_download_to(remote_file, stream, nullptr, progress_data, std::move(progress));
}
bool
Client::create_directory(const std::string &remote_directory, bool recursive)
{
bool is_existed = this->check(remote_directory);
if (is_existed)
return true;
bool resource_is_dir = true;
Path directory_urn(remote_directory, resource_is_dir);
if (recursive)
{
auto remote_parent_directory = directory_urn.parent().path();
if (remote_parent_directory == remote_directory)
return false;
bool is_created = this->create_directory(remote_parent_directory, true);
if (!is_created)
return false;
}
Header header =
{
"Accept: */*",
"Connection: Keep-Alive"};
auto target_urn = Path(this->webdav_root, true) + remote_directory;
target_urn = Path(target_urn.path(), true);
Request request(this->options());
auto url = this->webdav_hostname + target_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "MKCOL");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
return is_performed;
}
bool
Client::move(const std::string &remote_source_resource, const std::string &remote_destination_resource)
{
bool is_existed = this->check(remote_source_resource);
if (!is_existed)
return false;
Path root_urn(this->webdav_root, true);
auto source_resource_urn = root_urn + remote_source_resource;
auto destination_resource_urn = root_urn + remote_destination_resource;
Header header =
{
"Accept: */*",
"Destination: " + destination_resource_urn.path()};
Request request(this->options());
auto url = this->webdav_hostname + source_resource_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "MOVE");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
return is_performed;
}
bool
Client::copy(const std::string &remote_source_resource, const std::string &remote_destination_resource)
{
bool is_existed = this->check(remote_source_resource);
if (!is_existed)
return false;
Path root_urn(this->webdav_root, true);
auto source_resource_urn = root_urn + remote_source_resource;
auto destination_resource_urn = root_urn + remote_destination_resource;
Header header =
{
"Accept: */*",
"Destination: " + destination_resource_urn.path()};
Request request(this->options());
auto url = this->webdav_hostname + source_resource_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "COPY");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
return is_performed;
}
bool
Client::upload(
const std::string &remote_file,
const std::string &local_file,
progress_data_t progress_data,
progress_t progress)
{
return this->sync_upload(remote_file, local_file, nullptr, progress_data, std::move(progress));
}
void
Client::async_upload(
const std::string &remote_file,
const std::string &local_file,
callback_t callback,
progress_data_t progress_data,
progress_t progress)
{
std::thread uploading([=]()
{ this->sync_upload(remote_file, local_file, callback, progress_data, std::move(progress)); });
uploading.detach();
}
bool
Client::upload_from(
const std::string &remote_file,
std::istream &stream,
progress_data_t progress_data,
progress_t progress)
{
return this->sync_upload_from(remote_file, stream, nullptr, progress_data, std::move(progress));
}
bool
Client::upload_from(
const std::string &remote_file,
char *buffer_ptr,
unsigned long long buffer_size,
progress_data_t progress_data,
progress_t progress)
{
return this->sync_upload_from(remote_file, buffer_ptr, buffer_size, nullptr, progress_data, std::move(progress));
}
bool
Client::clean(const std::string &remote_resource)
{
bool is_existed = this->check(remote_resource);
if (!is_existed)
return true;
auto root_urn = Path(this->webdav_root, true);
auto resource_urn = root_urn + remote_resource;
Header header =
{
"Accept: */*",
"Connection: Keep-Alive"};
Request request(this->options());
auto url = this->webdav_hostname + resource_urn.quote(request.handle);
request.set(CURLOPT_CUSTOMREQUEST, "DELETE");
request.set(CURLOPT_URL, url.c_str());
request.set(CURLOPT_HTTPHEADER, reinterpret_cast<curl_slist *>(header.handle));
#ifdef WDC_VERBOSE
request.set(CURLOPT_VERBOSE, 1);
#endif
bool is_performed = request.perform();
this->http_code = request.status_code();
return is_performed;
}
class Environment
{
public:
Environment()
{
curl_global_init(CURL_GLOBAL_ALL);
}
~Environment()
{
curl_global_cleanup();
}
};
} // namespace WebDAV
static const WebDAV::Environment env;
+387
View File
@@ -0,0 +1,387 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#ifndef WEBDAV_CLIENT_HPP
#define WEBDAV_CLIENT_HPP
#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <curl/curl.h>
namespace WebDAV
{
using progress_data_t = void*;
using progress_t = int(void* context,
curl_off_t dltotal,
curl_off_t dlnow,
curl_off_t ultotal,
curl_off_t ulnow);
using callback_t = std::function<void(bool)> ;
using strings_t = std::vector<std::string>;
using dict_t = std::map<std::string, std::string>;
using dict_items_t = std::vector<dict_t>;
auto inline get(const dict_t& options, const std::string&& name) -> std::string
{
auto it = options.find(name);
if (it == options.end()) return "";
else return it->second;
}
///
/// \brief WebDAV Client
/// \author designerror
/// \version 1.1.4
/// \date 3/16/2018
///
class Client
{
public:
///
/// \param[in] webdav_hostname
/// \param[in] webdav_root
/// \param[in] webdav_username
/// \param[in] webdav_password
/// \param[in] proxy_hostname
/// \param[in] proxy_username
/// \param[in] proxy_password
/// \param[in] cert_path
/// \param[in] key_path
/// \include client/init.cpp
///
explicit Client(const dict_t& options);
///
/// Get free size of the WebDAV server
/// \return size in bytes
/// \include client/size.cpp
///
auto free_size() -> unsigned long long;
///
/// Check for existence of a remote resource
/// \param[in] remote_resource
/// \include client/check.cpp
///
auto check(const std::string& remote_resource = "/") -> bool;
///
/// Get information of a remote resource
/// \param[in] remote_resource
/// \include client/info.cpp
///
auto info(const std::string& remote_resource) -> dict_t;
///
/// Get information of a remote resource
/// \param[in] remote_resource
/// \include client/info.cpp
///
auto head(const std::string& remote_resource, dict_t *headers) -> bool;
///
/// Clean an remote resource
/// \param[in] remote_resource
/// \include client/clean.cpp
///
auto clean(const std::string& remote_resource) -> bool;
///
/// Checks whether the resource directory
/// \param[in] remote_resource
///
auto is_directory(const std::string& remote_resource) -> bool;
///
/// List a remote directory
/// \param[in] remote_directory
/// \include client/list.cpp
///
auto list(const std::string& remote_directory = "") -> dict_items_t;
///
/// Create a remote directory
/// \param[in] remote_directory
/// \param[in] recursive
/// \include client/mkdir.cpp
///
auto create_directory(
const std::string& remote_directory,
bool recursive = false
) -> bool;
///
/// Move a remote resource
/// \param[in] remote_source_resource
/// \param[in] remote_destination_resource
/// \include client/move.cpp
///
auto move(
const std::string& remote_source_resource,
const std::string& remote_destination_resource
) -> bool;
///
/// Copy a remote resource
/// \param[in] remote_source_resource
/// \param[in] remote_destination_resource
/// \include client/copy.cpp
///
auto copy(
const std::string& remote_source_resource,
const std::string& remote_destination_resource
) -> bool;
///
/// Download a remote file to a local file
/// \param[in] remote_file
/// \param[in] local_file
/// \param[in] progress
/// \snippet client/download.cpp download_to_file
///
auto download(
const std::string& remote_file,
const std::string& local_file,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
///
/// Download a remote file to a buffer
/// \param[in] remote_file
/// \param[out] buffer_ptr
/// \param[out] buffer_size
/// \param[in] progress
/// \snippet client/download.cpp download_to_buffer
///
auto download_to(
const std::string& remote_file,
char*& buffer_ptr,
unsigned long long& buffer_size,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
///
/// Download a remote file to a buffer for specified range
/// \param[in] remote_file
/// \param[out] buffer_ptr
/// \param[out] buffer_size
/// \param[in] range_from,
/// \param[in] range_to
/// \param[in] progress
/// \snippet client/download.cpp download_to_buffer
///
auto download_range_to(
const std::string& remote_file,
char*& buffer_ptr,
unsigned long long& buffer_size,
uint64_t range_from,
uint64_t range_to,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
///
/// Download a remote file to a stream
/// \param[in] remote_file
/// \param[out] stream
/// \param[in] progress
/// \snippet client/download.cpp download_to_stream
///
auto download_to(
const std::string& remote_file,
std::ostream& stream,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
///
/// Asynchronously download a remote file to a local file
/// \param[in] remote_file
/// \param[in] local_file
/// \param[in] callback
/// \param[in] progress
/// \snippet client/download.cpp async_download_to_file
///
auto async_download(
const std::string& remote_file,
const std::string& local_file,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> void;
///
/// Upload a remote file from a local file
/// \param[in] remote_file
/// \param[in] local_file
/// \param[in] progress
/// \snippet client/upload.cpp upload_from_file
///
auto upload(
const std::string& remote_file,
const std::string& local_file,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
///
/// Upload a remote file from a buffer
/// \param[in] remote_file
/// \param[in] buffer_ptr
/// \param[in] buffer_size
/// \param[in] progress
/// \snippet client/upload.cpp upload_from_buffer
///
auto upload_from(
const std::string& remote_file,
char* buffer_ptr,
unsigned long long buffer_size,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
///
/// Upload a remote file from a stream
/// \param[in] remote_file
/// \param[in] stream
/// \param[in] progress
/// \snippet client/upload.cpp upload_from_stream
///
auto upload_from(
const std::string& remote_file,
std::istream& stream,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
///
/// Asynchronously upload a remote file from a local file
/// \param[in] remote_file
/// \param[in] local_file
/// \param[in] callback
/// \param[in] progress
/// \snippet client/upload.cpp async_upload_from_file
///
auto async_upload(
const std::string& remote_file,
const std::string& local_file,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> void;
long status_code();
private:
auto sync_download(
const std::string& remote_file,
const std::string& local_file,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
auto sync_download_to(
const std::string& remote_file,
char*& buffer_ptr,
unsigned long long& buffer_size,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
auto sync_download_range_to(
const std::string& remote_file,
char*& buffer_ptr,
unsigned long long& buffer_size,
uint64_t range_from,
uint64_t range_to,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
bool sync_download_to(
const std::string& remote_file,
std::ostream& stream,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
);
bool sync_upload(
const std::string& remote_file,
const std::string& local_file,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
);
auto sync_upload_from(
const std::string& remote_file,
char* buffer_ptr,
unsigned long long buffer_size,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
auto sync_upload_from(
const std::string& remote_file,
std::istream& stream,
callback_t callback = nullptr,
progress_data_t progress_data = nullptr,
progress_t progress = nullptr
) -> bool;
enum { buffer_size = 1000 * 1000 };
std::string webdav_hostname;
std::string webdav_root;
std::string webdav_username;
std::string webdav_password;
std::string proxy_hostname;
std::string proxy_username;
std::string proxy_password;
std::string cert_path;
std::string key_path;
dict_t options();
long http_code;
int check_enabled = 0;
};
} // namespace WebDAV
#endif
+42
View File
@@ -0,0 +1,42 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#include "fsinfo.hpp"
#include <fstream>
namespace WebDAV
{
namespace FileInfo
{
auto exists(const std::string& path) -> bool
{
std::ifstream file(path);
return file.good();
}
auto size(const std::string& path_file) -> unsigned long long
{
std::ifstream file(path_file, std::ios::binary | std::ios::ate);
return static_cast<unsigned long long>(file.tellg());
}
} // namespace FileInfo
} // namespace WebDAV
+38
View File
@@ -0,0 +1,38 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#ifndef WEBDAV_FSINFO_HPP
#define WEBDAV_FSINFO_HPP
#include <fstream>
#include <string>
namespace WebDAV
{
namespace FileInfo
{
auto exists(const std::string& path) -> bool;
auto size(const std::string& path_file) -> unsigned long long;
} // namespace FileInfo
} // namespace WebDAV
#endif
+69
View File
@@ -0,0 +1,69 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#include "header.hpp"
#include <curl/curl.h>
namespace WebDAV
{
Header::Header(const std::initializer_list<std::string>& init_list) noexcept : handle(nullptr)
{
for (auto& item : init_list)
{
this->append(item);
}
}
Header::~Header() noexcept
{
curl_slist_free_all(reinterpret_cast<curl_slist*>(this->handle));
}
Header::Header(Header&& other) noexcept
{
handle = other.handle;
other.handle = nullptr;
}
auto Header::operator=(Header&& other) noexcept -> Header&
{
if (this != &other)
{
Header(std::move(other)).swap(*this);
}
return *this;
}
auto Header::swap(Header& other) noexcept -> void
{
using std::swap;
swap(handle, other.handle);
}
void
Header::append(const std::string& item) noexcept
{
this->handle = curl_slist_append(reinterpret_cast<curl_slist*>(this->handle), item.c_str());
}
} // namespace WebDAV
+51
View File
@@ -0,0 +1,51 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#ifndef WEBDAV_HEADER_HPP
#define WEBDAV_HEADER_HPP
#include <initializer_list>
#include <string>
namespace WebDAV
{
class Header final
{
public:
void* handle;
Header(const std::initializer_list<std::string>& init_list) noexcept;
Header(const Header& other) = delete;
Header(Header&& other) noexcept;
~Header() noexcept;
auto operator=(const Header& other) -> Header& = delete;
auto operator=(Header&& other) noexcept -> Header&;
void append(const std::string& item) noexcept;
private:
auto swap(Header& other) noexcept -> void;
};
} // namespace WebDAV
#endif
+50
View File
@@ -0,0 +1,50 @@
/*#***************************************************************************
# __ __ _____ _____
# Project | | | | | \ / ___|
# | |__| | | |\ \ / /
# | | | | ) ) ( (
# | /\ | | |/ / \ \___
# \_/ \_/ |_____/ \_____|
#
# Copyright (C) 2018, The WDC Project, <rusdevops@gmail.com>, et al.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the LICENSE file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################*/
#ifndef WEBDAV_PUGIEXT_HPP
#define WEBDAV_PUGIEXT_HPP
#include <pugixml.hpp>
namespace pugi
{
class PUGIXML_CLASS xml_string_writer: public xml_writer
{
public:
std::string result;
void write(const void* data, size_t size) final
{
result += std::string(static_cast<const char*>(data), size);
}
};
inline std::string node_to_string(const pugi::xml_node& node)
{
xml_string_writer writer;
node.print(writer);
return writer.result;
}
} // namespace pugi
#endif

Some files were not shown because too many files have changed in this diff Show More