boop
This commit is contained in:
parent
6266ec0fed
commit
fb17a80a37
295
src/common/Haru.ByteBanger.ts
Normal file
295
src/common/Haru.ByteBanger.ts
Normal file
@ -0,0 +1,295 @@
|
||||
export enum DiffResultType
|
||||
{
|
||||
Success = 0,
|
||||
OriginalFilePathInvalid,
|
||||
OriginalFileNotFound,
|
||||
OriginalFileReadFailed,
|
||||
PatchedFilePathInvalid,
|
||||
PatchedFileNotFound,
|
||||
PatchedFileReadFailed,
|
||||
FilesMatch
|
||||
}
|
||||
|
||||
export enum PatchResultType
|
||||
{
|
||||
Success = 0,
|
||||
InputLengthMismatch,
|
||||
InputChecksumMismatch,
|
||||
AlreadyPatched,
|
||||
OutputChecksumMismatch
|
||||
}
|
||||
|
||||
export class PatchItem
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
export class PatchInfo
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
class DiffResult
|
||||
{
|
||||
public readonly Result: DiffResultType
|
||||
public readonly PatchInfo: PatchInfo
|
||||
|
||||
public constructor(result: DiffResultType, patchInfo: PatchInfo)
|
||||
{
|
||||
this.Result = result;
|
||||
this.PatchInfo = patchInfo;
|
||||
}
|
||||
}
|
||||
|
||||
export class PatchResult
|
||||
{
|
||||
public readonly Result: PatchResultType
|
||||
public readonly PatchedData: Uint8Array
|
||||
|
||||
public constructor(result: PatchResultType, patchedData: Uint8Array)
|
||||
{
|
||||
this.Result = result;
|
||||
this.PatchedData = patchedData;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public class PatchItem
|
||||
{
|
||||
public int Offset { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public static PatchItem FromReader(BinaryReader br)
|
||||
{
|
||||
int offset = br.ReadInt32();
|
||||
int dataLength = br.ReadInt32();
|
||||
byte[] data = br.ReadBytes(dataLength);
|
||||
|
||||
return new PatchItem
|
||||
{
|
||||
Offset = offset,
|
||||
Data = data
|
||||
};
|
||||
}
|
||||
|
||||
internal void ToWriter(BinaryWriter bw)
|
||||
{
|
||||
// offset // 4B
|
||||
bw.Write(Offset);
|
||||
|
||||
// length // 4B
|
||||
bw.Write(Data.Length);
|
||||
|
||||
// data // xB
|
||||
bw.Write(Data, 0, Data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public class PatchInfo
|
||||
{
|
||||
public const string BYBA = "BYBA";
|
||||
public byte[] OriginalChecksum { get; set; }
|
||||
public int OriginalLength { get; set; }
|
||||
public byte[] PatchedChecksum { get; set; }
|
||||
public int PatchedLength { get; set; }
|
||||
public PatchItem[] Items { get; set; }
|
||||
|
||||
public static PatchInfo FromBytes(byte[] bytes)
|
||||
{
|
||||
if (bytes.Length < 82) throw new Exception("Input data too short, cannot be a valid patch");
|
||||
|
||||
PatchInfo pi = new PatchInfo();
|
||||
|
||||
using (MemoryStream ms = new MemoryStream(bytes))
|
||||
using (BinaryReader br = new BinaryReader(ms))
|
||||
{
|
||||
byte[] buf = null;
|
||||
|
||||
buf = br.ReadBytes(4);
|
||||
if (Encoding.ASCII.GetString(buf) != BYBA) throw new Exception("Invalid identifier");
|
||||
|
||||
if (br.ReadByte() != 1) throw new Exception("Invalid major file version (1 expected)");
|
||||
if (br.ReadByte() != 0) throw new Exception("Invalid minor file version (0 expected)");
|
||||
|
||||
pi.OriginalLength = br.ReadInt32();
|
||||
pi.OriginalChecksum = br.ReadBytes(32);
|
||||
pi.PatchedLength = br.ReadInt32();
|
||||
pi.PatchedChecksum = br.ReadBytes(32);
|
||||
|
||||
int itemCount = br.ReadInt32();
|
||||
|
||||
List<PatchItem> items = new List<PatchItem>();
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
items.Add(PatchItem.FromReader(br));
|
||||
pi.Items = items.ToArray();
|
||||
}
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
public byte[] ToBytes()
|
||||
{
|
||||
byte[] data;
|
||||
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(ms, Encoding.ASCII, true))
|
||||
{
|
||||
// identifier "BYBA" // 4B
|
||||
byte[] byba = Encoding.ASCII.GetBytes(BYBA);
|
||||
bw.Write(byba, 0, byba.Length);
|
||||
|
||||
// version "1.0" // 2B
|
||||
bw.Write((byte)1);
|
||||
bw.Write((byte)0);
|
||||
|
||||
// original len // 4B
|
||||
bw.Write(OriginalLength);
|
||||
|
||||
// original chk // 32B
|
||||
bw.Write(OriginalChecksum, 0, OriginalChecksum.Length);
|
||||
|
||||
// patched len // 4B
|
||||
bw.Write(PatchedLength);
|
||||
|
||||
// patched chk // 32B
|
||||
bw.Write(PatchedChecksum, 0, PatchedChecksum.Length);
|
||||
|
||||
// item count // 4B
|
||||
bw.Write(Items.Length);
|
||||
|
||||
// data
|
||||
foreach (PatchItem pi in Items)
|
||||
pi.ToWriter(bw);
|
||||
}
|
||||
|
||||
data = new byte[ms.Length];
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
ms.Read(data, 0, (int)ms.Length);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PatchUtil
|
||||
{
|
||||
public static DiffResult Diff(byte[] original, byte[] patched)
|
||||
{
|
||||
PatchInfo pi = new PatchInfo
|
||||
{
|
||||
OriginalLength = original.Length,
|
||||
PatchedLength = patched.Length
|
||||
};
|
||||
|
||||
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
|
||||
{
|
||||
pi.OriginalChecksum = sha256.ComputeHash(original);
|
||||
pi.PatchedChecksum = sha256.ComputeHash(patched);
|
||||
}
|
||||
|
||||
if ((pi.OriginalLength == pi.PatchedLength) && ArraysMatch(pi.OriginalChecksum, pi.PatchedChecksum))
|
||||
return new DiffResult(DiffResultType.FilesMatch, null);
|
||||
|
||||
int minLength = Math.Min(pi.OriginalLength, pi.PatchedLength);
|
||||
|
||||
List<PatchItem> items = new List<PatchItem>();
|
||||
List<byte> currentData = null;
|
||||
int diffOffsetStart = 0;
|
||||
|
||||
for (int i = 0; i < minLength; i++)
|
||||
{
|
||||
if (original[i] != patched[i])
|
||||
{
|
||||
if (currentData == null)
|
||||
{
|
||||
diffOffsetStart = i;
|
||||
currentData = new List<byte>();
|
||||
}
|
||||
|
||||
currentData.Add(patched[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentData != null)
|
||||
items.Add(new PatchItem { Offset = diffOffsetStart, Data = currentData.ToArray() });
|
||||
|
||||
currentData = null;
|
||||
diffOffsetStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentData != null)
|
||||
items.Add(new PatchItem { Offset = diffOffsetStart, Data = currentData.ToArray() });
|
||||
|
||||
if (pi.PatchedLength > pi.OriginalLength)
|
||||
{
|
||||
byte[] buf = new byte[pi.PatchedLength - pi.OriginalLength];
|
||||
Array.Copy(patched, pi.OriginalLength, buf, 0, buf.Length);
|
||||
items.Add(new PatchItem { Offset = pi.OriginalLength, Data = buf });
|
||||
}
|
||||
|
||||
pi.Items = items.ToArray();
|
||||
|
||||
return new DiffResult(DiffResultType.Success, pi);
|
||||
}
|
||||
|
||||
public static DiffResult Diff(string originalFile, string patchedFile)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(originalFile)) return new DiffResult(DiffResultType.OriginalFilePathInvalid, null);
|
||||
if (string.IsNullOrWhiteSpace(patchedFile)) return new DiffResult(DiffResultType.PatchedFilePathInvalid, null);
|
||||
if (!File.Exists(originalFile)) return new DiffResult(DiffResultType.OriginalFileNotFound, null);
|
||||
if (!File.Exists(patchedFile)) return new DiffResult(DiffResultType.PatchedFileNotFound, null);
|
||||
|
||||
byte[] originalData, patchedData;
|
||||
|
||||
try { originalData = File.ReadAllBytes(originalFile); }
|
||||
catch { return new DiffResult(DiffResultType.OriginalFileReadFailed, null); }
|
||||
|
||||
try { patchedData = File.ReadAllBytes(patchedFile); }
|
||||
catch { return new DiffResult(DiffResultType.PatchedFileReadFailed, null); }
|
||||
|
||||
return Diff(originalData, patchedData);
|
||||
}
|
||||
|
||||
public static PatchResult Patch(byte[] input, PatchInfo pi)
|
||||
{
|
||||
byte[] inputHash;
|
||||
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
|
||||
{
|
||||
inputHash = sha256.ComputeHash(input);
|
||||
}
|
||||
|
||||
if (ArraysMatch(inputHash, pi.PatchedChecksum)) return new PatchResult(PatchResultType.AlreadyPatched, null);
|
||||
if (!ArraysMatch(inputHash, pi.OriginalChecksum)) return new PatchResult(PatchResultType.InputChecksumMismatch, null);
|
||||
if (input.Length != pi.OriginalLength) return new PatchResult(PatchResultType.InputLengthMismatch, null);
|
||||
|
||||
byte[] patchedData = new byte[pi.PatchedLength];
|
||||
long minLen = Math.Min(pi.OriginalLength, pi.PatchedLength);
|
||||
Array.Copy(input, patchedData, minLen);
|
||||
|
||||
foreach (PatchItem itm in pi.Items)
|
||||
Array.Copy(itm.Data, 0, patchedData, itm.Offset, itm.Data.Length);
|
||||
|
||||
byte[] patchedHash;
|
||||
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
|
||||
{
|
||||
patchedHash = sha256.ComputeHash(patchedData);
|
||||
}
|
||||
|
||||
if (!ArraysMatch(patchedHash, pi.PatchedChecksum)) return new PatchResult(PatchResultType.OutputChecksumMismatch, null);
|
||||
|
||||
return new PatchResult(PatchResultType.Success, patchedData);
|
||||
}
|
||||
|
||||
private static bool ArraysMatch(byte[] a, byte[] b)
|
||||
{
|
||||
if (a.Length != b.Length) return false;
|
||||
|
||||
for (int i = 0; i < a.Length; i++)
|
||||
if (a[i] != b[i]) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
@ -83,6 +83,9 @@ export class NotificationServer implements IServer
|
||||
const message = Json.serialize(new PingNotificationModel());
|
||||
this.httpServer = new HttpServer("localhost", 8001);
|
||||
this.wsServer = new WsServer(this.httpServer, message);
|
||||
|
||||
// add cached responses
|
||||
// this.server.addService(url, cachedResponseService);
|
||||
}
|
||||
|
||||
public start(): void
|
||||
|
Loading…
x
Reference in New Issue
Block a user