Skip to content

Commit

Permalink
Added Tool for installing keys
Browse files Browse the repository at this point in the history
  • Loading branch information
nicola02nb committed Nov 13, 2024
1 parent 4cb5946 commit 4f5af0e
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 0 deletions.
68 changes: 68 additions & 0 deletions src/Ryujinx.HLE/FileSystem/ContentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils;
using LibHac.Tools.Ncm;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities;
Expand Down Expand Up @@ -474,6 +475,56 @@ public void InstallFirmware(string firmwareSource)
FinishInstallation(temporaryDirectory, registeredDirectory);
}

public void InstallKeys(string keysSource)
{
string systemDirectory = AppDataManager.KeysDirPath;
//if(AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile)
//{
// systemDirectory = AppDataManager.KeysDirPathUser;
//}

if (Directory.Exists(keysSource))
{
foreach (var filePath in Directory.EnumerateFiles(keysSource, "*.keys"))
{
File.Copy(filePath, Path.Combine(systemDirectory, Path.GetFileName(filePath)), true);
}

return;
}

if (!File.Exists(keysSource))
{
throw new FileNotFoundException("Keys file does not exist.");
}

FileInfo info = new(keysSource);

using FileStream file = File.OpenRead(keysSource);

switch (info.Extension)
{
case ".zip":
using (ZipArchive archive = ZipFile.OpenRead(keysSource))
{

foreach (var entry in archive.Entries)
{
if (Path.GetExtension(entry.FullName).Equals(".keys", StringComparison.OrdinalIgnoreCase))
{
entry.ExtractToFile(Path.Combine(systemDirectory, entry.Name), overwrite: true);
}
}
}
break;
case ".keys":
File.Copy(keysSource, Path.Combine(systemDirectory, info.Name), true);
break;
default:
throw new InvalidFirmwarePackageException("Input file is not a valid key package");
}
}

private void FinishInstallation(string temporaryDirectory, string registeredDirectory)
{
if (Directory.Exists(registeredDirectory))
Expand Down Expand Up @@ -947,5 +998,22 @@ public SystemVersion GetCurrentFirmwareVersion()

return null;
}

public bool AreKeysAlredyPresent()
{
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")) && !File.Exists(Path.Combine(AppDataManager.KeysDirPath, "title.keys")))
{
if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && (File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "prod.keys")) || File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "title.keys"))))
{
return true;
}
}
else
{
return true;
}

return false;
}
}
}
10 changes: 10 additions & 0 deletions src/Ryujinx/Assets/Locales/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
"MenuBarToolsInstallFirmware": "Install Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Install a firmware from XCI or ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Install a firmware from a directory",
"MenuBarToolsInstallKeys": "Install Keys",
"MenuBarFileToolsInstallKeysFromFile": "Install keys from KEYS or ZIP",
"MenuBarFileToolsInstallKeysFromFolder": "Install keys from a directory",
"MenuBarToolsManageFileTypes": "Manage file types",
"MenuBarToolsInstallFileTypes": "Install file types",
"MenuBarToolsUninstallFileTypes": "Uninstall file types",
Expand Down Expand Up @@ -504,6 +507,13 @@
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installing firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "System version {0} successfully installed.",
"DialogKeysInstallerKeysNotFoundErrorMessage": "A valid Keys file was not found in {0}.",
"DialogKeysInstallerKeysInstallTitle": "Install Keys",
"DialogKeysInstallerKeysInstallMessage": "New Keys file will be installed.",
"DialogKeysInstallerKeysInstallSubMessage": "\n\nThis will replace some of the current installed Keys.",
"DialogKeysInstallerKeysInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogKeysInstallerKeysInstallWaitMessage": "Installing Keys...",
"DialogKeysInstallerKeysInstallSuccessMessage": "New Keys file successfully installed.",
"DialogUserProfileDeletionWarningMessage": "There would be no other profiles to be opened if selected profile is deleted",
"DialogUserProfileDeletionConfirmMessage": "Do you want to delete the selected profile",
"DialogUserProfileUnsavedChangesTitle": "Warning - Unsaved Changes",
Expand Down
146 changes: 146 additions & 0 deletions src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,105 @@ await ContentDialogHelper.CreateInfoDialog(
}
}

private async Task HandleKeysInstallation(string filename)
{
try
{
//bool isValidKeysFilke = true;

//if (!isValidKeysFilke)
//{
// await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename));

// return;
//}

string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallTitle);
string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallMessage);

bool alreadyKesyInstalled = ContentManager.AreKeysAlredyPresent();
if (alreadyKesyInstalled)
{
dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSubMessage);
}

dialogMessage += LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallConfirmMessage];

UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
dialogTitle,
dialogMessage,
LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);

UpdateWaitWindow waitingDialog = new(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallWaitMessage]);

if (result == UserResult.Yes)
{
Logger.Info?.Print(LogClass.Application, $"Installing Keys");

Thread thread = new(() =>
{
Dispatcher.UIThread.InvokeAsync(delegate
{
waitingDialog.Show();
});

try
{
ContentManager.InstallKeys(filename);

Dispatcher.UIThread.InvokeAsync(async delegate
{
waitingDialog.Close();

string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSuccessMessage);

await ContentDialogHelper.CreateInfoDialog(
dialogTitle,
message,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
string.Empty,
LocaleManager.Instance[LocaleKeys.RyujinxInfo]);

Logger.Info?.Print(LogClass.Application, message);
});
}
catch (Exception ex)
{
Dispatcher.UIThread.InvokeAsync(async () =>
{
waitingDialog.Close();

await ContentDialogHelper.CreateErrorDialog(ex.Message);
});
}
finally
{
VirtualFileSystem.ReloadKeySet();
}
})
{
Name = "GUI.KeysInstallerThread",
};

thread.Start();
}
}
catch (MissingKeyException ex)
{
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime)
{
Logger.Error?.Print(LogClass.Application, ex.ToString());

await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys);
}
}
catch (Exception ex)
{
await ContentDialogHelper.CreateErrorDialog(ex.Message);
}
}
private void ProgressHandler<T>(T state, int current, int total) where T : Enum
{
Dispatcher.UIThread.Post(() =>
Expand Down Expand Up @@ -1467,6 +1566,53 @@ public async Task InstallFirmwareFromFolder()
}
}

public async Task InstallKeysFromFile()
{
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = false,
FileTypeFilter = new List<FilePickerFileType>
{
new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes])
{
Patterns = new[] { "*.keys", "*.zip" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" },
MimeTypes = new[] { "application/keys", "application/zip" },
},
new("KEYS")
{
Patterns = new[] { "*.keys" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
MimeTypes = new[] { "application/keys" },
},
new("ZIP")
{
Patterns = new[] { "*.zip" },
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
MimeTypes = new[] { "application/zip" },
},
},
});

if (result.Count > 0)
{
await HandleKeysInstallation(result[0].Path.LocalPath);
}
}

public async Task InstallKeysFromFolder()
{
var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
AllowMultiple = false,
});

if (result.Count > 0)
{
await HandleKeysInstallation(result[0].Path.LocalPath);
}
}

public void OpenRyujinxFolder()
{
OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
Expand Down
4 changes: 4 additions & 0 deletions src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@
<MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarFileToolsInstallFirmwareFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" Icon="{ext:Icon mdi-folder-cog}" />
</MenuItem>
<MenuItem Header="{ext:Locale MenuBarToolsInstallKeys}" Icon="{ext:Icon fa-solid fa-key}" IsEnabled="{Binding EnableNonGameRunningControls}">
<MenuItem Command="{Binding InstallKeysFromFile}" Header="{ext:Locale MenuBarFileToolsInstallKeysFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallKeysFromFolder}" Header="{ext:Locale MenuBarFileToolsInstallKeysFromFolder}" Icon="{ext:Icon mdi-folder-cog}" />
</MenuItem>
<MenuItem Header="{ext:Locale MenuBarToolsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}">
<MenuItem Header="{ext:Locale MenuBarToolsInstallFileTypes}" Click="InstallFileTypes_Click" IsEnabled="{Binding AreMimeTypesRegistered, Converter={x:Static BoolConverters.Not}}" />
<MenuItem Header="{ext:Locale MenuBarToolsUninstallFileTypes}" Click="UninstallFileTypes_Click" IsEnabled="{Binding AreMimeTypesRegistered}" />
Expand Down

0 comments on commit 4f5af0e

Please sign in to comment.