Added code for handling resource forks when they are in the

data fork without headers (not Macbinary, neither AppleDouble,
	are supported).
This commit is contained in:
2016-09-02 02:58:13 +01:00
commit cd99f65ebf
23 changed files with 1683 additions and 0 deletions

40
.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
#Autosave files
*~
#build
[Oo]bj/
[Bb]in/
packages/
TestResults/
# globs
Makefile.in
*.DS_Store
*.sln.cache
*.suo
*.cache
*.pidb
*.userprefs
*.usertasks
config.log
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.user
*.tar.gz
tarballs/
test-results/
Thumbs.db
#Mac bundle stuff
*.dmg
*.app
#resharper
*_Resharper.*
*.Resharper
#dotCover
*.dotCover

View File

@@ -0,0 +1,8 @@
2016-09-02 Natalia Portillo <claunia@claunia.com>
* Program.cs:
* AssemblyInfo.cs:
* Claunia.RsrcFork.CLI.csproj: Added code for handling
resource forks when they are in the data fork without headers
(not Macbinary, neither AppleDouble, are supported).

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{38A6F05E-8900-44E4-83A5-7A215175F78B}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Claunia.RsrcFork.CLI</RootNamespace>
<AssemblyName>Claunia.RsrcFork.CLI</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Claunia.RsrcFork\Claunia.RsrcFork.csproj">
<Project>{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}</Project>
<Name>Claunia.RsrcFork</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\LICENSE">
<Link>LICENSE</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
<CSharpFormattingPolicy IndentSwitchSection="True" NewLinesForBracesInProperties="True" NewLinesForBracesInAccessors="True" NewLinesForBracesInAnonymousMethods="True" NewLinesForBracesInControlBlocks="True" NewLinesForBracesInAnonymousTypes="True" NewLinesForBracesInObjectCollectionArrayInitializers="True" NewLinesForBracesInLambdaExpressionBody="True" NewLineForElse="True" NewLineForCatch="True" NewLineForFinally="True" NewLineForMembersInObjectInit="True" NewLineForMembersInAnonymousTypes="True" NewLineForClausesInQuery="True" SpacingAfterMethodDeclarationName="False" SpaceAfterMethodCallName="False" SpaceAfterControlFlowStatementKeyword="False" SpaceBeforeOpenSquareBracket="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,152 @@
//
// Program.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// 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.IO;
using System.Text;
using System.Linq;
namespace Claunia.RsrcFork.CLI
{
class MainClass
{
public static void Main (string [] args)
{
Console.WriteLine("Claunia.RsrcFork.CLI");
Console.WriteLine("© 2016 Natalia Portillo");
Console.WriteLine();
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)
{
if(args[0] != "-x")
{
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]))
{
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())
{
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), string.Format("{0}", id)), FileMode.Create, FileAccess.ReadWrite);
byte[] rez_b = rez.GetResource(id);
outStream.Write(rez_b, 0, rez_b.Length);
outStream.Close();
}
}
return;
}
}
public static void Usage()
{
Console.WriteLine("Usage:");
Console.WriteLine("\tClaunia.RsrcFork.CLI.exe -l resourcefork.bin - Lists resources in resource fork file");
Console.WriteLine("\t\tor");
Console.WriteLine("\tClaunia.RsrcFork.CLI.EXE -x -o output.dir resourcefork.bin - Extracts all resources to output.dir");
}
}
}

View File

@@ -0,0 +1,52 @@
//
// AssemblyInfo.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// 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.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("Claunia.RsrcFork.CLI")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("Claunia.com")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("© Claunia.com")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

View File

@@ -0,0 +1,12 @@
2016-09-02 Natalia Portillo <claunia@claunia.com>
* Test.cs:
* packages.config:
* UDIF.rsrc:
* DiskCopy6.rsrc:
* DiskCopy42.rsrc:
* Claunia.RsrcFork.Test.csproj:
* SelfMountingImage.rsrc: Added code for handling resource
forks when they are in the data fork without headers (not
Macbinary, neither AppleDouble, are supported).

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D204981A-84C2-454D-AE41-7B16E9265339}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Claunia.RsrcFork.Test</RootNamespace>
<AssemblyName>Claunia.RsrcFork.Test</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Test.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Samples\SelfMountingImage.rsrc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Samples\DiskCopy6.rsrc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Samples\DiskCopy42.rsrc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Samples\UDIF.rsrc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Samples\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Claunia.RsrcFork\Claunia.RsrcFork.csproj">
<Project>{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}</Project>
<Name>Claunia.RsrcFork</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\LICENSE">
<Link>LICENSE</Link>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy FileWidth="120" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
<CSharpFormattingPolicy SpacingAfterMethodDeclarationName="False" SpaceAfterMethodCallName="False" SpaceAfterControlFlowStatementKeyword="False" SpaceBeforeOpenSquareBracket="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,193 @@
//
// Test.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// 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.IO;
using NUnit.Framework;
namespace Claunia.RsrcFork.Test
{
[TestFixture]
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 };
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);
uint[] types = rsrc.GetTypes();
Assert.AreEqual(0x53545220, types[0]);
Assert.AreEqual(0x76657273, types[1]);
Resource str_ = rsrc.GetResource(0x53545220);
Assert.IsNotNull(str_);
short[] str_Ids = str_.GetIds();
Assert.AreEqual(-16396, str_Ids[0]);
Assert.AreEqual(10, str_.GetLength(-16396));
byte[] str1 = str_.GetResource(-16396);
Assert.AreEqual(DC42_Str, str1);
string strStr = str_.GetName(-16396);
Assert.IsNull(strStr);
Resource vers = rsrc.GetResource(0x76657273);
Assert.IsNotNull(vers);
short[] versIds = vers.GetIds();
Assert.AreEqual(1, versIds[0]);
Assert.AreEqual(45, vers.GetLength(1));
byte[] vers1 = vers.GetResource(1);
Assert.AreEqual(DC42_Vers, vers1);
string versStr = vers.GetName(1);
Assert.IsNull(versStr);
}
[Test]
public void TestDC6()
{
FileStream dc6Stream = new FileStream("Samples/DiskCopy6.rsrc", FileMode.Open, FileAccess.Read);
ResourceFork rsrc = new ResourceFork(dc6Stream);
uint[] types = rsrc.GetTypes();
Assert.AreEqual(0x53545220, types[0]);
Assert.AreEqual(0x6263656D, types[1]);
Assert.AreEqual(0x62636D23, types[2]);
Assert.AreEqual(0x76657273, types[3]);
Resource str_ = rsrc.GetResource(0x53545220);
Assert.IsNotNull(str_);
short[] str_Ids = str_.GetIds();
Assert.AreEqual(-16396, str_Ids[0]);
Assert.AreEqual(10, str_.GetLength(-16396));
byte[] str1 = str_.GetResource(-16396);
Assert.AreEqual(DC42_Str, str1);
string strStr = str_.GetName(-16396);
Assert.IsNull(strStr);
Resource vers = rsrc.GetResource(0x76657273);
Assert.IsNotNull(vers);
short[] versIds = vers.GetIds();
Assert.AreEqual(1, versIds[0]);
Assert.AreEqual(66, vers.GetLength(1));
string versStr = vers.GetName(1);
Assert.IsNull(versStr);
Resource bcem = rsrc.GetResource(0x6263656D);
Assert.IsNotNull(bcem);
short[] bcemIds = bcem.GetIds();
Assert.AreEqual(128, bcemIds[0]);
Assert.AreEqual(224, bcem.GetLength(128));
string bcemStr = bcem.GetName(128);
Assert.IsNull(bcemStr);
Resource bceS = rsrc.GetResource(0x6263656D);
Assert.IsNotNull(bceS);
short[] bceSIds = bceS.GetIds();
Assert.AreEqual(128, bceSIds[0]);
Assert.AreEqual(224, bcem.GetLength(128));
string bceSStr = bceS.GetName(128);
Assert.IsNull(bceSStr);
}
[Test]
public void TestSMI()
{
FileStream smiStream = new FileStream("Samples/SelfMountingImage.rsrc", FileMode.Open, FileAccess.Read);
ResourceFork rsrc = new ResourceFork(smiStream);
uint[] types = rsrc.GetTypes();
Assert.AreEqual(29, types.Length);
Assert.AreEqual(0x424E444C, types[0]);
Assert.AreEqual(0x434F4445, types[1]);
Assert.AreEqual(0x44415441, types[2]);
Assert.AreEqual(0x4449544C, types[3]);
Assert.AreEqual(0x444C4F47, types[4]);
Assert.AreEqual(0x44525652, types[5]);
Assert.AreEqual(0x46524546, types[6]);
Assert.AreEqual(0x49434E23, types[7]);
Assert.AreEqual(0x4D505352, types[8]);
Assert.AreEqual(0x4D574242, types[9]);
Assert.AreEqual(0x50415420, types[10]);
Resource code = rsrc.GetResource(0x434F4445);
Assert.IsNotNull(code);
short[] codeIds = code.GetIds();
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"
Resource bndl = rsrc.GetResource(0x424E444C);
Assert.IsNotNull(bndl);
short[] bndlIds = bndl.GetIds();
Assert.AreEqual(128, bndlIds[0]);
Assert.AreEqual(28, bndl.GetLength(128));
string bndlStr = bndl.GetName(128);
Assert.IsNull(bndlStr);
}
[Test]
public void TestUDIF()
{
FileStream udifStream = new FileStream("Samples/UDIF.rsrc", FileMode.Open, FileAccess.Read);
ResourceFork rsrc = new ResourceFork(udifStream);
uint[] types = rsrc.GetTypes();
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(524, blkx.GetLength(0));
string blkxStr = blkx.GetName(0);
Assert.AreEqual("Whole Device (Apple_XXX : 0)", blkxStr); //"First Segment"
Resource plst = rsrc.GetResource(0x706C7374);
Assert.IsNotNull(plst);
short[] plstIds = plst.GetIds();
Assert.AreEqual(0, plstIds[0]);
Assert.AreEqual(1544, plst.GetLength(0));
string plstStr = plst.GetName(0);
Assert.IsNull(plstStr);
}
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="2.6.4" targetFramework="net45" />
</packages>

38
Claunia.RsrcFork.sln Normal file
View File

@@ -0,0 +1,38 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Claunia.RsrcFork", "Claunia.RsrcFork\Claunia.RsrcFork.csproj", "{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Claunia.RsrcFork.Test", "Claunia.RsrcFork.Test\Claunia.RsrcFork.Test.csproj", "{D204981A-84C2-454D-AE41-7B16E9265339}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Claunia.RsrcFork.CLI", "Claunia.RsrcFork.CLI\Claunia.RsrcFork.CLI.csproj", "{38A6F05E-8900-44E4-83A5-7A215175F78B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}.Release|Any CPU.Build.0 = Release|Any CPU
{D204981A-84C2-454D-AE41-7B16E9265339}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D204981A-84C2-454D-AE41-7B16E9265339}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D204981A-84C2-454D-AE41-7B16E9265339}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D204981A-84C2-454D-AE41-7B16E9265339}.Release|Any CPU.Build.0 = Release|Any CPU
{38A6F05E-8900-44E4-83A5-7A215175F78B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{38A6F05E-8900-44E4-83A5-7A215175F78B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38A6F05E-8900-44E4-83A5-7A215175F78B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38A6F05E-8900-44E4-83A5-7A215175F78B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
$0.DotNetNamingPolicy = $1
$1.DirectoryNamespaceAssociation = Hierarchical
$1.ResourceNamePolicy = MSBuild
$0.StandardHeader = $2
$2.Text = @\n${FileName}\n \nAuthor:\n ${AuthorName} <${AuthorEmail}>\n\nCopyright (c) ${Year} ${CopyrightHolder}\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.
$2.IncludeInNewFiles = True
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,11 @@
2016-09-02 Natalia Portillo <claunia@claunia.com>
* Types.cs:
* Structs.cs:
* Resource.cs:
* ResourceFork.cs:
* Claunia.RsrcFork.csproj:
* AssemblyInfo.cs: Added code for handling resource forks when
they are in the data fork without headers (not Macbinary,
neither AppleDouble, are supported).

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Claunia.RsrcFork</RootNamespace>
<AssemblyName>Claunia.RsrcFork</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourceFork.cs" />
<Compile Include="Resource.cs" />
<Compile Include="Structs.cs" />
<Compile Include="Types.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\README.md">
<Link>README.md</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\LICENSE">
<Link>LICENSE</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy FileWidth="120" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
<CSharpFormattingPolicy IndentSwitchSection="True" SpacingAfterMethodDeclarationName="False" SpaceAfterMethodCallName="False" SpaceAfterControlFlowStatementKeyword="False" SpaceBeforeOpenSquareBracket="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,54 @@
//
// Author:
// Natalia Portillo claunia@claunia.com
//
// Copyright (c) 2016, © Claunia.com
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("Claunia.RsrcFork")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("Claunia.com")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("© Claunia.com")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

View File

@@ -0,0 +1,167 @@
//
// Resource.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// 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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Claunia.RsrcFork
{
public class Resource
{
readonly Dictionary<short, string> resourceNames;
readonly Dictionary<short, ResourceData> resources;
readonly Dictionary<short, byte[]> resourceCache;
readonly Stream rsrcStream;
readonly List<short> ids;
struct ResourceData
{
public long offset;
public long length;
}
/// <summary>
/// Initializates the specified resource type
/// </summary>
/// <param name="stream">Stream where the resources of this reside.</param>
/// <param name="resources">How many resource of this type are.</param>
/// <param name="referenceListOff">Offset from start of stream to reference list for this type.</param>
/// <param name="resourceNameOffset">Offset from start of stream to resource name list.</param>
/// <param name="resourceDataOffset">Offset from start of stream to resource data.</param>
/// <param name="OSType">Resource type.</param>
internal Resource(Stream stream, ushort resources, long referenceListOff, long resourceNameOffset, long resourceDataOffset, uint OSType)
{
rsrcStream = stream;
Dictionary<short, ResourceTypeReferenceListItem> referenceLists = new Dictionary<short, ResourceTypeReferenceListItem>();
resourceNames = new Dictionary<short, string>();
this.resources = new Dictionary<short, ResourceData>();
ids = new List<short>();
byte[] tmp;
rsrcStream.Seek(referenceListOff + 2, SeekOrigin.Begin);
for(int i = 0; i < resources; i++)
{
ResourceTypeReferenceListItem item = new ResourceTypeReferenceListItem();
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);
tmp = new byte[4];
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);
referenceLists.Add(item.id, item);
ids.Add(item.id);
}
foreach(ResourceTypeReferenceListItem item in referenceLists.Values)
{
string name;
ResourceData data = new ResourceData();
if(item.nameOff == -1)
name = null;
else
{
rsrcStream.Seek(resourceNameOffset + item.nameOff, SeekOrigin.Begin);
byte nameLen = (byte)rsrcStream.ReadByte();
byte[] nameBytes = new byte[nameLen];
rsrcStream.Read(nameBytes, 0, nameLen);
// TODO: Use MacRoman
name = Encoding.ASCII.GetString(nameBytes);
}
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);
resourceNames.Add(item.id, name);
this.resources.Add(item.id, data);
}
resourceCache = new Dictionary<short, byte[]>();
}
/// <summary>
/// Gets the name of the specified resource id, or null if there is no name
/// </summary>
/// <returns>The name.</returns>
/// <param name="id">Identifier.</param>
public string GetName(short id)
{
string name;
return resourceNames.TryGetValue(id, out name) ? name : null;
}
/// <summary>
/// Gets the resource contents
/// </summary>
/// <returns>The resource.</returns>
/// <param name="id">Identifier.</param>
public byte[] GetResource(short id)
{
byte[] resource;
if(resourceCache.TryGetValue(id, out resource))
return resource;
ResourceData data;
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);
return resource;
}
public long GetLength(short id)
{
ResourceData data;
return !resources.TryGetValue(id, out data) ? 0 : data.length;
}
public short[] GetIds()
{
return ids.ToArray();
}
}
}

View File

@@ -0,0 +1,188 @@
//
// ResourceFork.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// 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
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Claunia.RsrcFork
{
public class ResourceFork
{
Stream rsrcStream;
ResourceHeader header;
ResourceMap map;
Dictionary<uint, ResourceTypeListItem> resourceTypeList;
Dictionary<uint, Resource> resourceCache;
List<uint> osTypes;
/// <summary>
/// Initializates a resource fork using a byte array as backend
/// </summary>
/// <param name="buffer">Buffer.</param>
public ResourceFork(byte[] buffer)
{
rsrcStream = new MemoryStream(buffer, false);
Init();
}
/// <summary>
/// Initializates a resource fork using a stream as backed
/// </summary>
/// <param name="stream">Stream.</param>
public ResourceFork(Stream stream)
{
rsrcStream = stream;
Init();
}
~ResourceFork()
{
if(rsrcStream != null)
rsrcStream.Close();
}
public void Init()
{
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);
if(header.resourceDataOff <= 0 || header.resourceDataOff <= 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)
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(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);
// 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);
resourceTypeList = new Dictionary<uint, ResourceTypeListItem>();
osTypes = new List<uint>();
for(int i = 0; i <= map.numberOfTypes; i++) {
ResourceTypeListItem typeList = new ResourceTypeListItem();
tmp = new byte[4];
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);
resourceTypeList.Add(typeList.type, typeList);
osTypes.Add(typeList.type);
}
resourceCache = new Dictionary<uint, Resource>();
}
/// <summary>
/// Gets the resources with indicated type
/// </summary>
/// <returns>The resource.</returns>
/// <param name="OSType">OSType.</param>
public Resource GetResource(uint OSType)
{
Resource rsrc;
if(resourceCache.TryGetValue(OSType, out rsrc))
return rsrc;
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);
resourceCache.Add(OSType, rsrc);
return rsrc;
}
/// <summary>
/// Gets all OSTypes stored in this resource fork
/// </summary>
/// <returns>The types.</returns>
public uint[] GetTypes()
{
return osTypes.ToArray();
}
/// <summary>
/// Returns true if the specified OSType is present in this resource fork.
/// </summary>
/// <param name="OSType">OSType.</param>
public bool ContainsKey(uint OSType)
{
return resourceTypeList.ContainsKey(OSType);
}
}
}

121
Claunia.RsrcFork/Structs.cs Normal file
View File

@@ -0,0 +1,121 @@
//
// Structs.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// 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.
namespace Claunia.RsrcFork
{
struct ResourceHeader
{
/// <summary>
/// Offset from start of resource fork to resource data
/// </summary>
public int resourceDataOff;
/// <summary>
/// Offset from start of resource fork to resource map
/// </summary>
public int resourceMapOff;
/// <summary>
/// Length of resource data
/// </summary>
public int resourceDataLen;
/// <summary>
/// Length of resource map
/// </summary>
public int resourceMapLen;
}
struct ResourceMap
{
/// <summary>
/// Copy of the resource fork header
/// </summary>
public ResourceHeader header;
/// <summary>
/// Reserved for handle to next resource map
/// </summary>
public uint handleToNextMap;
/// <summary>
/// Reserved for file reference number
/// </summary>
public ushort fileRefNo;
/// <summary>
/// Resource fork attributes
/// </summary>
public ushort attributes;
/// <summary>
/// Offset from start of resource map to resource type list
/// </summary>
public short typeListOff;
/// <summary>
/// Offset from start of resource map to resource name list
/// </summary>
public short nameListOff;
/// <summary>
/// Number of types in the map minus 1
/// </summary>
public ushort numberOfTypes;
}
struct ResourceTypeListItem
{
/// <summary>
/// Resource type
/// </summary>
public uint type;
/// <summary>
/// Number of resources of this type minus 1
/// </summary>
public ushort resources;
/// <summary>
/// Offset from beginning of resource type list to reference list
/// </summary>
public short referenceOff;
}
struct ResourceTypeReferenceListItem
{
/// <summary>
/// Resource ID
/// </summary>
public short id;
/// <summary>
/// Offset from beginning of resource name list to resource name. -1 if it does not have a name
/// </summary>
public short nameOff;
/// <summary>
/// Resource attributes
/// </summary>
public byte attributes;
/// <summary>
/// Offset from beginning of resource data to resource. First byte is <see cref="attributes"/>.
/// </summary>
public int dataOff;
/// <summary>
/// Reserved for handle to resource
/// </summary>
public uint handle;
}
}

419
Claunia.RsrcFork/Types.cs Normal file
View File

@@ -0,0 +1,419 @@
//
// Types.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// 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;
using System.Linq;
namespace Claunia.RsrcFork
{
public static class Types
{
public static string GetName(uint OSType)
{
switch(OSType) {
case 0x61637462: // "actb"
return "Alert colour table";
case 0x61637572: // "acur"
return "Animated cursor";
case 0x41444253: // "ADBS"
return "Apple Desktop Bus service routine";
case 0x616C6973: // "alis"
return "Alias";
case 0x414C5254: // "ALRT"
return "Alert template";
case 0x4150504C: // "APPL"
return "Application list (Desktop file)";
case 0x6174706C: // "atpl"
return "AppleTalk resource";
case 0x626C6B78: // "blkx"
return "UDIF block chunks";
case 0x626D6170: // "bmap"
return "Bitmap graphic";
case 0x424E444C: // "BNDL"
return "Bundle linking FREF and ICN# to provide correct icon on Desktop";
case 0x424E444E: // "BNDN"
return "Data configured in big-endian form";
case 0x424F4F4C: // "BOOL"
return "Boolean word";
case 0x626F6F74: // "boot"
return "Copy of boot blocks";
case 0x43414348: // "CACH"
return "RAM cache control code";
case 0x63637462: // "cctb"
return "Control colour table";
case 0x43444546: // "CDEF"
return "Control definition";
case 0x63646576: // "cdev"
return "Control device code (control panel)";
case 0x63667267: // "cfrg"
return "Code fragment dictionary for PowerPC code";
case 0x43484152: // "CHAR"
return "ASCII character";
case 0x6369636E: // "cicn"
return "Large screen icon, colour";
case 0x434C5554: // "CLUT"
return "Color look-up table";
case 0x636C7574: // "clut"
return "Color look-up table";
case 0x434E544C: // "CNTL"
return "Control template";
case 0x434D444F: // "CMDO"
return "MPW or A/UX Comando data";
case 0x434D4E55: // "CMNU"
return "Menu with command ID numbers";
case 0x636D6E75: // "cmnu"
return "MacApp temporary menu resource";
case 0x434F4445: // "CODE"
return "Application code segment";
case 0x434F4C52: // "COLR"
return "QuickDraw RGB colour template";
case 0x63727372: // "crsr"
return "Cursor, colour";
case 0x63746162: // "ctag"
return "Cache table containing list of possible cache sizes";
case 0x43545923: // "CTY#"
return "City list";
case 0x43555253: // "CURS"
return "Cursor, black & white with mask";
case 0x44415441: // "DATA"
return "Data";
case 0x44415445: // "DATE"
return "System date and time";
case 0x64637462: // "dctb"
return "Dialog colour table";
case 0x4449434C: // "DICL"
return "Used by MacWorkstation";
case 0x4449544C: // "DITL"
return "Dialog item list";
case 0x444C4F47: // "DLOG"
return "Dialog template";
case 0x44525652: // "DRVR"
return "Driver";
case 0x44534154: // "DSAT"
return "Default startup alert table";
case 0x65727273: // "errs"
return "MacApp error string";
case 0x4642544E: // "FBTN"
return "MiniFinder button";
case 0x46434D54: // "FCMT"
return "Finder comment";
case 0x66637462: // "fctb"
return "Font colour table";
case 0x46444952: // "FDIR"
return "MiniFinder button directory ID";
case 0x66696E66: // "finf"
return "Font information";
case 0x464B4559: // "FKEY"
return "Function Key code";
case 0x666C6423: // "fld#"
return "Folder names list";
case 0x464C5452: // "FLTR"
return "Declare Filtered Template with comment";
case 0x666D6E75: // "fmnu"
return "Finder menu";
case 0x464D5452: // "FMTR"
return "Format record";
case 0x464F424A: // "FOBJ"
return "Folder information";
case 0x464F4E44: // "FOND"
return "Font family descriptor";
case 0x464F4E54: // "FONT"
return "Font description, bitmap";
case 0x66505254: // "fPRT"
return "Print Catalogue defaults for Finder";
case 0x46524546: // "FREF"
return "File reference for BNDL used to identify correct icon";
case 0x46525356: // "FRSV"
return "ROM font resources";
case 0x46574944: // "FWID"
return "Font width table";
case 0x67616D61: // "gama"
return "Gamma table giving color correction for screen";
case 0x474E524C: // "GNRL"
return "NBP timeout and retry info for AppleTalk";
case 0x68646C67: // "hdlg"
return "Balloon Help for dialog box items";
case 0x68666472: // "hfdr"
return "Balloon Help for application icon in Finder";
case 0x686D6E75: // "hmnu"
return "Balloon Help for menus in application";
case 0x686F7672: // "hovr"
return "Balloon Help that overrides Finder help";
case 0x68726374: // "hrct"
return "Balloon Help for rectangles in windows";
case 0x6877696E: // "hwin"
return "Bundles together the hrct and hdlg resources for a window";
case 0x69636C34: // "icl4"
return "Large Desktop icon, 4-bit colour";
case 0x69636C38: // "icl8"
return "Large Desktop icon, 8-bit colour";
case 0x69636D74: // "icmt"
return "Installer comment";
case 0x69636E73: // "icns"
return "Universal icon, all sizes";
case 0x49434E23: // "ICN#"
return "Large Desktop icon, black & white with mask";
case 0x49434F4E: // "ICON"
return "Large application icon, black & white";
case 0x69637334: // "ics4"
return "Small Desktop icon, 4-bit colour";
case 0x69637338: // "ics8"
return "Small Desktop icon, 8-bit colour";
case 0x69637323: // "ics#"
return "Small Desktop icon, black and white with mask";
case 0x69637462: // "ictb"
return "Dialog items colour table";
case 0x696E6262: // "inbb"
return "Installer boot block";
case 0x696E646D: // "indm"
return "Installer default map";
case 0x696E6661: // "infa"
return "Installer file atom";
case 0x696E6673: // "infs"
return "Installer file spec";
case 0x696E706B: // "inpk"
return "Installer package";
case 0x696E7261: // "inra"
return "Installer resource atom";
case 0x696E7363: // "insc"
return "Installer script";
case 0x494E4954: // "INIT"
return "Startup resource (extension, control panel or System file)";
case 0x69746C30: // "itl0"
return "International date and time format, now obsolete (INTL ID=0)";
case 0x49544C31: // "ITL1"
return "International long date format";
case 0x69746C31: // "itl1"
return "International names of days and months (INTL ID=1)";
case 0x69746C32: // "itl2"
return "International Utilities string comparison hooks";
case 0x69746C34: // "itl4"
return "International Tokenise tables & Localisation code";
case 0x69746C35: // "itl5"
return "International Character Set encoding";
case 0x69746C62: // "itlb"
return "International Utilities Package Script bundles";
case 0x69746C63: // "itlc"
return "International Script Manager configuration";
case 0x69746C6D: // "itlm"
return "Sorting order for Script, language and region";
case 0x69746C6B: // "itlk"
return "International exception dictionary for KCHR";
case 0x494E544C: // "INTL"
return "International formatting information";
case 0x4B434150: // "KCAP"
return "Physical keyboard layout used by Keycaps DA";
case 0x4B434852: // "KCHR"
return "Keyboard character software ASCII mapping";
case 0x4B455943: // "KEYC"
return "Old keyboard layout";
case 0x6B696E64: // "kind"
return "File description";
case 0x4B4D4150: // "KMAP"
return "Hardware keyboard mapping";
case 0x6B73636E: // "kscn"
return "Keyboard and script system icon";
case 0x4B535750: // "KSWP"
return "Keyboard script swapping table";
case 0x4C41594F: // "LAYO"
return "Layout resource";
case 0x4C444546: // "LDEF"
return "List definition";
case 0x6C6D656D: // "lmem"
return "Finder low memory globals";
case 0x4C4E444E: // "LNDN"
return "Data in little-endian format";
case 0x4C4E4743: // "LNGC"
return "Mac OS language code";
case 0x6D616368: // "mach"
return "Matches machine to CDEV control panel (control panel)";
case 0x4D414353: // "MACS"
return "Version number for System and Finder files";
case 0x4D424446: // "MBDF"
return "Default menu definition";
case 0x4D424152: // "MBAR"
return "Menu bar, contains set of MENU IDs";
case 0x6D636B79: // "mcky"
return "Mouse tracking speed presets for Mouse control panel";
case 0x6D636F64: // "mcod"
return "MacroMaker information";
case 0x6D637462: // "mctb"
return "Menu colour table";
case 0x4D444154: // "MDAT"
return "Modification date and time";
case 0x6D646374: // "mdct"
return "MacroMaker information";
case 0x4D444546: // "MDEF"
return "Menu definition";
case 0x6D656D21: // "mem!"
return "MacApp memory usage";
case 0x4D454E55: // "MENU"
return "Menu contents & style";
case 0x6D696E66: // "minf"
return "Macro info for MacroMaker";
case 0x6D697471: // "mitq"
return "Internal memory needs for colour Make Inverse Table";
case 0x6D6E7462: // "mntb"
return "MacApp menu table, relating command number to menu item";
case 0x4D6F6F56: // "MooV"
return "Movie";
case 0x6D707063: // "mppc"
return "MPP configuration resource";
case 0x6D737472: // "mstr"
return "Finder substitute file storing Open and Quit strings";
case 0x4E425043: // "NBPC"
return "AppleTalk NBP configuration";
case 0x4E464E54: // "NFNT"
return "New Font Numbering Table bitmap font, indexed via Font & Style menus";
case 0x6E637473: // "ncts"
return "List of constants";
case 0x6E726374: // "nrct"
return "Rectangle position list";
case 0x6F70656E: // "open"
return "Openable file types";
case 0x5041434B: // "PACK"
return "High-level software packages";
case 0x50415041: // "PAPA"
return "Printer name, type and zone";
case 0x50415420: // "PAT "
return "Black & white QuickDraw pattern, 8 by 8 pixels";
case 0x50415423: // "PAT#"
return "Black & white QuickDraw pattern list";
case 0x50444546: // "PDEF"
return "Printer definition";
case 0x50494354: // "PICT"
return "Picture";
case 0x706C7374: // "plst"
return "UDIF partition list";
case 0x706C7474: // "pltt"
return "Colour palette";
case 0x706E6F74: // "pnot"
return "Preview notification";
case 0x504E5420: // "PNT "
return "QuickDraw Point";
case 0x504F5354: // "POST"
return "PostScript data";
case 0x70706174: // "ppat"
return "Colour pixel pattern";
case 0x70706363: // "ppcc"
return "PPC browser communications";
case 0x70707423: // "ppt#"
return "List of ppat patterns";
case 0x50524546: // "PREF"
return "Preferences";
case 0x50524330: // "PRC0"
return "Default printer page setup defaults";
case 0x50524333: // "PRC3"
return "Print record";
case 0x50524543: // "PREC"
return "Printer driver's private data";
case 0x50534150: // "PSAP"
return "String";
case 0x50544348: // "PTCH"
return "ROM patch code";
case 0x71727363: // "qrsc"
return "Query resource used in Sytem 7.0";
case 0x52454354: // "RECT"
return "QuickDraw rectangle";
case 0x7265736C: // "resl"
return "Resident MacApp segments";
case 0x52474E43: // "RGNC"
return "Mac OS System Region Code";
case 0x524F7623: // "ROv#"
return "List of ROM resource overrides";
case 0x52534944: // "RSID"
return "Signed resource ID integer";
case 0x53435043: // "SCPC"
return "MacOS system script code";
case 0x7363726E: // "scrn"
return "Screen configuration for Monitors control panel";
case 0x73656721: // "seg!"
return "MacApp memory management";
case 0x53455244: // "SERD"
return "RAMSerial Driver";
case 0x73666E23: // "sfn#"
return "System Font list";
case 0x73666E74: // "sfnt"
return "Spline or scalable font";
case 0x5349434E: // "SICN"
return "Small application icon, black & white";
case 0x53495A45: // "SIZE"
return "Finder size information";
case 0x736E6420: // "snd "
return "Sound";
case 0x736E7468: // "snth"
return "Sound synthesiser resource";
case 0x53545220: // "STR "
return "String in Pascal format";
case 0x53545223: // "STR#"
return "String list in Pascal format";
case 0x7374796C: // "styl"
return "Style information for text used by TextEdit";
case 0x7379737A: // "sysz"
return "System Heap request";
case 0x54455854: // "TEXT"
return "Unlabelled text string";
case 0x746C7374: // "tlst"
return "Title list";
case 0x544D504C: // "TMPL"
return "ResEdit template";
case 0x544E414D: // "TNAM"
return "Type name";
case 0x76696577: // "view"
return "MacApp view resource";
case 0x76657273: // "vers"
return "Version";
case 0x77637462: // "wctb"
return "Window colour table";
case 0x57444546: // "WDEF"
return "Window definition";
case 0x57494E44: // "WIND"
return "Window template";
case 0x77737472: // "wstr"
return "String used by qrsc";
case 0x58434D44: // "XCMD"
return "HyperCard external command";
case 0x5846434E: // "XFCN"
return "HyperCard external function";
default:
return null;
}
}
public static string GetName(string OSType)
{
if(OSType.Length != 4)
return null;
byte[] typB = Encoding.ASCII.GetBytes(OSType);
uint type = BitConverter.ToUInt32(typB.Reverse().ToArray(), 0);
return GetName(type);
}
}
}

19
LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2015-2016 Natalia Portillo <claunia@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.

6
README.md Normal file
View File

@@ -0,0 +1,6 @@
Claunia.RsrcFork
================
Copyright © 2011-2016 Natalia Portillo <claunia@claunia.com>
Library and command line application for handling resource forks.