Files
sharpcompress/src/SharpCompress/Common/Zip/ZipFilePart.cs

170 lines
6.6 KiB
C#
Raw Normal View History

2015-12-30 11:19:42 +00:00
using System;
using System.IO;
using System.Linq;
using SharpCompress.Common.Zip.Headers;
using SharpCompress.Compressor;
using SharpCompress.Compressor.BZip2;
using SharpCompress.Compressor.Deflate;
using SharpCompress.Compressor.LZMA;
using SharpCompress.Compressor.PPMd;
Merge branch 'master' into dnx Conflicts: NuGet/sharpcompress.nuspec SharpCompress/Common/Zip/WinzipAesCryptoStream.Portable.cs SharpCompress/Common/Zip/WinzipAesEncryptionData.Portable.cs SharpCompress/Crypto/PBKDF2.cs SharpCompress/SharpCompress.Portable.csproj SharpCompress/SharpCompress.PortableTest.csproj SharpCompress/SharpCompress.Unsigned.csproj SharpCompress/SharpCompress.WindowsStore.csproj SharpCompress/SharpCompress.csproj src/SharpCompress/Archive/ArchiveFactory.cs src/SharpCompress/Archive/Rar/FileInfoRarFilePart.cs src/SharpCompress/Archive/Rar/RarArchive.cs src/SharpCompress/Archive/Rar/RarArchiveEntry.cs src/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs src/SharpCompress/Common/GZip/GZipFilePart.cs src/SharpCompress/Common/GZip/GZipVolume.cs src/SharpCompress/Common/Rar/Headers/MarkHeader.cs src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs src/SharpCompress/Common/SevenZip/ArchiveReader.cs src/SharpCompress/Common/SevenZip/DataReader.cs src/SharpCompress/Common/Tar/Headers/TarHeader.cs src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs src/SharpCompress/Common/Zip/ZipFilePart.cs src/SharpCompress/Compressor/Deflate/GZipStream.cs src/SharpCompress/Compressor/Deflate/Inflate.cs src/SharpCompress/Compressor/Deflate/ZlibBaseStream.cs src/SharpCompress/Compressor/LZMA/Bcj2DecoderStream.cs src/SharpCompress/Compressor/LZMA/LzmaStream.cs src/SharpCompress/Compressor/PPMd/H/FreqData.cs src/SharpCompress/Compressor/PPMd/H/PPMContext.cs src/SharpCompress/Compressor/PPMd/H/RarMemBlock.cs src/SharpCompress/Compressor/PPMd/H/RarNode.cs src/SharpCompress/Compressor/PPMd/H/State.cs src/SharpCompress/Compressor/PPMd/PpmdProperties.cs src/SharpCompress/Compressor/Rar/VM/RarVM.cs src/SharpCompress/EnumExtensions.cs src/SharpCompress/IO/MarkingBinaryReader.cs src/SharpCompress/Reader/ReaderFactory.cs src/SharpCompress/Utility.cs src/SharpCompress/Writer/IWriter.Extensions.cs src/SharpCompress/Writer/Zip/ZipCentralDirectoryEntry.cs src/SharpCompress/Writer/Zip/ZipWriter.cs test/SharpCompress.Test/Tar/TarArchiveTests.cs test/SharpCompress.Test/Tar/TarReaderTests.cs
2016-02-13 09:24:44 +00:00
using SharpCompress.Converter;
2015-12-30 11:19:42 +00:00
using SharpCompress.IO;
namespace SharpCompress.Common.Zip
{
internal abstract class ZipFilePart : FilePart
{
internal ZipFilePart(ZipFileEntry header, Stream stream)
{
Header = header;
header.Part = this;
this.BaseStream = stream;
}
internal Stream BaseStream { get; private set; }
internal ZipFileEntry Header { get; set; }
internal override string FilePartName
{
get { return Header.Name; }
}
internal override Stream GetCompressedStream()
{
if (!Header.HasData)
{
return Stream.Null;
}
Stream decompressionStream = CreateDecompressionStream(GetCryptoStream(CreateBaseStream()));
if (LeaveStreamOpen)
{
return new NonDisposingStream(decompressionStream);
}
return decompressionStream;
}
internal override Stream GetRawStream()
{
if (!Header.HasData)
{
return Stream.Null;
}
return CreateBaseStream();
}
protected abstract Stream CreateBaseStream();
protected bool LeaveStreamOpen
{
get { return FlagUtility.HasFlag(Header.Flags, HeaderFlags.UsePostDataDescriptor); }
}
protected Stream CreateDecompressionStream(Stream stream)
{
switch (Header.CompressionMethod)
{
case ZipCompressionMethod.None:
{
return stream;
}
case ZipCompressionMethod.Deflate:
{
return new DeflateStream(stream, CompressionMode.Decompress);
}
case ZipCompressionMethod.BZip2:
{
return new BZip2Stream(stream, CompressionMode.Decompress);
}
case ZipCompressionMethod.LZMA:
{
if (FlagUtility.HasFlag(Header.Flags, HeaderFlags.Encrypted))
{
throw new NotSupportedException("LZMA with pkware encryption.");
}
var reader = new BinaryReader(stream);
reader.ReadUInt16(); //LZMA version
var props = new byte[reader.ReadUInt16()];
reader.Read(props, 0, props.Length);
return new LzmaStream(props, stream,
Header.CompressedSize > 0 ? Header.CompressedSize - 4 - props.Length : -1,
FlagUtility.HasFlag(Header.Flags, HeaderFlags.Bit1)
? -1
: (long)Header.UncompressedSize);
}
case ZipCompressionMethod.PPMd:
{
var props = new byte[2];
stream.Read(props, 0, props.Length);
return new PpmdStream(new PpmdProperties(props), stream, false);
}
case ZipCompressionMethod.WinzipAes:
{
ExtraData data = Header.Extra.Where(x => x.Type == ExtraDataType.WinZipAes).SingleOrDefault();
if (data == null)
{
throw new InvalidFormatException("No Winzip AES extra data found.");
}
if (data.Length != 7)
{
throw new InvalidFormatException("Winzip data length is not 7.");
}
Merge branch 'master' into dnx Conflicts: NuGet/sharpcompress.nuspec SharpCompress/Common/Zip/WinzipAesCryptoStream.Portable.cs SharpCompress/Common/Zip/WinzipAesEncryptionData.Portable.cs SharpCompress/Crypto/PBKDF2.cs SharpCompress/SharpCompress.Portable.csproj SharpCompress/SharpCompress.PortableTest.csproj SharpCompress/SharpCompress.Unsigned.csproj SharpCompress/SharpCompress.WindowsStore.csproj SharpCompress/SharpCompress.csproj src/SharpCompress/Archive/ArchiveFactory.cs src/SharpCompress/Archive/Rar/FileInfoRarFilePart.cs src/SharpCompress/Archive/Rar/RarArchive.cs src/SharpCompress/Archive/Rar/RarArchiveEntry.cs src/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs src/SharpCompress/Common/GZip/GZipFilePart.cs src/SharpCompress/Common/GZip/GZipVolume.cs src/SharpCompress/Common/Rar/Headers/MarkHeader.cs src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs src/SharpCompress/Common/SevenZip/ArchiveReader.cs src/SharpCompress/Common/SevenZip/DataReader.cs src/SharpCompress/Common/Tar/Headers/TarHeader.cs src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs src/SharpCompress/Common/Zip/ZipFilePart.cs src/SharpCompress/Compressor/Deflate/GZipStream.cs src/SharpCompress/Compressor/Deflate/Inflate.cs src/SharpCompress/Compressor/Deflate/ZlibBaseStream.cs src/SharpCompress/Compressor/LZMA/Bcj2DecoderStream.cs src/SharpCompress/Compressor/LZMA/LzmaStream.cs src/SharpCompress/Compressor/PPMd/H/FreqData.cs src/SharpCompress/Compressor/PPMd/H/PPMContext.cs src/SharpCompress/Compressor/PPMd/H/RarMemBlock.cs src/SharpCompress/Compressor/PPMd/H/RarNode.cs src/SharpCompress/Compressor/PPMd/H/State.cs src/SharpCompress/Compressor/PPMd/PpmdProperties.cs src/SharpCompress/Compressor/Rar/VM/RarVM.cs src/SharpCompress/EnumExtensions.cs src/SharpCompress/IO/MarkingBinaryReader.cs src/SharpCompress/Reader/ReaderFactory.cs src/SharpCompress/Utility.cs src/SharpCompress/Writer/IWriter.Extensions.cs src/SharpCompress/Writer/Zip/ZipCentralDirectoryEntry.cs src/SharpCompress/Writer/Zip/ZipWriter.cs test/SharpCompress.Test/Tar/TarArchiveTests.cs test/SharpCompress.Test/Tar/TarReaderTests.cs
2016-02-13 09:24:44 +00:00
ushort method = DataConverter.LittleEndian.GetUInt16(data.DataBytes, 0);
2015-12-30 11:19:42 +00:00
if (method != 0x01 && method != 0x02)
{
throw new InvalidFormatException("Unexpected vendor version number for WinZip AES metadata");
}
Merge branch 'master' into dnx Conflicts: NuGet/sharpcompress.nuspec SharpCompress/Common/Zip/WinzipAesCryptoStream.Portable.cs SharpCompress/Common/Zip/WinzipAesEncryptionData.Portable.cs SharpCompress/Crypto/PBKDF2.cs SharpCompress/SharpCompress.Portable.csproj SharpCompress/SharpCompress.PortableTest.csproj SharpCompress/SharpCompress.Unsigned.csproj SharpCompress/SharpCompress.WindowsStore.csproj SharpCompress/SharpCompress.csproj src/SharpCompress/Archive/ArchiveFactory.cs src/SharpCompress/Archive/Rar/FileInfoRarFilePart.cs src/SharpCompress/Archive/Rar/RarArchive.cs src/SharpCompress/Archive/Rar/RarArchiveEntry.cs src/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs src/SharpCompress/Common/GZip/GZipFilePart.cs src/SharpCompress/Common/GZip/GZipVolume.cs src/SharpCompress/Common/Rar/Headers/MarkHeader.cs src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs src/SharpCompress/Common/SevenZip/ArchiveReader.cs src/SharpCompress/Common/SevenZip/DataReader.cs src/SharpCompress/Common/Tar/Headers/TarHeader.cs src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs src/SharpCompress/Common/Zip/ZipFilePart.cs src/SharpCompress/Compressor/Deflate/GZipStream.cs src/SharpCompress/Compressor/Deflate/Inflate.cs src/SharpCompress/Compressor/Deflate/ZlibBaseStream.cs src/SharpCompress/Compressor/LZMA/Bcj2DecoderStream.cs src/SharpCompress/Compressor/LZMA/LzmaStream.cs src/SharpCompress/Compressor/PPMd/H/FreqData.cs src/SharpCompress/Compressor/PPMd/H/PPMContext.cs src/SharpCompress/Compressor/PPMd/H/RarMemBlock.cs src/SharpCompress/Compressor/PPMd/H/RarNode.cs src/SharpCompress/Compressor/PPMd/H/State.cs src/SharpCompress/Compressor/PPMd/PpmdProperties.cs src/SharpCompress/Compressor/Rar/VM/RarVM.cs src/SharpCompress/EnumExtensions.cs src/SharpCompress/IO/MarkingBinaryReader.cs src/SharpCompress/Reader/ReaderFactory.cs src/SharpCompress/Utility.cs src/SharpCompress/Writer/IWriter.Extensions.cs src/SharpCompress/Writer/Zip/ZipCentralDirectoryEntry.cs src/SharpCompress/Writer/Zip/ZipWriter.cs test/SharpCompress.Test/Tar/TarArchiveTests.cs test/SharpCompress.Test/Tar/TarReaderTests.cs
2016-02-13 09:24:44 +00:00
ushort vendorId = DataConverter.LittleEndian.GetUInt16(data.DataBytes, 2);
2015-12-30 11:19:42 +00:00
if (vendorId != 0x4541)
{
throw new InvalidFormatException("Unexpected vendor ID for WinZip AES metadata");
}
Merge branch 'master' into dnx Conflicts: NuGet/sharpcompress.nuspec SharpCompress/Common/Zip/WinzipAesCryptoStream.Portable.cs SharpCompress/Common/Zip/WinzipAesEncryptionData.Portable.cs SharpCompress/Crypto/PBKDF2.cs SharpCompress/SharpCompress.Portable.csproj SharpCompress/SharpCompress.PortableTest.csproj SharpCompress/SharpCompress.Unsigned.csproj SharpCompress/SharpCompress.WindowsStore.csproj SharpCompress/SharpCompress.csproj src/SharpCompress/Archive/ArchiveFactory.cs src/SharpCompress/Archive/Rar/FileInfoRarFilePart.cs src/SharpCompress/Archive/Rar/RarArchive.cs src/SharpCompress/Archive/Rar/RarArchiveEntry.cs src/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs src/SharpCompress/Common/GZip/GZipFilePart.cs src/SharpCompress/Common/GZip/GZipVolume.cs src/SharpCompress/Common/Rar/Headers/MarkHeader.cs src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs src/SharpCompress/Common/SevenZip/ArchiveReader.cs src/SharpCompress/Common/SevenZip/DataReader.cs src/SharpCompress/Common/Tar/Headers/TarHeader.cs src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs src/SharpCompress/Common/Zip/ZipFilePart.cs src/SharpCompress/Compressor/Deflate/GZipStream.cs src/SharpCompress/Compressor/Deflate/Inflate.cs src/SharpCompress/Compressor/Deflate/ZlibBaseStream.cs src/SharpCompress/Compressor/LZMA/Bcj2DecoderStream.cs src/SharpCompress/Compressor/LZMA/LzmaStream.cs src/SharpCompress/Compressor/PPMd/H/FreqData.cs src/SharpCompress/Compressor/PPMd/H/PPMContext.cs src/SharpCompress/Compressor/PPMd/H/RarMemBlock.cs src/SharpCompress/Compressor/PPMd/H/RarNode.cs src/SharpCompress/Compressor/PPMd/H/State.cs src/SharpCompress/Compressor/PPMd/PpmdProperties.cs src/SharpCompress/Compressor/Rar/VM/RarVM.cs src/SharpCompress/EnumExtensions.cs src/SharpCompress/IO/MarkingBinaryReader.cs src/SharpCompress/Reader/ReaderFactory.cs src/SharpCompress/Utility.cs src/SharpCompress/Writer/IWriter.Extensions.cs src/SharpCompress/Writer/Zip/ZipCentralDirectoryEntry.cs src/SharpCompress/Writer/Zip/ZipWriter.cs test/SharpCompress.Test/Tar/TarArchiveTests.cs test/SharpCompress.Test/Tar/TarReaderTests.cs
2016-02-13 09:24:44 +00:00
Header.CompressionMethod = (ZipCompressionMethod)DataConverter.LittleEndian.GetUInt16(data.DataBytes, 5);
2015-12-30 11:19:42 +00:00
return CreateDecompressionStream(stream);
}
default:
{
throw new NotSupportedException("CompressionMethod: " + Header.CompressionMethod);
}
}
}
protected Stream GetCryptoStream(Stream plainStream)
{
if ((Header.CompressedSize == 0)
2016-01-02 15:02:45 +00:00
#if !NO_CRYPTO
2015-12-30 11:19:42 +00:00
&& ((Header.PkwareTraditionalEncryptionData != null)
|| (Header.WinzipAesEncryptionData != null)))
#else
&& (Header.PkwareTraditionalEncryptionData != null))
#endif
{
throw new NotSupportedException("Cannot encrypt file with unknown size at start.");
}
if ((Header.CompressedSize == 0)
&& FlagUtility.HasFlag(Header.Flags, HeaderFlags.UsePostDataDescriptor))
{
plainStream = new NonDisposingStream(plainStream); //make sure AES doesn't close
}
else
{
plainStream = new ReadOnlySubStream(plainStream, Header.CompressedSize); //make sure AES doesn't close
}
if (Header.PkwareTraditionalEncryptionData != null)
{
return new PkwareTraditionalCryptoStream(plainStream, Header.PkwareTraditionalEncryptionData,
CryptoMode.Decrypt);
}
2016-01-02 15:02:45 +00:00
#if !NO_FILE
2015-12-30 11:19:42 +00:00
if (Header.WinzipAesEncryptionData != null)
{
//only read 10 less because the last ten are auth bytes
return new WinzipAesCryptoStream(plainStream, Header.WinzipAesEncryptionData, Header.CompressedSize - 10);
}
#endif
return plainStream;
}
}
2013-04-07 10:58:58 +01:00
}