Added filter for PCExchange files.

This commit is contained in:
2016-09-12 01:13:12 +01:00
parent 65635bd149
commit fe623a5dfb
4 changed files with 343 additions and 6 deletions

View File

@@ -46,6 +46,7 @@
<Compile Include="AppleDouble.cs" /> <Compile Include="AppleDouble.cs" />
<Compile Include="MacBinary.cs" /> <Compile Include="MacBinary.cs" />
<Compile Include="BZip2.cs" /> <Compile Include="BZip2.cs" />
<Compile Include="PCExchange.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="..\LICENSE.LGPL"> <EmbeddedResource Include="..\LICENSE.LGPL">

View File

@@ -67,8 +67,13 @@ namespace DiscImageChef.Filters
public Filter GetFilter(string path) public Filter GetFilter(string path)
{ {
Filter noFilter = null;
foreach(Filter filter in filtersList.Values) foreach(Filter filter in filtersList.Values)
{ {
if(filter.UUID != new Guid("12345678-AAAA-BBBB-CCCC-123456789000"))
{
System.Console.WriteLine("Trying filter {0}", filter.Name);
if(filter.Identify(path)) if(filter.Identify(path))
{ {
Filter foundFilter = (Filter)filter.GetType().GetConstructor(Type.EmptyTypes).Invoke(new object[] { }); Filter foundFilter = (Filter)filter.GetType().GetConstructor(Type.EmptyTypes).Invoke(new object[] { });
@@ -78,8 +83,11 @@ namespace DiscImageChef.Filters
return foundFilter; return foundFilter;
} }
} }
else
noFilter = filter;
}
return null; return noFilter;
} }
public SortedDictionary<string, Filter> GetFiltersList() public SortedDictionary<string, Filter> GetFiltersList()

View File

@@ -0,0 +1,327 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : PCExchange.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Component
//
// --[ Description ] ----------------------------------------------------------
//
// Provides a filter to open handle files written by PCExchange in FAT
// volumes
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
using System;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace DiscImageChef.Filters
{
public class PCExchange : Filter
{
const string FileId = "FILEID.DAT";
const string FinderInfo = "FINDER.DAT";
const string Resources = "RESOURCE.FRK";
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct PCExchangeEntry
{
/// <summary>
/// Name in Macintosh. If PCExchange version supports FAT's LFN they are the same.
/// Illegal characters for FAT get substituted with '_' both here and in FAT's LFN entry.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] macName;
/// <summary>
/// File type
/// </summary>
public uint type;
/// <summary>
/// File creator
/// </summary>
public uint creator;
/// <summary>
/// Finder flags
/// </summary>
public ushort fdFlags;
/// <summary>
/// File's icon vertical position within its window
/// </summary>
public ushort verticalPosition;
/// <summary>
/// File's icon horizontal position within its window
/// </summary>
public ushort horizontalPosition;
/// <summary>
/// Unknown, all bytes are empty but last, except in volume's label entry
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)]
public byte[] unknown1;
/// <summary>
/// File's creation date
/// </summary>
public uint creationDate;
/// <summary>
/// File's modification date
/// </summary>
public uint modificationDate;
/// <summary>
/// File's last backup date
/// </summary>
public uint backupDate;
/// <summary>
/// Unknown, but is unique, starts 0x7FFFFFFF and counts in reverse.
/// Probably file ID for alias look up?
/// </summary>
public uint unknown2;
/// <summary>
/// Name as in FAT entry (not LFN).
/// Resource fork file is always using this name, never LFN.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] dosName;
/// <summary>
/// Unknown, flags?
/// </summary>
public byte unknown3;
}
bool opened;
string basePath;
string dataPath;
string rsrcPath;
DateTime lastWriteTime;
DateTime creationTime;
long dataLen;
long rsrcLen;
public PCExchange()
{
Name = "PCExchange";
UUID = new Guid("9264EB9F-D634-4F9B-BE12-C24CD44988C6");
}
public override void Close()
{
opened = false;
}
public override string GetBasePath()
{
return basePath;
}
public override DateTime GetCreationTime()
{
return creationTime;
}
public override long GetDataForkLength()
{
return dataLen;
}
public override Stream GetDataForkStream()
{
return new FileStream(dataPath, FileMode.Open, FileAccess.Read);
}
public override string GetFilename()
{
return basePath != null ? Path.GetFileName(basePath) : null;
}
public override DateTime GetLastWriteTime()
{
return lastWriteTime;
}
public override long GetLength()
{
return dataLen + rsrcLen;
}
public override string GetParentFolder()
{
return Path.GetDirectoryName(basePath);
}
public override string GetPath()
{
return basePath;
}
public override long GetResourceForkLength()
{
return rsrcLen;
}
public override Stream GetResourceForkStream()
{
return new FileStream(rsrcPath, FileMode.Open, FileAccess.Read);
}
public override bool HasResourceFork()
{
return rsrcPath != null;
}
public override bool Identify(byte[] buffer)
{
System.Console.WriteLine("parentFolder");
return false;
}
public override bool Identify(Stream stream)
{
System.Console.WriteLine("parentFolder");
return false;
}
public override bool Identify(string path)
{
System.Console.WriteLine("parentFolder");
string parentFolder = Path.GetDirectoryName(path);
System.Console.WriteLine("parentFolder {0}", parentFolder);
if(!File.Exists(Path.Combine(parentFolder, FinderInfo)))
return false;
if(!Directory.Exists(Path.Combine(parentFolder, Resources)))
return false;
string baseFilename = Path.GetFileName(path);
bool dataFound = false;
bool rsrcFound = false;
FileStream finderDatStream = new FileStream(Path.Combine(parentFolder, FinderInfo), FileMode.Open, FileAccess.Read);
while(finderDatStream.Position + 0x5C < finderDatStream.Length)
{
PCExchangeEntry datEntry = new PCExchangeEntry();
byte[] datEntry_b = new byte[Marshal.SizeOf(datEntry)];
finderDatStream.Read(datEntry_b, 0, Marshal.SizeOf(datEntry));
datEntry = BigEndianMarshal.ByteArrayToStructureBigEndian<PCExchangeEntry>(datEntry_b);
string macName = StringHandlers.PascalToString(datEntry.macName);
byte[] tmpDosName_b = new byte[8];
byte[] tmpDosExt_b = new byte[3];
Array.Copy(datEntry.dosName, 0, tmpDosName_b, 0, 8);
Array.Copy(datEntry.dosName, 8, tmpDosExt_b, 0, 3);
string dosName = (Encoding.ASCII.GetString(tmpDosName_b).Trim() + "." + Encoding.ASCII.GetString(tmpDosExt_b).Trim());
string dosNameLow = dosName.ToLower(CultureInfo.CurrentCulture);
if(baseFilename == macName || baseFilename == dosName || baseFilename == dosNameLow)
{
dataFound |= File.Exists(Path.Combine(parentFolder, macName)) || File.Exists(Path.Combine(parentFolder, dosName)) ||
File.Exists(Path.Combine(parentFolder, dosNameLow));
rsrcFound |= File.Exists(Path.Combine(parentFolder, Resources, dosName)) ||
File.Exists(Path.Combine(parentFolder, Resources, dosNameLow));
break;
}
}
finderDatStream.Close();
return dataFound && rsrcFound;
}
public override bool IsOpened()
{
return opened;
}
public override void Open(byte[] buffer)
{
throw new NotSupportedException();
}
public override void Open(Stream stream)
{
throw new NotSupportedException();
}
public override void Open(string path)
{
string parentFolder = Path.GetDirectoryName(path);
string baseFilename = Path.GetFileName(path);
FileStream finderDatStream = new FileStream(Path.Combine(parentFolder, FinderInfo), FileMode.Open, FileAccess.Read);
while(finderDatStream.Position + 0x5C < finderDatStream.Length)
{
PCExchangeEntry datEntry = new PCExchangeEntry();
byte[] datEntry_b = new byte[Marshal.SizeOf(datEntry)];
finderDatStream.Read(datEntry_b, 0, Marshal.SizeOf(datEntry));
datEntry = BigEndianMarshal.ByteArrayToStructureBigEndian<PCExchangeEntry>(datEntry_b);
string macName = StringHandlers.PascalToString(datEntry.macName);
byte[] tmpDosName_b = new byte[8];
byte[] tmpDosExt_b = new byte[3];
Array.Copy(datEntry.dosName, 0, tmpDosName_b, 0, 8);
Array.Copy(datEntry.dosName, 8, tmpDosExt_b, 0, 3);
string dosName = (Encoding.ASCII.GetString(tmpDosName_b).Trim() + "." + Encoding.ASCII.GetString(tmpDosExt_b).Trim());
string dosNameLow = dosName.ToLower(CultureInfo.CurrentCulture);
if(baseFilename == macName || baseFilename == dosName || baseFilename == dosNameLow)
{
if(File.Exists(Path.Combine(parentFolder, macName)))
dataPath = Path.Combine(parentFolder, macName);
else if(File.Exists(Path.Combine(parentFolder, dosName)))
dataPath = Path.Combine(parentFolder, dosName);
else if(File.Exists(Path.Combine(parentFolder, dosNameLow)))
dataPath = Path.Combine(parentFolder, dosNameLow);
else
dataPath = null;
if(File.Exists(Path.Combine(parentFolder, Resources, dosName)))
rsrcPath = Path.Combine(parentFolder, Resources, dosName);
else if(File.Exists(Path.Combine(parentFolder, Resources, dosNameLow)))
rsrcPath = Path.Combine(parentFolder, Resources, dosNameLow);
else
rsrcPath = null;
lastWriteTime = DateHandlers.MacToDateTime(datEntry.modificationDate);
creationTime = DateHandlers.MacToDateTime(datEntry.creationDate);
break;
}
}
dataLen = new FileInfo(dataPath).Length;
rsrcLen = new FileInfo(rsrcPath).Length;
System.Console.WriteLine("dataPath = {0}", dataPath);
System.Console.WriteLine("rsrcPath = {0}", rsrcPath);
System.Console.WriteLine("dataLen = {0}", dataLen);
System.Console.WriteLine("rsrcLen = {0}", rsrcLen);
System.Console.WriteLine("basePath = {0}", basePath);
basePath = path;
opened = true;
}
}
}

View File

@@ -153,6 +153,7 @@ Supported filters
* AppleSingle * AppleSingle
* MacBinary I, II, III * MacBinary I, II, III
* BZip2 * BZip2
* Apple PCExchange (FINDER.DAT & RESOURCE.FRK)
Changelog Changelog
========= =========