From 241396f9ff992707ec51270330d64ad0d9c80082 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 18 Dec 2022 19:42:49 -0700 Subject: [PATCH] Move to read db on console to reduce strain on the ftp. --- Playstation/OrbisLibAPI/APIPackets.h | 3 +- Playstation/OrbisLibAPI/AppDatabase.cpp | 181 ++++++++++++++++++ Playstation/OrbisLibAPI/AppDatabase.h | 50 +++++ Playstation/OrbisLibAPI/Apps.cpp | 65 ++++++- Playstation/OrbisLibAPI/Apps.h | 2 + Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj | 7 +- .../OrbisLibAPI/OrbisLibAPI.vcxproj.filters | 12 ++ Playstation/OrbisLibAPI/SocketListener.cpp | 8 +- Playstation/OrbisLibAPI/Version.h | 22 +-- Playstation/OrbisLibAPI/build.bat | 6 +- Playstation/OrbisLibAPI/main.cpp | 5 +- .../OrbisLib/Classes/Target/Application.cs | 106 +++++++++- .../OrbisLib/Common/API/APIPackets.cs | 42 +++- .../OrbisLib/Common/Database/App/AppBrowse.cs | 113 ----------- .../Common/Database/App/AppBrowseVersion.cs | 31 --- .../OrbisLib/Common/Database/App/AppInfo.cs | 33 ---- .../OrbisLib/Common/Helpers/Helper.cs | 1 + .../Controls/AppPanel.xaml.cs | 57 ++---- .../MVVM/View/AppListView.xaml.cs | 158 +++++---------- .../Resources/BuildNumber.txt | 2 +- .../Resources/BuildString.txt | 2 +- 21 files changed, 539 insertions(+), 367 deletions(-) create mode 100644 Playstation/OrbisLibAPI/AppDatabase.cpp create mode 100644 Playstation/OrbisLibAPI/AppDatabase.h delete mode 100644 Windows/Libraries/OrbisLib/Common/Database/App/AppBrowse.cs delete mode 100644 Windows/Libraries/OrbisLib/Common/Database/App/AppBrowseVersion.cs delete mode 100644 Windows/Libraries/OrbisLib/Common/Database/App/AppInfo.cs diff --git a/Playstation/OrbisLibAPI/APIPackets.h b/Playstation/OrbisLibAPI/APIPackets.h index fa910c0..8ed1628 100644 --- a/Playstation/OrbisLibAPI/APIPackets.h +++ b/Playstation/OrbisLibAPI/APIPackets.h @@ -20,6 +20,8 @@ enum APICommands /* ####### Apps functions ####### */ APP_START, + API_APPS_GET_LIST, + API_APPS_GET_INFO_STR, API_APPS_STATUS, API_APPS_START, API_APPS_STOP, @@ -104,7 +106,6 @@ enum APICommands API_TARGET_SET_LED, API_TARGET_DUMP_PROC, API_TARGET_SET_SETTINGS, - API_TARGET_GET_APPDB, API_TARGET_GETFILE, TARGET_END, diff --git a/Playstation/OrbisLibAPI/AppDatabase.cpp b/Playstation/OrbisLibAPI/AppDatabase.cpp new file mode 100644 index 0000000..8e731bb --- /dev/null +++ b/Playstation/OrbisLibAPI/AppDatabase.cpp @@ -0,0 +1,181 @@ +#include "Common.h" +#include "AppDatabase.h" +#include "sqlite3.h" + +sqlite3* AppDatabase::OpenDatabase() +{ + sqlite3* db; + + auto res = sqlite3_open("/system_data/priv/mms/app.db", &db); + if (res != SQLITE_OK) + { + klog("OpenDatabase(): Failed because %s\n", sqlite3_errmsg(db)); + return nullptr; + } + else + { + return db; + } +} + +const char* GetText(sqlite3_stmt* stmt, int column) +{ + auto res = sqlite3_column_text(stmt, column); + if (res != 0) + { + return (const char*)res; + } + + return ""; +} + +bool AppDatabase::GetApps(std::vector &Apps) +{ + int res; + + auto db = OpenDatabase(); + if (db == nullptr) + { + return false; + } + + // Get the current user id. + int ForegroundAccountId; + sceUserServiceGetForegroundUser(&ForegroundAccountId); + + // build statement. + char query[0x200]; + snprintf(query, sizeof(query), "SELECT * FROM tbl_appbrowse_0%i", ForegroundAccountId); + + // Prepare statement. + sqlite3_stmt* stmt; + res = sqlite3_prepare(db, query, -1, &stmt, NULL); + if (res != SQLITE_OK) + { + klog("sqlite3_prepare(): Failed because %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return false; + } + + // Execute step until all rows are read. + while ((res = sqlite3_step(stmt)) == SQLITE_ROW) + { + AppInfo info; + strcpy(info.TitleId, GetText(stmt, 0)); + strcpy(info.ContentId, GetText(stmt, 1)); + strcpy(info.TitleName, GetText(stmt, 2)); + strcpy(info.MetaDataPath, GetText(stmt, 3)); + strcpy(info.LastAccessTime, GetText(stmt, 4)); + info.Visible = sqlite3_column_int(stmt, 8); + info.SortPriority = sqlite3_column_int(stmt, 9); + info.DispLocation = sqlite3_column_int(stmt, 12); + info.CanRemove = sqlite3_column_int(stmt, 13) == 1; + strcpy(info.Category, GetText(stmt, 14)); + info.ContentSize = sqlite3_column_int(stmt, 22); + strcpy(info.InstallDate, GetText(stmt, 23)); + strcpy(info.UICategory, GetText(stmt, 25)); + + Apps.push_back(info); + } + + if (res != SQLITE_DONE) { + printf("GetApps(): Res %d Error: %s\n", res, sqlite3_errmsg(db)); + } + + // Release resources. + sqlite3_finalize(stmt); + sqlite3_close(db); + + return true; +} + +bool AppDatabase::GetAppInfoString(const char* TitleId, char* Out, size_t OutSize, const char* Key) +{ + int res; + + auto db = OpenDatabase(); + if (db == nullptr) + { + return false; + } + + // build statement. + char query[0x200]; + snprintf(query, sizeof(query), "SELECT * FROM tbl_appinfo WHERE titleId='%s' AND key='%s'", TitleId, Key); + + // Prepare statement. + sqlite3_stmt* stmt; + res = sqlite3_prepare(db, query, -1, &stmt, NULL); + if (res != SQLITE_OK) + { + klog("sqlite3_prepare(): Failed because %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return false; + } + + res = sqlite3_step(stmt); + + if (res == SQLITE_ROW) + { + strlcpy(Out, GetText(stmt, 2), OutSize); + + // Release resources. + sqlite3_finalize(stmt); + sqlite3_close(db); + + return true; + } + + if (res != SQLITE_DONE) { + printf("GetApps(): Res %d Error: %s\n", res, sqlite3_errmsg(db)); + } + + // Release resources. + sqlite3_finalize(stmt); + sqlite3_close(db); + + return false; +} + +bool AppDatabase::SetVisibility(const char* TitleId, VisibilityType Visibility) +{ + int res; + + auto db = OpenDatabase(); + if (db == nullptr) + { + return false; + } + + // Get the current user id. + int ForegroundAccountId; + sceUserServiceGetForegroundUser(&ForegroundAccountId); + + // build statement. + char query[0x200]; + snprintf(query, sizeof(query), "UPDATE tbl_appbrowse_0%i SET visible=%i WHERE titleId='%s'", ForegroundAccountId, Visibility, TitleId); + + // Execute Statement. + res = sqlite3_exec(db, query, nullptr, nullptr, nullptr); + if (res != SQLITE_OK) + { + klog("sqlite3_exec(): Failed because %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return false; + } + + // Release resources. + sqlite3_close(db); + + return true; +} + +AppDatabase::AppDatabase() +{ + +} + +AppDatabase::~AppDatabase() +{ + +} \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/AppDatabase.h b/Playstation/OrbisLibAPI/AppDatabase.h new file mode 100644 index 0000000..d90b59c --- /dev/null +++ b/Playstation/OrbisLibAPI/AppDatabase.h @@ -0,0 +1,50 @@ +#pragma once +#include "Common.h" +#include "sqlite3.h" + +class AppDatabase +{ +public: + enum VisibilityType + { + VT_NONE, + VT_VISIBLE, + VT_INVISIBLE, + }; + + enum DispLocation + { + DL_NONE = 0, + DL_CONTENTAREA = 1, + DL_TV_VIDEO = 2, + DL_LIBRARY = 4, + DL_UNK = 5, + }; + + struct AppInfo + { + char TitleId[10]; + char ContentId[100]; + char TitleName[200]; + char MetaDataPath[100]; + char LastAccessTime[100]; + int Visible; + int SortPriority; + int DispLocation; + bool CanRemove; + char Category[10]; + int ContentSize; + char InstallDate[100]; + char UICategory[10]; + }; + + static bool GetApps(std::vector &Apps); + static bool GetAppInfoString(const char* TitleId, char* Out, size_t OutSize, const char* Key); + static bool SetVisibility(const char* TitleId, VisibilityType Visibility); + + AppDatabase(); + ~AppDatabase(); + +private: + static sqlite3* OpenDatabase(); +}; diff --git a/Playstation/OrbisLibAPI/Apps.cpp b/Playstation/OrbisLibAPI/Apps.cpp index 7a15352..80f7ccc 100644 --- a/Playstation/OrbisLibAPI/Apps.cpp +++ b/Playstation/OrbisLibAPI/Apps.cpp @@ -2,20 +2,38 @@ #include "Apps.h" #include #include +#include "AppDatabase.h" void Apps::HandleAPI(OrbisNetId Sock, APIPacket* Packet) { - // Get the titleId of the App - char titleId[9]; - sceNetRecv(Sock, titleId, sizeof(titleId), 0); + char titleId[10]; + memset(titleId, 0, sizeof(titleId)); + + // For commands that need it get the titleId of the App + if (Packet->Command > API_APPS_GET_LIST) + { + sceNetRecv(Sock, titleId, sizeof(titleId), 0); + } switch (Packet->Command) { default: break; - case API_APPS_STATUS: + case API_APPS_GET_LIST: + GetAppsList(Sock); + + break; + + case API_APPS_GET_INFO_STR: + + GetAppInfoString(Sock, titleId); + + break; + + case API_APPS_STATUS: + SendAppStatus(Sock, titleId); break; @@ -34,6 +52,45 @@ void Apps::HandleAPI(OrbisNetId Sock, APIPacket* Packet) } } +void Apps::GetAppsList(OrbisNetId Sock) +{ + std::vector AppList; + if (!AppDatabase::GetApps(AppList)) + { + SockSendInt(Sock, 0); + return; + } + + // Send the number of apps. + SockSendInt(Sock, AppList.size()); + + // Send all of the apps. + for (const auto& App : AppList) + { + sceNetSend(Sock, &App, sizeof(AppDatabase::AppInfo), 0); + } +} + +void Apps::GetAppInfoString(OrbisNetId Sock, const char* TitleId) +{ + // Get the key we are interested in. + char KeyValue[50]; + sceNetRecv(Sock, KeyValue, sizeof(KeyValue), 0); + + klog("TitleId: %s\n", TitleId); + klog("Key: %s\n", KeyValue); + + // Look up the key for that titleId in the app.db. + char OutStr[200]; + memset(OutStr, 0, sizeof(OutStr)); + AppDatabase::GetAppInfoString(TitleId, OutStr, sizeof(OutStr), KeyValue); + + klog("OutStr: %s\n", OutStr); + + // Send back the result. + sceNetSend(Sock, OutStr, sizeof(OutStr), 0); +} + void Apps::SendAppStatus(OrbisNetId Sock, const char* TitleId) { int appId = 0; diff --git a/Playstation/OrbisLibAPI/Apps.h b/Playstation/OrbisLibAPI/Apps.h index b8cae6b..a5e0b5d 100644 --- a/Playstation/OrbisLibAPI/Apps.h +++ b/Playstation/OrbisLibAPI/Apps.h @@ -11,6 +11,8 @@ public: void HandleAPI(OrbisNetId Sock, APIPacket* Packet); private: + void GetAppsList(OrbisNetId Sock); + void GetAppInfoString(OrbisNetId Sock, const char* TitleId); void SendAppStatus(OrbisNetId Sock, const char* TitleId); void StartApp(OrbisNetId Sock, const char* TitleId); void KillApp(OrbisNetId Sock, const char* TitleId); diff --git a/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj b/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj index 9cab5ae..4e7e5de 100644 --- a/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj +++ b/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj @@ -51,8 +51,8 @@ call build.bat $(IntDir) "$(TargetName)" "$(SolutionDir)" $(SolutionDir) - $(OO_PS4_TOOLCHAIN)\include;External\GoldHEN_Plugins_SDK\include;$(NMakeIncludeSearchPath) - E:\Greg\Repos\Orbis-Suite-3.0\External\GoldHEN_Plugins_SDK\include;$(IncludePath) + $(OO_PS4_TOOLCHAIN)\include;External\GoldHEN_Plugins_SDK\include;External\LibSQLite-ps4\include;$(NMakeIncludeSearchPath) + E:\Greg\Repos\Orbis-Suite-3.0\External\LibSQLite-ps4\include;E:\Greg\Repos\Orbis-Suite-3.0\External\GoldHEN_Plugins_SDK\include;$(IncludePath) eboot.bin @@ -63,6 +63,7 @@ del /s /q /f $(IntDir)\*.oelf + @@ -81,9 +82,11 @@ del /s /q /f $(IntDir)\*.oelf + + diff --git a/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj.filters b/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj.filters index 36cab4f..7a930a3 100644 --- a/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj.filters +++ b/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj.filters @@ -43,6 +43,9 @@ {5094835e-2ace-4366-93ee-a65317ee8a62} + + {9184ee1e-6be1-4208-9c34-f2cca837b49f} + @@ -97,6 +100,9 @@ Source Files\API\CmdGroups + + Source Files\Utilities\PS Utils + @@ -156,5 +162,11 @@ Header Files\API\CmdGroups + + Header Files\SQLite + + + Header Files\Utilities\PS Utils + \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/SocketListener.cpp b/Playstation/OrbisLibAPI/SocketListener.cpp index b5e6753..cfe621a 100644 --- a/Playstation/OrbisLibAPI/SocketListener.cpp +++ b/Playstation/OrbisLibAPI/SocketListener.cpp @@ -34,8 +34,8 @@ void* SocketListener::DoWork() // Make new TCP Socket this->Socket = sceNetSocket("Listener Socket", ORBIS_NET_AF_INET, ORBIS_NET_SOCK_STREAM, ORBIS_NET_IPPROTO_TCP); - // Set Sending and reciving time out to 1000 ms - int sock_timeout = 10000; + // Set Sending and reciving time out to 2s + int sock_timeout = 2000000; sceNetSetsockopt(this->Socket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_SNDTIMEO, &sock_timeout, sizeof(sock_timeout)); sceNetSetsockopt(this->Socket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_RCVTIMEO, &sock_timeout, sizeof(sock_timeout)); @@ -96,6 +96,10 @@ void* SocketListener::DoWork() int optval = 1; sceNetSetsockopt(ClientSocket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_NOSIGPIPE, &optval, sizeof(optval)); + int sock_timeout = 2000000; + sceNetSetsockopt(ClientSocket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_SNDTIMEO, &sock_timeout, sizeof(sock_timeout)); + sceNetSetsockopt(ClientSocket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_RCVTIMEO, &sock_timeout, sizeof(sock_timeout)); + // Set up thread params. ClientThreadParams* Params = new ClientThreadParams(); Params->socketListener = this; diff --git a/Playstation/OrbisLibAPI/Version.h b/Playstation/OrbisLibAPI/Version.h index cd93f95..d897bfe 100644 --- a/Playstation/OrbisLibAPI/Version.h +++ b/Playstation/OrbisLibAPI/Version.h @@ -1,11 +1,11 @@ -#pragma once -#define ORBISLIB_MAJOR 3 -#define ORBISLIB_MINOR 0 -#define ORBISLIB_BUILDVERSION 577 -#define stringify(a) stringify_(a) -#define stringify_(a) #a -#if defined(_DEBUG) -#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) -#else -#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) -#endif +#pragma once +#define ORBISLIB_MAJOR 3 +#define ORBISLIB_MINOR 0 +#define ORBISLIB_BUILDVERSION 635 +#define stringify(a) stringify_(a) +#define stringify_(a) #a +#if defined(_DEBUG) +#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) +#else +#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) +#endif diff --git a/Playstation/OrbisLibAPI/build.bat b/Playstation/OrbisLibAPI/build.bat index cbece3b..07f4676 100644 --- a/Playstation/OrbisLibAPI/build.bat +++ b/Playstation/OrbisLibAPI/build.bat @@ -1,7 +1,7 @@ SETLOCAL EnableDelayedExpansion Rem Libraries to link in -set libraries=-lc++ -lc -lSceSysModule -lkernel -lSceVideoOut -lSceSystemService -lSceSysCore -lSceSystemStateMgr -lSceNet -lScePad -lSceUserService -lSceRegMgr -lSceFreeType -lSceMsgDialog -lSceCommonDialog -lGoldHEN_Hook +set libraries=-lc++ -lc -lSceSysModule -lkernel -lSceVideoOut -lSceSystemService -lSceSysCore -lSceSystemStateMgr -lSceNet -lScePad -lSceUserService -lSceRegMgr -lSceFreeType -lSceMsgDialog -lSceCommonDialog -lGoldHEN_Hook -lSQLite Rem Read the script arguments into local vars set intdir=%1 @@ -13,7 +13,7 @@ set outputOelf=%intdir%%targetname%.oelf Rem Compile object files for all the source files for %%f in (*.cpp) do ( - clang++ -cc1 -triple x86_64-scei-ps4-elf -I"%OO_PS4_TOOLCHAIN%\\include" -I"%OO_PS4_TOOLCHAIN%\\include\\c++\\v1" -I"..\\..\\External\\GoldHEN_Plugins_SDK\\include" -I"..\\..\\External\\ps4-libjbc" -DORBISLIB_DEBUG -emit-obj -o %intdir%\%%~nf.o %%~nf.cpp + clang++ -cc1 -triple x86_64-scei-ps4-elf -I"%OO_PS4_TOOLCHAIN%\\include" -I"%OO_PS4_TOOLCHAIN%\\include\\c++\\v1" -I"..\\..\\External\\GoldHEN_Plugins_SDK\\include" -I"..\\..\\External\\ps4-libjbc" -I"..\\..\\External\\LibSQLite-ps4\\include" -DORBISLIB_DEBUG -emit-obj -o %intdir%\%%~nf.o %%~nf.cpp ) Rem Get a list of object files for linking @@ -21,7 +21,7 @@ set obj_files= for %%f in (%1\\*.o) do set obj_files=!obj_files! .\%%f Rem Link the input ELF -ld.lld -m elf_x86_64 -pie --script "%OO_PS4_TOOLCHAIN%\link.x" --eh-frame-hdr -o "%outputElf%" "-L%OO_PS4_TOOLCHAIN%\\lib" "-L..\\..\\External\\GoldHEN_Plugins_SDK" %libraries% --verbose "%OO_PS4_TOOLCHAIN%\lib\crt1.o" %obj_files% "..\\..\\External\\ps4-libjbc\\jbc.o" +ld.lld -m elf_x86_64 -pie --script "%OO_PS4_TOOLCHAIN%\link.x" --eh-frame-hdr -o "%outputElf%" "-L%OO_PS4_TOOLCHAIN%\\lib" "-L..\\..\\External\\GoldHEN_Plugins_SDK" "-L..\\..\\External\\LibSQLite-ps4" %libraries% --verbose "%OO_PS4_TOOLCHAIN%\lib\crt1.o" %obj_files% "..\\..\\External\\ps4-libjbc\\jbc.o" Rem Create the eboot %OO_PS4_TOOLCHAIN%\bin\windows\create-fself.exe -in "%outputElf%" --out "%outputOelf%" --eboot "eboot.bin" --paid 0x3800000000010003 diff --git a/Playstation/OrbisLibAPI/main.cpp b/Playstation/OrbisLibAPI/main.cpp index e546f18..fa0b12a 100644 --- a/Playstation/OrbisLibAPI/main.cpp +++ b/Playstation/OrbisLibAPI/main.cpp @@ -2,11 +2,8 @@ #include "Version.h" #include "API.h" #include "GoldHEN.h" -#include #include -#include -#include -#include +#include "AppDatabase.h" #include "GeneralIPC.h" diff --git a/Windows/Libraries/OrbisLib/Classes/Target/Application.cs b/Windows/Libraries/OrbisLib/Classes/Target/Application.cs index 84be02f..dda697c 100644 --- a/Windows/Libraries/OrbisLib/Classes/Target/Application.cs +++ b/Windows/Libraries/OrbisLib/Classes/Target/Application.cs @@ -4,12 +4,17 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace OrbisSuite { + public record AppInfo(string TitleId, string ContentId, string TitleName, string MetaDataPath, DateTime LastAccessTime, + int Visible, int SortPriority, int DisplayLocation, bool CanRemove, string Category, int ContentSize, DateTime InstallDate, string UICategory); + public class Application { private Target Target; @@ -19,6 +24,95 @@ namespace OrbisSuite this.Target = Target; } + public List GetAppList() + { + var AppList = new List(); + + // Check to see the API is online. + if (!Target.Info.Details.IsAPIAvailable) + { + return AppList; + } + + // Make the initial request. + APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_GET_LIST }, out Socket Sock); + + // Make sure the request was sucessful. + if (apiResult != APIResults.API_OK) + return AppList; + + // Get the number of apps installed. + int Count = Sock.RecvInt32(); + + // Itterate through the count to recieve all the apps details. + for (int i = 0; i < Count; i++) + { + // Recieve the bytes of the struct. + var Packet = new AppInfoPacket(); + var RawPacket = new byte[Marshal.SizeOf(Packet)]; + var bytes = Sock.Receive(RawPacket); + + if (bytes <= 0) + break; + + // Convert the recieved bytes to a struct. + Helpers.BytestoStruct(RawPacket, ref Packet); + + // Try to parse the date time strings. + if (!DateTime.TryParse(Packet.LastAccessTime, out DateTime LastAccessTime)) + LastAccessTime = DateTime.MinValue; + + if (!DateTime.TryParse(Packet.LastAccessTime, out DateTime InstallDate)) + InstallDate = DateTime.MinValue; + + // For some reason there is garbage after the string so this stops that :) + var firstNullIndex = Array.FindIndex(Packet.TitleName, b => b == 0); + string titleName = Encoding.UTF8.GetString(Packet.TitleName, 0, firstNullIndex); + + // Add the entry to the list. + AppList.Add(new AppInfo(Packet.TitleId, Packet.ContentId, titleName, Packet.MetaDataPath, LastAccessTime, Packet.Visible, + Packet.SortPriority, Packet.DispLocation, Packet.CanRemove == 1, Packet.Category, Packet.ContentSize, InstallDate, Packet.UICategory)); + } + + // close socket. + Sock.Close(); + + return AppList; + } + + public string GetAppInfoString(string TitleId, string Key) + { + if (!Regex.IsMatch(TitleId, @"[a-zA-Z]{4}\d{5}")) + { + Console.WriteLine($"Invaild titleId format {TitleId}"); + return string.Empty; + } + + if (!Target.Info.Details.IsAPIAvailable) + { + return string.Empty; + } + + var apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_GET_INFO_STR }, out Socket Sock); + + if (apiResult != APIResults.API_OK) + return string.Empty; + + // Send the titleId of the app. + Sock.Send(Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray()); + + // Send the bytes of the key string. + Sock.Send(Encoding.ASCII.GetBytes(Key.PadRight(50, '\0'))); + + var resultBuffer = new byte[200]; + Sock.Receive(resultBuffer); + + // close socket. + Sock.Close(); + + return Encoding.ASCII.GetString(resultBuffer); + } + public AppState GetAppState(string TitleId) { if (!Regex.IsMatch(TitleId, @"[a-zA-Z]{4}\d{5}")) @@ -32,13 +126,13 @@ namespace OrbisSuite return AppState.STATE_NOT_RUNNING; } - APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APP_STATUS }, out Socket Sock); + APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_STATUS }, out Socket Sock); if (apiResult != APIResults.API_OK) return AppState.STATE_ERROR; // Send the titleId of the app. - var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(9, '\0')).Take(9).ToArray(); + var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray(); Sock.Send(bytes); // Get the state from API. @@ -63,13 +157,13 @@ namespace OrbisSuite return false; } - APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APP_START }, out Socket Sock); + APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_START }, out Socket Sock); if (apiResult != APIResults.API_OK) return false; // Send the titleId of the app. - var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(9, '\0')).Take(9).ToArray(); + var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray(); Sock.Send(bytes); // Get the state from API. @@ -94,13 +188,13 @@ namespace OrbisSuite return false; } - APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APP_STOP }, out Socket Sock); + APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_STOP }, out Socket Sock); if (apiResult != APIResults.API_OK) return false; // Send the titleId of the app. - var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(9, '\0')).Take(9).ToArray(); + var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray(); Sock.Send(bytes); // Get the state from API. diff --git a/Windows/Libraries/OrbisLib/Common/API/APIPackets.cs b/Windows/Libraries/OrbisLib/Common/API/APIPackets.cs index 424b226..4a9f942 100644 --- a/Windows/Libraries/OrbisLib/Common/API/APIPackets.cs +++ b/Windows/Libraries/OrbisLib/Common/API/APIPackets.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; +using System.Text; namespace OrbisSuite.Common { @@ -17,12 +18,14 @@ namespace OrbisSuite.Common /* ####### Apps functions ####### */ APP_START, - API_APP_STATUS, - API_APP_START, - API_APP_STOP, - API_APP_SUSPEND, - API_APP_RESUME, - API_APP_DELETE, + API_APPS_GET_LIST, + API_APPS_GET_INFO_STR, + API_APPS_STATUS, + API_APPS_START, + API_APPS_STOP, + API_APPS_SUSPEND, + API_APPS_RESUME, + API_APPS_DELETE, APP_END, /* ############################## */ @@ -101,7 +104,6 @@ namespace OrbisSuite.Common API_TARGET_SET_LED, API_TARGET_DUMP_PROC, API_TARGET_SET_SETTINGS, - API_TARGET_GET_APPDB, API_TARGET_GETFILE, TARGET_END, @@ -158,6 +160,32 @@ namespace OrbisSuite.Common STATE_SUSPENDED, }; + [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi), Serializable] + public struct AppInfoPacket + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] + public string TitleId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] + public string ContentId; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)] + public byte[] TitleName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] + public string MetaDataPath; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] + public string LastAccessTime; + public int Visible; + public int SortPriority; + public int DispLocation; + public char CanRemove; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] + public string Category; + public int ContentSize; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] + public string InstallDate; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] + public string UICategory; + }; + #endregion #region Debug diff --git a/Windows/Libraries/OrbisLib/Common/Database/App/AppBrowse.cs b/Windows/Libraries/OrbisLib/Common/Database/App/AppBrowse.cs deleted file mode 100644 index c97124c..0000000 --- a/Windows/Libraries/OrbisLib/Common/Database/App/AppBrowse.cs +++ /dev/null @@ -1,113 +0,0 @@ -using SQLite; -using System.Data; - -namespace OrbisSuite.Common.Database.App -{ - public class Master - { - public string type { get; set; } - - public string name { get; set; } - - public string tbl_name { get; set; } - - public int rootpage { get; set; } - - public string sql { get; set; } - } - - [Table("tbl_appbrowse")] - public class AppBrowse - { - [PrimaryKey, NotNull] - public string titleId { get; set; } = ""; - - public string contentId { get; set; } = ""; - - public string titleName { get; set; } = ""; - - public string metaDataPath { get; set; } = ""; - - public int visible { get; set; } = 0; - - public int sortPriority { get; set; } = 0; - - public int dispLocation { get; set; } = 0; - - public int canRemove { get; set; } = 0; - - public string category { get; set; } = ""; - - public int contentSize { get; set; } = 0; - - public string installDate { get; set; } = ""; - - public string uiCategory { get; set; } = ""; - - public static bool AppBrowseRemoveUserId(string dbPath, int UserId) - { - var db = new SQLiteConnection(dbPath); - - // List all of the tables in this data base. - var dbList = db.Query("SELECT name FROM sqlite_master WHERE type = 'table'"); - - // Make sure we got some tables back. - if (dbList.Count <= 0) - { - return false; - } - - // The name of the table with the user id appended to the end. - var tableName = $"tbl_appbrowse_{UserId.ToString().PadLeft(10, '0')}"; - - // Search for the table we want to rename to not have the userId on the end. - var appBrowseTable = dbList.Find(e => e.name.Equals(tableName))?.name; - - // Make sure we found a table matching our pattern. - if (appBrowseTable != null) - { - // Make sure we haven't already renamed this table. - if (appBrowseTable.Equals("tbl_appbrowse")) - { - return true; - } - - // Rename it so we can use it. - var result = db.Execute($"ALTER TABLE `{appBrowseTable}` RENAME TO `tbl_appbrowse`") > 0; - db.Close(); - return result; - } - else - { - return false; - } - - } - - public static bool AppBrowseAddUserId(string dbPath, int UserId) - { - var db = new SQLiteConnection(dbPath); - - // The name of the table with the user id appended to the end. - var tableName = $"tbl_appbrowse_{UserId.ToString().PadLeft(10, '0')}"; - - // Rename it so we can use it. - var result = db.Execute($"ALTER TABLE `tbl_appbrowse` RENAME TO `{tableName}`") > 0; - db.Close(); - return result; - } - - public static List GetAppBrowseList(string dbPath) - { - var db = new SQLiteConnection(dbPath); - var result = db.Table().ToList(); - db.Close(); - return result; - } - - /*public static bool Save(string dbPath) - { - - }*/ - } -} diff --git a/Windows/Libraries/OrbisLib/Common/Database/App/AppBrowseVersion.cs b/Windows/Libraries/OrbisLib/Common/Database/App/AppBrowseVersion.cs deleted file mode 100644 index 2b6c9b4..0000000 --- a/Windows/Libraries/OrbisLib/Common/Database/App/AppBrowseVersion.cs +++ /dev/null @@ -1,31 +0,0 @@ -using SQLite; -using System; -using System.Linq.Expressions; - -namespace OrbisSuite.Common.Database.App -{ - [Table("tbl_version")] - public class AppBrowseVersion - { - [PrimaryKey, NotNull] - public string category { get; set; } = ""; - - public int status { get; set; } - - public static int GetAppBrowseVersion(string DataBasePath) - { - var db = new SQLiteConnection(DataBasePath); - - var result = db.Find((Expression>)(x => x.category.Equals("sync_server"))); - db.Close(); - if(result != null) - { - return result.status; - } - else - { - return 0; - } - } - } -} diff --git a/Windows/Libraries/OrbisLib/Common/Database/App/AppInfo.cs b/Windows/Libraries/OrbisLib/Common/Database/App/AppInfo.cs deleted file mode 100644 index 443d0a8..0000000 --- a/Windows/Libraries/OrbisLib/Common/Database/App/AppInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using SQLite; -using System.Linq.Expressions; - -namespace OrbisSuite.Common.Database.App -{ - [Table("tbl_appinfo")] - public class AppInfo - { - [PrimaryKey, NotNull] - public string titleId { get; set; } = ""; - - [PrimaryKey, NotNull] - public string key { get; set; } = ""; - - public string val { get; set; } - - public static string GetStringFromAppInfo(string DataBasePath, string TitleId, string Key) - { - var db = new SQLiteConnection(DataBasePath); - - var result = db.Find((Expression>)(x => x.titleId.Equals(TitleId) && x.key.Equals(Key))); - db.Close(); - if (result != null) - { - return result.val; - } - else - { - return ""; - } - } - } -} diff --git a/Windows/Libraries/OrbisLib/Common/Helpers/Helper.cs b/Windows/Libraries/OrbisLib/Common/Helpers/Helper.cs index 6cf7cb4..0b03174 100644 --- a/Windows/Libraries/OrbisLib/Common/Helpers/Helper.cs +++ b/Windows/Libraries/OrbisLib/Common/Helpers/Helper.cs @@ -1,6 +1,7 @@ using System.IO; using System.Net.NetworkInformation; using System.Net.Sockets; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Text; diff --git a/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs b/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs index 066804b..a8c63ef 100644 --- a/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs +++ b/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs @@ -1,24 +1,12 @@ using OrbisSuite; using OrbisSuite.Common; -using OrbisSuite.Common.Database.App; -using SimpleUI.Controls; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using static System.Net.Mime.MediaTypeNames; namespace OrbisNeighborHood.Controls { @@ -27,11 +15,11 @@ namespace OrbisNeighborHood.Controls /// public partial class AppPanel : UserControl { - public AppBrowse App; + public AppInfo App; private AppState AppState = AppState.STATE_NOT_RUNNING; - public AppPanel(AppBrowse App, string AppVersion) + public AppPanel(AppInfo App, string AppVersion) { InitializeComponent(); @@ -44,17 +32,17 @@ namespace OrbisNeighborHood.Controls Task.Run(() => UpdateApp()); } - public void Update(AppBrowse App, string AppVersion) + public void Update(AppInfo App, string AppVersion) { // Set the Info about this application. - ApplicationNameElement.Text = App.titleName; - TitleIdElement.FieldText = App.titleId; + ApplicationNameElement.Text = App.TitleName; + TitleIdElement.FieldText = App.TitleId; VersionElement.FieldText = AppVersion.TrimStart('0'); - TypeElement.FieldText = $"{App.uiCategory} ({App.category})"; - SizeElement.FieldText = App.contentSize <= 0 ? "N/A" : Utilities.BytesToString(App.contentSize); + TypeElement.FieldText = $"{App.UICategory} ({App.Category})"; + SizeElement.FieldText = App.ContentSize <= 0 ? "N/A" : Utilities.BytesToString(App.ContentSize); // Get the path to our icon and make sure it exists. - string iconPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}\Orbis Suite\AppCache\{OrbisLib.Instance.SelectedTarget.Info.Details.ForegroundAccountId.ToString("X")}\{App.titleId}\icon0.png"; + string iconPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}\Orbis Suite\AppCache\{App.TitleId}\icon0.png"; if(!string.IsNullOrEmpty(iconPath) && File.Exists(iconPath) && new FileInfo(iconPath).Length > 0) { // Load and cache image in memory. @@ -68,17 +56,14 @@ namespace OrbisNeighborHood.Controls IconImage.Source = image; } - if (DateTime.TryParse(App.installDate, out var dateTime)) - { - InstallDateElement.FieldText = dateTime.ToString("ddd dd MMM yyy hh:mm tt"); - } + InstallDateElement.FieldText = App.InstallDate.ToString("ddd dd MMM yyy hh:mm tt"); // Set the tool tips. - StartStop.ToolTip = $"Start {App.titleName}."; - Visibility.ToolTip = $"Hide {App.titleName} from Home Menu."; - ChangeIcon.ToolTip = $"Change the icon of {App.titleName}."; + StartStop.ToolTip = $"Start {App.TitleName}."; + Visibility.ToolTip = $"Hide {App.TitleName} from Home Menu."; + ChangeIcon.ToolTip = $"Change the icon of {App.TitleName}."; // 3 more TBD here. - Delete.ToolTip = $"Delete {App.titleName}."; + Delete.ToolTip = $"Delete {App.TitleName}."; } private void UpdateApp() @@ -88,30 +73,30 @@ namespace OrbisNeighborHood.Controls var currentTarget = OrbisLib.Instance.SelectedTarget; // Get Current App status. - var newAppState = currentTarget.Application.GetAppState(App.titleId); + var newAppState = currentTarget.Application.GetAppState(App.TitleId); if (newAppState >= 0) AppState = newAppState; // App status. if (AppState == AppState.STATE_RUNNING || AppState == AppState.STATE_SUSPENDED) { - Dispatcher.Invoke(() => StartStop.ToolTip = $"Stop {App.titleName}."); + Dispatcher.Invoke(() => StartStop.ToolTip = $"Stop {App.TitleName}."); Dispatcher.Invoke(() => StartStop.ImageSource = "/OrbisNeighborHood;component/Images/Stop.png"); } else { - Dispatcher.Invoke(() => StartStop.ToolTip = $"Start {App.titleName}."); + Dispatcher.Invoke(() => StartStop.ToolTip = $"Start {App.TitleName}."); Dispatcher.Invoke(() => StartStop.ImageSource = "/OrbisNeighborHood;component/Images/Start.png"); } // App Visibility. - if (App.visible == 0 || App.visible == 2) + if (App.Visible == 0 || App.Visible == 2) { - Dispatcher.Invoke(() => Visibility.ToolTip = $"Show {App.titleName} from Home Menu."); + Dispatcher.Invoke(() => Visibility.ToolTip = $"Show {App.TitleName} from Home Menu."); } else { - Dispatcher.Invoke(() => Visibility.ToolTip = $"Hide {App.titleName} from Home Menu."); + Dispatcher.Invoke(() => Visibility.ToolTip = $"Hide {App.TitleName} from Home Menu."); } Thread.Sleep(1000); @@ -127,11 +112,11 @@ namespace OrbisNeighborHood.Controls var currentTarget = OrbisLib.Instance.SelectedTarget; if (AppState == AppState.STATE_RUNNING || AppState == AppState.STATE_SUSPENDED) { - currentTarget.Application.Stop(App.titleId); + currentTarget.Application.Stop(App.TitleId); } else { - currentTarget.Application.Start(App.titleId); + currentTarget.Application.Start(App.TitleId); } }); } diff --git a/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs b/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs index b95151b..732d660 100644 --- a/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs +++ b/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs @@ -6,7 +6,6 @@ using System.Windows; using System.Windows.Controls; using System.IO; using System.Threading.Tasks; -using OrbisSuite.Common.Database.App; using System.Collections.Generic; using System.Threading; using System.Linq; @@ -18,10 +17,6 @@ namespace OrbisNeighborHood.MVVM.View /// public partial class AppListView : UserControl { - private static string _AppDatabaseRemotePath = @"/system_data/priv/mms/app.db"; - - private static Mutex appDataBaseMtx = new Mutex(); - private static readonly List TitleIdExlusionList = new List() { "NPXS20108", @@ -38,6 +33,10 @@ namespace OrbisNeighborHood.MVVM.View "NPXS20106", "NPXS20114", "NPXS20120", + "NPXS20109", + "NPXS20112", + "NPXS20133", + "NPXS20132", // Destiny? lol "CUSA00219", @@ -55,8 +54,14 @@ namespace OrbisNeighborHood.MVVM.View // Refresh the info about the current target. RefreshTargetInfo(); - // Create task to periodically check for app.db changes. - Task.Run(() => CheckAppDatabase()); + Task.Run(() => + { + // Initially populate the app list. + InitAppList(); + + // Create task to periodically check for app.db changes. + // Task.Run(() => CheckAppDatabase()); + }); } #region Properties @@ -103,32 +108,32 @@ namespace OrbisNeighborHood.MVVM.View #endregion - public void AddApp(string UserDirectoryPath, string AppVersion, AppBrowse App) + public void AddApp(string appCachePath, AppInfo App) { var currentTarget = OrbisLib.Instance.SelectedTarget; // Make sure the titleId format is correct. Helps weed out bad entries and folders. - if (!Regex.IsMatch(App.titleId, @"[a-zA-Z]{4}\d{5}")) + if (!Regex.IsMatch(App.TitleId, @"[a-zA-Z]{4}\d{5}")) return; // Skip the Destiny entries that just exist for some reason even after a restore?... lol - if ((App.titleId.Equals("CUSA00219") || App.titleId.Equals("CUSA00568") || App.titleId.Equals("CUSA01000")) && App.contentSize <= 0) + if ((App.TitleId.Equals("CUSA00219") || App.TitleId.Equals("CUSA00568") || App.TitleId.Equals("CUSA01000")) && App.ContentSize <= 0) return; // Skip some that aren't technically an app. - if (TitleIdExlusionList.Contains(App.titleId)) + if (TitleIdExlusionList.Contains(App.TitleId)) return; // Weed out some more bad entries created by default. - if (App.titleName.Length <= 2) + if (App.TitleName.Length <= 2) return; // Make sure only add ones with a category. - if (App.uiCategory.Length <= 0 || App.category.Length <= 0) + if (App.UICategory.Length <= 0 || App.Category.Length <= 0) return; // Directory to cache stuff for app. - string currentAppPath = Path.Combine(UserDirectoryPath, App.titleId); + string currentAppPath = Path.Combine(appCachePath, App.TitleId); // Create Directory for current app. if (!Directory.Exists(currentAppPath)) @@ -137,27 +142,30 @@ namespace OrbisNeighborHood.MVVM.View } // Cache icon0.png for app if we have not already. - if (!File.Exists(Path.Combine(currentAppPath, "icon0.png")) && !string.IsNullOrEmpty(App.metaDataPath) && currentTarget.Info.Details.IsAvailable) //TODO: Maybe add a isFTPAvailable. + if (!File.Exists(Path.Combine(currentAppPath, "icon0.png")) && !string.IsNullOrEmpty(App.MetaDataPath) && currentTarget.Info.Details.IsAvailable) //TODO: Maybe add a isFTPAvailable. { - currentTarget.FTP.DownloadFile($"{App.metaDataPath}/icon0.png", Path.Combine(currentAppPath, "icon0.png")); + currentTarget.FTP.DownloadFile($"{App.MetaDataPath}/icon0.png", Path.Combine(currentAppPath, "icon0.png")); } + // Fetch the App version. + var appVersion = currentTarget.Application.GetAppInfoString(App.TitleId, "APP_VER"); + // Add or update app list item. Dispatcher.Invoke(() => { - var panel = AppList.Items.Cast().ToList().Find(x => x.App.titleId == App.titleId); + var panel = AppList.Items.Cast().ToList().Find(x => x.App.TitleId == App.TitleId); if (panel != null) { - panel.Update(App, AppVersion); + panel.Update(App, appVersion); } else { - AppList.Items.Add(new AppPanel(App, AppVersion)); + AppList.Items.Add(new AppPanel(App, appVersion)); } }); } - private async Task InitAppList() + private void InitAppList() { // Clear lists so we can re-populate them. Dispatcher.Invoke(() => AppList.Items.Clear()); @@ -181,48 +189,19 @@ namespace OrbisNeighborHood.MVVM.View Directory.CreateDirectory(appCachePath); } - // Path where we will store this data. - var ForegroundAccountId = currentTarget.Info.Details.ForegroundAccountId; - string userDirectoryPath = Path.Combine(appCachePath, ForegroundAccountId.ToString("X")); - - // Create Directory for database. - if (!Directory.Exists(userDirectoryPath)) - { - Directory.CreateDirectory(userDirectoryPath); - } - - // Check to see if we have a database. - string appDataBasePath = Path.Combine(userDirectoryPath, "app.db"); - if (!File.Exists(appDataBasePath)) - { - Console.WriteLine("No app.db is cached."); - return; - } - - appDataBaseMtx.WaitOne(); - - // Rename the table we need in the app.db. - AppBrowse.AppBrowseRemoveUserId(appDataBasePath, ForegroundAccountId); - - // Get all apps from the app.db - var appList = AppBrowse.GetAppBrowseList(appDataBasePath); + var appList = currentTarget.Application.GetAppList(); foreach (var app in appList) { Parallel.Invoke(() => { - AddApp(userDirectoryPath, AppInfo.GetStringFromAppInfo(appDataBasePath, app.titleId, "APP_VER"), app); + AddApp(appCachePath, app); }); } - - appDataBaseMtx.ReleaseMutex(); } private async Task CheckAppDatabase() { - // Update the current App list. Called here because it must be initialized before the update is called. - await InitAppList(); - while (true) { try @@ -238,75 +217,30 @@ namespace OrbisNeighborHood.MVVM.View continue; } - // Path where we will store this data. - var ForegroundAccountId = currentTarget.Info.Details.ForegroundAccountId; - string userDirectoryPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Orbis Suite\AppCache\", ForegroundAccountId.ToString("X")); + // Appcache location. + string appCachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Orbis Suite\AppCache\"); - // Download database. - string appDataBasePath = Path.Combine(userDirectoryPath, "app.db"); - if (File.Exists(appDataBasePath)) + // Get the current app list. + var appList = currentTarget.Application.GetAppList(); + + // Check for deletions. + foreach (var app in AppList.Items.Cast().ToList()) { - // Download the new app.db. - string newAppDataBasePath = Path.Combine(userDirectoryPath, "new_app.db"); - if (currentTarget.FTP.DownloadFile(_AppDatabaseRemotePath, newAppDataBasePath)) + if (appList.Find(x => x.TitleId == app.App.TitleId) == null) { - // Get app.db versions. - var newVersion = AppBrowseVersion.GetAppBrowseVersion(newAppDataBasePath); - var oldVersion = AppBrowseVersion.GetAppBrowseVersion(appDataBasePath); - - // Compare the app.db versions. - if (newVersion > oldVersion) - { - appDataBaseMtx.WaitOne(); - - // Remove the out dated database. - File.Delete(appDataBasePath); - - // Rename the new database. - File.Move(newAppDataBasePath, appDataBasePath); - - // Rename the table we need in the app.db. - AppBrowse.AppBrowseRemoveUserId(appDataBasePath, ForegroundAccountId); - - // Get all apps from the app.db - var appList = AppBrowse.GetAppBrowseList(appDataBasePath); - - // Check for deletions. - foreach (var app in AppList.Items.Cast().ToList()) - { - if (appList.Find(x => x.titleId == app.App.titleId) == null) - { - Dispatcher.Invoke(() => AppList.Items.Remove(app)); - } - } - - // Check for new apps / updates. - foreach (var app in appList) - { - Parallel.Invoke(() => - { - AddApp(userDirectoryPath, AppInfo.GetStringFromAppInfo(appDataBasePath, app.titleId, "APP_VER"), app); - }); - } - - appDataBaseMtx.ReleaseMutex(); - } - else - { - // Remove new database as ours is current. - File.Delete(newAppDataBasePath); - } + Dispatcher.Invoke(() => AppList.Items.Remove(app)); } } - else if (currentTarget.Info.Details.IsAvailable) + + // Check for new apps / updates. + foreach (var app in appList) { - // Download the app database for the first time. - if (OrbisLib.Instance.SelectedTarget.FTP.DownloadFile(_AppDatabaseRemotePath, appDataBasePath)) + Parallel.Invoke(() => { - // Initialize the Application List now that we have an app.db. - InitAppList(); - } + AddApp(appCachePath, app); + }); } + await Task.Delay(1000); } catch (Exception ex) diff --git a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt index 4ac7a82..39c15c3 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt @@ -1 +1 @@ -1856 +1956 diff --git a/Windows/OrbisNeighborHood/Resources/BuildString.txt b/Windows/OrbisNeighborHood/Resources/BuildString.txt index 3e26f93..f3c7c94 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildString.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildString.txt @@ -1 +1 @@ -Version 3.0.1856 Debug Build Saturday December 17 2022 6:19 PM +Version 3.0.1956 Debug Build Sunday December 18 2022 7:40 PM