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));