private static bool ReadHeader(ZipEntry ze, Encoding defaultEncoding) { // no seek - stream integrity should be protected by the caller int bytesRead = 0; ze._RelativeOffsetOfHeader = (int) ze.ArchiveStream.Position; int signature = ZipSharedUtilities.ReadSignature(ze.ArchiveStream); bytesRead += 4; if (IsNotValidSig(signature)) { ze.ArchiveStream.Seek(-4L, SeekOrigin.Current); if (ZipDirEntry.IsNotValidSig(signature) && (signature != 0x6054b50L)) { throw new BadReadException(String.Format(" ZipEntry::ReadHeader(): Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, ze.ArchiveStream.Position)); } return false; } byte[] block = new byte[0x1a]; int n = ze.ArchiveStream.Read(block, 0, block.Length); if (n != block.Length) { return false; } bytesRead += n; int i = 0; ze._VersionNeeded = (short) (block[i++] + (block[i++] * 0x100)); ze._BitField = (short) (block[i++] + (block[i++] * 0x100)); ze._CompressionMethod = (short) (block[i++] + (block[i++] * 0x100)); ze._TimeBlob = ((block[i++] + (block[i++] * 0x100)) + ((block[i++] * 0x100) * 0x100)) + (((block[i++] * 0x100) * 0x100) * 0x100); ze._LastModified = ZipSharedUtilities.PackedToDateTime(ze._TimeBlob); if ((ze._BitField & 8) != 8) { ze._Crc32 = ((block[i++] + (block[i++] * 0x100)) + ((block[i++] * 0x100) * 0x100)) + (((block[i++] * 0x100) * 0x100) * 0x100); ze._CompressedSize = ((block[i++] + (block[i++] * 0x100)) + ((block[i++] * 0x100) * 0x100)) + (((block[i++] * 0x100) * 0x100) * 0x100); ze._UncompressedSize = ((block[i++] + (block[i++] * 0x100)) + ((block[i++] * 0x100) * 0x100)) + (((block[i++] * 0x100) * 0x100) * 0x100); } else { i += 12; } short filenameLength = (short) (block[i++] + (block[i++] * 0x100)); short extraFieldLength = (short) (block[i++] + (block[i++] * 0x100)); block = new byte[filenameLength]; n = ze.ArchiveStream.Read(block, 0, block.Length); bytesRead += n; var s1 = ZipSharedUtilities.StringFromBuffer(block, block.Length, Encoding.GetEncoding(1251)); var s2 = ZipSharedUtilities.StringFromBuffer(block, block.Length, Encoding.ASCII); var s3 = ZipSharedUtilities.StringFromBuffer(block, block.Length, Encoding.UTF8); var s4 = ZipSharedUtilities.StringFromBuffer(block, block.Length, Encoding.Default); var s5 = ZipSharedUtilities.StringFromBuffer(block, block.Length, Encoding.GetEncoding(1252)); if ((ze._BitField & 0x800) == 0x800) { ze._FileNameInArchive = ZipSharedUtilities.StringFromBuffer(block, block.Length, Encoding.UTF8); ze.UseUtf8Encoding = true; } else { ze._FileNameInArchive = ZipSharedUtilities.StringFromBuffer(block, block.Length, defaultEncoding); ze._encoding = defaultEncoding; } ze._LocalFileName = ze._FileNameInArchive; if (extraFieldLength > 0) { ze._Extra = new byte[extraFieldLength]; n = ze.ArchiveStream.Read(ze._Extra, 0, ze._Extra.Length); bytesRead += n; } if (!ze.FileName.EndsWith("/") && ((ze._BitField & 8) == 8)) { long posn = ze.ArchiveStream.Position; bool wantMore = true; long SizeOfDataRead = 0L; int tries = 0; while (wantMore) { tries++; long d = ZipSharedUtilities.FindSignature(ze.ArchiveStream, 0x8074b50); if (d == -1L) { return false; } SizeOfDataRead += d; block = new byte[12]; n = ze.ArchiveStream.Read(block, 0, block.Length); if (n != 12) { return false; } bytesRead += n; i = 0; ze._Crc32 = ((block[i++] + (block[i++] * 0x100)) + ((block[i++] * 0x100) * 0x100)) + (((block[i++] * 0x100) * 0x100) * 0x100); ze._CompressedSize = ((block[i++] + (block[i++] * 0x100)) + ((block[i++] * 0x100) * 0x100)) + (((block[i++] * 0x100) * 0x100) * 0x100); ze._UncompressedSize = ((block[i++] + (block[i++] * 0x100)) + ((block[i++] * 0x100) * 0x100)) + (((block[i++] * 0x100) * 0x100) * 0x100); if (SizeOfDataRead != ze._CompressedSize) { ze.ArchiveStream.Seek(-12L, SeekOrigin.Current); SizeOfDataRead += 4L; } } ze.ArchiveStream.Seek(posn, SeekOrigin.Begin); } ze._CompressedFileDataSize = ze._CompressedSize; if ((ze._BitField & 1) == 1) { throw new NotSupportedException("Encryption is not supported"); } ze._TotalEntrySize = bytesRead + ze._CompressedFileDataSize; ze._LengthOfHeader = bytesRead; return true; }
internal static ZipEntry Read(Stream s, Encoding defaultEncoding) { // no seek - stream integrity should be protected by the caller ZipEntry entry = new ZipEntry { _Source = EntrySource.Zipfile, _archiveStream = s }; if (!ReadHeader(entry, defaultEncoding)) { return null; } entry.__FileDataPosition = entry.ArchiveStream.Position; s.Seek((long) entry._CompressedFileDataSize, SeekOrigin.Current); if (!entry.FileName.EndsWith("/") && ((entry._BitField & 8) == 8)) { s.Seek(0x10L, SeekOrigin.Current); } HandleUnexpectedDataDescriptor(entry); return entry; }
internal static ZipEntry Create(String filename, String nameInArchive, Stream stream) { if (String.IsNullOrEmpty(filename)) { throw new ZipException("The entry name must be non-null and non-empty."); } ZipEntry entry = new ZipEntry(); if (stream != null) { entry._sourceStream = stream; entry._LastModified = DateTime.Now; } else { entry._LastModified = (File.Exists(filename) || Directory.Exists(filename)) ? ZipSharedUtilities.RoundToEvenSecond(File.GetLastWriteTime(filename)) : DateTime.Now; if (!(entry._LastModified.IsDaylightSavingTime() || !DateTime.Now.IsDaylightSavingTime())) { entry._LastModified += new TimeSpan(1, 0, 0); } if (!(!entry._LastModified.IsDaylightSavingTime() || DateTime.Now.IsDaylightSavingTime())) { entry._LastModified -= new TimeSpan(1, 0, 0); } } entry._LocalFileName = filename; entry._FileNameInArchive = nameInArchive.Replace('\\', '/'); return entry; }
private static void HandleUnexpectedDataDescriptor(ZipEntry entry) { // no seek - stream integrity should be protected by the caller Stream s = entry.ArchiveStream; if (ZipSharedUtilities.ReadInt(s) == entry._Crc32) { if (ZipSharedUtilities.ReadInt(s) == entry._CompressedSize) { if (ZipSharedUtilities.ReadInt(s) != entry._UncompressedSize) { s.Seek(-12L, SeekOrigin.Current); } } else { s.Seek(-8L, SeekOrigin.Current); } } else { s.Seek(-4L, SeekOrigin.Current); } }
internal void CopyMetaData(ZipEntry source) { this.__FileDataPosition = source.__FileDataPosition; this.CompressionMethod = source.CompressionMethod; this._CompressedFileDataSize = source._CompressedFileDataSize; this._UncompressedSize = source._UncompressedSize; this._BitField = source._BitField; this._LastModified = source._LastModified; }