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.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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<AppInfo> &Apps)
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
char UICategory[10];
|
||||
};
|
||||
|
||||
static int GetDBVersion();
|
||||
static bool GetApps(std::vector<AppInfo> &Apps);
|
||||
static bool GetAppInfoString(const char* TitleId, char* Out, size_t OutSize, const char* Key);
|
||||
static bool SetVisibility(const char* TitleId, VisibilityType Visibility);
|
||||
|
||||
@@ -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<AppDatabase::AppInfo> 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<kinfo_proc> 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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@ void ThreadPool::WorkingLoop()
|
||||
job = JobQueue.front();
|
||||
JobQueue.pop();
|
||||
}
|
||||
job();
|
||||
|
||||
if (job != nullptr)
|
||||
job();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<AppBrowse> 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<AppBrowse>($"SELECT * FROM {tableName}");
|
||||
|
||||
// Close the handle.
|
||||
db.Close();
|
||||
|
||||
// Return the Results.
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Func<AppBrowseVersion, bool>>)(x => x.category.Equals("sync_server")));
|
||||
db.Close();
|
||||
if (result != null)
|
||||
{
|
||||
return result.status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Func<AppInfo, bool>>)(x => x.titleId.Equals(TitleId) && x.key.Equals(Key)));
|
||||
db.Close();
|
||||
if (result != null)
|
||||
{
|
||||
return result.val;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,13 @@ namespace OrbisLib2.Common.Helpers
|
||||
/// </summary>
|
||||
/// <param name="s">The current socket.</param>
|
||||
/// <param name="data">The data to be recieved.</param>
|
||||
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)
|
||||
|
||||
@@ -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<AppInfo> GetAppList()
|
||||
public string GetAppDBPath()
|
||||
{
|
||||
var AppList = new List<AppInfo>();
|
||||
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<AppBrowse> 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<AppBrowse>();
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
/// </summary>
|
||||
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.");
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1 +1 @@
|
||||
2642
|
||||
2676
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<INetFwRule> firewallRules = firewallPolicy.Rules.OfType<INetFwRule>().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<ILoggerFactory>()
|
||||
|
||||
Reference in New Issue
Block a user