From 8e45432aab96f8693a317f01de1345bedd9726a1 Mon Sep 17 00:00:00 2001
From: Deterous <138427222+Deterous@users.noreply.github.com>
Date: Sat, 3 Feb 2024 23:15:13 +0900
Subject: [PATCH] Throw error for BD-Video hybrid discs without layerbreak
---
IRDKit/Program.cs | 155 +++++++++++++++++++++++++++++-----------------
LibIRD/IRD.cs | 1 -
LibIRD/ReIRD.cs | 82 ++++++++++++------------
3 files changed, 137 insertions(+), 101 deletions(-)
diff --git a/IRDKit/Program.cs b/IRDKit/Program.cs
index d200115..dac7e36 100644
--- a/IRDKit/Program.cs
+++ b/IRDKit/Program.cs
@@ -174,21 +174,16 @@ namespace IRDKit
return;
}
- // Only one ISO is being processed
- if (!string.IsNullOrEmpty(opt.IRDPath) && opt.ISOPath.Count() == 1)
- {
- // Save to given output path and filename, if only 1 IRD is being created
- string irdPath = ISO2IRD(isoPath, irdPath: opt.IRDPath, hexKey: opt.Key, keyPath: opt.KeyFile, getKeyLog: opt.GetKeyLog, layerbreak: opt.Layerbreak, verbose: opt.Verbose);
- if (irdPath != null)
- Console.WriteLine($"IRD saved to {irdPath}");
- }
+ string irdPath;
+ // Save to given output path and filename, if only 1 IRD is being created
+ if (opt.ISOPath.Count() == 1)
+ irdPath = ISO2IRD(isoPath, irdPath: opt.IRDPath, hexKey: opt.Key, keyPath: opt.KeyFile, getKeyLog: opt.GetKeyLog, layerbreak: opt.Layerbreak, verbose: opt.Verbose);
+ // Save to given output path, if more than 1 IRD is being created
else
- {
- // Save to given output path, if more than 1 IRD is being created
- string irdPath = ISO2IRD(isoPath, irdPath: Path.GetDirectoryName(opt.IRDPath), verbose: opt.Verbose);
- if (irdPath != null)
- Console.WriteLine($"IRD saved to {irdPath}");
- }
+ irdPath = ISO2IRD(isoPath, irdPath: Path.GetDirectoryName(opt.IRDPath), verbose: opt.Verbose);
+
+ if (irdPath != null)
+ Console.WriteLine($"IRD saved to {irdPath}");
}
}
@@ -661,7 +656,16 @@ namespace IRDKit
public static string ISO2IRD(string isoPath, string irdPath = null, string hexKey = null, string keyPath = null, string getKeyLog = null, long? layerbreak = null, bool verbose = false)
{
// Check file exists
- FileInfo iso = new(isoPath);
+ FileInfo iso;
+ try
+ {
+ iso = new(isoPath);
+ }
+ catch (Exception e)
+ {
+ Console.Error.WriteLine(e.Message + ", failed to create IRD");
+ return null;
+ }
if (!iso.Exists)
{
Console.Error.WriteLine($"{nameof(isoPath)} is not a valid file or directory");
@@ -685,18 +689,21 @@ namespace IRDKit
// Get disc key from hex string
byte[] discKey = Convert.FromHexString(hexKey);
if (discKey == null || discKey.Length != 16)
- throw new ArgumentException(hexKey);
-
- Console.WriteLine($"Creating {irdPath} with Key: {hexKey}");
- IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
- ird1.Write(irdPath);
- if (verbose)
- ird1.Print();
- return irdPath;
+ Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
+ else
+ {
+ Console.WriteLine($"Creating {irdPath} with Key: {hexKey}");
+ IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
+ ird1.Write(irdPath);
+ if (verbose)
+ ird1.Print();
+ return irdPath;
+ }
}
- catch (ArgumentException)
+ catch (ArgumentException e)
{
- Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
+ Console.Error.WriteLine(e.Message + ", failed to create IRD");
+ return null;
}
catch (FileNotFoundException)
{
@@ -708,20 +715,26 @@ namespace IRDKit
// Create new reproducible redump-style IRD with a given key file
if (keyPath != null)
{
- // Read key from .key file
- byte[] discKey = File.ReadAllBytes(keyPath);
try
{
- IRD ird2 = new ReIRD(isoPath, discKey, layerbreak);
- Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}");
- ird2.Write(irdPath);
- if (verbose)
- ird2.Print();
- return irdPath;
+ // Read key from .key file
+ byte[] discKey = File.ReadAllBytes(keyPath);
+ if (discKey == null || discKey.Length != 16)
+ Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
+ else
+ {
+ IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
+ Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}");
+ ird1.Write(irdPath);
+ if (verbose)
+ ird1.Print();
+ return irdPath;
+ }
}
- catch (ArgumentException)
+ catch (ArgumentException e)
{
- Console.Error.WriteLine($"{Convert.ToHexString(discKey)} is not a valid key, detecting key automatically...");
+ Console.Error.WriteLine(e.Message + ", failed to create IRD");
+ return null;
}
catch (FileNotFoundException)
{
@@ -736,12 +749,17 @@ namespace IRDKit
try
{
Console.WriteLine($"Creating {irdPath} with key from: {getKeyLog}");
- IRD ird3 = new ReIRD(isoPath, getKeyLog);
- ird3.Write(irdPath);
+ IRD ird1 = new ReIRD(isoPath, getKeyLog);
+ ird1.Write(irdPath);
if (verbose)
- ird3.Print();
+ ird1.Print();
return irdPath;
}
+ catch (ArgumentException e)
+ {
+ Console.Error.WriteLine(e.Message + ", failed to create IRD");
+ return null;
+ }
catch (FileNotFoundException)
{
Console.Error.WriteLine("File not found, failed to create IRD");
@@ -758,20 +776,23 @@ namespace IRDKit
try
{
// Read key from .key file
- byte[] discKey = File.ReadAllBytes(keyfilePath);
+ byte[] discKey = File.ReadAllBytes(keyPath);
if (discKey == null || discKey.Length != 16)
- throw new ArgumentException(keyfilePath);
-
- Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}");
- IRD ird2 = new ReIRD(isoPath, discKey, layerbreak);
- ird2.Write(irdPath);
- if (verbose)
- ird2.Print();
- return irdPath;
+ Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
+ else
+ {
+ IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
+ Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}");
+ ird1.Write(irdPath);
+ if (verbose)
+ ird1.Print();
+ return irdPath;
+ }
}
- catch (ArgumentException)
+ catch (ArgumentException e)
{
- Console.Error.WriteLine("Given key file not valid, detecting key automatically...");
+ Console.Error.WriteLine(e.Message + ", failed to create IRD");
+ return null;
}
catch (FileNotFoundException)
{
@@ -788,13 +809,18 @@ namespace IRDKit
// Found .getkey.log file, check it is valid
try
{
- Console.WriteLine($"Creating {irdPath} with key from: {logfilePath}");
- IRD ird3 = new ReIRD(isoPath, logfilePath);
- ird3.Write(irdPath);
+ Console.WriteLine($"Creating {irdPath} with key from: {getKeyLog}");
+ IRD ird1 = new ReIRD(isoPath, getKeyLog);
+ ird1.Write(irdPath);
if (verbose)
- ird3.Print();
+ ird1.Print();
return irdPath;
}
+ catch (ArgumentException e)
+ {
+ Console.Error.WriteLine(e.Message + ", failed to create IRD");
+ return null;
+ }
catch (FileNotFoundException)
{
Console.Error.WriteLine("File not found, failed to create IRD");
@@ -868,11 +894,24 @@ namespace IRDKit
// Create IRD with key from redump
Console.WriteLine($"Creating {irdPath} with Key from redump.org: {Convert.ToHexString(key)}");
- IRD ird = new ReIRD(isoPath, key, layerbreak);
- ird.Write(irdPath);
- if (verbose)
- ird.Print();
- return irdPath;
+ try
+ {
+ IRD ird = new ReIRD(isoPath, key, layerbreak);
+ ird.Write(irdPath);
+ if (verbose)
+ ird.Print();
+ return irdPath;
+ }
+ catch (ArgumentException e)
+ {
+ Console.Error.WriteLine(e.Message + ", failed to create IRD");
+ return null;
+ }
+ catch (FileNotFoundException)
+ {
+ Console.Error.WriteLine("File not found, failed to create IRD");
+ return null;
+ }
}
#endregion
diff --git a/LibIRD/IRD.cs b/LibIRD/IRD.cs
index 9e4151c..6e5b3aa 100644
--- a/LibIRD/IRD.cs
+++ b/LibIRD/IRD.cs
@@ -539,7 +539,6 @@ namespace LibIRD
///
private protected void ParseGetKeyLog(string getKeyLog)
{
-
// Validate .getkey.log file path
ArgumentNullException.ThrowIfNull(getKeyLog, nameof(getKeyLog));
if (!File.Exists(getKeyLog))
diff --git a/LibIRD/ReIRD.cs b/LibIRD/ReIRD.cs
index be742fe..8b73594 100644
--- a/LibIRD/ReIRD.cs
+++ b/LibIRD/ReIRD.cs
@@ -1,6 +1,8 @@
-using System;
+using DiscUtils.Iso9660;
+using System;
using System.IO;
using System.IO.Hashing;
+using System.Security;
namespace LibIRD
{
@@ -51,15 +53,6 @@ namespace LibIRD
///
public class ReIRD : IRD
{
- #region Properties
-
- ///
- /// ISO file size
- ///
- private long Size { get; set; }
-
- #endregion
-
#region Constructors
///
@@ -67,25 +60,11 @@ namespace LibIRD
///
/// Path to the ISO
/// Path to the GetKey log file
- /// Layerbreak value, in sectors
///
- public ReIRD(string isoPath, string getKeyLog, long? layerbreak = null) : base(isoPath, getKeyLog, true)
+ public ReIRD(string isoPath, string getKeyLog) : base(isoPath, getKeyLog, true)
{
// Generate Unique Identifier using ISO CRC32
UID = GenerateUID(isoPath);
-
- // Determine ISO file size
- Size = CalculateSize(isoPath);
-
- // Generate Data 2 using Disc ID
- DiscID = GenerateID(Size);
-
- // Generate Disc PIC
- byte[] pic = GeneratePIC(Size, layerbreak * SectorSize);
-
- // Check that GetKey log matches expected PIC
- if (!((ReadOnlySpan)PIC).SequenceEqual(pic))
- throw new InvalidDataException("Unexpected PIC in .getkey.log");
}
///
@@ -101,16 +80,16 @@ namespace LibIRD
UID = GenerateUID(isoPath);
// Determine ISO file size
- Size = CalculateSize(isoPath);
+ long size = CalculateSize(isoPath);
// Set Disc Key
DiscKey = key;
// Generate Data 2 using Disc ID
- DiscID = GenerateID(Size, region);
+ DiscID = GenerateID(size, region);
// Generate Disc PIC
- PIC = GeneratePIC(Size, layerbreak * SectorSize);
+ PIC = GeneratePIC(isoPath, size, layerbreak * SectorSize);
// Generate IRD fields
GenerateIRD(isoPath, true);
@@ -143,12 +122,13 @@ namespace LibIRD
/// Layer break value, byte at which disc layers are split across
/// True to generate a PIC in 3k3y style (0x03 at 115th byte for BD-50 discs)
///
- private static byte[] GeneratePIC(long size, long? layerbreak = null, bool exactIRD = false)
+ private static byte[] GeneratePIC(string isoPath, long size, long? layerbreak = null, bool exactIRD = false)
{
// Validate size
if (size <= 0 || (size % SectorSize) != 0)
throw new ArgumentException("ISO Size in bytes must be a positive integer multiple of 2048", nameof(size));
- // Validate layerbreak
+
+ // Validate provided layerbreak
if (layerbreak != null)
{
if (layerbreak <= 0 || (layerbreak >= size))
@@ -156,8 +136,16 @@ namespace LibIRD
if (layerbreak >= 2 * BDLayerSize || layerbreak % SectorSize != 0)
throw new ArgumentException("Unexpected layerbreak value", nameof(size));
}
- // If layerbreak value was not set, assume it is a non-hybrid disc with default layerbreak
- long layer_break = layerbreak ?? BDLayerSize;
+ else
+ {
+ // If no layerbreak provided, ensure ISO is not BD-Video hybrid
+ using FileStream fs = new FileStream(isoPath, FileMode.Open, FileAccess.Read) ?? throw new FileNotFoundException(isoPath);
+ CDReader reader = new(fs, true, true);
+ if (reader.DirectoryExists("\\BDMV"))
+ throw new ArgumentException("Layerbreak must be provided for BD-Video hybrid discs");
+ // Assume disc has default layerbreak
+ layerbreak = BDLayerSize;
+ }
// Generate the PIC based on the size and layerbreak of the ISO
byte[] pic;
@@ -167,7 +155,7 @@ namespace LibIRD
long l0_start_sector = 1048576;
// Layer 0 end sector = start sector + layerbreak - 2
- long l0_end_sector = (layer_break / SectorSize) + l0_start_sector - 2;
+ long l0_end_sector = ((long)layerbreak / SectorSize) + l0_start_sector - 2;
// Convert end sector location to hex values for PIC
byte[] l0es = [(byte)((l0_end_sector >> 24) & 0xFF),
(byte)((l0_end_sector >> 16) & 0xFF),
@@ -175,7 +163,7 @@ namespace LibIRD
(byte)((l0_end_sector >> 0) & 0xFF)];
// Layer 1 start sector = end of disc (0x01EFFFFE) - layerbreak + 2
- long l1_start_sector = 32505854 - (layer_break / SectorSize) + 2;
+ long l1_start_sector = 32505854 - ((long)layerbreak! / SectorSize) + 2;
// Convert start of start sector location to hex values for PIC
byte[] l1ss = [(byte)((l1_start_sector >> 24) & 0xFF),
(byte)((l1_start_sector >> 16) & 0xFF),
@@ -257,11 +245,16 @@ namespace LibIRD
///
private static uint GenerateUID(string isoPath)
{
- // Validate ISO path
- ArgumentNullException.ThrowIfNull(isoPath, nameof(isoPath));
-
// Check file exists
- var iso = new FileInfo(isoPath);
+ FileInfo iso;
+ try
+ {
+ iso = new FileInfo(isoPath);
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("Invalid ISO Path: " + e.Message);
+ }
if (!iso.Exists)
throw new FileNotFoundException(nameof(isoPath));
@@ -286,11 +279,16 @@ namespace LibIRD
///
private static long CalculateSize(string isoPath)
{
- // Validate ISO path
- ArgumentNullException.ThrowIfNull(isoPath, nameof(isoPath));
-
// Check file exists
- var iso = new FileInfo(isoPath);
+ FileInfo iso;
+ try
+ {
+ iso = new FileInfo(isoPath);
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("Invalid ISO Path: " + e.Message);
+ }
if (!iso.Exists)
throw new FileNotFoundException(nameof(isoPath));