调整repack处理逻辑

This commit is contained in:
Chenx221 2024-10-08 12:33:19 +08:00
parent 31e0439b87
commit f23d1b5653

View File

@ -1,4 +1,6 @@
using System.Text; using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using MimeDetective; using MimeDetective;
@ -29,7 +31,7 @@ namespace LightvnTools
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Usage:"); Console.WriteLine("Usage:");
Console.WriteLine(" Unpack: -u (-r) <folder>"); Console.WriteLine(" Unpack: -u (-r) <folder>");
Console.WriteLine(" Repack: -p <folder>"); Console.WriteLine(" Repack: -p <folder> (-k)");
Console.ReadKey(); Console.ReadKey();
return; return;
} }
@ -63,7 +65,7 @@ namespace LightvnTools
{ {
if (IsVndat(file)) if (IsVndat(file))
{ {
UnpackVndat(file, Path.GetFileNameWithoutExtension(file), zipPassword); UnpackVndat(file, Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(file)), zipPassword);
} }
else if (Path.GetExtension(file).Contains("mcdat")) else if (Path.GetExtension(file).Contains("mcdat"))
{ {
@ -90,20 +92,45 @@ namespace LightvnTools
{ {
if (Directory.Exists(args[1])) if (Directory.Exists(args[1]))
{ {
RepackVndat(args[1], zipPassword); var packDirectory = Path.Combine(Path.GetDirectoryName(args[1]), "pack");
GetFilesRecursive(args[1]).ToList().ForEach(path =>
if (!Directory.Exists(packDirectory))
{ {
if (path.Contains("mcdat")) Directory.CreateDirectory(packDirectory);
{
Console.WriteLine($"Decrypting {path}...");
XOR(path, $"{path}.dec");
} }
else if (path.Contains("dec"))
string[] files = Directory.GetFiles(args[1]);
string[] directories = Directory.GetDirectories(args[1]);
// mcdat
foreach (string file in files)
{ {
Console.WriteLine($"Encrypting {path}..."); string fileName = Path.GetFileName(file);
XOR(path, path.Replace("dec", "enc"));
if (Regex.IsMatch(fileName, @"^\d+\.mcdat\.dec$") ||
(Regex.IsMatch(fileName, @"^\d+\.\w+$") && !fileName.EndsWith(".mcdat", StringComparison.OrdinalIgnoreCase)))
{
Console.WriteLine($"Pack mcdat file: {file}");
string numberPart = Regex.Match(fileName, @"^\d+").Value;
string decryptedFileName = Path.Combine(packDirectory, numberPart + ".mcdat");
XOR(file, decryptedFileName);
}
}
// vndat
foreach (string directory in directories)
{
Console.WriteLine($"Found directory: {directory}");
string outputFile = Path.Combine(packDirectory, Path.GetFileName(directory) + ".vndat");
if (args.Length < 3) //no pwd
{
RepackVndat(directory, outputFile);
}
else if (args[2] == "-k") //pwd
{
RepackVndat(directory, outputFile, zipPassword);
}
} }
});
} }
else else
{ {
@ -154,36 +181,27 @@ namespace LightvnTools
try try
{ {
Console.WriteLine($"Writing {entryPath}..."); Console.WriteLine($"Writing {entryPath}...");
using Stream inputStream = zipFile.GetInputStream(entry); using Stream inputStream = zipFile.GetInputStream(entry);
using FileStream outputStream = File.Create(entryPath); using FileStream outputStream = File.Create(entryPath);
if (usePassword)
{
inputStream.CopyTo(outputStream); inputStream.CopyTo(outputStream);
} }
else
{
using MemoryStream memoryStream = new();
inputStream.CopyTo(memoryStream);
byte[] buffer = XOR(memoryStream.ToArray());
outputStream.Write(buffer, 0, buffer.Length);
}
}
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Failed to write {entryPath}! {ex.Message}"); Console.WriteLine($"Failed to write {entryPath}! {ex.Message}");
} }
} }
} }
Console.WriteLine("Done.");
}
// Only XOR the `.vndat` contents if the archive is not password protected.
if (!usePassword)
{
string[] files = GetFilesRecursive(outputFolder);
if (files.Length > 0)
{
foreach (string file in files)
{
Console.WriteLine($"XORing {file}...");
XOR(file);
}
Console.WriteLine("Done.");
}
} }
} }
@ -192,24 +210,18 @@ namespace LightvnTools
/// </summary> /// </summary>
/// <param name="sourceFolder"></param> /// <param name="sourceFolder"></param>
/// <param name="password"></param> /// <param name="password"></param>
static void RepackVndat(string sourceFolder, string? password = "") static void RepackVndat(string sourceFolder, string outputFile, string? password = "")
{ {
string outputFile = $"{Path.GetFileName(sourceFolder)}.vndat";
string[] files = GetFilesRecursive(sourceFolder); string[] files = GetFilesRecursive(sourceFolder);
string? tempFolder = $"{sourceFolder}_temp"; string? tempFolder = $"{sourceFolder}_temp";
if (Directory.Exists(tempFolder))
// Only backup original file once
string backupFile = $"{outputFile}.bak";
if (!File.Exists(backupFile))
{ {
Console.WriteLine($"Backup the original file as {Path.GetFileName(backupFile)}..."); Directory.Delete(tempFolder, true);
File.Copy(outputFile, backupFile);
} }
bool usePassword = !string.IsNullOrEmpty(password);
bool usePassword = IsPasswordProtectedZip(backupFile);
using ZipOutputStream zipStream = new(File.Create(outputFile)); using ZipOutputStream zipStream = new(File.Create(outputFile));
zipStream.SetLevel(0);
// Uses the backup file to check if it's encrypted to bypass // Uses the backup file to check if it's encrypted to bypass
// the file is being used by another process exception. // the file is being used by another process exception.
if (usePassword) if (usePassword)
@ -221,13 +233,17 @@ namespace LightvnTools
{ {
Console.WriteLine($"Creating a temporary copy of {Path.GetFileName(sourceFolder)} to perform XOR encryption..."); Console.WriteLine($"Creating a temporary copy of {Path.GetFileName(sourceFolder)} to perform XOR encryption...");
CopyFolder(sourceFolder, tempFolder);
files = GetFilesRecursive(tempFolder);
foreach (string file in files) foreach (string file in files)
{ {
Console.WriteLine($"Encrypting {Path.GetRelativePath(sourceFolder, file)}..."); string tempFilePath = Path.Combine(tempFolder, Path.GetRelativePath(sourceFolder, file));
XOR(file); string directory = Path.GetDirectoryName(tempFilePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
byte[] processedData = XOR(File.ReadAllBytes(file));
File.WriteAllBytes(tempFilePath, processedData);
files = GetFilesRecursive(tempFolder);
} }
} }
@ -246,7 +262,7 @@ namespace LightvnTools
zipStream.PutNextEntry(entry); zipStream.PutNextEntry(entry);
using FileStream fileStream = file.OpenRead(); using FileStream fileStream = file.OpenRead();
byte[] buffer = new byte[4096]; // Optimum size byte[] buffer = new byte[8192]; // Optimum size
int bytesRead; int bytesRead;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0) while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{ {