diff --git a/Claunia.RsrcFork.CLI/Claunia.RsrcFork.CLI.csproj b/Claunia.RsrcFork.CLI/Claunia.RsrcFork.CLI.csproj index d20cd1d..caa4c09 100644 --- a/Claunia.RsrcFork.CLI/Claunia.RsrcFork.CLI.csproj +++ b/Claunia.RsrcFork.CLI/Claunia.RsrcFork.CLI.csproj @@ -29,7 +29,7 @@ true - + diff --git a/Claunia.RsrcFork.CLI/Program.cs b/Claunia.RsrcFork.CLI/Program.cs index 50051f0..4d5ba2b 100644 --- a/Claunia.RsrcFork.CLI/Program.cs +++ b/Claunia.RsrcFork.CLI/Program.cs @@ -31,7 +31,7 @@ using System.Text; namespace Claunia.RsrcFork.CLI; -class MainClass +internal class MainClass { public static void Main(string[] args) { @@ -39,103 +39,101 @@ class MainClass Console.WriteLine("© 2016 Natalia Portillo"); Console.WriteLine(); - if(args.Length != 2 && args.Length != 4) + if(args.Length != 2 && + args.Length != 4) { Usage(); - return; - } - - if(args.Length == 2) - { - if(args[0] != "-l") - { - Usage(); - return; - } - - if(!File.Exists(args[1])) - { - Console.WriteLine("Specified file does not exist."); - return; - } - - FileStream rsrcStream = new FileStream(args[1], FileMode.Open, FileAccess.Read); - - ResourceFork rsrc = new ResourceFork(rsrcStream); - - foreach(uint type in rsrc.GetTypes()) - { - byte[] typeBytes = BitConverter.GetBytes(type); - typeBytes = typeBytes.Reverse().ToArray(); - string typeName = Types.GetName(type); - if(typeName != null) - Console.WriteLine("\"{0}\" (0x{1:X8}) - {2}", Encoding.ASCII.GetString(typeBytes), type, - typeName); - else Console.WriteLine("\"{0}\" (0x{1:X8})", Encoding.ASCII.GetString(typeBytes), type); - - Resource rez = rsrc.GetResource(type); - Console.WriteLine("{0,6}{1,8}\t{2}", "ID", "Length", "Name"); - Console.WriteLine("{0,6}{1,8}--{2}", "------", "--------", "----------------"); - foreach(short id in rez.GetIds()) - if(rez.GetName(id) != null) - Console.WriteLine("{0,6}{1,8}\t\"{2}\"", id, rez.GetLength(id), rez.GetName(id)); - else Console.WriteLine("{0,6}{1,8}", id, rez.GetLength(id)); - - Console.WriteLine(); - } return; } - if(args.Length == 4) + switch(args.Length) { - if(args[0] != "-x") - { + case 2 when args[0] != "-l": Usage(); - return; - } - if(args[1] != "-o") - { - Usage(); return; - } - - if(Directory.Exists(args[2])) - { - Console.WriteLine("Output directory exists, not proceeding"); - return; - } - - if(!File.Exists(args[3])) - { + case 2 when !File.Exists(args[1]): Console.WriteLine("Specified file does not exist."); + return; - } - - FileStream rsrcStream = new FileStream(args[3], FileMode.Open, FileAccess.Read); - FileStream outStream; - - ResourceFork rsrc = new ResourceFork(rsrcStream); - - foreach(uint type in rsrc.GetTypes()) + case 2: { - byte[] typeBytes = BitConverter.GetBytes(type); - typeBytes = typeBytes.Reverse().ToArray(); + var rsrcStream = new FileStream(args[1], FileMode.Open, FileAccess.Read); - Directory.CreateDirectory(Path.Combine(args[2], Encoding.ASCII.GetString(typeBytes))); + var rsrc = new ResourceFork(rsrcStream); - Resource rez = rsrc.GetResource(type); - foreach(short id in rez.GetIds()) + foreach(uint type in rsrc.GetTypes()) { - outStream = - new - FileStream(Path.Combine(args[2], Encoding.ASCII.GetString(typeBytes), string.Format("{0}", id)), - FileMode.Create, FileAccess.ReadWrite); - byte[] rez_b = rez.GetResource(id); - outStream.Write(rez_b, 0, rez_b.Length); - outStream.Close(); + byte[] typeBytes = BitConverter.GetBytes(type); + typeBytes = typeBytes.Reverse().ToArray(); + string typeName = Types.GetName(type); + + if(typeName != null) + Console.WriteLine("\"{0}\" (0x{1:X8}) - {2}", Encoding.ASCII.GetString(typeBytes), type, + typeName); + else + Console.WriteLine("\"{0}\" (0x{1:X8})", Encoding.ASCII.GetString(typeBytes), type); + + Resource rez = rsrc.GetResource(type); + Console.WriteLine("{0,6}{1,8}\t{2}", "ID", "Length", "Name"); + Console.WriteLine("{0,6}{1,8}--{2}", "------", "--------", "----------------"); + + foreach(short id in rez.GetIds()) + if(rez.GetName(id) != null) + Console.WriteLine("{0,6}{1,8}\t\"{2}\"", id, rez.GetLength(id), rez.GetName(id)); + else + Console.WriteLine("{0,6}{1,8}", id, rez.GetLength(id)); + + Console.WriteLine(); } + + return; + } + case 4 when args[0] != "-x": + Usage(); + + return; + case 4 when args[1] != "-o": + Usage(); + + return; + case 4 when Directory.Exists(args[2]): + Console.WriteLine("Output directory exists, not proceeding"); + + return; + case 4 when !File.Exists(args[3]): + Console.WriteLine("Specified file does not exist."); + + return; + case 4: + { + var rsrcStream = new FileStream(args[3], FileMode.Open, FileAccess.Read); + FileStream outStream; + + var rsrc = new ResourceFork(rsrcStream); + + foreach(uint type in rsrc.GetTypes()) + { + byte[] typeBytes = BitConverter.GetBytes(type); + typeBytes = typeBytes.Reverse().ToArray(); + + Directory.CreateDirectory(Path.Combine(args[2], Encoding.ASCII.GetString(typeBytes))); + + Resource rez = rsrc.GetResource(type); + + foreach(short id in rez.GetIds()) + { + outStream = new FileStream(Path.Combine(args[2], Encoding.ASCII.GetString(typeBytes), $"{id}"), + FileMode.Create, FileAccess.ReadWrite); + + byte[] rez_b = rez.GetResource(id); + outStream.Write(rez_b, 0, rez_b.Length); + outStream.Close(); + } + } + + break; } } } diff --git a/Claunia.RsrcFork.Test/Claunia.RsrcFork.Test.csproj b/Claunia.RsrcFork.Test/Claunia.RsrcFork.Test.csproj index 5d6da28..47f7e55 100644 --- a/Claunia.RsrcFork.Test/Claunia.RsrcFork.Test.csproj +++ b/Claunia.RsrcFork.Test/Claunia.RsrcFork.Test.csproj @@ -29,7 +29,7 @@ false - + @@ -46,7 +46,7 @@ - + @@ -60,15 +60,15 @@ - - + + - - + + diff --git a/Claunia.RsrcFork.Test/Test.cs b/Claunia.RsrcFork.Test/Test.cs index 843e90d..6a04abf 100644 --- a/Claunia.RsrcFork.Test/Test.cs +++ b/Claunia.RsrcFork.Test/Test.cs @@ -35,17 +35,20 @@ public class Test { readonly byte[] DC42_Vers = { - 0x06, 0x40, 0x80, 0x00, 0x00, 0x00, 0x09, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x1C, - 0x34, 0x2E, 0x32, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, - 0x6D, 0x3D, 0x24, 0x41, 0x35, 0x31, 0x34, 0x37, 0x46, 0x37, 0x45 + 0x06, 0x40, 0x80, 0x00, 0x00, 0x00, 0x09, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x1C, 0x34, + 0x2E, 0x32, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, 0x3D, + 0x24, 0x41, 0x35, 0x31, 0x34, 0x37, 0x46, 0x37, 0x45 + }; + readonly byte[] DC42_Str = + { + 0x09, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x43, 0x6F, 0x70, 0x79 }; - readonly byte[] DC42_Str = {0x09, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x43, 0x6F, 0x70, 0x79}; [Test] public void TestDC42() { - FileStream dc42Stream = new FileStream("Samples/DiskCopy42.rsrc", FileMode.Open, FileAccess.Read); - ResourceFork rsrc = new ResourceFork(dc42Stream); + var dc42Stream = new FileStream("Samples/DiskCopy42.rsrc", FileMode.Open, FileAccess.Read); + var rsrc = new ResourceFork(dc42Stream); uint[] types = rsrc.GetTypes(); Assert.AreEqual(0x53545220, types[0]); @@ -56,7 +59,7 @@ public class Test short[] str_Ids = str_.GetIds(); Assert.AreEqual(-16396, str_Ids[0]); - Assert.AreEqual(10, str_.GetLength(-16396)); + Assert.AreEqual(10, str_.GetLength(-16396)); byte[] str1 = str_.GetResource(-16396); Assert.AreEqual(DC42_Str, str1); @@ -67,7 +70,7 @@ public class Test Resource vers = rsrc.GetResource(0x76657273); Assert.IsNotNull(vers); short[] versIds = vers.GetIds(); - Assert.AreEqual(1, versIds[0]); + Assert.AreEqual(1, versIds[0]); Assert.AreEqual(45, vers.GetLength(1)); byte[] vers1 = vers.GetResource(1); @@ -76,21 +79,21 @@ public class Test string versStr = vers.GetName(1); Assert.IsNull(versStr); - Version versDec = new Version(vers1); - Assert.AreEqual(6, versDec.MajorVersion); - Assert.AreEqual(40, versDec.MinorVersion); + var versDec = new Version(vers1); + Assert.AreEqual(6, versDec.MajorVersion); + Assert.AreEqual(40, versDec.MinorVersion); Assert.AreEqual(Version.DevelopmentStage.Final, versDec.DevStage); - Assert.AreEqual(0, versDec.PreReleaseVersion); - Assert.AreEqual(0, versDec.RegionCode); - Assert.AreEqual("Disk Copy", versDec.VersionString); + Assert.AreEqual(0, versDec.PreReleaseVersion); + Assert.AreEqual(0, versDec.RegionCode); + Assert.AreEqual("Disk Copy", versDec.VersionString); Assert.AreEqual("4.2, data checksum=$A5147F7E", versDec.VersionMessage); } [Test] public void TestDC6() { - FileStream dc6Stream = new FileStream("Samples/DiskCopy6.rsrc", FileMode.Open, FileAccess.Read); - ResourceFork rsrc = new ResourceFork(dc6Stream); + var dc6Stream = new FileStream("Samples/DiskCopy6.rsrc", FileMode.Open, FileAccess.Read); + var rsrc = new ResourceFork(dc6Stream); uint[] types = rsrc.GetTypes(); Assert.AreEqual(0x53545220, types[0]); @@ -103,7 +106,7 @@ public class Test short[] str_Ids = str_.GetIds(); Assert.AreEqual(-16396, str_Ids[0]); - Assert.AreEqual(10, str_.GetLength(-16396)); + Assert.AreEqual(10, str_.GetLength(-16396)); byte[] str1 = str_.GetResource(-16396); Assert.AreEqual(DC42_Str, str1); @@ -114,7 +117,7 @@ public class Test Resource vers = rsrc.GetResource(0x76657273); Assert.IsNotNull(vers); short[] versIds = vers.GetIds(); - Assert.AreEqual(1, versIds[0]); + Assert.AreEqual(1, versIds[0]); Assert.AreEqual(66, vers.GetLength(1)); string versStr = vers.GetName(1); @@ -136,25 +139,25 @@ public class Test string bceSStr = bceS.GetName(128); Assert.IsNull(bceSStr); - byte[] vers1 = vers.GetResource(1); - Version versDec = new Version(vers1); - Assert.AreEqual(6, versDec.MajorVersion); - Assert.AreEqual(40, versDec.MinorVersion); - Assert.AreEqual(Version.DevelopmentStage.Final, versDec.DevStage); - Assert.AreEqual(0, versDec.PreReleaseVersion); - Assert.AreEqual(0, versDec.RegionCode); - Assert.AreEqual("6.4 Disk Copy", versDec.VersionString); + byte[] vers1 = vers.GetResource(1); + var versDec = new Version(vers1); + Assert.AreEqual(6, versDec.MajorVersion); + Assert.AreEqual(40, versDec.MinorVersion); + Assert.AreEqual(Version.DevelopmentStage.Final, versDec.DevStage); + Assert.AreEqual(0, versDec.PreReleaseVersion); + Assert.AreEqual(0, versDec.RegionCode); + Assert.AreEqual("6.4 Disk Copy", versDec.VersionString); Assert.AreEqual("Mac? OS HFS 1680K disk image\rCRC28: $07213FB7", versDec.VersionMessage); } [Test] public void TestSMI() { - FileStream smiStream = new FileStream("Samples/SelfMountingImage.rsrc", FileMode.Open, FileAccess.Read); - ResourceFork rsrc = new ResourceFork(smiStream); + var smiStream = new FileStream("Samples/SelfMountingImage.rsrc", FileMode.Open, FileAccess.Read); + var rsrc = new ResourceFork(smiStream); uint[] types = rsrc.GetTypes(); - Assert.AreEqual(29, types.Length); + Assert.AreEqual(29, types.Length); Assert.AreEqual(0x424E444C, types[0]); Assert.AreEqual(0x434F4445, types[1]); Assert.AreEqual(0x44415441, types[2]); @@ -170,8 +173,8 @@ public class Test Resource code = rsrc.GetResource(0x434F4445); Assert.IsNotNull(code); short[] codeIds = code.GetIds(); - Assert.AreEqual(0, codeIds[0]); - Assert.AreEqual(1, codeIds[1]); + Assert.AreEqual(0, codeIds[0]); + Assert.AreEqual(1, codeIds[1]); Assert.AreEqual(35130, code.GetLength(1)); string codeStr = code.GetName(1); Assert.AreEqual("First Segment", codeStr); //"First Segment" @@ -180,38 +183,38 @@ public class Test Assert.IsNotNull(bndl); short[] bndlIds = bndl.GetIds(); Assert.AreEqual(128, bndlIds[0]); - Assert.AreEqual(28, bndl.GetLength(128)); + Assert.AreEqual(28, bndl.GetLength(128)); string bndlStr = bndl.GetName(128); Assert.IsNull(bndlStr); Resource vers = rsrc.GetResource(0x76657273); Assert.IsNotNull(vers); - byte[] vers1 = vers.GetResource(1); - Version versDec = new Version(vers1); - Assert.AreEqual(1, versDec.MajorVersion); - Assert.AreEqual(10, versDec.MinorVersion); - Assert.AreEqual(Version.DevelopmentStage.Beta, versDec.DevStage); - Assert.AreEqual(6, versDec.PreReleaseVersion); - Assert.AreEqual(0, versDec.RegionCode); - Assert.AreEqual("1.1b6", versDec.VersionString); + byte[] vers1 = vers.GetResource(1); + var versDec = new Version(vers1); + Assert.AreEqual(1, versDec.MajorVersion); + Assert.AreEqual(10, versDec.MinorVersion); + Assert.AreEqual(Version.DevelopmentStage.Beta, versDec.DevStage); + Assert.AreEqual(6, versDec.PreReleaseVersion); + Assert.AreEqual(0, versDec.RegionCode); + Assert.AreEqual("1.1b6", versDec.VersionString); Assert.AreEqual("1.1b6, Copyright 1997-2001 Apple Computer, Inc.", versDec.VersionMessage); } [Test] public void TestUDIF() { - FileStream udifStream = new FileStream("Samples/UDIF.rsrc", FileMode.Open, FileAccess.Read); - ResourceFork rsrc = new ResourceFork(udifStream); + var udifStream = new FileStream("Samples/UDIF.rsrc", FileMode.Open, FileAccess.Read); + var rsrc = new ResourceFork(udifStream); uint[] types = rsrc.GetTypes(); - Assert.AreEqual(2, types.Length); + Assert.AreEqual(2, types.Length); Assert.AreEqual(0x626C6B78, types[0]); Assert.AreEqual(0x706C7374, types[1]); Resource blkx = rsrc.GetResource(0x626C6B78); Assert.IsNotNull(blkx); short[] blkxIds = blkx.GetIds(); - Assert.AreEqual(0, blkxIds[0]); + Assert.AreEqual(0, blkxIds[0]); Assert.AreEqual(524, blkx.GetLength(0)); string blkxStr = blkx.GetName(0); Assert.AreEqual("Whole Device (Apple_XXX : 0)", blkxStr); //"First Segment" @@ -219,7 +222,7 @@ public class Test Resource plst = rsrc.GetResource(0x706C7374); Assert.IsNotNull(plst); short[] plstIds = plst.GetIds(); - Assert.AreEqual(0, plstIds[0]); + Assert.AreEqual(0, plstIds[0]); Assert.AreEqual(1544, plst.GetLength(0)); string plstStr = plst.GetName(0); Assert.IsNull(plstStr); diff --git a/Claunia.RsrcFork/Claunia.RsrcFork.csproj b/Claunia.RsrcFork/Claunia.RsrcFork.csproj index e216940..1e017c7 100644 --- a/Claunia.RsrcFork/Claunia.RsrcFork.csproj +++ b/Claunia.RsrcFork/Claunia.RsrcFork.csproj @@ -60,6 +60,6 @@ - + \ No newline at end of file diff --git a/Claunia.RsrcFork/PascalString.cs b/Claunia.RsrcFork/PascalString.cs index 229de3f..3c35b68 100644 --- a/Claunia.RsrcFork/PascalString.cs +++ b/Claunia.RsrcFork/PascalString.cs @@ -29,37 +29,27 @@ using System.Text; namespace Claunia.RsrcFork; -/// -/// Contains convertes between .NET and Pascal strings. Only ASCII supported right now. -/// +/// Contains convertes between .NET and Pascal strings. Only ASCII supported right now. public static class PascalString { - /// - /// Converts an ASCII Pascal string to a .NET string. - /// + /// Converts an ASCII Pascal string to a .NET string. /// The .NET string. /// The ASCII Pascal string. - public static string GetString(byte[] PStr) - { - if(PStr == null || PStr[0] >= PStr.Length) return null; + public static string GetString(byte[] PStr) => + PStr == null || PStr[0] >= PStr.Length ? null : Encoding.ASCII.GetString(PStr, 1, PStr[0]); - return Encoding.ASCII.GetString(PStr, 1, PStr[0]); - } - - /// - /// Converts a .NET string to an ASCII Pascal string. - /// + /// Converts a .NET string to an ASCII Pascal string. /// The ASCII Pascal string. /// The .NET string. public static byte[] GetBytes(string str) { - if(str == null) return new byte[1]; + if(str == null) + return new byte[1]; byte[] str_b = Encoding.ASCII.GetBytes(str); byte[] PStr; - if(str_b.Length >= 256) PStr = new byte[256]; - else PStr = new byte[str_b.Length + 1]; + PStr = str_b.Length >= 256 ? new byte[256] : new byte[str_b.Length + 1]; Array.Copy(str_b, 0, PStr, 1, PStr.Length - 1); PStr[0] = (byte)(PStr.Length - 1); diff --git a/Claunia.RsrcFork/Resource.cs b/Claunia.RsrcFork/Resource.cs index 66bf911..f093650 100644 --- a/Claunia.RsrcFork/Resource.cs +++ b/Claunia.RsrcFork/Resource.cs @@ -32,149 +32,127 @@ using System.Text; namespace Claunia.RsrcFork; -/// -/// This class represents a resource type. -/// +/// This class represents a resource type. public class Resource { - readonly List ids; - readonly Dictionary resourceCache; - readonly Dictionary resourceNames; - readonly Dictionary resources; - readonly Stream rsrcStream; + readonly List _ids; + readonly Dictionary _resourceCache; + readonly Dictionary _resourceNames; + readonly Dictionary _resources; + readonly Stream _rsrcStream; - /// - /// Initializates the specified resource type. - /// + /// Initializates the specified resource type. /// Stream where the resources of this reside. /// How many resource of this type are. /// Offset from start of stream to reference list for this type. /// Offset from start of stream to resource name list. /// Offset from start of stream to resource data. /// Resource type. - internal Resource(Stream stream, ushort resources, long referenceListOff, long resourceNameOffset, - long resourceDataOffset, uint OSType) + internal Resource(Stream stream, ushort resources, long referenceListOff, long resourceNameOffset, + long resourceDataOffset, uint OSType) { - rsrcStream = stream; - Dictionary referenceLists = - new Dictionary(); - resourceNames = new Dictionary(); - this.resources = new Dictionary(); - ids = new List(); + _rsrcStream = stream; + Dictionary referenceLists = new(); + _resourceNames = new Dictionary(); + _resources = new Dictionary(); + _ids = new List(); byte[] tmp; - rsrcStream.Seek(referenceListOff + 2, SeekOrigin.Begin); + _rsrcStream.Seek(referenceListOff + 2, SeekOrigin.Begin); + for(int i = 0; i < resources; i++) { - ResourceTypeReferenceListItem item = new ResourceTypeReferenceListItem(); + ResourceTypeReferenceListItem item = new(); tmp = new byte[2]; - rsrcStream.Read(tmp, 0, 2); - item.id = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 2); - item.nameOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 2); + item.Id = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 2); + item.NameOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); tmp = new byte[4]; - rsrcStream.Read(tmp, 0, 4); - item.attributes = tmp[0]; + _rsrcStream.Read(tmp, 0, 4); + item.Attributes = tmp[0]; tmp[0] = 0; - item.dataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 4); - item.handle = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0); + item.DataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + item.Handle = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0); - referenceLists.Add(item.id, item); - ids.Add(item.id); + referenceLists.Add(item.Id, item); + _ids.Add(item.Id); } foreach(ResourceTypeReferenceListItem item in referenceLists.Values) { string name; - ResourceData data = new ResourceData(); + ResourceData data = new(); - if(item.nameOff == -1) name = null; + if(item.NameOff == -1) + name = null; else { - rsrcStream.Seek(resourceNameOffset + item.nameOff, SeekOrigin.Begin); - byte nameLen = (byte)rsrcStream.ReadByte(); + _rsrcStream.Seek(resourceNameOffset + item.NameOff, SeekOrigin.Begin); + byte nameLen = (byte)_rsrcStream.ReadByte(); byte[] nameBytes = new byte[nameLen]; - rsrcStream.Read(nameBytes, 0, nameLen); + _rsrcStream.Read(nameBytes, 0, nameLen); + // TODO: Use MacRoman name = Encoding.ASCII.GetString(nameBytes); } - rsrcStream.Seek(resourceDataOffset + item.dataOff, SeekOrigin.Begin); + _rsrcStream.Seek(resourceDataOffset + item.DataOff, SeekOrigin.Begin); tmp = new byte[4]; - rsrcStream.Read(tmp, 0, 4); - data.offset = rsrcStream.Position; - data.length = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + data.Offset = _rsrcStream.Position; + data.Length = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0); - resourceNames.Add(item.id, name); - this.resources.Add(item.id, data); + _resourceNames.Add(item.Id, name); + _resources.Add(item.Id, data); } - resourceCache = new Dictionary(); + _resourceCache = new Dictionary(); } - /// - /// Gets the name of the specified resource id, or null if there is no name. - /// + /// Gets the name of the specified resource id, or null if there is no name. /// The name. /// Identifier. - public string GetName(short id) - { - string name; - return resourceNames.TryGetValue(id, out name) ? name : null; - } + public string GetName(short id) => _resourceNames.TryGetValue(id, out string name) ? name : null; - /// - /// Gets the resource contents. - /// + /// Gets the resource contents. /// The resource. /// Identifier. public byte[] GetResource(short id) { - byte[] resource; + if(_resourceCache.TryGetValue(id, out byte[] resource)) + return resource; - if(resourceCache.TryGetValue(id, out resource)) return resource; + if(!_resources.TryGetValue(id, out ResourceData data)) + return null; - ResourceData data; + resource = new byte[data.Length]; + _rsrcStream.Seek(data.Offset, SeekOrigin.Begin); + _rsrcStream.Read(resource, 0, resource.Length); - if(!resources.TryGetValue(id, out data)) return null; - - resource = new byte[data.length]; - rsrcStream.Seek(data.offset, SeekOrigin.Begin); - rsrcStream.Read(resource, 0, resource.Length); - - resourceCache.Add(id, resource); + _resourceCache.Add(id, resource); return resource; } - /// - /// Gets the length of the resource specified by ID. - /// + /// Gets the length of the resource specified by ID. /// The length. /// Resource identifier. - public long GetLength(short id) - { - ResourceData data; - return !resources.TryGetValue(id, out data) ? 0 : data.length; - } + public long GetLength(short id) => !_resources.TryGetValue(id, out ResourceData data) ? 0 : data.Length; - /// - /// Gets the IDs of all the resources contained by this instance. - /// + /// Gets the IDs of all the resources contained by this instance. /// The identifiers. - public short[] GetIds() => ids.ToArray(); + public short[] GetIds() => _ids.ToArray(); - /// - /// Checks if the resource specified by ID is contained by this instance. - /// + /// Checks if the resource specified by ID is contained by this instance. /// true, if the resource is contained in this instance, false otherwise. /// Resource identifier. - public bool ContainsId(short id) => ids.Contains(id); + public bool ContainsId(short id) => _ids.Contains(id); struct ResourceData { - public long offset; - public long length; + public long Offset; + public long Length; } } \ No newline at end of file diff --git a/Claunia.RsrcFork/ResourceFork.cs b/Claunia.RsrcFork/ResourceFork.cs index 288e820..8bff765 100644 --- a/Claunia.RsrcFork/ResourceFork.cs +++ b/Claunia.RsrcFork/ResourceFork.cs @@ -30,161 +30,146 @@ using System.Linq; namespace Claunia.RsrcFork; -/// -/// This class represents a resource fork. -/// +/// This class represents a resource fork. public class ResourceFork { - ResourceHeader header; - ResourceMap map; - List osTypes; - Dictionary resourceCache; - Dictionary resourceTypeList; - readonly Stream rsrcStream; + readonly Stream _rsrcStream; + ResourceHeader _header; + ResourceMap _map; + List _osTypes; + Dictionary _resourceCache; + Dictionary _resourceTypeList; - /// - /// Initializates a resource fork using a byte array as backend. - /// + /// Initializates a resource fork using a byte array as backend. /// Buffer. public ResourceFork(byte[] buffer) { - rsrcStream = new MemoryStream(buffer, false); + _rsrcStream = new MemoryStream(buffer, false); Init(); } - /// - /// Initializates a resource fork using a stream as backed. - /// + /// Initializates a resource fork using a stream as backed. /// Stream. public ResourceFork(Stream stream) { - rsrcStream = stream; + _rsrcStream = stream; Init(); } - /// - /// Cleans up this instances and closes the underlying stream. - /// - ~ResourceFork() - { - if(rsrcStream != null) rsrcStream.Dispose(); - } + /// Cleans up this instances and closes the underlying stream. + ~ResourceFork() => _rsrcStream?.Dispose(); - /// - /// Initializes this instance. - /// + /// Initializes this instance. void Init() { - header = new ResourceHeader(); + _header = new ResourceHeader(); byte[] tmp = new byte[4]; - rsrcStream.Seek(0, SeekOrigin.Begin); - rsrcStream.Read(tmp, 0, 4); - header.resourceDataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 4); - header.resourceMapOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 4); - header.resourceDataLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 4); - header.resourceMapLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Seek(0, SeekOrigin.Begin); + _rsrcStream.Read(tmp, 0, 4); + _header.ResourceDataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + _header.ResourceMapOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + _header.ResourceDataLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + _header.ResourceMapLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); - if(header.resourceDataOff <= 0 || header.resourceMapOff <= 0 || header.resourceDataLen <= 0 || - header.resourceMapLen <= 0) throw new InvalidCastException("Not a resource fork"); - - if(header.resourceDataOff + header.resourceDataLen > rsrcStream.Length || - header.resourceMapOff + header.resourceMapLen > rsrcStream.Length) + if(_header.ResourceDataOff <= 0 || + _header.ResourceMapOff <= 0 || + _header.ResourceDataLen <= 0 || + _header.ResourceMapLen <= 0) throw new InvalidCastException("Not a resource fork"); - map = new ResourceMap(); - map.header = new ResourceHeader(); - rsrcStream.Seek(header.resourceMapOff, SeekOrigin.Begin); - rsrcStream.Read(tmp, 0, 4); - map.header.resourceDataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 4); - map.header.resourceMapOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 4); - map.header.resourceDataLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 4); - map.header.resourceMapLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + if(_header.ResourceDataOff + _header.ResourceDataLen > _rsrcStream.Length || + _header.ResourceMapOff + _header.ResourceMapLen > _rsrcStream.Length) + throw new InvalidCastException("Not a resource fork"); - if(map.header.resourceDataOff != header.resourceDataOff || - map.header.resourceDataLen != header.resourceDataLen || - map.header.resourceMapOff != header.resourceMapOff || - map.header.resourceMapLen != header.resourceMapLen) + _map = new ResourceMap + { + Header = new ResourceHeader() + }; + + _rsrcStream.Seek(_header.ResourceMapOff, SeekOrigin.Begin); + _rsrcStream.Read(tmp, 0, 4); + _map.Header.ResourceDataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + _map.Header.ResourceMapOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + _map.Header.ResourceDataLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + _map.Header.ResourceMapLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0); + + if(_map.Header.ResourceDataOff != _header.ResourceDataOff || + _map.Header.ResourceDataLen != _header.ResourceDataLen || + _map.Header.ResourceMapOff != _header.ResourceMapOff || + _map.Header.ResourceMapLen != _header.ResourceMapLen) throw new InvalidCastException("Header copy is not same as header."); - rsrcStream.Read(tmp, 0, 4); - map.handleToNextMap = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0); - tmp = new byte[2]; - rsrcStream.Read(tmp, 0, 2); - map.fileRefNo = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 2); - map.attributes = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 2); - map.typeListOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 2); - map.nameListOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + _map.HandleToNextMap = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0); + tmp = new byte[2]; + _rsrcStream.Read(tmp, 0, 2); + _map.FileRefNo = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 2); + _map.Attributes = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 2); + _map.TypeListOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 2); + _map.NameListOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); // Number of types is part of the resource type list not of the map - rsrcStream.Seek(header.resourceMapOff + map.typeListOff, SeekOrigin.Begin); - rsrcStream.Read(tmp, 0, 2); - map.numberOfTypes = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Seek(_header.ResourceMapOff + _map.TypeListOff, SeekOrigin.Begin); + _rsrcStream.Read(tmp, 0, 2); + _map.NumberOfTypes = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0); - resourceTypeList = new Dictionary(); - osTypes = new List(); + _resourceTypeList = new Dictionary(); + _osTypes = new List(); - for(int i = 0; i <= map.numberOfTypes; i++) + for(int i = 0; i <= _map.NumberOfTypes; i++) { - ResourceTypeListItem typeList = new ResourceTypeListItem(); + ResourceTypeListItem typeList = new(); tmp = new byte[4]; - rsrcStream.Read(tmp, 0, 4); - typeList.type = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 4); + typeList.Type = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0); tmp = new byte[2]; - rsrcStream.Read(tmp, 0, 2); - typeList.resources = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0); - rsrcStream.Read(tmp, 0, 2); - typeList.referenceOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 2); + typeList.Resources = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0); + _rsrcStream.Read(tmp, 0, 2); + typeList.ReferenceOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0); - resourceTypeList.Add(typeList.type, typeList); - osTypes.Add(typeList.type); + _resourceTypeList.Add(typeList.Type, typeList); + _osTypes.Add(typeList.Type); } - resourceCache = new Dictionary(); + _resourceCache = new Dictionary(); } - /// - /// Gets the resources with indicated type - /// + /// Gets the resources with indicated type /// The resource. /// OSType. public Resource GetResource(uint OSType) { - Resource rsrc; + if(_resourceCache.TryGetValue(OSType, out Resource rsrc)) + return rsrc; - if(resourceCache.TryGetValue(OSType, out rsrc)) return rsrc; + if(!_resourceTypeList.TryGetValue(OSType, out ResourceTypeListItem typeList)) + return null; - ResourceTypeListItem typeList; - if(!resourceTypeList.TryGetValue(OSType, out typeList)) return null; + rsrc = new Resource(_rsrcStream, (ushort)(typeList.Resources + 1), + _header.ResourceMapOff + _map.TypeListOff + typeList.ReferenceOff - 2, + _header.ResourceMapOff + _map.NameListOff, _header.ResourceDataOff, OSType); - rsrc = new Resource(rsrcStream, (ushort)(typeList.resources + 1), - header.resourceMapOff + map.typeListOff + typeList.referenceOff - 2, - header.resourceMapOff + map.nameListOff, - header.resourceDataOff, OSType); - - resourceCache.Add(OSType, rsrc); + _resourceCache.Add(OSType, rsrc); return rsrc; } - /// - /// Gets all OSTypes stored in this resource fork - /// + /// Gets all OSTypes stored in this resource fork /// The types. - public uint[] GetTypes() => osTypes.ToArray(); + public uint[] GetTypes() => _osTypes.ToArray(); - /// - /// Returns true if the specified OSType is present in this resource fork. - /// + /// Returns true if the specified OSType is present in this resource fork. /// OSType. - public bool ContainsKey(uint OSType) => resourceTypeList.ContainsKey(OSType); + public bool ContainsKey(uint OSType) => _resourceTypeList.ContainsKey(OSType); } \ No newline at end of file diff --git a/Claunia.RsrcFork/Resources/Version.cs b/Claunia.RsrcFork/Resources/Version.cs index 8a3b224..3be3bd8 100644 --- a/Claunia.RsrcFork/Resources/Version.cs +++ b/Claunia.RsrcFork/Resources/Version.cs @@ -30,43 +30,27 @@ using Claunia.RsrcFork; namespace Resources; -/// -/// This class handles the "VERS" resource fork -/// +/// This class handles the "VERS" resource fork public class Version { - /// - /// Known development stages - /// + /// Known development stages public enum DevelopmentStage : byte { - /// - /// Pre-alpha. - /// + /// Pre-alpha. PreAlpha = 0x20, - /// - /// Alpha. - /// + /// Alpha. Alpha = 0x40, - /// - /// Beta. - /// + /// Beta. Beta = 0x60, - /// - /// Final release. - /// + /// Final release. Final = 0x80 } - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. /// Byte array containing the "VERS" resource. public Version(byte[] resource) { - byte[] tmpShort, tmpStr, tmpMsg; - - tmpShort = new byte[2]; + byte[] tmpShort = new byte[2]; MajorVersion = BCDToNumber(resource[0]); MinorVersion = BCDToNumber(resource[1]); @@ -74,81 +58,62 @@ public class Version PreReleaseVersion = BCDToNumber(resource[3]); Array.Copy(resource, 4, tmpShort, 0, 2); RegionCode = BitConverter.ToUInt16(tmpShort.Reverse().ToArray(), 0); - tmpStr = new byte[resource[6] + 1]; + byte[] tmpStr = new byte[resource[6] + 1]; Array.Copy(resource, 6, tmpStr, 0, tmpStr.Length); VersionString = PascalString.GetString(tmpStr); - tmpMsg = new byte[resource[6 + tmpStr.Length] + 1]; + byte[] tmpMsg = new byte[resource[6 + tmpStr.Length] + 1]; Array.Copy(resource, 6 + tmpStr.Length, tmpMsg, 0, tmpMsg.Length); VersionMessage = PascalString.GetString(tmpMsg); } - /// - /// Gets the OSTYPE of this resource. - /// + /// Gets the OSTYPE of this resource. /// The OSTYPE. public static uint OSType { get; } = 0x76657273; - /// - /// Gets a byte array with the "VERS" resource contained by this instance. - /// + /// Gets a byte array with the "VERS" resource contained by this instance. /// The "VERS" resource. public byte[] GetBytes() { - byte[] tmpShort, tmpStr, tmpMsg; - tmpShort = BitConverter.GetBytes(RegionCode).Reverse().ToArray(); - tmpStr = PascalString.GetBytes(VersionString); - tmpMsg = PascalString.GetBytes(VersionMessage); - - byte[] vers = new byte[6 + tmpStr.Length + tmpMsg.Length]; + byte[] tmpShort = BitConverter.GetBytes(RegionCode).Reverse().ToArray(); + byte[] tmpStr = PascalString.GetBytes(VersionString); + byte[] tmpMsg = PascalString.GetBytes(VersionMessage); + byte[] vers = new byte[6 + tmpStr.Length + tmpMsg.Length]; vers[0] = NumberToBCD(MajorVersion); vers[1] = NumberToBCD(MinorVersion); vers[2] = (byte)DevStage; vers[3] = NumberToBCD(PreReleaseVersion); - Array.Copy(tmpShort, 0, vers, 4, 2); - Array.Copy(tmpStr, 0, vers, 6, tmpStr.Length); - Array.Copy(tmpMsg, 0, vers, 6 + tmpStr.Length, tmpMsg.Length); + Array.Copy(tmpShort, 0, vers, 4, 2); + Array.Copy(tmpStr, 0, vers, 6, tmpStr.Length); + Array.Copy(tmpMsg, 0, vers, 6 + tmpStr.Length, tmpMsg.Length); return vers; } - byte BCDToNumber(byte bcd) => Convert.ToByte(string.Format("{0:X2}", bcd), 10); + byte BCDToNumber(byte bcd) => Convert.ToByte($"{bcd:X2}", 10); byte NumberToBCD(byte number) { - if(number >= 100) number = 99; + if(number >= 100) + number = 99; - return Convert.ToByte(string.Format("{0:D2}", number), 16); + return Convert.ToByte($"{number:D2}", 16); } #region On-disk structure - /// - /// Major version. - /// + /// Major version. public byte MajorVersion; - /// - /// Minor version. - /// + /// Minor version. public byte MinorVersion; - /// - /// Development stage. - /// + /// Development stage. public DevelopmentStage DevStage; - /// - /// Pre-release version. - /// + /// Pre-release version. public byte PreReleaseVersion; - /// - /// Region code. - /// + /// Region code. public ushort RegionCode; - /// - /// Version string. - /// + /// Version string. public string VersionString; - /// - /// Version message. - /// + /// Version message. public string VersionMessage; #endregion } \ No newline at end of file diff --git a/Claunia.RsrcFork/Structs.cs b/Claunia.RsrcFork/Structs.cs index b890eb8..a03c3d9 100644 --- a/Claunia.RsrcFork/Structs.cs +++ b/Claunia.RsrcFork/Structs.cs @@ -26,94 +26,56 @@ namespace Claunia.RsrcFork; -struct ResourceHeader +internal struct ResourceHeader { - /// - /// Offset from start of resource fork to resource data - /// - public int resourceDataOff; - /// - /// Offset from start of resource fork to resource map - /// - public int resourceMapOff; - /// - /// Length of resource data - /// - public int resourceDataLen; - /// - /// Length of resource map - /// - public int resourceMapLen; + /// Offset from start of resource fork to resource data + public int ResourceDataOff; + /// Offset from start of resource fork to resource map + public int ResourceMapOff; + /// Length of resource data + public int ResourceDataLen; + /// Length of resource map + public int ResourceMapLen; } -struct ResourceMap +internal struct ResourceMap { - /// - /// Copy of the resource fork header - /// - public ResourceHeader header; - /// - /// Reserved for handle to next resource map - /// - public uint handleToNextMap; - /// - /// Reserved for file reference number - /// - public ushort fileRefNo; - /// - /// Resource fork attributes - /// - public ushort attributes; - /// - /// Offset from start of resource map to resource type list - /// - public short typeListOff; - /// - /// Offset from start of resource map to resource name list - /// - public short nameListOff; - /// - /// Number of types in the map minus 1 - /// - public ushort numberOfTypes; + /// Copy of the resource fork header + public ResourceHeader Header; + /// Reserved for handle to next resource map + public uint HandleToNextMap; + /// Reserved for file reference number + public ushort FileRefNo; + /// Resource fork attributes + public ushort Attributes; + /// Offset from start of resource map to resource type list + public short TypeListOff; + /// Offset from start of resource map to resource name list + public short NameListOff; + /// Number of types in the map minus 1 + public ushort NumberOfTypes; } -struct ResourceTypeListItem +internal struct ResourceTypeListItem { - /// - /// Resource type - /// - public uint type; - /// - /// Number of resources of this type minus 1 - /// - public ushort resources; - /// - /// Offset from beginning of resource type list to reference list - /// - public short referenceOff; + /// Resource type + public uint Type; + /// Number of resources of this type minus 1 + public ushort Resources; + /// Offset from beginning of resource type list to reference list + public short ReferenceOff; } -struct ResourceTypeReferenceListItem +internal struct ResourceTypeReferenceListItem { - /// - /// Resource ID - /// - public short id; - /// - /// Offset from beginning of resource name list to resource name. -1 if it does not have a name - /// - public short nameOff; - /// - /// Resource attributes - /// - public byte attributes; - /// - /// Offset from beginning of resource data to resource. First byte is . - /// - public int dataOff; - /// - /// Reserved for handle to resource - /// - public uint handle; + /// Resource ID + public short Id; + /// Offset from beginning of resource name list to resource name. -1 if it does not have a name + public short NameOff; + /// Resource attributes + public byte Attributes; + /// Offset from beginning of resource data to resource. First byte is . + public int DataOff; + /// Reserved for handle to resource + public uint Handle; } \ No newline at end of file diff --git a/Claunia.RsrcFork/Types.cs b/Claunia.RsrcFork/Types.cs index 54500b0..dd0d8e4 100644 --- a/Claunia.RsrcFork/Types.cs +++ b/Claunia.RsrcFork/Types.cs @@ -30,14 +30,10 @@ using System.Text; namespace Claunia.RsrcFork; -/// -/// This class contains static methods for OSTYPE handling. -/// +/// This class contains static methods for OSTYPE handling. public static class Types { - /// - /// Gets a descriptive name of a resource from its OSTYPE. - /// + /// Gets a descriptive name of a resource from its OSTYPE. /// The name corresponding to the specified OSTYPE. /// The OSTYPE. public static string GetName(uint OSType) @@ -688,14 +684,13 @@ public static class Types } } - /// - /// Gets a descriptive name of a resource from its OSTYPE. - /// + /// Gets a descriptive name of a resource from its OSTYPE. /// The name corresponding to the specified OSTYPE. /// The OSTYPE. public static string GetName(string OSType) { - if(OSType.Length != 4) return null; + if(OSType.Length != 4) + return null; byte[] typB = Encoding.ASCII.GetBytes(OSType); uint type = BitConverter.ToUInt32(typB.Reverse().ToArray(), 0);