From 01eb234fee7766aa6cc96b7dc1f4e6075d8c31fe Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Tue, 6 Sep 2016 21:03:57 +0100 Subject: [PATCH] Added support for decoding "vers" resource. --- Claunia.RsrcFork.Test/ChangeLog | 4 + Claunia.RsrcFork.Test/Test.cs | 35 +++++++ Claunia.RsrcFork/ChangeLog | 7 ++ Claunia.RsrcFork/Claunia.RsrcFork.csproj | 5 + Claunia.RsrcFork/PascalString.cs | 60 ++++++++++++ Claunia.RsrcFork/Resources/Version.cs | 116 +++++++++++++++++++++++ 6 files changed, 227 insertions(+) create mode 100644 Claunia.RsrcFork/PascalString.cs create mode 100644 Claunia.RsrcFork/Resources/Version.cs diff --git a/Claunia.RsrcFork.Test/ChangeLog b/Claunia.RsrcFork.Test/ChangeLog index a63057a..3dcb3c0 100644 --- a/Claunia.RsrcFork.Test/ChangeLog +++ b/Claunia.RsrcFork.Test/ChangeLog @@ -1,3 +1,7 @@ +2016-09-06 Natalia Portillo + + * Test.cs: Added support for decoding "vers" resource. + 2016-09-02 Natalia Portillo * Claunia.RsrcFork.Test.csproj: Downgrade framework requisites diff --git a/Claunia.RsrcFork.Test/Test.cs b/Claunia.RsrcFork.Test/Test.cs index f01d2de..da30d97 100644 --- a/Claunia.RsrcFork.Test/Test.cs +++ b/Claunia.RsrcFork.Test/Test.cs @@ -26,6 +26,7 @@ using System.IO; using NUnit.Framework; +using Resources; namespace Claunia.RsrcFork.Test { @@ -70,6 +71,15 @@ namespace Claunia.RsrcFork.Test string versStr = vers.GetName(1); Assert.IsNull(versStr); + + 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("Disk Copy", versDec.VersionString); + Assert.AreEqual("4.2, data checksum=$A5147F7E", versDec.VersionMessage); } [Test] @@ -121,6 +131,16 @@ namespace Claunia.RsrcFork.Test Assert.AreEqual(224, bcem.GetLength(128)); 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); + Assert.AreEqual("Mac? OS HFS 1680K disk image\rCRC28: $07213FB7", versDec.VersionMessage); } [Test] @@ -159,6 +179,18 @@ namespace Claunia.RsrcFork.Test 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); + Assert.AreEqual("1.1b6, Copyright 1997-2001 Apple Computer, Inc.", versDec.VersionMessage); } [Test] @@ -187,6 +219,9 @@ namespace Claunia.RsrcFork.Test Assert.AreEqual(1544, plst.GetLength(0)); string plstStr = plst.GetName(0); Assert.IsNull(plstStr); + + Resource vers = rsrc.GetResource(0x76657273); + Assert.IsNull(vers); } } } diff --git a/Claunia.RsrcFork/ChangeLog b/Claunia.RsrcFork/ChangeLog index 40359d3..1262f01 100644 --- a/Claunia.RsrcFork/ChangeLog +++ b/Claunia.RsrcFork/ChangeLog @@ -1,3 +1,10 @@ +2016-09-06 Natalia Portillo + + * PascalString.cs: + * Version.cs: + * Claunia.RsrcFork.csproj: Added support for decoding "vers" + resource. + 2016-09-06 Natalia Portillo * Types.cs: Added new resource OSTypes. diff --git a/Claunia.RsrcFork/Claunia.RsrcFork.csproj b/Claunia.RsrcFork/Claunia.RsrcFork.csproj index 024e507..81bc259 100644 --- a/Claunia.RsrcFork/Claunia.RsrcFork.csproj +++ b/Claunia.RsrcFork/Claunia.RsrcFork.csproj @@ -38,6 +38,8 @@ + + @@ -51,6 +53,9 @@ PreserveNewest + + + diff --git a/Claunia.RsrcFork/PascalString.cs b/Claunia.RsrcFork/PascalString.cs new file mode 100644 index 0000000..4667b82 --- /dev/null +++ b/Claunia.RsrcFork/PascalString.cs @@ -0,0 +1,60 @@ +// +// PascalString.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2016 © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Text; +namespace Claunia.RsrcFork +{ + public static class PascalString + { + public static string GetString(byte[] PStr) + { + if(PStr == null || PStr[0] >= PStr.Length) + return null; + + return Encoding.ASCII.GetString(PStr, 1, PStr[0]); + } + + public static byte[] GetBytes(string str) + { + 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]; + + Array.Copy(str_b, 0, PStr, 1, PStr.Length - 1); + PStr[0] = (byte)(PStr.Length - 1); + + return PStr; + } + } +} + diff --git a/Claunia.RsrcFork/Resources/Version.cs b/Claunia.RsrcFork/Resources/Version.cs new file mode 100644 index 0000000..06cc6ba --- /dev/null +++ b/Claunia.RsrcFork/Resources/Version.cs @@ -0,0 +1,116 @@ +// +// Version.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2016 © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using Claunia.RsrcFork; + +namespace Resources +{ + public class Version + { + static uint ostype = 0x76657273; + + #region On-disk structure + public byte MajorVersion; + public byte MinorVersion; + public DevelopmentStage DevStage; + public byte PreReleaseVersion; + public ushort RegionCode; + public string VersionString; + public string VersionMessage; + #endregion + + public enum DevelopmentStage : byte + { + PreAlpha = 0x20, + Alpha = 0x40, + Beta = 0x60, + Final = 0x80 + } + + public Version(byte[] resource) + { + byte[] tmpShort, tmpStr, tmpMsg; + + tmpShort = new byte[2]; + + MajorVersion = BCDToNumber(resource[0]); + MinorVersion = BCDToNumber(resource[1]); + DevStage = (DevelopmentStage)resource[2]; + PreReleaseVersion = BCDToNumber(resource[3]); + Array.Copy(resource, 4, tmpShort, 0, 2); + RegionCode = BitConverter.ToUInt16(tmpShort.Reverse().ToArray(), 0); + tmpStr = new byte[resource[6] + 1]; + Array.Copy(resource, 6, tmpStr, 0, tmpStr.Length); + VersionString = PascalString.GetString(tmpStr); + System.Console.WriteLine("{0} == {1}, \"{2}\"", resource[6], tmpStr.Length, VersionString); + tmpMsg = new byte[resource[6 + tmpStr.Length] + 1]; + Array.Copy(resource, 6 + tmpStr.Length, tmpMsg, 0, tmpMsg.Length); + VersionMessage = PascalString.GetString(tmpMsg); + } + + 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]; + + 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); + + return vers; + } + + public static uint OSType { + get { + return ostype; + } + } + + byte BCDToNumber(byte bcd) + { + return Convert.ToByte(string.Format("{0:X2}", bcd), 10); + } + + byte NumberToBCD(byte number) + { + if(number >= 100) + number = 99; + + return Convert.ToByte(string.Format("{0:D2}", number), 16); + } + } +} +