From a1248d114fbbf9a4c0598e43090499b8dfa7f9d2 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 18 Feb 2023 15:45:51 -0700 Subject: [PATCH] Fix Application view, app db will now be backed up, changed to completely use lncutil & hacky way to use sqlite net pcl with a dynamic table name. --- Playstation/OrbisLibAPI/APIPackets.h | 3 +- Playstation/OrbisLibAPI/AppDatabase.cpp | 39 +++++ Playstation/OrbisLibAPI/AppDatabase.h | 1 + Playstation/OrbisLibAPI/Apps.cpp | 103 ++++++++----- Playstation/OrbisLibAPI/Apps.h | 3 +- Playstation/OrbisLibAPI/SocketListener.cpp | 9 +- Playstation/OrbisLibAPI/Sockets.cpp | 3 +- Playstation/OrbisLibAPI/ThreadPool.cpp | 4 +- Playstation/OrbisLibAPI/Version.h | 22 +-- Playstation/OrbisLibAPI/main.cpp | 2 +- .../OrbisLib2/Common/API/APIPackets.cs | 3 +- .../Common/Database/App/AppBrowse.cs | 67 +++++++++ .../Common/Database/App/AppBrowseVersion.cs | 35 +++++ .../OrbisLib2/Common/Database/App/AppInfo.cs | 33 +++++ .../OrbisLib2/Common/Helpers/Sockets.cs | 10 +- .../OrbisLib2/Targets/Application.cs | 136 +++++++++++------- .../OrbisLib2/Targets/TargetManager.cs | 3 + .../Controls/AppPanel.xaml.cs | 14 +- .../MVVM/View/AppListView.xaml.cs | 8 +- .../Resources/BuildNumber.txt | 2 +- .../Resources/BuildString.txt | 2 +- Windows/OrbisSuiteService/Program.cs | 4 + 22 files changed, 382 insertions(+), 124 deletions(-) create mode 100644 Windows/Libraries/OrbisLib2/Common/Database/App/AppBrowse.cs create mode 100644 Windows/Libraries/OrbisLib2/Common/Database/App/AppBrowseVersion.cs create mode 100644 Windows/Libraries/OrbisLib2/Common/Database/App/AppInfo.cs diff --git a/Playstation/OrbisLibAPI/APIPackets.h b/Playstation/OrbisLibAPI/APIPackets.h index d0897b3..b8717ec 100644 --- a/Playstation/OrbisLibAPI/APIPackets.h +++ b/Playstation/OrbisLibAPI/APIPackets.h @@ -20,7 +20,8 @@ enum APICommands /* ####### Apps functions ####### */ APP_START, - API_APPS_GET_LIST, + API_APPS_CHECK_VER, + API_APPS_GET_DB, API_APPS_GET_INFO_STR, API_APPS_STATUS, API_APPS_START, diff --git a/Playstation/OrbisLibAPI/AppDatabase.cpp b/Playstation/OrbisLibAPI/AppDatabase.cpp index c748fd3..5eea21f 100644 --- a/Playstation/OrbisLibAPI/AppDatabase.cpp +++ b/Playstation/OrbisLibAPI/AppDatabase.cpp @@ -29,6 +29,45 @@ const char* GetText(sqlite3_stmt* stmt, int column) return ""; } +int AppDatabase::GetDBVersion() +{ + int res; + int version = 0; + + auto db = OpenDatabase(); + if (db == nullptr) + { + return false; + } + + // Prepare statement. + sqlite3_stmt* stmt; + res = sqlite3_prepare(db, "SELECT * FROM tbl_version WHERE category='sync_server'", -1, &stmt, NULL); + if (res != SQLITE_OK) + { + klog("sqlite3_prepare(): Failed because %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return false; + } + + // execute a single step. + res = sqlite3_step(stmt); + if (res == SQLITE_ROW) + { + version = sqlite3_column_int(stmt, 1); + } + + if (res != SQLITE_DONE) { + printf("GetApps(): Res %d Error: %s\n", res, sqlite3_errmsg(db)); + } + + // Release resources. + sqlite3_finalize(stmt); + sqlite3_close(db); + + return version; +} + bool AppDatabase::GetApps(std::vector &Apps) { int res; diff --git a/Playstation/OrbisLibAPI/AppDatabase.h b/Playstation/OrbisLibAPI/AppDatabase.h index b80dd61..3d6d40d 100644 --- a/Playstation/OrbisLibAPI/AppDatabase.h +++ b/Playstation/OrbisLibAPI/AppDatabase.h @@ -38,6 +38,7 @@ public: char UICategory[10]; }; + static int GetDBVersion(); 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); diff --git a/Playstation/OrbisLibAPI/Apps.cpp b/Playstation/OrbisLibAPI/Apps.cpp index 3758f4c..38aec3b 100644 --- a/Playstation/OrbisLibAPI/Apps.cpp +++ b/Playstation/OrbisLibAPI/Apps.cpp @@ -12,7 +12,7 @@ void Apps::HandleAPI(OrbisNetId Sock, APIPacket* Packet) memset(titleId, 0, sizeof(titleId)); // For commands that need it get the titleId of the App - if (Packet->Command > API_APPS_GET_LIST) + if (Packet->Command > API_APPS_GET_DB) { sceNetRecv(Sock, titleId, sizeof(titleId), 0); } @@ -22,9 +22,15 @@ void Apps::HandleAPI(OrbisNetId Sock, APIPacket* Packet) default: break; - case API_APPS_GET_LIST: + case API_APPS_CHECK_VER: - GetAppsList(Sock); + CheckDBVersion(Sock); + + break; + + case API_APPS_GET_DB: + + GetDB(Sock); break; @@ -84,18 +90,62 @@ void Apps::HandleAPI(OrbisNetId Sock, APIPacket* Packet) } } -void Apps::GetAppsList(OrbisNetId Sock) +void Apps::CheckDBVersion(OrbisNetId Sock) { - std::vector AppList; - if (!AppDatabase::GetApps(AppList)) + int remoteVersion = 0; + auto currentVersion = AppDatabase::GetDBVersion(); + + // Get the remote version. + if (!Sockets::RecvInt(Sock, &remoteVersion)) + { + klog("GetAppsList(): Failed to get remote app db version.\n"); + return; + } + + // Send if the remote version is out of date. + Sockets::SendInt(Sock, remoteVersion != currentVersion ? 1 : 0); +} + +void Apps::GetDB(OrbisNetId Sock) +{ + // Open the file. + auto fd = sceKernelOpen("/system_data/priv/mms/app.db", ORBIS_KERNEL_O_RDONLY, 0); + if (!fd) { Sockets::SendInt(Sock, 0); return; } - Sockets::SendInt(Sock, AppList.size()); + // Get File stats. + OrbisKernelStat stats; + if (sceKernelFstat(fd, &stats) != 0) + { + Sockets::SendInt(Sock, 0); + return; + } - Sockets::SendLargeData(Sock, (unsigned char*)AppList.data(), AppList.size() * sizeof(AppInfoPacket)); + // Store the file size. + auto fileSize = stats.st_size; + + // Allocate space to read data. + auto fileData = (unsigned char*)malloc(fileSize); + + // ReadFile. + if (sceKernelRead(fd, fileData, fileSize) <= 0) + { + Sockets::SendInt(Sock, 0); + return; + } + + // Send the size of the db file. + Sockets::SendInt(Sock, fileSize); + + // Send the db file. + Sockets::SendLargeData(Sock, fileData, fileSize); + + // clean up. + free(fileData); + sceKernelClose(fd); } void Apps::GetAppInfoString(OrbisNetId Sock, const char* TitleId) @@ -113,47 +163,29 @@ void Apps::GetAppInfoString(OrbisNetId Sock, const char* TitleId) sceNetSend(Sock, OutStr, sizeof(OutStr), 0); } -// TODO: Currently cant get the appId of child processes like the Web Browser since it is a child of the ShellUI. int Apps::GetAppId(const char* TitleId) { - int appId = 0; + bool isLaunched = false; + auto res = sceLncUtilIsAppLaunched(TitleId, &isLaunched); - // Get the list of running processes. - std::vector processList; - GetProcessList(processList); + if (!isLaunched || res != 0) + return 0; - for (const auto& i : processList) - { - // Get the app info using the pid. - OrbisAppInfo appInfo; - sceKernelGetAppInfo(i.pid, &appInfo); - - // Using the titleId match our desired app and return the appId from the appinfo. - if (!strcmp(appInfo.TitleId, TitleId)) - { - appId = appInfo.AppId; - - break; - } - } - - return appId; + return sceLncUtilGetAppId(TitleId); } void Apps::SendAppStatus(OrbisNetId Sock, const char* TitleId) { auto appId = GetAppId(TitleId); - - // If we have no appId that means the process is not running. if (appId <= 0) { Sockets::SendInt(Sock, STATE_NOT_RUNNING); } else { - bool state = false; - auto res = sceSystemServiceIsAppSuspended(appId, &state); - if (res == 0 && state) + bool isSuspended = 0; + auto res = sceLncUtilIsAppSuspended(appId, &isSuspended); + if (res == 0 && isSuspended) { Sockets::SendInt(Sock, STATE_SUSPENDED); } @@ -192,7 +224,6 @@ void Apps::StartApp(OrbisNetId Sock, const char* TitleId) void Apps::KillApp(OrbisNetId Sock, const char* TitleId) { auto appId = GetAppId(TitleId); - if (appId > 0 && sceSystemServiceKillApp(appId, -1, 0, 0) == 0) { Sockets::SendInt(Sock, 1); @@ -206,7 +237,6 @@ void Apps::KillApp(OrbisNetId Sock, const char* TitleId) void Apps::SuspendApp(OrbisNetId Sock, const char* TitleId) { auto appId = GetAppId(TitleId); - if (appId > 0 && sceLncUtilSuspendApp(appId, 0) == 0) { Sockets::SendInt(Sock, 1); @@ -220,7 +250,6 @@ void Apps::SuspendApp(OrbisNetId Sock, const char* TitleId) void Apps::ResumeApp(OrbisNetId Sock, const char* TitleId) { auto appId = GetAppId(TitleId); - if (appId > 0 && sceLncUtilResumeApp(appId, 0) == 0 && sceLncUtilSetAppFocus(appId, 0) == 0) { Sockets::SendInt(Sock, 1); diff --git a/Playstation/OrbisLibAPI/Apps.h b/Playstation/OrbisLibAPI/Apps.h index a3adb9f..6b53895 100644 --- a/Playstation/OrbisLibAPI/Apps.h +++ b/Playstation/OrbisLibAPI/Apps.h @@ -11,7 +11,8 @@ public: void HandleAPI(OrbisNetId Sock, APIPacket* Packet); private: - void GetAppsList(OrbisNetId Sock); + void CheckDBVersion(OrbisNetId Sock); + void GetDB(OrbisNetId Sock); void GetAppInfoString(OrbisNetId Sock, const char* TitleId); int GetAppId(const char* TitleId); void SendAppStatus(OrbisNetId Sock, const char* TitleId); diff --git a/Playstation/OrbisLibAPI/SocketListener.cpp b/Playstation/OrbisLibAPI/SocketListener.cpp index bd6a717..0aaa91f 100644 --- a/Playstation/OrbisLibAPI/SocketListener.cpp +++ b/Playstation/OrbisLibAPI/SocketListener.cpp @@ -74,10 +74,13 @@ void SocketListener::ListenThread() int optval = 1; sceNetSetsockopt(ClientSocket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_NOSIGPIPE, &optval, sizeof(optval)); - ThreadPool::QueueJob([=] + ThreadPool::QueueJob([=] { - ClientCallBack(tdParam, ClientSocket, ClientAddr.sin_addr); - sceNetSocketClose(ClientSocket); + auto sock = ClientSocket; + auto addr = ClientAddr.sin_addr; + + ClientCallBack(tdParam, sock, addr); + sceNetSocketClose(sock); }); // Reset ClientSocket. diff --git a/Playstation/OrbisLibAPI/Sockets.cpp b/Playstation/OrbisLibAPI/Sockets.cpp index 441d4d5..1066626 100644 --- a/Playstation/OrbisLibAPI/Sockets.cpp +++ b/Playstation/OrbisLibAPI/Sockets.cpp @@ -41,7 +41,7 @@ bool Sockets::SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen if (res < 0) { - klog("SendLargeData() Error: %llX\n", res); + klog("SendLargeData() Error: %llX(%llX)\n", res, *sceNetErrnoLoc()); return false; } @@ -65,6 +65,7 @@ bool Sockets::RecvLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen if (res < 0) { + klog("RecvLargeData() Error: %llX(%llX)\n", res, *sceNetErrnoLoc()); return false; } diff --git a/Playstation/OrbisLibAPI/ThreadPool.cpp b/Playstation/OrbisLibAPI/ThreadPool.cpp index 46169b6..76e7d20 100644 --- a/Playstation/OrbisLibAPI/ThreadPool.cpp +++ b/Playstation/OrbisLibAPI/ThreadPool.cpp @@ -26,7 +26,9 @@ void ThreadPool::WorkingLoop() job = JobQueue.front(); JobQueue.pop(); } - job(); + + if (job != nullptr) + job(); } } diff --git a/Playstation/OrbisLibAPI/Version.h b/Playstation/OrbisLibAPI/Version.h index cce5f40..b750bf9 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 1117 -#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 1141 +#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/main.cpp b/Playstation/OrbisLibAPI/main.cpp index 9afdf21..851d2ec 100644 --- a/Playstation/OrbisLibAPI/main.cpp +++ b/Playstation/OrbisLibAPI/main.cpp @@ -66,7 +66,7 @@ int main() klog("\n%s\n\n", ORBISLIB_BUILDSTRING); // Start up the thread pool. - ThreadPool::Init(50); + ThreadPool::Init(20); // Init a thread to monitor the system usage stats. // SystemMonitor::Init(); diff --git a/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs b/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs index b3634c9..aad02b8 100644 --- a/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs +++ b/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs @@ -17,7 +17,8 @@ namespace OrbisLib2.Common.API /* ####### Apps functions ####### */ APP_START, - API_APPS_GET_LIST, + API_APPS_CHECK_VER, + API_APPS_GET_DB, API_APPS_GET_INFO_STR, API_APPS_STATUS, API_APPS_START, diff --git a/Windows/Libraries/OrbisLib2/Common/Database/App/AppBrowse.cs b/Windows/Libraries/OrbisLib2/Common/Database/App/AppBrowse.cs new file mode 100644 index 0000000..75a7207 --- /dev/null +++ b/Windows/Libraries/OrbisLib2/Common/Database/App/AppBrowse.cs @@ -0,0 +1,67 @@ +using SQLite; +using System; +using System.Collections.Generic; +using System.Diagnostics.Metrics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OrbisLib2.Common.Database.App +{ + public class AppBrowse + { + [PrimaryKey, NotNull] + [Column("titleId")] + public string TitleId { get; set; } = ""; + + [Column("contentId")] + public string ContentId { get; set; } = ""; + + [Column("titleName")] + public string TitleName { get; set; } = ""; + + [Column("metaDataPath")] + public string MetaDataPath { get; set; } = ""; + + [Column("visible")] + public int Visible { get; set; } = 0; + + [Column("sortPriority")] + public int SortPriority { get; set; } = 0; + + [Column("dispLocation")] + public int DispLocation { get; set; } = 0; + + [Column("canRemove")] + public int CanRemove { get; set; } = 0; + + [Column("category")] + public string Category { get; set; } = ""; + + [Column("contentSize")] + public int ContentSize { get; set; } = 0; + + [Column("installDate")] + public string InstallDate { get; set; } = ""; + + [Column("uiCategory")] + public string UICategory { get; set; } = ""; + + public static List GetAppBrowseList(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')}"; + + // Query the table with the userId that we want. + var result = db.Query($"SELECT * FROM {tableName}"); + + // Close the handle. + db.Close(); + + // Return the Results. + return result; + } + } +} diff --git a/Windows/Libraries/OrbisLib2/Common/Database/App/AppBrowseVersion.cs b/Windows/Libraries/OrbisLib2/Common/Database/App/AppBrowseVersion.cs new file mode 100644 index 0000000..4124529 --- /dev/null +++ b/Windows/Libraries/OrbisLib2/Common/Database/App/AppBrowseVersion.cs @@ -0,0 +1,35 @@ +using SQLite; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace OrbisLib2.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/OrbisLib2/Common/Database/App/AppInfo.cs b/Windows/Libraries/OrbisLib2/Common/Database/App/AppInfo.cs new file mode 100644 index 0000000..c1db1dc --- /dev/null +++ b/Windows/Libraries/OrbisLib2/Common/Database/App/AppInfo.cs @@ -0,0 +1,33 @@ +using SQLite; +using System.Linq.Expressions; + +namespace OrbisLib2.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/OrbisLib2/Common/Helpers/Sockets.cs b/Windows/Libraries/OrbisLib2/Common/Helpers/Sockets.cs index 1bc1907..377f146 100644 --- a/Windows/Libraries/OrbisLib2/Common/Helpers/Sockets.cs +++ b/Windows/Libraries/OrbisLib2/Common/Helpers/Sockets.cs @@ -12,13 +12,13 @@ namespace OrbisLib2.Common.Helpers /// /// The current socket. /// The data to be recieved. - public static void RecvLarge(this Socket s, byte[] data) + public static int RecvLarge(this Socket s, byte[] data) { + int Left = data.Length; + int Received = 0; + try { - int Left = data.Length; - int Received = 0; - while (Left > 0) { var chunkSize = Math.Min(8192, Left); @@ -32,6 +32,8 @@ namespace OrbisLib2.Common.Helpers { Console.WriteLine(ex.Message); } + + return Received; } public static void SendLarge(this Socket s, byte[] data) diff --git a/Windows/Libraries/OrbisLib2/Targets/Application.cs b/Windows/Libraries/OrbisLib2/Targets/Application.cs index 255dbda..3a04bcf 100644 --- a/Windows/Libraries/OrbisLib2/Targets/Application.cs +++ b/Windows/Libraries/OrbisLib2/Targets/Application.cs @@ -1,17 +1,18 @@ using OrbisLib2.Common.API; +using OrbisLib2.Common.Database.App; using OrbisLib2.Common.Helpers; using System.Data.Entity.Core.Metadata.Edm; using System.Drawing; +using System.IO; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; +using System.Windows.Controls; +using static SQLite.SQLite3; namespace OrbisLib2.Targets { - 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 { public enum VisibilityType : int @@ -28,71 +29,108 @@ namespace OrbisLib2.Targets this.Target = Target; } - public List GetAppList() + public string GetAppDBPath() { - var AppList = new List(); - var result = API.SendCommand(Target, 5, APICommands.API_APPS_GET_LIST, (Socket Sock, APIResults Result) => + var foregroundAccountId = Target.Info.ForegroundAccountId; + if (foregroundAccountId <= 0) + return string.Empty; + + // Create the db cache folder if it does not exist. + var dbCachePath = @$"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}\Orbis Suite\DBCache"; + if (!Directory.Exists(dbCachePath)) { - // Get the number of apps installed. - var Count = Sock.RecvInt32(); + Directory.CreateDirectory(dbCachePath); + } - // Recieve all of the arrary as one large packet. - var dataSize = Count * Marshal.SizeOf(typeof(AppInfoPacket)); - var data = new byte[dataSize]; - Sock.RecvLarge(data); + // create a folder for this target if it does not exist yet. + var targetFolder = @$"{dbCachePath}\{Target.Info.MACAddressLAN.Replace(":", "-")}"; + if (!Directory.Exists(targetFolder)) + { + Directory.CreateDirectory(targetFolder); + } - // Allocate and copy the packet to begin marshaling it. - IntPtr ptr = Marshal.AllocHGlobal(dataSize); - Marshal.Copy(data, 0, ptr, dataSize); + return @$"{targetFolder}\app.db"; + } - for(int i = 0; i < Count; i++) - { - // Marshal each part of the buffer to a struct. - var Packet = new AppInfoPacket(); - Packet = (AppInfoPacket)Marshal.PtrToStructure(IntPtr.Add(ptr, i * Marshal.SizeOf(typeof(AppInfoPacket))), typeof(AppInfoPacket)); + public bool IsOutOfDate() + { + var databasePath = GetAppDBPath(); - // Try to parse the date time strings. - if (!DateTime.TryParse(Packet.LastAccessTime, out DateTime LastAccessTime)) - LastAccessTime = DateTime.MinValue; + if (!File.Exists(databasePath)) + { + return true; + } - if (!DateTime.TryParse(Packet.LastAccessTime, out DateTime InstallDate)) - InstallDate = DateTime.MinValue; + var currentAppVersion = AppBrowseVersion.GetAppBrowseVersion(databasePath); - // 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); + bool result = false; + API.SendCommand(Target, 5, APICommands.API_APPS_CHECK_VER, (Socket Sock, APIResults Result) => + { + // Send the current app version. + Sock.SendInt32(currentAppVersion); - 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)); - } - - Marshal.FreeHGlobal(ptr); + // Get the state from API. + result = Sock.RecvInt32() == 1; }); - return AppList; + return result; + } + + public void UpdateLocalDB() + { + if(IsOutOfDate()) + { + API.SendCommand(Target, 5, APICommands.API_APPS_GET_DB, (Socket Sock, APIResults Result) => + { + var fileSize = Sock.RecvInt32(); + var newDatabaseBytes = new byte[fileSize]; + if (Sock.RecvLarge(newDatabaseBytes) < fileSize) + return; + + var databasePath = GetAppDBPath(); + var oldDatabasePath = @$"{databasePath}.old"; + + // If we already have a db back it up. + if (File.Exists(databasePath)) + { + File.Copy(databasePath, oldDatabasePath, true); + + // Remove the last db + File.Delete(databasePath); + } + + // Write the new DB. + File.WriteAllBytes(databasePath, newDatabaseBytes); + }); + } + } + + public List GetAppList() + { + var databasePath = GetAppDBPath(); + + // Update the DB if needed. + UpdateLocalDB(); + + // Make sure we actually have a DB now. + if (!File.Exists(databasePath)) + { + return new List(); + } + + return AppBrowse.GetAppBrowseList(databasePath, Target.Info.ForegroundAccountId); } public string GetAppInfoString(string TitleId, string Key) { - if (!Regex.IsMatch(TitleId, @"[a-zA-Z]{4}\d{5}")) + var databasePath = GetAppDBPath(); + + if (!File.Exists(databasePath)) { - Console.WriteLine($"Invaild titleId format {TitleId}"); return string.Empty; } - var resultBuffer = new byte[200]; - var result = API.SendCommand(Target, 5, APICommands.API_APPS_GET_INFO_STR, (Socket Sock, APIResults Result) => - { - // 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'))); - - Sock.Receive(resultBuffer); - }); - - return Encoding.ASCII.GetString(resultBuffer); + return AppInfo.GetStringFromAppInfo(databasePath, TitleId, Key); } public AppState GetAppState(string TitleId) diff --git a/Windows/Libraries/OrbisLib2/Targets/TargetManager.cs b/Windows/Libraries/OrbisLib2/Targets/TargetManager.cs index e50aa99..3fee399 100644 --- a/Windows/Libraries/OrbisLib2/Targets/TargetManager.cs +++ b/Windows/Libraries/OrbisLib2/Targets/TargetManager.cs @@ -174,6 +174,9 @@ namespace OrbisLib2.Targets // TODO: Implement this into the API. savedTarget.Info.CurrentProcessId = 0;// TODO: Update this to process Id Packet.CurrentProc; + // Misc + savedTarget.Info.ForegroundAccountId = Packet.ForegroundAccountId; + // Storage. savedTarget.Info.HDDUsedSpace = (long)(Packet.TotalSpace - Packet.FreeSpace); savedTarget.Info.HDDFreeSpace = (long)Packet.FreeSpace; diff --git a/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs b/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs index 85873b6..191146b 100644 --- a/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs +++ b/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs @@ -1,4 +1,5 @@ using OrbisLib2.Common.API; +using OrbisLib2.Common.Database.App; using OrbisLib2.General; using OrbisLib2.Targets; using System; @@ -18,12 +19,12 @@ namespace OrbisNeighborHood.Controls /// public partial class AppPanel : UserControl { - public AppInfo App; + public AppBrowse App; private AppState AppState = AppState.STATE_NOT_RUNNING; private VisibilityType Visible = VisibilityType.VT_NONE; - public AppPanel(AppInfo App, string AppVersion) + public AppPanel(AppBrowse App, string AppVersion) { InitializeComponent(); @@ -36,7 +37,7 @@ namespace OrbisNeighborHood.Controls Task.Run(() => UpdateApp()); } - public void Update(AppInfo App, string AppVersion) + public void Update(AppBrowse App, string AppVersion) { // Set the Info about this application. ApplicationNameElement.Text = App.TitleName; @@ -60,7 +61,10 @@ namespace OrbisNeighborHood.Controls IconImage.Source = image; } - InstallDateElement.FieldText = App.InstallDate.ToString("ddd dd MMM yyy hh:mm tt"); + if (!DateTime.TryParse(App.InstallDate, out DateTime InstallDate)) + InstallDate = DateTime.MinValue; + + InstallDateElement.FieldText = InstallDate.ToString("ddd dd MMM yyy hh:mm tt"); // Set the tool tips. StartStop.ToolTip = $"Start {App.TitleName}."; @@ -118,7 +122,7 @@ namespace OrbisNeighborHood.Controls } // App Visibility. - Visible = currentTarget.Application.GetVisibility(App.TitleId); + //Visible = currentTarget.Application.GetVisibility(App.TitleId); if (Visible == VisibilityType.VT_NONE || Visible == VisibilityType.VT_INVISIBLE) { Dispatcher.Invoke(() => Visibility.ToolTip = $"Show {App.TitleName} from Home Menu."); diff --git a/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs b/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs index 1362f0a..f1220de 100644 --- a/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs +++ b/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs @@ -120,14 +120,8 @@ namespace OrbisNeighborHood.MVVM.View if (TargetManager.Targets.Count <= 0) continue; - // Make sure the Target is online so we can pull the db. - var currentTarget = TargetManager.SelectedTarget; - if (currentTarget == null || !currentTarget.Info.IsAvailable) - { - continue; - } - // Get the current app list. + var currentTarget = TargetManager.SelectedTarget; var appList = currentTarget.Application.GetAppList(); // Check for adding apps. diff --git a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt index f570f1c..5e84f34 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt @@ -1 +1 @@ -2642 +2676 diff --git a/Windows/OrbisNeighborHood/Resources/BuildString.txt b/Windows/OrbisNeighborHood/Resources/BuildString.txt index 5d40308..343ea2d 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildString.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildString.txt @@ -1 +1 @@ -Version 3.0.2642 Debug Build Friday February 17 2023 10:08 PM +Version 3.0.2676 Debug Build Saturday February 18 2023 3:43 PM diff --git a/Windows/OrbisSuiteService/Program.cs b/Windows/OrbisSuiteService/Program.cs index bd1cdbc..6ba8270 100644 --- a/Windows/OrbisSuiteService/Program.cs +++ b/Windows/OrbisSuiteService/Program.cs @@ -38,6 +38,9 @@ class Service : ServiceBase public void OnStartPublic(string[] args) { +#if DEBUG + +#else // setup up rule in firewall for event listener. INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")); List firewallRules = firewallPolicy.Rules.OfType().Where(x => x.Name.Contains("OrbisSuiteEvents")).ToList(); @@ -56,6 +59,7 @@ class Service : ServiceBase firewallRule.LocalPorts = Config.EventPort.ToString(); firewallPolicy.Rules.Add(firewallRule); } +#endif // Create logger instance. var logger = _serviceProvider.GetService()