Add rif/act method GUI

This commit is contained in:
Li 2023-04-22 15:54:29 +12:00
parent cc838ff1b5
commit c14a5cc73c
31 changed files with 817 additions and 12 deletions

2
.gitignore vendored
View File

@ -3,7 +3,7 @@
.vs/*
*.7z
*.pdn
*.user
*Thumbs.db
PbpResign/bin/*

View File

@ -214,5 +214,14 @@
<Setter.Value>1</Setter.Value>
</Setter>
</Style>
<Style Selector="Window">
<Setter Property="Background">
<Setter.Value>Black</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>Black</Setter.Value>
</Setter>
</Style>
</Application.Styles>
</Application>

View File

@ -10,10 +10,19 @@
<ItemGroup>
<None Remove=".gitignore" />
<None Remove="DEFAULTICON.PNG" />
<None Remove="Popup\Global\KeySelector\ACTRIFMETHOD.PNG" />
<None Remove="Popup\Global\KeySelector\EBOOTMETHOD.PNG" />
<None Remove="Popup\Global\KeySelector\EBOOTMETHOD1.png" />
<None Remove="Popup\Global\KeySelector\EBOOTMETHOD2.png" />
<None Remove="Popup\Global\KeySelector\KEYSTXTMETHOD.PNG" />
<None Remove="PS1CD.PNG" />
<None Remove="UMD.png" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Popup\Global\KeySelector\ACTRIFMETHOD.PNG" />
<AvaloniaResource Include="Popup\Global\KeySelector\EBOOTMETHOD1.PNG" />
<AvaloniaResource Include="Popup\Global\KeySelector\EBOOTMETHOD2.PNG" />
<AvaloniaResource Include="Popup\Global\KeySelector\KEYSTXTMETHOD.PNG" />
<AvaloniaResource Include="Ps1\PS1CD.PNG" />
<AvaloniaResource Include="Psp\UMD.PNG">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>

View File

@ -85,7 +85,10 @@ namespace ChovySign_GUI.Global
}
set
{
this.filePath.Text = value;
if (File.Exists(value))
this.filePath.Text = value;
else
this.filePath.Text = "";
}
}

View File

@ -28,7 +28,7 @@
<Label HorizontalAlignment="Left" VerticalAlignment="Center" Content="Key:" Grid.Column="0"/>
<TextBox HorizontalAlignment="Stretch" Watermark="Version Key" Name="vKey" Grid.Column="1"/>
</Grid>
<Button Name="getKeys" Content="Get Keys" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2"/>
<Button Name="getKeys" Click="getKeysClick" Content="Get Keys" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2"/>
</Grid>
</Border>
</UserControl>

View File

@ -1,12 +1,108 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using ChovySign_GUI.Popup.Global.KeySelector;
using GameBuilder.Psp;
using GameBuilder.VersionKey;
using Ionic.Zlib;
using LibChovy.Config;
using System;
using System.Net.Sockets;
using System.Text;
namespace ChovySign_GUI.Global
{
public partial class KeySelector : UserControl
{
private string licenseDataConfigKey
{
get
{
return "KEY_INDEX_" + keyIndex + "_LICENSE_DATA";
}
}
private string versionKeyConfigKey
{
get
{
return "KEY_INDEX_" + keyIndex + "_VERSION_KEY";
}
}
private int keyIndex = 1;
private void reloadCfg()
{
byte[]? licenseData = ChovyConfig.CurrentConfig.GetBytes(licenseDataConfigKey);
byte[]? vKeyData = ChovyConfig.CurrentConfig.GetBytes(versionKeyConfigKey);
if (licenseData is not null)
zRif.Text = new NpDrmRif(licenseData).ZRif;
if (vKeyData is not null)
vKey.Text = BitConverter.ToString(vKeyData).Replace("-", "");
}
private async void getKeysClick(object sender, RoutedEventArgs e)
{
Button? btn = sender as Button;
if (btn is null) return;
btn.IsEnabled = false;
Window? currentWindow = this.VisualRoot as Window;
if (currentWindow is not Window) throw new Exception("could not find current window");
KeyObtainMethods keyObt = new KeyObtainMethods();
keyObt.KeyIndex = keyIndex;
VersionKeyMethod method = await keyObt.ShowDialog<VersionKeyMethod>(currentWindow);
byte[]? key = null;
NpDrmRif? rif = null;
switch (method)
{
case VersionKeyMethod.ACT_RIF_METHOD:
ActRifMethodGUI actRifMethodGUI = new ActRifMethodGUI();
byte[][]? keys = await actRifMethodGUI.ShowDialog<byte[][]>(currentWindow);
if (keys is null) break;
key = keys[keyIndex];
rif = actRifMethodGUI.Rif;
break;
}
if (key is not null)
{
ChovyConfig.CurrentConfig.SetBytes(versionKeyConfigKey, key);
vKey.Text = BitConverter.ToString(key).Replace("-", "");
}
if (rif is not null)
{
ChovyConfig.CurrentConfig.SetBytes(licenseDataConfigKey, rif.Rif);
zRif.Text = rif.ZRif;
}
btn.IsEnabled = true;
}
public int KeyIndex
{
get
{
return keyIndex;
}
set
{
keyIndex = value;
reloadCfg();
}
}
public KeySelector()
{
InitializeComponent();
reloadCfg();
}
}
}

View File

@ -1,9 +1,46 @@
using Avalonia.Controls;
using Avalonia.Controls;
using Avalonia.Input;
using Org.BouncyCastle.Asn1.X509;
using System;
using System.Text;
namespace ChovySign_GUI.Global
{
public partial class LabeledTextBox : UserControl
{
public event EventHandler<EventArgs>? TextChanged;
private string lastTxt;
private string? allowedChars;
protected virtual void OnTextChanged(EventArgs e)
{
if (TextChanged is not null)
TextChanged(this, e);
}
public int MaxLength
{
get
{
return this.txtBox.MaxLength;
}
set
{
this.txtBox.MaxLength = value;
}
}
public bool Password
{
get
{
return this.txtBox.PasswordChar == default(char);
}
set
{
if (value) this.txtBox.PasswordChar = 'X';
else this.txtBox.PasswordChar = default(char);
}
}
public string Label
{
get
@ -29,11 +66,23 @@ namespace ChovySign_GUI.Global
this.txtBox.Watermark = value;
}
}
public string AllowedChars
{
get
{
if(allowedChars is null) return "";
return allowedChars;
}
set
{
allowedChars = value.ToUpperInvariant();
}
}
public string Text
{
get
{
if (this.txtBox.Text is null) return "";
return this.txtBox.Text;
}
set
@ -44,6 +93,27 @@ namespace ChovySign_GUI.Global
public LabeledTextBox()
{
InitializeComponent();
lastTxt = this.txtBox.Text;
allowedChars = null;
this.txtBox.KeyUp += onKeyUp;
}
private void onKeyUp(object? sender, KeyEventArgs e)
{
TextBox? txt = sender as TextBox;
if(txt is null) return;
if(allowedChars is not null)
{
StringBuilder s = new StringBuilder();
foreach (char c in txt.Text.ToUpperInvariant())
if (allowedChars.Contains(c)) s.Append(c);
txt.Text = s.ToString().ToUpperInvariant();
}
if (txt.Text != lastTxt) OnTextChanged(new EventArgs());
lastTxt = txt.Text;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,26 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Global="clr-namespace:ChovySign_GUI.Global"
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="200"
x:Class="ChovySign_GUI.Popup.Global.KeySelector.ActRifMethodGUI"
SizeToContent="Height" MinWidth="600" MinHeight="200" CanResize="False"
Title="Act/Rif Method">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Global:LabeledTextBox Name="idpsInput" MaxLength="32" AllowedChars="1234567890ABCDEF" Label="IDPS / ConsoleID:" Watermark="00000001010200140C00000000000000" Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Stretch"/>
<Global:BrowseButton Name="rifFile" Extension="rif" FileTypeName="Rights Information" Label="LICENSE.RIF: (found @ ux0:/pspemu/PSP/LICENSE)" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Stretch"/>
<Global:BrowseButton Name="actFile" Extension="dat" FileTypeName="Activation Data" Label="ACT.DAT: (found @ tm0:/npdrm/act.dat)" Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Stretch"/>
<Button Name="keyGen" Click="keyGenClick" Content="Generate Keys" Grid.Row="3" HorizontalAlignment="Center"/>
<CheckBox Name="hideConsoleId" Content="Hide ConsoleID" Grid.Row="3" VerticalAlignment="Bottom"/>
</Grid>
</Window>

View File

@ -0,0 +1,155 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using ChovySign_GUI.Global;
using GameBuilder.Psp;
using GameBuilder.VersionKey;
using Li.Utilities;
using LibChovy.Config;
using System;
using System.IO;
using static ChovySign_GUI.Popup.Global.MessageBox;
namespace ChovySign_GUI.Popup.Global.KeySelector
{
public partial class ActRifMethodGUI : Window
{
private const string keygenHideConsoleIdKey = "KEYGEN_HIDE_CONSOLEID";
private const string keygenIdpsKey = "KEYGEN_CID";
private const string keygenActKey = "KEYGEN_ACT";
private const string keygenRifKey = "KEYGEN_RIF";
private NpDrmRif? rif;
public NpDrmRif? Rif
{
get
{
return rif;
}
}
public ActRifMethodGUI()
{
bool? lastHideConsoleId = ChovyConfig.CurrentConfig.GetBool(keygenHideConsoleIdKey);
byte[]? lastCid = ChovyConfig.CurrentConfig.GetBytes(keygenIdpsKey);
string? lastAct = ChovyConfig.CurrentConfig.GetString(keygenActKey);
string? lastRif = ChovyConfig.CurrentConfig.GetString(keygenRifKey);
InitializeComponent();
// reload previous settings
if(lastHideConsoleId is not null)
{
hideConsoleId.IsChecked = lastHideConsoleId;
this.idpsInput.Password = (bool)lastHideConsoleId;
}
if (lastAct is not null)
actFile.FilePath = lastAct;
if (lastCid is not null)
idpsInput.Text = BitConverter.ToString(lastCid).Replace("-", "");
if (lastAct is not null)
actFile.FilePath = lastAct;
if (lastRif is not null)
rifFile.FilePath = lastRif;
hideConsoleId.Checked += onChangeCidState;
hideConsoleId.Unchecked += onChangeCidState;
idpsInput.TextChanged += onIdpsChange;
actFile.FileChanged += onActFileChange;
rifFile.FileChanged += onRifFileChange;
check();
}
private void onRifFileChange(object? sender, EventArgs e)
{
BrowseButton? filePth = sender as BrowseButton;
if (filePth is null) return;
if (!filePth.ContainsFile) return;
ChovyConfig.CurrentConfig.SetString(keygenRifKey, filePth.FilePath);
check();
}
private void onActFileChange(object? sender, EventArgs e)
{
BrowseButton? filePth = sender as BrowseButton;
if (filePth is null) return;
if (!filePth.ContainsFile) return;
ChovyConfig.CurrentConfig.SetString(keygenActKey, filePth.FilePath);
check();
}
private void onIdpsChange(object? sender, EventArgs e)
{
LabeledTextBox? labledTxtBox = sender as LabeledTextBox;
if (labledTxtBox is null) return;
if (labledTxtBox.Text.Length != 32) return;
try
{
byte[] idps = MathUtil.StringToByteArray(labledTxtBox.Text);
ChovyConfig.CurrentConfig.SetBytes(keygenIdpsKey, idps);
check();
}
catch{ };
}
private void keyGenClick(object sender, RoutedEventArgs e)
{
byte[][] keys = new byte[0x5][];
Window? currentWindow = this.VisualRoot as Window;
if (currentWindow is not Window) throw new Exception("could not find current window");
try
{
// read data
byte[] idps = MathUtil.StringToByteArray(idpsInput.Text);
byte[] act = File.ReadAllBytes(actFile.FilePath);
byte[] rif = File.ReadAllBytes(rifFile.FilePath);
// generate keys
for (int i = 0; i < 0x5; i++)
keys[i] = ActRifMethod.GetVersionKey(act, rif, idps, i).VersionKey;
this.rif = new NpDrmRif(rif);
this.Close(keys);
}
catch { MessageBox.Show(currentWindow, "Failed to generate key...", "Failed", MessageBoxButtons.Ok); }
}
private void check()
{
bool s = true;
if (idpsInput.Text.Length != 32) s = false;
if (!actFile.ContainsFile) s = false;
if (!rifFile.ContainsFile) s = false;
keyGen.IsEnabled = s;
}
private void onChangeCidState(object? sender, RoutedEventArgs e)
{
CheckBox? checkBox = sender as CheckBox;
if (checkBox is null) return;
bool? hideConsoleId = checkBox.IsChecked;
if (hideConsoleId is null) return;
ChovyConfig.CurrentConfig.SetBool(keygenHideConsoleIdKey, (bool)hideConsoleId);
this.idpsInput.Password = (bool)hideConsoleId;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -0,0 +1,29 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="1400" d:DesignHeight="150"
x:Class="ChovySign_GUI.Popup.Global.KeySelector.KeyObtainMethods"
Title="VersionKey Obtain Method" SizeToContent="WidthAndHeight"
MaxWidth="1400" MaxHeight="150">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="5*"/>
</Grid.RowDefinitions>
<Button Content="EBOOT.PBP Method" Click="ebootMethodClick" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Content="IDPS+RIF+ACT Method" Click="actRifMethodClick" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Content="KEYS.TXT Method" Click="keysTxtMethodClick" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Image Name="ebootMethodPs1Graphic" Source="/Popup/Global/KeySelector/EBOOTMETHOD1.PNG" Grid.Row="1" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
<Image Name="ebootMethodPspGraphic" Source="/Popup/Global/KeySelector/EBOOTMETHOD2.PNG" Grid.Row="1" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
<Image Name="actRifMethodGraphic" Source="/Popup/Global/KeySelector/ACTRIFMETHOD.PNG" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
<Image Name="keysTxtMethodGraphic" Source="/Popup/Global/KeySelector/KEYSTXTMETHOD.PNG" Grid.Row="1" Grid.Column="2" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
</Grid>
</Window>

View File

@ -0,0 +1,52 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using GameBuilder.VersionKey;
namespace ChovySign_GUI.Popup.Global.KeySelector
{
public partial class KeyObtainMethods : Window
{
private int keyIndex;
private VersionKeyMethod method;
public VersionKeyMethod Method
{
get
{
return method;
}
}
public int KeyIndex
{
set
{
keyIndex = value;
if (keyIndex == 1) { ebootMethodPspGraphic.IsVisible = false; ebootMethodPs1Graphic.IsVisible = true; }
else { ebootMethodPspGraphic.IsVisible = true; ebootMethodPs1Graphic.IsVisible = false; }
}
}
private void ebootMethodClick(object sender, RoutedEventArgs e)
{
this.method = VersionKeyMethod.EBOOT_PBP_METHOD;
this.Close(method);
}
private void actRifMethodClick(object sender, RoutedEventArgs e)
{
this.method = VersionKeyMethod.ACT_RIF_METHOD;
this.Close(method);
}
private void keysTxtMethodClick(object sender, RoutedEventArgs e)
{
this.method = VersionKeyMethod.KEYS_TXT_METHOD;
this.Close(method);
}
public KeyObtainMethods()
{
InitializeComponent();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ChovySign_GUI.Global.MessageBox" SizeToContent="WidthAndHeight" CanResize="False">
x:Class="ChovySign_GUI.Popup.Global.MessageBox" SizeToContent="WidthAndHeight" CanResize="False">
<StackPanel HorizontalAlignment="Center">
<TextBlock HorizontalAlignment="Center" Name="Text"/>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Name="Buttons">

View File

@ -3,7 +3,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
namespace ChovySign_GUI.Global
namespace ChovySign_GUI.Popup.Global
{
partial class MessageBox : Window
{

View File

@ -1,6 +1,7 @@
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using ChovySign_GUI.Global;
using ChovySign_GUI.Popup.Global;
using GameBuilder.Pops;
using LibChovy.Art;
using System;

View File

@ -20,7 +20,7 @@
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Global:KeySelector Name="keySelector" Grid.Row="0" Grid.Column="1"/>
<Global:KeySelector Name="keySelector" KeyIndex="1" Grid.Row="0" Grid.Column="1"/>
<Ps1:CueSelector Name="discSelector" Grid.Row="1" Grid.Column="1"/>
<Ps1:GameInfoSelector Name="gameInfo" Grid.Row="2" Grid.Column="1"/>

View File

@ -19,7 +19,7 @@
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Global:KeySelector Name="keySelector" Grid.Row="0" Grid.Column="1"/>
<Global:KeySelector Name="keySelector" KeyIndex="2" Grid.Row="0" Grid.Column="1"/>
<Psp:IsoSelector Name="isoSelector" Grid.Row="1" Grid.Column="1"/>
<Global:ProgressStatus Name="progressStatus" Grid.Row="2" Grid.Column="1"/>

View File

@ -80,6 +80,16 @@ namespace GameBuilder {
}
}
/// <summary>
/// Looks up a localized string similar to EP9000-NPEG00005_00-0000000000000001 51409FAC25DEAD80B44A9DAF0EB6A335 A0B1439B8E76B90AB2169978750B1E84 5AB0B5E2C32EE3BAFEF80ADE35BD7888 0B8450E063523674011C6B2B94829F7A
///.
/// </summary>
public static string KEYSTXT {
get {
return ResourceManager.GetString("KEYSTXT", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>

View File

@ -124,6 +124,9 @@
<data name="DATAPSPSDCFG" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\DATAPSPSDCFG.BIN;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="KEYSTXT" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\KEYS.TXT;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="SIMPLE" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\SIMPLE.PNG;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>

View File

@ -0,0 +1 @@
EP9000-NPEG00005_00-0000000000000001 51409FAC25DEAD80B44A9DAF0EB6A335 A0B1439B8E76B90AB2169978750B1E84 5AB0B5E2C32EE3BAFEF80ADE35BD7888 0B8450E063523674011C6B2B94829F7A

View File

@ -11,16 +11,16 @@ namespace GameBuilder.VersionKey
{
public class ActRifMethod
{
public static NpDrmInfo GetVersionKey(byte[] actDat, byte[] licenseDat, byte[] consoleId, int keyType)
public static NpDrmInfo GetVersionKey(byte[] actDat, byte[] licenseDat, byte[] consoleId, int keyIndex)
{
byte[] versionKey = new byte[0x10];
SceNpDrm.SetPSID(consoleId);
SceNpDrm.sceNpDrmGetVersionKey(versionKey, actDat, licenseDat, keyType);
SceNpDrm.sceNpDrmGetVersionKey(versionKey, actDat, licenseDat, keyIndex);
SceNpDrm.Aid = BitConverter.ToUInt64(licenseDat, 0x8);
string contentId = Encoding.UTF8.GetString(licenseDat, 0x10, 0x24);
return new NpDrmInfo(versionKey, contentId, keyType);
return new NpDrmInfo(versionKey, contentId, keyIndex);
}
}
}

View File

@ -0,0 +1,31 @@
using GameBuilder.Psp;
using Li.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameBuilder.VersionKey
{
public class KeysTxtMethod
{
public static NpDrmInfo GetVersionKey(string contentId, int keyIndex)
{
using (TextReader txt = new StringReader(Resources.KEYSTXT))
{
for(string? line = txt.ReadLine();
line is not null;
line = txt.ReadLine())
{
line = line.ReplaceLineEndings("");
string[] data = line.Split(' ');
if (data[0].Equals(contentId, StringComparison.InvariantCultureIgnoreCase))
return new NpDrmInfo(MathUtil.StringToByteArray(data[1 + keyIndex]), contentId, keyIndex);
}
}
throw new Exception("content id is not in keys.txt");
}
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameBuilder.VersionKey
{
public enum VersionKeyMethod
{
ACT_RIF_METHOD = 0,
EBOOT_PBP_METHOD = 1,
KEYS_TXT_METHOD = 3
}
}

View File

@ -15,6 +15,12 @@ namespace Li.Utilities
return larger - smaller;
}
public static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(hex.Substring(x, 2), 16)).ToArray();
}
public static int CalculatePaddingAmount(int total, int alignTo)
{
int remainder = total % alignTo;

View File

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace LibChovy.Config
{
public abstract class ChovyConfig
{
public const string PRODUCT_NAME = "Chovy-Sign2";
public const string PRODUCT_FAMILY = "CHOVYProject";
public virtual object? this[string index]
{
get
{
string? str = GetString(index);
if (str is not null) return str;
int? v = GetInt(index);
if (v is not null) return v;
byte[]? byt = GetBytes(index);
if (byt is not null) return byt;
bool? b = GetBool(index);
if (b is not null) return b;
return null;
}
set
{
if (value is string) SetString(index, (string)value);
if (value is int) SetInt(index, (int)value);
if (value is byte[]) SetBytes(index, (byte[])value);
if (value is bool) SetBool(index, (bool)value);
// idk
}
}
public abstract string? GetString(string key);
public abstract bool? GetBool(string key);
public abstract int? GetInt(string key);
public abstract byte[]? GetBytes(string key);
public abstract void SetString(string key, string value);
public abstract void SetBool(string key, bool value);
public abstract void SetInt(string key, int value);
public abstract void SetBytes(string key, byte[] value);
private static ChovyConfig? config = null;
public static ChovyConfig CurrentConfig
{
get
{
if(config is null)
{
if (OperatingSystem.IsWindows()) config = new ChovyRegistryConfig();
else config = new ChovyFileConfig();
return config;
}
else
{
return config;
}
}
}
}
}

View File

@ -0,0 +1,143 @@
using Ionic.Zlib;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibChovy.Config
{
public class ChovyFileConfig : ChovyConfig
{
private const char SEPERATOR = ',';
private static string configFileName = Path.Combine(Directory.GetCurrentDirectory(), Path.ChangeExtension(PRODUCT_NAME, ".cfg"));
private Dictionary<string, object> config;
private void saveDict()
{
using (StreamWriter cfgWriter = new StreamWriter(new ZlibStream(File.Open(configFileName, FileMode.Create, FileAccess.Write), CompressionMode.Compress)))
{
foreach(KeyValuePair<string, object> configOption in config)
{
string[] line = new string[3];
line[0] = configOption.Key.Replace(SEPERATOR.ToString(), "").ToLowerInvariant();
string? type = null;
string? value = null;
if (configOption.Value is string) { type = "string"; value = (string)(configOption.Value); }
if (configOption.Value is int) { type = "int"; value = ((int)(configOption.Value)).ToString(); };
if (configOption.Value is bool) { type = "bool"; value = (((bool)(configOption.Value)) ? "1" : "0"); }
if (configOption.Value is byte[]) { type = "byte"; value = Convert.ToBase64String(ZlibStream.CompressBuffer((byte[])configOption.Value)); }
if (type is null || value is null) continue;
line[1] = type;
line[2] = value;
cfgWriter.WriteLine(String.Join(SEPERATOR, line));
}
}
}
private void loadDict()
{
if (!File.Exists(configFileName))
saveDict();
using (StreamReader cfgReader = new StreamReader(new ZlibStream(File.Open(configFileName, FileMode.Open, FileAccess.Read), CompressionMode.Decompress)))
{
for(string? line = cfgReader.ReadLine();
line is not null;
line = cfgReader.ReadLine())
{
line = line.ReplaceLineEndings("");
string[] cfg = line.Split(SEPERATOR);
if (cfg.Length != 3) continue;
string key = cfg[0].Replace(SEPERATOR.ToString(), "").ToLowerInvariant();
string type = cfg[1];
string value = cfg[2];
try
{
switch (type)
{
case "int":
config[key] = Int32.Parse(value);
break;
case "string":
config[key] = value;
break;
case "bool":
config[key] = Int32.Parse(value) == 1;
break;
case "byte":
config[key] = ZlibStream.UncompressBuffer(Convert.FromBase64String(value));
break;
}
}
catch (Exception) { continue; }
}
}
}
public ChovyFileConfig()
{
config = new Dictionary<string, object>();
loadDict();
}
public override bool? GetBool(string key)
{
if (!config.ContainsKey(key)) return null;
return config[key] as bool?;
}
public override byte[]? GetBytes(string key)
{
if (!config.ContainsKey(key)) return null;
return config[key] as byte[];
}
public override int? GetInt(string key)
{
if (!config.ContainsKey(key)) return null;
return config[key] as int?;
}
public override string? GetString(string key)
{
if (!config.ContainsKey(key)) return null;
return config[key] as string;
}
public override void SetBool(string key, bool value)
{
config[key] = value;
saveDict();
}
public override void SetBytes(string key, byte[] value)
{
config[key] = value;
saveDict();
}
public override void SetInt(string key, int value)
{
config[key] = value;
saveDict();
}
public override void SetString(string key, string value)
{
config[key] = value;
saveDict();
}
}
}

View File

@ -0,0 +1,72 @@
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
#pragma warning disable CA1416 // Validate platform compatibility
// platform is checked in constructor, however .net seems to wants me to check again in every function, No.
namespace LibChovy.Config
{
public class ChovyRegistryConfig : ChovyConfig
{
private static string chovyKeyPath = Path.Combine("Software", PRODUCT_FAMILY, PRODUCT_NAME);
private RegistryKey chovyRegistryKey;
public ChovyRegistryConfig()
{
if (!OperatingSystem.IsWindows()) throw new PlatformNotSupportedException("Cannot use ChovyRegistryConfig on OS other than windows.");
chovyRegistryKey = Registry.CurrentUser.CreateSubKey(chovyKeyPath, true);
}
public override bool? GetBool(string key)
{
int? v = chovyRegistryKey.GetValue(key) as int?;
if (v is null) return null;
if (v == 1) return true;
if (v == 0) return false;
return null;
}
public override byte[]? GetBytes(string key)
{
return (chovyRegistryKey.GetValue(key) as byte[]);
}
public override int? GetInt(string key)
{
return (chovyRegistryKey.GetValue(key) as int?);
}
public override string? GetString(string key)
{
return (chovyRegistryKey.GetValue(key) as string);
}
public override void SetBool(string key, bool value)
{
chovyRegistryKey.SetValue(key, value ? 1 : 0, RegistryValueKind.DWord);
}
public override void SetBytes(string key, byte[] value)
{
chovyRegistryKey.SetValue(key, value, RegistryValueKind.Binary);
}
public override void SetInt(string key, int value)
{
chovyRegistryKey.SetValue(key, value, RegistryValueKind.DWord);
}
public override void SetString(string key, string value)
{
chovyRegistryKey.SetValue(key, value, RegistryValueKind.String);
}
}
}
#pragma warning restore CA1416 // Validate platform compatibility