Fixed various things in ZIP format (still not done though)
This commit is contained in:
parent
ebcb751b6a
commit
37ac3e097e
@ -18,14 +18,14 @@ namespace UniversalEditor.Compression.Modules.Deflate
|
||||
|
||||
protected override void CompressInternal(Stream inputStream, Stream outputStream)
|
||||
{
|
||||
System.IO.Compression.DeflateStream dst = new System.IO.Compression.DeflateStream(inputStream, System.IO.Compression.CompressionMode.Compress);
|
||||
System.IO.Compression.DeflateStream dst = new System.IO.Compression.DeflateStream(outputStream, System.IO.Compression.CompressionMode.Compress);
|
||||
int read = 0;
|
||||
int start = 0;
|
||||
do
|
||||
{
|
||||
byte[] buffer = new byte[BUFFERSIZE];
|
||||
read = dst.Read(buffer, start, buffer.Length);
|
||||
outputStream.Write(buffer, 0, read);
|
||||
read = inputStream.Read(buffer, start, buffer.Length);
|
||||
dst.Write(buffer, 0, read);
|
||||
}
|
||||
while (read == BUFFERSIZE);
|
||||
}
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
{
|
||||
public enum ZIPCreationPlatform
|
||||
{
|
||||
/// <summary>
|
||||
/// MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
|
||||
/// </summary>
|
||||
MSDOS = 0,
|
||||
Amiga = 1,
|
||||
OpenVMS = 2,
|
||||
Unix = 3,
|
||||
VMCMS = 4,
|
||||
AtariST = 5,
|
||||
/// <summary>
|
||||
/// OS/2 H.P.F.S.
|
||||
/// </summary>
|
||||
HPFS = 6,
|
||||
Macintosh = 7,
|
||||
/// <summary>
|
||||
/// Z-System
|
||||
/// </summary>
|
||||
ZSystem = 8,
|
||||
/// <summary>
|
||||
/// CP/M
|
||||
/// </summary>
|
||||
CPM = 9,
|
||||
/// <summary>
|
||||
/// Windows NTFS
|
||||
/// </summary>
|
||||
WindowsNTFS = 10,
|
||||
/// <summary>
|
||||
/// MVS (OS/390 - Z/OS)
|
||||
/// </summary>
|
||||
MVS = 11,
|
||||
VSE = 12,
|
||||
AcornRISC = 13,
|
||||
VFAT = 14,
|
||||
AlternateMVS = 15,
|
||||
BeOS = 16,
|
||||
Tandem = 17,
|
||||
/// <summary>
|
||||
/// OS/400
|
||||
/// </summary>
|
||||
OS400 = 18,
|
||||
/// <summary>
|
||||
/// Mac OS X (Darwin)
|
||||
/// </summary>
|
||||
Darwin = 19
|
||||
}
|
||||
}
|
||||
@ -18,12 +18,16 @@ namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
{
|
||||
private ZIPSettings mvarSettings = new ZIPSettings();
|
||||
|
||||
private string mvarComment = String.Empty;
|
||||
public string Comment { get { return mvarComment; } set { mvarComment = value; } }
|
||||
|
||||
public override DataFormatReference MakeReference()
|
||||
{
|
||||
DataFormatReference dfr = base.MakeReference();
|
||||
dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
|
||||
dfr.Filters.Add("PKWARE ZIP archive", new byte?[][] { new byte?[] { 80, 0x4b } }, new string[] { "*.zip", "*.zipx", "*.pk3" /*, "*.xpi", "*.maff", "*.lwtp", "*.fwtp" */ });
|
||||
dfr.ContentTypes.Add("application/zip");
|
||||
dfr.ExportOptions.Add(new CustomOptionText("Comment", "&Comment: ", String.Empty, Int16.MaxValue));
|
||||
return dfr;
|
||||
}
|
||||
|
||||
@ -143,22 +147,20 @@ namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
if (fsom == null) return;
|
||||
|
||||
Dictionary<string, File> files = new Dictionary<string, File>();
|
||||
foreach (Folder folder in fsom.Folders) RecursiveLoadFolder(folder, ref files, null);
|
||||
foreach (File file in fsom.Files) files.Add(file.Name, file);
|
||||
Dictionary<File, int> relativeOffsetsOfLocalHeaders = new Dictionary<File, int>();
|
||||
|
||||
File[] files = fsom.GetAllFiles();
|
||||
IO.Writer bw = base.Accessor.Writer;
|
||||
foreach (KeyValuePair<string, File> kvp in files)
|
||||
foreach (File file in files)
|
||||
{
|
||||
File file = kvp.Value;
|
||||
|
||||
relativeOffsetsOfLocalHeaders.Add(file, (int)bw.Accessor.Position);
|
||||
// signature first
|
||||
bw.WriteBytes(new byte[] { 80, 0x4b, 3, 4 });
|
||||
|
||||
short iMinimumVersionNeededToExtract = 0x14;
|
||||
bw.WriteInt16(iMinimumVersionNeededToExtract);
|
||||
|
||||
ZIPGeneralPurposeFlags iGeneralPurposeBitFlag = ZIPGeneralPurposeFlags.UnknownCRCAndFileSize;
|
||||
ZIPGeneralPurposeFlags iGeneralPurposeBitFlag = ZIPGeneralPurposeFlags.None;
|
||||
bw.WriteInt16((short)iGeneralPurposeBitFlag);
|
||||
|
||||
// If bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written.
|
||||
@ -182,20 +184,21 @@ namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
short iFileLastModificationDate = (short)(DateTime.Now.ToFileTime() >> 2);
|
||||
bw.WriteInt16(iFileLastModificationDate);
|
||||
|
||||
byte[] uncompressedData = file.GetDataAsByteArray();
|
||||
|
||||
bool isEncrypted = false;
|
||||
int iCRC32 = 0;
|
||||
int iCRC32 = (int)(new UniversalEditor.Checksum.Modules.CRC32.CRC32ChecksumModule()).Calculate(uncompressedData);
|
||||
bw.WriteInt32(iCRC32);
|
||||
|
||||
byte[] uncompressedData = file.GetDataAsByteArray();
|
||||
byte[] compressedData = CompressionModule.FromKnownCompressionMethod(_compressionMethod).Compress(file.GetDataAsByteArray());
|
||||
bw.WriteInt32((int)0);
|
||||
bw.WriteInt32((int)0);
|
||||
bw.WriteInt32((int)compressedData.Length);
|
||||
bw.WriteInt32((int)uncompressedData.Length);
|
||||
|
||||
short fileNameLength = (short)kvp.Key.Length;
|
||||
short fileNameLength = (short)file.Name.Length;
|
||||
short extraFieldLength = 0;
|
||||
bw.WriteInt16(fileNameLength);
|
||||
bw.WriteInt16(extraFieldLength);
|
||||
bw.WriteFixedLengthString(kvp.Key, fileNameLength);
|
||||
bw.WriteFixedLengthString(file.Name, fileNameLength);
|
||||
/*
|
||||
long pos = br.Accessor.Position;
|
||||
while (br.Accessor.Position < (pos + extraFieldLength))
|
||||
@ -212,19 +215,21 @@ namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
}
|
||||
}
|
||||
|
||||
long ofs = bw.Accessor.Position;
|
||||
// write the central directory
|
||||
foreach (KeyValuePair<string, File> kvp in files)
|
||||
foreach (File file in files)
|
||||
{
|
||||
bw.WriteBytes(new byte[] { (byte)'P', (byte)'K', 0x01, 0x02 });
|
||||
|
||||
File file = kvp.Value;
|
||||
short u = 0x2D;
|
||||
bw.WriteInt16(u);
|
||||
ZIPCreationPlatform creationPlatform = ZIPCreationPlatform.WindowsNTFS; // Windows NTFS
|
||||
byte formatVersion = 0x3F;
|
||||
short u = BitConverter.ToInt16(new byte[] { (byte)creationPlatform, formatVersion }, 0);
|
||||
bw.WriteInt16(u);
|
||||
|
||||
short iMinimumVersionNeededToExtract = 0x14;
|
||||
bw.WriteInt16(iMinimumVersionNeededToExtract);
|
||||
short iGeneralPurposeBitFlag = 0x08;
|
||||
bw.WriteInt16(iGeneralPurposeBitFlag);
|
||||
ZIPGeneralPurposeFlags iGeneralPurposeBitFlag = ZIPGeneralPurposeFlags.None;
|
||||
bw.WriteInt16((short)iGeneralPurposeBitFlag);
|
||||
|
||||
short compressionMethod = 0;
|
||||
CompressionMethod _compressionMethod = CompressionMethod.Deflate;
|
||||
@ -244,21 +249,74 @@ namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
bw.WriteInt16(iFileLastModificationDate);
|
||||
|
||||
bool isEncrypted = false;
|
||||
int iCRC32 = 0;
|
||||
byte[] uncompressedData = file.GetDataAsByteArray();
|
||||
int iCRC32 = (int)(new UniversalEditor.Checksum.Modules.CRC32.CRC32ChecksumModule()).Calculate(uncompressedData);
|
||||
bw.WriteInt32(iCRC32);
|
||||
|
||||
byte[] uncompressedData = file.GetDataAsByteArray();
|
||||
byte[] compressedData = CompressionModule.FromKnownCompressionMethod(_compressionMethod).Compress(file.GetDataAsByteArray());
|
||||
bw.WriteInt32((int)0);
|
||||
bw.WriteInt32((int)0);
|
||||
bw.WriteInt32((int)compressedData.Length);
|
||||
bw.WriteInt32((int)uncompressedData.Length);
|
||||
|
||||
short fileNameLength = (short)file.Name.Length;
|
||||
|
||||
byte[] extraField = new byte[0];
|
||||
|
||||
short fileNameLength = (short)kvp.Key.Length;
|
||||
short extraFieldLength = 0;
|
||||
bw.WriteInt16(fileNameLength);
|
||||
bw.WriteInt16(extraFieldLength);
|
||||
bw.WriteFixedLengthString(kvp.Key, fileNameLength);
|
||||
}
|
||||
}
|
||||
bw.WriteInt16((short)extraField.Length);
|
||||
|
||||
string fileComment = String.Empty;
|
||||
|
||||
bw.WriteInt16((short)fileComment.Length);
|
||||
short diskNumber = 0;
|
||||
bw.WriteInt16(diskNumber);
|
||||
ZIPInternalFileAttributes internalFileAttributes = ZIPInternalFileAttributes.None;
|
||||
bw.WriteInt16((short)internalFileAttributes);
|
||||
|
||||
int externalFileAttributes = 0;
|
||||
bw.WriteInt32(externalFileAttributes);
|
||||
|
||||
bw.WriteInt32(relativeOffsetsOfLocalHeaders[file]);
|
||||
|
||||
bw.WriteFixedLengthString(file.Name.Replace("\\", "/"), fileNameLength);
|
||||
|
||||
bw.WriteBytes(extraField);
|
||||
|
||||
bw.WriteFixedLengthString(fileComment);
|
||||
}
|
||||
long centralDirectoryLength = (bw.Accessor.Position - ofs);
|
||||
|
||||
#region End of Central Directory
|
||||
{
|
||||
bw.WriteBytes(new byte[] { 0x50, 0x4B, 0x05, 0x06 });
|
||||
|
||||
// The number of this disk (containing the end of central
|
||||
// directory record)
|
||||
bw.WriteInt16(0);
|
||||
|
||||
// Number of the disk on which the central directory starts
|
||||
bw.WriteInt16(0);
|
||||
|
||||
// The number of central directory entries on this disk
|
||||
bw.WriteInt16((short)files.Length);
|
||||
|
||||
// Total number of entries in the central directory.
|
||||
bw.WriteInt16((short)files.Length);
|
||||
|
||||
// Size of the central directory in bytes
|
||||
bw.WriteInt32((int)centralDirectoryLength);
|
||||
|
||||
// Offset of the start of the central directory on the disk on
|
||||
// which the central directory starts
|
||||
bw.WriteInt32((int)ofs);
|
||||
|
||||
// The length of the following comment field
|
||||
bw.WriteInt16((short)mvarComment.Length);
|
||||
|
||||
// Optional comment for the Zip file
|
||||
bw.WriteFixedLengthString(mvarComment);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
private void RecursiveLoadFolder(Folder folder, ref Dictionary<string, File> files, string parentFolderName)
|
||||
{
|
||||
@ -330,24 +388,29 @@ namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
}
|
||||
short iMinimumVersionNeededToExtract = br.ReadInt16();
|
||||
short iGeneralPurposeBitFlag = br.ReadInt16();
|
||||
switch (br.ReadInt16())
|
||||
{
|
||||
case 8:
|
||||
method = CompressionMethod.Deflate;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
method = CompressionMethod.Deflate64;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
method = CompressionMethod.Bzip2;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
method = CompressionMethod.LZMA;
|
||||
break;
|
||||
}
|
||||
switch (br.ReadInt16())
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
method = CompressionMethod.Deflate;
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
method = CompressionMethod.Deflate64;
|
||||
break;
|
||||
}
|
||||
case 12:
|
||||
{
|
||||
method = CompressionMethod.Bzip2;
|
||||
break;
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
method = CompressionMethod.LZMA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
short iFileLastModificationTime = br.ReadInt16();
|
||||
short iFileLastModificationDate = br.ReadInt16();
|
||||
bool isEncrypted = false;
|
||||
|
||||
@ -5,13 +5,14 @@ using System.Text;
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
{
|
||||
public enum ZIPGeneralPurposeFlags : short
|
||||
{
|
||||
/// <summary>
|
||||
/// The CRC-32 and file sizes are not known when the header is written. The fields in the local header are filled with zero,
|
||||
/// and the CRC-32 and size are appended in a 12-byte structure (optionally preceded by a 4-byte signature) immediately after
|
||||
/// the compressed data.
|
||||
/// </summary>
|
||||
UnknownCRCAndFileSize = 0x08
|
||||
}
|
||||
public enum ZIPGeneralPurposeFlags : short
|
||||
{
|
||||
None = 0x00,
|
||||
/// <summary>
|
||||
/// The CRC-32 and file sizes are not known when the header is written. The fields in the local header are filled with zero,
|
||||
/// and the CRC-32 and size are appended in a 12-byte structure (optionally preceded by a 4-byte signature) immediately after
|
||||
/// the compressed data.
|
||||
/// </summary>
|
||||
UnknownCRCAndFileSize = 0x08
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.ZIP
|
||||
{
|
||||
public enum ZIPInternalFileAttributes : short
|
||||
{
|
||||
None = 0x00,
|
||||
ApparentTextFile = 0x01,
|
||||
/// <summary>
|
||||
/// Control field records precede logical records
|
||||
/// </summary>
|
||||
ControlFieldRecordsPrecedeLogicalRecords = 0x04
|
||||
}
|
||||
}
|
||||
@ -139,8 +139,10 @@
|
||||
<Compile Include="DataFormats\FileSystem\WinRAR\RARHeaderFlags.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\WinRAR\RARHeaderType.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\WinRAR\RARHostOperatingSystem.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\ZIP\ZIPCreationPlatform.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\ZIP\ZIPDataFormat.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\ZIP\ZIPGeneralPurposeFlags.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\ZIP\ZIPInternalFileAttributes.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\ZIP\ZIPSettings.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user