83 lines
2.6 KiB
C#
83 lines
2.6 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text.RegularExpressions;
|
||
|
||
namespace TinfoilVibeServer.Utilities;
|
||
|
||
/// <summary>
|
||
/// Streams a multipart RAR as a single, seekable stream.
|
||
/// Supports:
|
||
/// • myGame.rar (single volume)
|
||
/// • myGame.r00 / r01 … (RAR 4.x style)
|
||
/// • myGame.part01.rar … (WinRAR “part” style)
|
||
/// </summary>
|
||
public static class MultiPartRarHelper
|
||
{
|
||
public static string GetBaseNameForRarVolume(string fileName)
|
||
{
|
||
string baseName = string.Empty;
|
||
// Multipart – remove the ".rNN" or ".partNN" suffix
|
||
var m = Regex.Match(fileName,
|
||
@"^(?<base>.+?)(\.r\d\d|\.part\d\d)\.rar$",
|
||
RegexOptions.IgnoreCase);
|
||
if (!m.Success)
|
||
{
|
||
if (fileName.EndsWith(".rar", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
// Single‑volume archive – just drop the suffix
|
||
baseName = fileName.Substring(0, fileName.Length - 4);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
baseName = m.Groups["base"].Value;
|
||
}
|
||
return baseName;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Returns the list of files that belong to the same multipart set.
|
||
/// </summary>
|
||
public static List<string> DiscoverVolumes(string dir, string baseName)
|
||
{
|
||
// Pattern: <base>.(rar | rNN | partNN.rar)
|
||
string pattern =
|
||
$@"^{Regex.Escape(baseName)}(\.rar|\.r\d\d|\.part\d\d\.rar)$";
|
||
|
||
return Directory.GetFiles(dir)
|
||
.Where(f => Regex.IsMatch(Path.GetFileName(f), pattern, RegexOptions.IgnoreCase))
|
||
.OrderBy(f => GetPartNumber(Path.GetFileName(f), baseName))
|
||
.ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gives each file a numeric key that guarantees the correct order.
|
||
/// 0 → .rar (first volume)
|
||
/// 1 → .r00 or .part01
|
||
/// 2 → .r01 or .part02
|
||
/// … and so on.
|
||
/// </summary>
|
||
private static int GetPartNumber(string fileName, string baseName)
|
||
{
|
||
// 1️⃣ ".rar" → 0
|
||
if (fileName.Equals($"{baseName}.rar", StringComparison.OrdinalIgnoreCase))
|
||
return 0;
|
||
|
||
// 2️⃣ ".rNN" or ".partNN.rar"
|
||
var m = Regex.Match(fileName,
|
||
$@"\.r(?<num>\d\d)$|\.part(?<num>\d\d)\.rar$",
|
||
RegexOptions.IgnoreCase);
|
||
|
||
if (m.Success)
|
||
{
|
||
int partNum = int.Parse(m.Groups["num"].Value);
|
||
return partNum + 1; // so r00 → 1, r01 → 2; part01 → 1, part02 → 2
|
||
}
|
||
|
||
// 3️⃣ unknown pattern – treat as first part
|
||
return 0;
|
||
}
|
||
|
||
} |