public Stream GetEntryStream(StiZipEntry entry) { if (_isDisposed) { throw new ObjectDisposedException("ZipFile"); } if (entry.IsCrypted) { throw new StiZipException("Encryption is not supported"); } long start = LocateEntry(entry); CompressionMethod method = entry.CompressionMethod; Stream result = new StiPartialInputStream(this, start, entry.CompressedSize); switch (method) { case CompressionMethod.Stored: break; case CompressionMethod.Deflated: byte[] buf = new byte[entry.CompressedSize]; _baseStream.Seek(start, SeekOrigin.Begin); _baseStream.Read(buf, 0, buf.Length); MemoryStream ms = new MemoryStream(buf); result = new System.IO.Compression.DeflateStream(ms, System.IO.Compression.CompressionMode.Decompress); break; default: throw new StiZipException("Unsupported compression method " + method); } return(result); }
private long LocateEntry(StiZipEntry entry) { _baseStream.Seek(offsetOfFirstEntry + entry.Offset, SeekOrigin.Begin); if ((int)ReadLEUint() != StiZipConstants.LocalHeaderSignature) { throw new StiZipException(string.Format("Wrong local header signature @{0:X}", offsetOfFirstEntry + entry.Offset)); } short extractVersion = (short)ReadLEUshort(); short localFlags = (short)ReadLEUshort(); short compressionMethod = (short)ReadLEUshort(); short fileTime = (short)ReadLEUshort(); short fileDate = (short)ReadLEUshort(); uint crcValue = ReadLEUint(); long compressedSize = ReadLEUint(); long size = ReadLEUint(); int storedNameLength = ReadLEUshort(); int extraDataLength = ReadLEUshort(); byte[] nameData = new byte[storedNameLength]; Utils.ReadFully(_baseStream, nameData); byte[] extraData = new byte[extraDataLength]; Utils.ReadFully(_baseStream, extraData); StiZipExtraData localExtraData = new StiZipExtraData(extraData); if (entry.IsFile) { if (!entry.IsCompressionMethodSupported()) { throw new StiZipException("Compression method not supported"); } if ((extractVersion > StiZipConstants.VersionMadeBy) || ((extractVersion > 20) && (extractVersion < StiZipConstants.VersionZip64)) || ((localFlags & (int) (GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0)) { throw new StiZipException("The library does not support the zip version required to extract this entry"); } } int extraLength = storedNameLength + extraDataLength; return(offsetOfFirstEntry + entry.Offset + StiZipConstants.LocalHeaderBaseSize + extraLength); }
private void ReadEntries() { long locatedEndOfCentralDir = LocateBlockWithSignature( StiZipConstants.EndOfCentralDirectorySignature, _baseStream.Length, StiZipConstants.EndOfCentralRecordBaseSize, 0xffff); if (locatedEndOfCentralDir < 0) { throw new StiZipException("Cannot find central directory"); } ushort thisDiskNumber = ReadLEUshort(); ushort startCentralDirDisk = ReadLEUshort(); ulong entriesForThisDisk = ReadLEUshort(); ulong entriesForWholeCentralDir = ReadLEUshort(); ulong centralDirSize = ReadLEUint(); long offsetOfCentralDir = ReadLEUint(); bool isZip64 = false; #region Check if zip64 header information is required. if ((thisDiskNumber == 0xffff) || (startCentralDirDisk == 0xffff) || (entriesForThisDisk == 0xffff) || (entriesForWholeCentralDir == 0xffff) || (centralDirSize == 0xffffffff) || (offsetOfCentralDir == 0xffffffff)) { isZip64 = true; long offset = LocateBlockWithSignature(StiZipConstants.Zip64CentralDirLocatorSignature, locatedEndOfCentralDir, 0, 0x1000); if (offset < 0) { throw new StiZipException("Cannot find Zip64 locator"); } ReadLEUint(); ulong offset64 = ReadLEUlong(); uint totalDisks = ReadLEUint(); _baseStream.Position = (long)offset64; long sig64 = ReadLEUint(); if (sig64 != StiZipConstants.Zip64CentralFileHeaderSignature) { throw new StiZipException(string.Format("Invalid Zip64 Central directory signature at {0:X}", offset64)); } ulong recordSize = ReadLEUlong(); int versionMadeBy = ReadLEUshort(); int versionToExtract = ReadLEUshort(); uint thisDisk = ReadLEUint(); uint centralDirDisk = ReadLEUint(); entriesForThisDisk = ReadLEUlong(); entriesForWholeCentralDir = ReadLEUlong(); centralDirSize = ReadLEUlong(); offsetOfCentralDir = (long)ReadLEUlong(); } #endregion _entries = new StiZipEntry[entriesForThisDisk]; if (!isZip64 && (offsetOfCentralDir < locatedEndOfCentralDir - (4 + (long)centralDirSize))) { offsetOfFirstEntry = locatedEndOfCentralDir - (4 + (long)centralDirSize + offsetOfCentralDir); if (offsetOfFirstEntry <= 0) { throw new StiZipException("Invalid embedded zip archive"); } } _baseStream.Seek(offsetOfFirstEntry + offsetOfCentralDir, SeekOrigin.Begin); for (ulong i = 0; i < entriesForThisDisk; i++) { if (ReadLEUint() != StiZipConstants.CentralHeaderSignature) { throw new StiZipException("Wrong Central Directory signature"); } int versionMadeBy = ReadLEUshort(); int versionToExtract = ReadLEUshort(); int bitFlags = ReadLEUshort(); int method = ReadLEUshort(); uint dostime = ReadLEUint(); uint crc = ReadLEUint(); long csize = (long)ReadLEUint(); long size = (long)ReadLEUint(); int nameLen = ReadLEUshort(); int extraLen = ReadLEUshort(); int commentLen = ReadLEUshort(); int diskStartNo = ReadLEUshort(); int internalAttributes = ReadLEUshort(); uint externalAttributes = ReadLEUint(); long offset = ReadLEUint(); byte[] buffer = new byte[Math.Max(nameLen, commentLen)]; Utils.ReadFully(_baseStream, buffer, 0, nameLen); string name = StiZipConstants.ConvertToStringExt(bitFlags, buffer, nameLen); StiZipEntry entry = new StiZipEntry(name, versionToExtract, versionMadeBy, (CompressionMethod)method); entry.zipFile = this; entry.Crc = crc & 0xffffffffL; entry.Size = size & 0xffffffffL; entry.CompressedSize = csize & 0xffffffffL; entry.Flags = bitFlags; entry.DosTime = (uint)dostime; entry.ZipFileIndex = (long)i; entry.Offset = offset; entry.ExternalFileAttributes = (int)externalAttributes; if (extraLen > 0) { byte[] extra = new byte[extraLen]; Utils.ReadFully(_baseStream, extra); entry.ExtraData = extra; } entry.ProcessExtraData(false); if (commentLen > 0) { Utils.ReadFully(_baseStream, buffer, 0, commentLen); entry.Comment = StiZipConstants.ConvertToStringExt(bitFlags, buffer, commentLen); } _entries[i] = entry; } }