Compare commits

12 Commits
v1.0 ... master

23 changed files with 1504 additions and 1699 deletions

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownProjectSettings" wasCopied="true">
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true" replaceUnicodeEmoji="false" lastLayoutSetsDefault="false">
<PanelProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
</PanelProvider>
</PreviewSettings>
<ParserSettings gitHubSyntaxChange="false" emojiShortcuts="1" emojiImages="0">
<PegdownExtensions>
<option name="ABBREVIATIONS" value="false" />
<option name="ANCHORLINKS" value="true" />
<option name="ASIDE" value="false" />
<option name="ATXHEADERSPACE" value="true" />
<option name="AUTOLINKS" value="true" />
<option name="DEFINITIONS" value="false" />
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
<option name="FENCED_CODE_BLOCKS" value="true" />
<option name="FOOTNOTES" value="false" />
<option name="HARDWRAPS" value="false" />
<option name="HTML_DEEP_PARSER" value="false" />
<option name="INSERTED" value="false" />
<option name="QUOTES" value="false" />
<option name="RELAXEDHRULES" value="true" />
<option name="SMARTS" value="false" />
<option name="STRIKETHROUGH" value="true" />
<option name="SUBSCRIPT" value="false" />
<option name="SUPERSCRIPT" value="false" />
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
<option name="SUPPRESS_INLINE_HTML" value="false" />
<option name="TABLES" value="true" />
<option name="TASKLISTITEMS" value="true" />
<option name="TOC" value="false" />
<option name="WIKILINKS" value="false" />
</PegdownExtensions>
<ParserOptions>
<option name="ADMONITION_EXT" value="false" />
<option name="ATTRIBUTES_EXT" value="false" />
<option name="COMMONMARK_LISTS" value="true" />
<option name="DUMMY" value="false" />
<option name="EMOJI_SHORTCUTS" value="true" />
<option name="ENUMERATED_REFERENCES_EXT" value="false" />
<option name="FLEXMARK_FRONT_MATTER" value="false" />
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
<option name="GFM_TABLE_RENDERING" value="true" />
<option name="GITBOOK_URL_ENCODING" value="false" />
<option name="GITHUB_LISTS" value="false" />
<option name="GITHUB_WIKI_LINKS" value="false" />
<option name="GITLAB_EXT" value="false" />
<option name="GITLAB_MATH_EXT" value="false" />
<option name="GITLAB_MERMAID_EXT" value="false" />
<option name="HEADER_ID_NON_ASCII_TO_LOWERCASE" value="false" />
<option name="HEADER_ID_NO_DUPED_DASHES" value="false" />
<option name="JEKYLL_FRONT_MATTER" value="false" />
<option name="MACROS_EXT" value="false" />
<option name="NO_TEXT_ATTRIBUTES" value="false" />
<option name="PARSE_HTML_ANCHOR_ID" value="false" />
<option name="PLANTUML_FENCED_CODE" value="false" />
<option name="PUML_FENCED_CODE" value="false" />
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
</ParserOptions>
</ParserSettings>
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" plantUmlConversion="0" mathConversion="-1">
<GeneratorProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
</GeneratorProvider>
<headerTop />
<headerBottom />
<bodyTop />
<bodyBottom />
</HtmlSettings>
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
<StylesheetProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
</StylesheetProvider>
<ScriptProviders />
<cssText />
<cssUriHistory />
</CssSettings>
<AnnotatorSettings targetHasSpaces="true" linkCaseMismatch="true" wikiCaseMismatch="true" wikiLinkHasDashes="true" notUnderWikiHome="true" targetNotWikiPageExt="true" notUnderSourceWikiHome="true" targetNameHasAnchor="true" targetPathHasAnchor="true" wikiLinkHasSlash="true" wikiLinkHasSubdir="true" wikiLinkHasOnlyAnchor="true" linkTargetsWikiHasExt="true" linkTargetsWikiHasBadExt="true" notUnderSameRepo="true" targetNotUnderVcs="false" linkNeedsExt="true" linkHasBadExt="true" linkTargetNeedsExt="true" linkTargetHasBadExt="true" wikiLinkNotInWiki="true" imageTargetNotInRaw="true" repoRelativeAcrossVcsRoots="true" multipleWikiTargetsMatch="true" unresolvedLinkReference="true" linkIsIgnored="true" anchorIsIgnored="true" anchorIsUnresolved="true" anchorLineReferenceIsUnresolved="true" anchorLineReferenceFormat="true" anchorHasDuplicates="true" abbreviationDuplicates="true" abbreviationNotUsed="true" attributeIdDuplicateDefinition="true" attributeIdNotUsed="true" footnoteDuplicateDefinition="true" footnoteUnresolved="true" footnoteDuplicates="true" footnoteNotUsed="true" macroDuplicateDefinition="true" macroUnresolved="true" macroDuplicates="true" macroNotUsed="true" referenceDuplicateDefinition="true" referenceUnresolved="true" referenceDuplicates="true" referenceNotUsed="true" referenceUnresolvedNumericId="true" enumRefDuplicateDefinition="true" enumRefUnresolved="true" enumRefDuplicates="true" enumRefNotUsed="true" enumRefLinkUnresolved="true" enumRefLinkDuplicates="true" simTocUpdateNeeded="true" simTocTitleSpaceNeeded="true" />
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="css" scriptDir="js" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
<LinkMapSettings>
<textMaps />
</LinkMapSettings>
</component>
</project>

View File

@@ -0,0 +1,3 @@
<component name="MarkdownNavigator.ProfileManager">
<settings default="" pdf-export="" plain-text-search-scope="Project Files" />
</component>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MacroExpansionManager">
<option name="directoryName" value="zznODNyy" />
</component>
<component name="com.jetbrains.rider.android.RiderAndroidMiscFileCreationComponent">
<option name="ENSURE_MISC_FILE_EXISTS" value="true" />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -9,6 +8,8 @@
<AssemblyName>Claunia.RsrcFork.CLI</AssemblyName>
<ReleaseVersion>1.0</ReleaseVersion>
<SynchReleaseVersion>false</SynchReleaseVersion>
<TargetFramework>net6.0</TargetFramework>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -28,11 +29,7 @@
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Program.cs"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Claunia.RsrcFork\Claunia.RsrcFork.csproj">
@@ -46,15 +43,4 @@
<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

@@ -4,7 +4,7 @@
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2016 © Claunia.com
// Copyright (c) 2016-2019 Natalia Portillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -23,102 +23,95 @@
// 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;
using System.Text;
namespace Claunia.RsrcFork.CLI
namespace Claunia.RsrcFork.CLI;
internal class MainClass
{
class MainClass
public static void Main(string[] args)
{
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)
{
Console.WriteLine("Claunia.RsrcFork.CLI");
Console.WriteLine("© 2016 Natalia Portillo");
Console.WriteLine();
Usage();
if(args.Length != 2 && args.Length != 4)
{
return;
}
switch(args.Length)
{
case 2 when args[0] != "-l":
Usage();
return;
}
case 2 when !File.Exists(args[1]):
Console.WriteLine("Specified file does not exist.");
if(args.Length == 2)
return;
case 2:
{
if(args[0] != "-l")
{
Usage();
return;
}
var rsrcStream = new FileStream(args[1], FileMode.Open, FileAccess.Read);
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);
var 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);
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();
if(args.Length == 4)
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:
{
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);
var rsrcStream = new FileStream(args[3], FileMode.Open, FileAccess.Read);
FileStream outStream;
ResourceFork rsrc = new ResourceFork(rsrcStream);
var rsrc = new ResourceFork(rsrcStream);
foreach(uint type in rsrc.GetTypes())
{
@@ -128,25 +121,28 @@ namespace Claunia.RsrcFork.CLI
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);
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();
}
}
return;
break;
}
}
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");
}
}
}
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

@@ -1,52 +0,0 @@
//
// 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

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -9,6 +8,8 @@
<AssemblyName>Claunia.RsrcFork.Test</AssemblyName>
<ReleaseVersion>1.0</ReleaseVersion>
<SynchReleaseVersion>false</SynchReleaseVersion>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -28,16 +29,9 @@
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
</Reference>
<Compile Include="Test.cs"/>
</ItemGroup>
<ItemGroup>
<Compile Include="Test.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Samples\SelfMountingImage.rsrc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -52,7 +46,7 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Samples\" />
<Folder Include="Samples\"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Claunia.RsrcFork\Claunia.RsrcFork.csproj">
@@ -65,13 +59,16 @@
<Link>LICENSE</Link>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0"/>
<PackageReference Include="NUnit" Version="3.13.2"/>
</ItemGroup>
<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" />
<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>

View File

@@ -4,7 +4,7 @@
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2016 © Claunia.com
// Copyright (c) 2016-2019 Natalia Portillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -28,201 +28,206 @@ using System.IO;
using NUnit.Framework;
using Resources;
namespace Claunia.RsrcFork.Test
namespace Claunia.RsrcFork.Test;
[TestFixture]
public class Test
{
[TestFixture]
public class Test
readonly byte[] DC42_Vers =
{
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 };
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);
[Test]
public void TestDC42()
{
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]);
Assert.AreEqual(0x76657273, types[1]);
uint[] types = rsrc.GetTypes();
Assert.AreEqual(0x53545220, types[0]);
Assert.AreEqual(0x76657273, types[1]);
Resource str_ = rsrc.GetResource(0x53545220);
Assert.IsNotNull(str_);
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));
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);
byte[] str1 = str_.GetResource(-16396);
Assert.AreEqual(DC42_Str, str1);
string strStr = str_.GetName(-16396);
Assert.IsNull(strStr);
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));
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);
byte[] vers1 = vers.GetResource(1);
Assert.AreEqual(DC42_Vers, vers1);
string versStr = vers.GetName(1);
Assert.IsNull(versStr);
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]
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);
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]
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);
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]
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);
Resource vers = rsrc.GetResource(0x76657273);
Assert.IsNull(vers);
}
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("4.2, data checksum=$A5147F7E", versDec.VersionMessage);
}
}
[Test]
public void TestDC6()
{
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]);
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);
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()
{
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(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);
Resource vers = rsrc.GetResource(0x76657273);
Assert.IsNotNull(vers);
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()
{
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(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);
Resource vers = rsrc.GetResource(0x76657273);
Assert.IsNull(vers);
}
}

View File

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

View File

@@ -1,63 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\NuGet.Build.Packaging.0.1.248\build\NuGet.Build.Packaging.props" Condition="Exists('..\packages\NuGet.Build.Packaging.0.1.248\build\NuGet.Build.Packaging.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<VersionPrefix>1.1</VersionPrefix>
<Company>Claunia.com</Company>
<Copyright>© 2016-2021 Natalia Portillo</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<NeutralLanguage>en-US</NeutralLanguage>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<LangVersion>latest</LangVersion>
<ProjectGuid>{CA231ED3-0C78-496C-AAFE-D085F6E9BEC6}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Claunia.RsrcFork</RootNamespace>
<AssemblyName>Claunia.RsrcFork</AssemblyName>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ReleaseVersion>1.0</ReleaseVersion>
<ReleaseVersion>1.2</ReleaseVersion>
<SynchReleaseVersion>false</SynchReleaseVersion>
<PackageId>Claunia.RsrcFork</PackageId>
<PackageVersion>1.0</PackageVersion>
<PackageVersion>1.2</PackageVersion>
<Authors>Natalia Portillo</Authors>
<PackageLicenseUrl>https://raw.githubusercontent.com/claunia/Claunia.RsrcFork/master/LICENSE</PackageLicenseUrl>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Owners>claunia</Owners>
<PackageProjectUrl>https://www.github.com/claunia/Claunia.RsrcFork</PackageProjectUrl>
<Summary>Library for handling resource forks.</Summary>
<Title>Claunia.RsrcFork</Title>
<Description>Library for handling resource forks.</Description>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<PackageReleaseNotes>Update to .NET 6.</PackageReleaseNotes>
<TargetFramework>net6.0</TargetFramework>
</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 Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;RELEASE</DefineConstants>
<DocumentationFile>bin\Release\Claunia.RsrcFork.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG</DefineConstants>
</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" />
<Compile Include="Resources\Version.cs" />
<Compile Include="PascalString.cs" />
</ItemGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith('netcoreapp')) Or $(TargetFramework.StartsWith('netstandard'))">
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<DefineConstants>$(DefineConstants);NATIVE_SPAN</DefineConstants>
</PropertyGroup>
<ItemGroup>
<None Include="..\README.md">
<Link>README.md</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\LICENSE">
@@ -68,22 +62,4 @@
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy FileWidth="120" TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" TabsToSpaces="True" scope="text/x-csharp">
<inheritsSet />
<inheritsScope />
</TextStylePolicy>
<CSharpFormattingPolicy IndentBlock="True" IndentBraces="False" IndentSwitchSection="True" IndentSwitchCaseSection="True" LabelPositioning="OneLess" NewLinesForBracesInTypes="True" NewLinesForBracesInMethods="True" NewLineForMembersInObjectInit="False" NewLineForMembersInAnonymousTypes="False" NewLineForClausesInQuery="False" SpacingAfterMethodDeclarationName="False" SpaceWithinMethodDeclarationParenthesis="False" SpaceBetweenEmptyMethodDeclarationParentheses="False" SpaceAfterMethodCallName="False" SpaceWithinMethodCallParentheses="False" SpaceBetweenEmptyMethodCallParentheses="False" SpaceAfterControlFlowStatementKeyword="False" SpaceWithinExpressionParentheses="False" SpaceWithinCastParentheses="False" SpaceWithinOtherParentheses="False" SpaceAfterCast="False" SpacesIgnoreAroundVariableDeclaration="False" SpaceBeforeOpenSquareBracket="False" SpaceBetweenEmptySquareBrackets="False" SpaceWithinSquareBrackets="False" SpaceAfterColonInBaseTypeDeclaration="True" SpaceAfterComma="True" SpaceAfterDot="False" SpaceAfterSemicolonsInForStatement="True" SpaceBeforeColonInBaseTypeDeclaration="True" SpaceBeforeComma="False" SpaceBeforeDot="False" SpaceBeforeSemicolonsInForStatement="False" SpacingAroundBinaryOperator="Single" WrappingPreserveSingleLine="True" WrappingKeepStatementsOnSingleLine="True" PlaceSystemDirectiveFirst="True" NewLinesForBracesInProperties="False" NewLinesForBracesInAccessors="False" NewLinesForBracesInAnonymousMethods="False" NewLinesForBracesInControlBlocks="False" NewLinesForBracesInAnonymousTypes="False" NewLinesForBracesInObjectCollectionArrayInitializers="False" NewLinesForBracesInLambdaExpressionBody="False" NewLineForElse="False" NewLineForCatch="False" NewLineForFinally="False" scope="text/x-csharp">
<inheritsSet />
<inheritsScope />
</CSharpFormattingPolicy>
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
<Import Project="..\packages\NuGet.Build.Packaging.0.1.248\build\NuGet.Build.Packaging.targets" Condition="Exists('..\packages\NuGet.Build.Packaging.0.1.248\build\NuGet.Build.Packaging.targets')" />
</Project>

View File

@@ -4,7 +4,7 @@
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2016 © Claunia.com
// Copyright (c) 2016-2021 Natalia Portillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -23,51 +23,37 @@
// 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
namespace Claunia.RsrcFork;
/// <summary>Contains convertes between .NET and Pascal strings. Only ASCII supported right now.</summary>
public static class PascalString
{
/// <summary>
/// Contains convertes between .NET and Pascal strings. Only ASCII supported right now.
/// </summary>
public static class PascalString
/// <summary>Converts an ASCII Pascal string to a .NET string.</summary>
/// <returns>The .NET string.</returns>
/// <param name="PStr">The ASCII Pascal string.</param>
public static string GetString(byte[] PStr) =>
PStr == null || PStr[0] >= PStr.Length ? null : Encoding.ASCII.GetString(PStr, 1, PStr[0]);
/// <summary>Converts a .NET string to an ASCII Pascal string.</summary>
/// <returns>The ASCII Pascal string.</returns>
/// <param name="str">The .NET string.</param>
public static byte[] GetBytes(string str)
{
/// <summary>
/// Converts an ASCII Pascal string to a .NET string.
/// </summary>
/// <returns>The .NET string.</returns>
/// <param name="PStr">The ASCII Pascal string.</param>
public static string GetString(byte[] PStr)
{
if(PStr == null || PStr[0] >= PStr.Length)
return null;
if(str == null)
return new byte[1];
return Encoding.ASCII.GetString(PStr, 1, PStr[0]);
}
byte[] str_b = Encoding.ASCII.GetBytes(str);
byte[] PStr;
/// <summary>
/// Converts a .NET string to an ASCII Pascal string.
/// </summary>
/// <returns>The ASCII Pascal string.</returns>
/// <param name="str">The .NET string.</param>
public static byte[] GetBytes(string str)
{
if(str == null)
return new byte[1];
byte[] str_b = Encoding.ASCII.GetBytes(str);
byte[] PStr;
PStr = str_b.Length >= 256 ? new byte[256] : new byte[str_b.Length + 1];
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);
Array.Copy(str_b, 0, PStr, 1, PStr.Length - 1);
PStr[0] = (byte)(PStr.Length - 1);
return PStr;
}
return PStr;
}
}
}

View File

@@ -1,54 +0,0 @@
//
// 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

@@ -4,7 +4,7 @@
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2016 © Claunia.com
// Copyright (c) 2016-2021 Natalia Portillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -30,160 +30,129 @@ using System.IO;
using System.Linq;
using System.Text;
namespace Claunia.RsrcFork
namespace Claunia.RsrcFork;
/// <summary>This class represents a resource type.</summary>
public class Resource
{
/// <summary>
/// This class represents a resource type.
/// </summary>
public class Resource
readonly List<short> _ids;
readonly Dictionary<short, byte[]> _resourceCache;
readonly Dictionary<short, string> _resourceNames;
readonly Dictionary<short, ResourceData> _resources;
readonly Stream _rsrcStream;
/// <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)
{
readonly Dictionary<short, string> resourceNames;
readonly Dictionary<short, ResourceData> resources;
readonly Dictionary<short, byte[]> resourceCache;
readonly Stream rsrcStream;
readonly List<short> ids;
_rsrcStream = stream;
Dictionary<short, ResourceTypeReferenceListItem> referenceLists = new();
_resourceNames = new Dictionary<short, string>();
_resources = new Dictionary<short, ResourceData>();
_ids = new List<short>();
byte[] tmp;
struct ResourceData
_rsrcStream.Seek(referenceListOff + 2, SeekOrigin.Begin);
for(int i = 0; i < resources; i++)
{
public long offset;
public long length;
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);
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);
}
/// <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)
foreach(ResourceTypeReferenceListItem item in referenceLists.Values)
{
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;
string name;
ResourceData data = new();
rsrcStream.Seek(referenceListOff + 2, SeekOrigin.Begin);
for(int i = 0; i < resources; i++)
if(item.NameOff == -1)
name = null;
else
{
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);
_rsrcStream.Seek(resourceNameOffset + item.NameOff, SeekOrigin.Begin);
byte nameLen = (byte)_rsrcStream.ReadByte();
byte[] nameBytes = new byte[nameLen];
_rsrcStream.Read(nameBytes, 0, nameLen);
referenceLists.Add(item.id, item);
ids.Add(item.id);
// TODO: Use MacRoman
name = Encoding.ASCII.GetString(nameBytes);
}
foreach(ResourceTypeReferenceListItem item in referenceLists.Values)
{
string name;
ResourceData data = new ResourceData();
_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);
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[]>();
_resourceNames.Add(item.Id, name);
_resources.Add(item.Id, data);
}
/// <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;
}
/// <summary>
/// Gets the length of the resource specified by ID.
/// </summary>
/// <returns>The length.</returns>
/// <param name="id">Resource identifier.</param>
public long GetLength(short id)
{
ResourceData data;
return !resources.TryGetValue(id, out data) ? 0 : data.length;
}
/// <summary>
/// Gets the IDs of all the resources contained by this instance.
/// </summary>
/// <returns>The identifiers.</returns>
public short[] GetIds()
{
return ids.ToArray();
}
/// <summary>
/// Checks if the resource specified by ID is contained by this instance.
/// </summary>
/// <returns><c>true</c>, if the resource is contained in this instance, <c>false</c> otherwise.</returns>
/// <param name="id">Resource identifier.</param>
public bool ContainsId(short id)
{
return ids.Contains(id);
}
_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) => _resourceNames.TryGetValue(id, out string name) ? name : null;
/// <summary>Gets the resource contents.</summary>
/// <returns>The resource.</returns>
/// <param name="id">Identifier.</param>
public byte[] GetResource(short id)
{
if(_resourceCache.TryGetValue(id, out byte[] resource))
return resource;
if(!_resources.TryGetValue(id, out ResourceData 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;
}
/// <summary>Gets the length of the resource specified by ID.</summary>
/// <returns>The length.</returns>
/// <param name="id">Resource identifier.</param>
public long GetLength(short id) => !_resources.TryGetValue(id, out ResourceData data) ? 0 : data.Length;
/// <summary>Gets the IDs of all the resources contained by this instance.</summary>
/// <returns>The identifiers.</returns>
public short[] GetIds() => _ids.ToArray();
/// <summary>Checks if the resource specified by ID is contained by this instance.</summary>
/// <returns><c>true</c>, if the resource is contained in this instance, <c>false</c> otherwise.</returns>
/// <param name="id">Resource identifier.</param>
public bool ContainsId(short id) => _ids.Contains(id);
struct ResourceData
{
public long Offset;
public long Length;
}
}

View File

@@ -4,7 +4,7 @@
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2016 © Claunia.com
// Copyright (c) 2016-2021 Natalia Portillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -28,167 +28,148 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Claunia.RsrcFork
namespace Claunia.RsrcFork;
/// <summary>This class represents a resource fork.</summary>
public class ResourceFork
{
/// <summary>
/// This class represents a resource fork.
/// </summary>
public class ResourceFork
readonly Stream _rsrcStream;
ResourceHeader _header;
ResourceMap _map;
List<uint> _osTypes;
Dictionary<uint, Resource> _resourceCache;
Dictionary<uint, ResourceTypeListItem> _resourceTypeList;
/// <summary>Initializates a resource fork using a byte array as backend.</summary>
/// <param name="buffer">Buffer.</param>
public ResourceFork(byte[] buffer)
{
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();
}
/// <summary>
/// Initializes this instance.
/// </summary>
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.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)
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);
}
_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();
}
/// <summary>Cleans up this instances and closes the underlying stream.</summary>
~ResourceFork() => _rsrcStream?.Dispose();
/// <summary>Initializes this instance.</summary>
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.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)
throw new InvalidCastException("Not a resource fork");
_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);
// 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();
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)
{
if(_resourceCache.TryGetValue(OSType, out Resource rsrc))
return rsrc;
if(!_resourceTypeList.TryGetValue(OSType, out ResourceTypeListItem 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() => _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) => _resourceTypeList.ContainsKey(OSType);
}

View File

@@ -4,7 +4,7 @@
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2016 © Claunia.com
// Copyright (c) 2016-2021 Natalia Portillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -28,139 +28,92 @@ using System;
using System.Linq;
using Claunia.RsrcFork;
namespace Resources
namespace Resources;
/// <summary>This class handles the "VERS" resource fork</summary>
public class Version
{
/// <summary>
/// This class handles the "VERS" resource fork
/// </summary>
public class Version
/// <summary>Known development stages</summary>
public enum DevelopmentStage : byte
{
static uint ostype = 0x76657273;
#region On-disk structure
/// <summary>
/// Major version.
/// </summary>
public byte MajorVersion;
/// <summary>
/// Minor version.
/// </summary>
public byte MinorVersion;
/// <summary>
/// Development stage.
/// </summary>
public DevelopmentStage DevStage;
/// <summary>
/// Pre-release version.
/// </summary>
public byte PreReleaseVersion;
/// <summary>
/// Region code.
/// </summary>
public ushort RegionCode;
/// <summary>
/// Version string.
/// </summary>
public string VersionString;
/// <summary>
/// Version message.
/// </summary>
public string VersionMessage;
#endregion
/// <summary>
/// Known development stages
/// </summary>
public enum DevelopmentStage : byte
{
/// <summary>
/// Pre-alpha.
/// </summary>
PreAlpha = 0x20,
/// <summary>
/// Alpha.
/// </summary>
Alpha = 0x40,
/// <summary>
/// Beta.
/// </summary>
Beta = 0x60,
/// <summary>
/// Final release.
/// </summary>
Final = 0x80
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Resources.Version"/> class.
/// </summary>
/// <param name="resource">Byte array containing the "VERS" resource.</param>
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);
tmpMsg = new byte[resource[6 + tmpStr.Length] + 1];
Array.Copy(resource, 6 + tmpStr.Length, tmpMsg, 0, tmpMsg.Length);
VersionMessage = PascalString.GetString(tmpMsg);
}
/// <summary>
/// Gets a byte array with the "VERS" resource contained by this instance.
/// </summary>
/// <returns>The "VERS" resource.</returns>
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;
}
/// <summary>
/// Gets the OSTYPE of this resource.
/// </summary>
/// <value>The OSTYPE.</value>
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);
}
/// <summary>Pre-alpha.</summary>
PreAlpha = 0x20,
/// <summary>Alpha.</summary>
Alpha = 0x40,
/// <summary>Beta.</summary>
Beta = 0x60,
/// <summary>Final release.</summary>
Final = 0x80
}
}
/// <summary>Initializes a new instance of the <see cref="T:Resources.Version" /> class.</summary>
/// <param name="resource">Byte array containing the "VERS" resource.</param>
public Version(byte[] resource)
{
byte[] 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);
byte[] tmpStr = new byte[resource[6] + 1];
Array.Copy(resource, 6, tmpStr, 0, tmpStr.Length);
VersionString = PascalString.GetString(tmpStr);
byte[] tmpMsg = new byte[resource[6 + tmpStr.Length] + 1];
Array.Copy(resource, 6 + tmpStr.Length, tmpMsg, 0, tmpMsg.Length);
VersionMessage = PascalString.GetString(tmpMsg);
}
/// <summary>Gets the OSTYPE of this resource.</summary>
/// <value>The OSTYPE.</value>
public static uint OSType { get; } = 0x76657273;
/// <summary>Gets a byte array with the "VERS" resource contained by this instance.</summary>
/// <returns>The "VERS" resource.</returns>
public byte[] GetBytes()
{
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);
return vers;
}
byte BCDToNumber(byte bcd) => Convert.ToByte($"{bcd:X2}", 10);
byte NumberToBCD(byte number)
{
if(number >= 100)
number = 99;
return Convert.ToByte($"{number:D2}", 16);
}
#region On-disk structure
/// <summary>Major version.</summary>
public byte MajorVersion;
/// <summary>Minor version.</summary>
public byte MinorVersion;
/// <summary>Development stage.</summary>
public DevelopmentStage DevStage;
/// <summary>Pre-release version.</summary>
public byte PreReleaseVersion;
/// <summary>Region code.</summary>
public ushort RegionCode;
/// <summary>Version string.</summary>
public string VersionString;
/// <summary>Version message.</summary>
public string VersionMessage;
#endregion
}

View File

@@ -4,7 +4,7 @@
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2016 © Claunia.com
// Copyright (c) 2016-2021 Natalia Portillo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -24,98 +24,58 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace Claunia.RsrcFork
namespace Claunia.RsrcFork;
internal struct ResourceHeader
{
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;
}
/// <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;
}
internal 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;
}
internal 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;
}
internal 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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NuGet.Build.Packaging" version="0.1.248" targetFramework="net40" developmentDependency="true" />
</packages>

View File

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

View File

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