Skip to content

Commit

Permalink
Check hashed contents of memories and saves before saving archives (#324
Browse files Browse the repository at this point in the history
)

* update AssetsService to check content hash before saving compressed screenshots or save states

* prettier filenames for achives, includes date stamp again
  • Loading branch information
jz-k authored Sep 6, 2024
1 parent 82099fe commit dbc8988
Showing 1 changed file with 56 additions and 6 deletions.
62 changes: 56 additions & 6 deletions src/services/AssetsService.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using Pannella.Helpers;

namespace Pannella.Services;

public class AssetsService
{
private const string BLACKLIST = "https://raw.githubusercontent.com/mattpannella/pupdate/main/blacklist.json";
private const string BLACKLIST =
"https://raw.githubusercontent.com/mattpannella/pupdate/main/blacklist.json";

private readonly bool useLocalBlacklist;
private List<string> blacklist;
Expand Down Expand Up @@ -46,7 +49,11 @@ public static void BackupMemories(string directory, string backupLocation)
BackupDirectory(directory, "Memories", backupLocation);
}

private static void BackupDirectory(string rootDirectory, string folderName, string backupLocation)
public static void BackupDirectory(
string rootDirectory,
string folderName,
string backupLocation
)
{
if (string.IsNullOrEmpty(rootDirectory))
{
Expand All @@ -60,22 +67,65 @@ private static void BackupDirectory(string rootDirectory, string folderName, str

Console.WriteLine($"Compressing and backing up {folderName} directory...");
string savesPath = Path.Combine(rootDirectory, folderName);
string fileName = $"{folderName}_Backup_{DateTime.Now:yyyy-MM-dd_HH.mm.ss}.zip";
string archiveName = Path.Combine(backupLocation, fileName);

if (Directory.Exists(savesPath))
{
string directoryHash = ComputeDirectoryHash(savesPath);
string truncatedHash = directoryHash.Substring(0, 8);
string dateStamp = DateTime.Now.ToString("yyyy-MM-dd_HH.mm.ss");
string fileName = $"{folderName}_Backup_{dateStamp}-version{truncatedHash}.zip";
string archiveName = Path.Combine(backupLocation, fileName);

if (!Directory.Exists(backupLocation))
{
Directory.CreateDirectory(backupLocation);
}

ZipFile.CreateFromDirectory(savesPath, archiveName);
Console.WriteLine("Complete.");
bool isDuplicateBackup = Directory
.GetFiles(backupLocation, $"{folderName}_Backup_*-version{truncatedHash}.zip")
.Any();

if (!isDuplicateBackup)
{
ZipFile.CreateFromDirectory(savesPath, archiveName);
Console.WriteLine("Complete.");
}
else
{
Console.WriteLine($"Backup with the same contents already exists, skipping...");
}
}
else
{
Console.WriteLine($"No {folderName} directory found, skipping backup...");
}
}

private static string ComputeDirectoryHash(string directoryPath)
{
using (var sha256 = SHA256.Create())
{
var allFiles = Directory
.GetFiles(directoryPath, "*.*", SearchOption.AllDirectories)
.OrderBy(p => p)
.ToList();

var hashBuilder = new StringBuilder();

foreach (var filePath in allFiles)
{
byte[] fileBytes = File.ReadAllBytes(filePath);
byte[] hashBytes = sha256.ComputeHash(fileBytes);

hashBuilder.Append(
BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant()
);
}

byte[] finalHashBytes = sha256.ComputeHash(
Encoding.UTF8.GetBytes(hashBuilder.ToString())
);
return BitConverter.ToString(finalHashBytes).Replace("-", "").ToLowerInvariant();
}
}
}

0 comments on commit dbc8988

Please sign in to comment.