private static System.Text.Encoding GetEncoding(ZipContainer container, string t) { switch (container.AlternateEncodingUsage) { case ZipOption.Always: return(container.AlternateEncoding); case ZipOption.Never: return(container.DefaultEncoding); } // AsNecessary is in force var e = container.DefaultEncoding; if (t == null) { return(e); } var bytes = e.GetBytes(t); var t2 = e.GetString(bytes, 0, bytes.Length); if (t2.Equals(t)) { return(e); } return(container.AlternateEncoding); }
// Token: 0x0600051C RID: 1308 RVA: 0x000251D0 File Offset: 0x000233D0 private static Encoding GetEncoding(ZipContainer container, string t) { switch (container.AlternateEncodingUsage) { case ZipOption.Default: return(container.DefaultEncoding); case ZipOption.Always: return(container.AlternateEncoding); } Encoding defaultEncoding = container.DefaultEncoding; if (t == null) { return(defaultEncoding); } byte[] bytes = defaultEncoding.GetBytes(t); string @string = defaultEncoding.GetString(bytes, 0, bytes.Length); if (@string.Equals(t)) { return(defaultEncoding); } return(container.AlternateEncoding); }
/// <summary> /// Extract to a stream /// In other words, you can extract to a stream or to a directory (filesystem), but not both! /// The Password param is required for encrypted entries. /// </summary> void InternalExtractToStream(Stream outStream, string password, ZipContainer zipContainer, ZipEntrySource zipEntrySource, string fileName) { // workitem 10355 if (zipContainer.ZipFile == null) { throw new InvalidOperationException("Use Extract() only with ZipFile."); } zipContainer.ZipFile.Reset(false); if (zipEntrySource != ZipEntrySource.ZipFile) { throw new BadStateException("You must call ZipFile.Save before calling any Extract method"); } OnBeforeExtract(this, null, zipContainer.ZipFile); _ioOperationCanceled = false; try { ValidateCompression(_CompressionMethod_FromZipFile, fileName, GetUnsupportedCompressionMethod(_CompressionMethod)); ValidateEncryption(Encryption, fileName, _UnsupportedAlgorithmId); if (IsDoneWithOutputToStream()) { WriteStatus("extract dir {0}...", null); // if true, then the entry was a directory and has been created. // We need to fire the Extract Event. OnAfterExtract(null); return; } // If no password explicitly specified, use the password on the entry itself, // or on the zipfile itself. if (_Encryption_FromZipFile != EncryptionAlgorithm.None) { EnsurePassword(password); } WriteStatus("extract entry {0} to stream...", fileName); var archiveStream = ArchiveStream; if (ExtractToStream(archiveStream, outStream, Encryption, _Crc32)) { goto ExitTry; } OnAfterExtract(null); ExitTry :; } catch (Exception) { _ioOperationCanceled = true; throw; } }
/// <summary> /// Reads one <c>ZipEntry</c> from the given stream. If the entry is encrypted, we don't /// decrypt at this point. We also do not decompress. Mostly we read metadata. /// </summary> /// <param name="zc">the ZipContainer this entry belongs to.</param> /// <param name="first">true of this is the first entry being read from the stream.</param> /// <returns>the <c>ZipEntry</c> read from the stream.</returns> internal static ZipEntry ReadEntry(ZipContainer zc, bool first) { ZipFile zf = zc.ZipFile; Stream s = zc.ReadStream; System.Text.Encoding defaultEncoding = zc.ProvisionalAlternateEncoding; ZipEntry entry = new ZipEntry(); entry._Source = ZipEntrySource.ZipFile; entry._container = zc; entry._archiveStream = s; if (zf != null) { zf.OnReadEntry(true, null); } if (first) { HandlePK00Prefix(s); } // Read entry header, including any encryption header if (!ReadHeader(entry, defaultEncoding)) { return(null); } // Store the position in the stream for this entry // change for workitem 8098 entry.__FileDataPosition = entry.ArchiveStream.Position; // seek past the data without reading it. We will read on Extract() s.Seek(entry._CompressedFileDataSize + entry._LengthOfTrailer, SeekOrigin.Current); // workitem 10178 Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); // ReadHeader moves the file pointer to the end of the entry header, // as well as any encryption header. // CompressedFileDataSize includes: // the maybe compressed, maybe encrypted file data // the encryption trailer, if any // the bit 3 descriptor, if any // workitem 5306 // http://www.codeplex.com/DotNetZip/WorkItem/View.aspx?WorkItemId=5306 HandleUnexpectedDataDescriptor(entry); if (zf != null) { zf.OnReadBytes(entry); zf.OnReadEntry(false, entry); } return(entry); }
private void _Init(Stream stream, bool leaveOpen) { _inputStream = stream; if (!_inputStream.CanRead) { throw new ZipException("The stream must be readable."); } _container = new ZipContainer(this); _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437"); _leaveUnderlyingStreamOpen = leaveOpen; _findRequired = true; }
private void _Init(Stream stream, bool leaveOpen, string name) { _inputStream = stream; if (!_inputStream.CanRead) { throw new ZipException("The stream must be readable."); } _container = new ZipContainer(this); _provisionalAlternateEncoding = SharedUtilities.ibm437; _leaveUnderlyingStreamOpen = leaveOpen; _findRequired = true; _name = name ?? "(stream)"; }
/// <summary> /// Reads one <c>ZipEntry</c> from the given stream. If the entry is encrypted, we don't /// decrypt at this point. We also do not decompress. Mostly we read metadata. /// </summary> /// <param name="zc">the ZipContainer this entry belongs to.</param> /// <param name="first">true of this is the first entry being read from the stream.</param> /// <returns>the <c>ZipEntry</c> read from the stream.</returns> internal static ZipEntry ReadEntry(ZipContainer zc, bool first) { ZipFile zf = zc.ZipFile; Stream s = zc.ReadStream; System.Text.Encoding defaultEncoding = zc.ProvisionalAlternateEncoding; ZipEntry entry = new ZipEntry(); entry._Source = ZipEntrySource.ZipFile; entry._container = zc; entry._archiveStream = s; if (zf != null) zf.OnReadEntry(true, null); if (first) HandlePK00Prefix(s); // Read entry header, including any encryption header if (!ReadHeader(entry, defaultEncoding)) return null; // Store the position in the stream for this entry // change for workitem 8098 entry.__FileDataPosition = entry.ArchiveStream.Position; // seek past the data without reading it. We will read on Extract() s.Seek(entry._CompressedFileDataSize + entry._LengthOfTrailer, SeekOrigin.Current); // workitem 10178 Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); // ReadHeader moves the file pointer to the end of the entry header, // as well as any encryption header. // CompressedFileDataSize includes: // the maybe compressed, maybe encrypted file data // the encryption trailer, if any // the bit 3 descriptor, if any // workitem 5306 // http://www.codeplex.com/DotNetZip/WorkItem/View.aspx?WorkItemId=5306 HandleUnexpectedDataDescriptor(entry); if (zf != null) { zf.OnReadBytes(entry); zf.OnReadEntry(false, entry); } return entry; }
private void _Init(Stream stream, bool leaveOpen, string name) { _inputStream = stream; if (!_inputStream.CanRead) { throw new ZipException("The stream must be readable."); } _container = new ZipContainer(this); #if (Core) _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("utf-8"); #else _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437"); #endif _leaveUnderlyingStreamOpen = leaveOpen; _findRequired = true; _name = name ?? "(stream)"; }
internal static ZipEntry ReadEntry(ZipContainer zc, bool first) { ZipFile zf = zc.ZipFile; Stream s = zc.ReadStream; System.Text.Encoding defaultEncoding = zc.AlternateEncoding; ZipEntry entry = new ZipEntry(); entry._Source = ZipEntrySource.ZipFile; entry._container = zc; entry._archiveStream = s; if (zf != null) { zf.OnReadEntry(true, null); } if (first) { HandlePK00Prefix(s); } // Read entry header, including any encryption header if (!ReadHeader(entry, defaultEncoding)) { return(null); } // Store the position in the stream for this entry // change for workitem 8098 entry.__FileDataPosition = entry.ArchiveStream.Position; // seek past the data without reading it. We will read on Extract() s.Seek(entry._CompressedFileDataSize + entry._LengthOfTrailer, SeekOrigin.Current); HandleUnexpectedDataDescriptor(entry); if (zf != null) { zf.OnReadBytes(entry); zf.OnReadEntry(false, entry); } return(entry); }
private void _Init(Stream stream, bool leaveOpen, string name) { _inputStream = stream; if (!_inputStream.CanRead) { throw new ZipException("The stream must be readable."); } _container = new ZipContainer(this); #if NETSTANDARD2_0 || NETSTANDARD2_1 if (_provisionalAlternateEncoding == null) { _provisionalAlternateEncoding = System.Text.Encoding.ASCII; } #elif NETCOREAPP2_0 || NET5_0 || NET6_0 || NETCOREAPP3_0 || NETCOREAPP3_1 if (_provisionalAlternateEncoding == null) { try { _provisionalAlternateEncoding = System.Text.CodePagesEncodingProvider.Instance.GetEncoding(1252); } catch (Exception /*e*/) { } } #else if (_provisionalAlternateEncoding == null) { try { _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding(1252); } catch (Exception /*e*/) { } } #endif _leaveUnderlyingStreamOpen = leaveOpen; _findRequired = true; _name = name ?? "(stream)"; }
// build the TOC by reading each entry in the file. private static void ReadIntoInstance_Orig(ZipFile zf) { zf.OnReadStarted(); //zf._entries = new System.Collections.Generic.List<ZipEntry>(); zf._entries = new System.Collections.Generic.Dictionary<String,ZipEntry>(); ZipEntry e; if (zf.Verbose) if (zf.Name == null) zf.StatusMessageTextWriter.WriteLine("Reading zip from stream..."); else zf.StatusMessageTextWriter.WriteLine("Reading zip {0}...", zf.Name); // work item 6647: PK00 (packed to removable disk) bool firstEntry = true; ZipContainer zc = new ZipContainer(zf); while ((e = ZipEntry.ReadEntry(zc, firstEntry)) != null) { if (zf.Verbose) zf.StatusMessageTextWriter.WriteLine(" {0}", e.FileName); zf._entries.Add(e.FileName,e); firstEntry = false; } // read the zipfile's central directory structure here. // workitem 9912 // But, because it may be corrupted, ignore errors. try { ZipEntry de; // in lieu of hashset, use a dictionary var previouslySeen = new Dictionary<String,Object>(); while ((de = ZipEntry.ReadDirEntry(zf, previouslySeen)) != null) { // Housekeeping: Since ZipFile exposes ZipEntry elements in the enumerator, // we need to copy the comment that we grab from the ZipDirEntry // into the ZipEntry, so the application can access the comment. // Also since ZipEntry is used to Write zip files, we need to copy the // file attributes to the ZipEntry as appropriate. ZipEntry e1 = zf._entries[de.FileName]; if (e1 != null) { e1._Comment = de.Comment; if (de.IsDirectory) e1.MarkAsDirectory(); } previouslySeen.Add(de.FileName,null); // to prevent dupes } // workitem 8299 if (zf._locEndOfCDS > 0) zf.ReadStream.Seek(zf._locEndOfCDS, SeekOrigin.Begin); ReadCentralDirectoryFooter(zf); if (zf.Verbose && !String.IsNullOrEmpty(zf.Comment)) zf.StatusMessageTextWriter.WriteLine("Zip file Comment: {0}", zf.Comment); } catch (ZipException) { } catch (IOException) { } zf.OnReadCompleted(); }
// Token: 0x060005F6 RID: 1526 RVA: 0x00039A20 File Offset: 0x00037C20 private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, ZipContainer container) { Encoding encoding = ZipOutput.GetEncoding(container, comment); int num = 22; byte[] array = null; short num2 = 0; if (comment != null && comment.Length != 0) { array = encoding.GetBytes(comment); num2 = (short)array.Length; } num += (int)num2; byte[] array2 = new byte[num]; byte[] bytes = BitConverter.GetBytes(101010256U); Array.Copy(bytes, 0, array2, 0, 4); array2[4] = 0; array2[5] = 0; array2[6] = 0; byte[] array3 = array2; int num3 = 7; int num4 = 8; array3[num3] = 0; if (entryCount < 65535) { if (zip64 != Zip64Option.Always) { array2[num4++] = (byte)(entryCount & 255); array2[num4++] = (byte)((entryCount & 65280) >> 8); array2[num4++] = (byte)(entryCount & 255); array2[num4++] = (byte)((entryCount & 65280) >> 8); goto IL_F2; } } for (int i = 0; i < 4; i++) { array2[num4++] = byte.MaxValue; } IL_F2: long num5 = EndOfCentralDirectory - StartOfCentralDirectory; if (num5 < 4294967295L && StartOfCentralDirectory < 4294967295L) { array2[num4++] = (byte)(num5 & 255L); array2[num4++] = (byte)((num5 & 65280L) >> 8); array2[num4++] = (byte)((num5 & 16711680L) >> 16); array2[num4++] = (byte)((num5 & 4278190080L) >> 24); array2[num4++] = (byte)(StartOfCentralDirectory & 255L); array2[num4++] = (byte)((StartOfCentralDirectory & 65280L) >> 8); array2[num4++] = (byte)((StartOfCentralDirectory & 16711680L) >> 16); array2[num4++] = (byte)((StartOfCentralDirectory & 4278190080L) >> 24); } else { for (int i = 0; i < 8; i++) { array2[num4++] = byte.MaxValue; } } if (comment != null && comment.Length != 0) { if ((int)num2 + num4 + 2 > array2.Length) { num2 = (short)(array2.Length - num4 - 2); } array2[num4++] = (byte)(num2 & 255); array2[num4++] = (byte)(((int)num2 & 65280) >> 8); if (num2 != 0) { int i = 0; while (i < (int)num2 && num4 + i < array2.Length) { array2[num4 + i] = array[i]; i++; } num4 += i; } } else { array2[num4++] = 0; array2[num4++] = 0; } return(array2); }
// Token: 0x0600051D RID: 1309 RVA: 0x00025244 File Offset: 0x00023444 private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, ZipContainer container) { Encoding encoding = ZipOutput.GetEncoding(container, comment); int num = 22; byte[] array = null; short num2 = 0; if (comment != null && comment.Length != 0) { array = encoding.GetBytes(comment); num2 = (short)array.Length; } num += (int)num2; byte[] array2 = new byte[num]; int num3 = 0; byte[] bytes = BitConverter.GetBytes(101010256u); Array.Copy(bytes, 0, array2, num3, 4); num3 += 4; array2[num3++] = 0; array2[num3++] = 0; array2[num3++] = 0; array2[num3++] = 0; if (entryCount >= 65535 || zip64 == Zip64Option.Always) { for (int i = 0; i < 4; i++) { array2[num3++] = byte.MaxValue; } } else { array2[num3++] = (byte)(entryCount & 255); array2[num3++] = (byte)((entryCount & 65280) >> 8); array2[num3++] = (byte)(entryCount & 255); array2[num3++] = (byte)((entryCount & 65280) >> 8); } long num4 = EndOfCentralDirectory - StartOfCentralDirectory; if (num4 >= (long)((ulong)-1) || StartOfCentralDirectory >= (long)((ulong)-1)) { for (int i = 0; i < 8; i++) { array2[num3++] = byte.MaxValue; } } else { array2[num3++] = (byte)(num4 & 255L); array2[num3++] = (byte)((num4 & 65280L) >> 8); array2[num3++] = (byte)((num4 & 16711680L) >> 16); array2[num3++] = (byte)((num4 & (long)((ulong)-16777216)) >> 24); array2[num3++] = (byte)(StartOfCentralDirectory & 255L); array2[num3++] = (byte)((StartOfCentralDirectory & 65280L) >> 8); array2[num3++] = (byte)((StartOfCentralDirectory & 16711680L) >> 16); array2[num3++] = (byte)((StartOfCentralDirectory & (long)((ulong)-16777216)) >> 24); } if (comment == null || comment.Length == 0) { array2[num3++] = 0; array2[num3++] = 0; } else { if ((int)num2 + num3 + 2 > array2.Length) { num2 = (short)(array2.Length - num3 - 2); } array2[num3++] = (byte)(num2 & 255); array2[num3++] = (byte)(((int)num2 & 65280) >> 8); if (num2 != 0) { int i = 0; while (i < (int)num2 && num3 + i < array2.Length) { array2[num3 + i] = array[i]; i++; } num3 += i; } } return(array2); }
// Token: 0x0600051B RID: 1307 RVA: 0x00024F38 File Offset: 0x00023138 public static bool WriteCentralDirectoryStructure(Stream s, ICollection <ZipEntry> entries, uint numSegments, Zip64Option zip64, string comment, ZipContainer container) { ZipSegmentedStream zipSegmentedStream = s as ZipSegmentedStream; if (zipSegmentedStream != null) { zipSegmentedStream.ContiguousWrite = true; } long num = 0L; using (MemoryStream memoryStream = new MemoryStream()) { foreach (ZipEntry zipEntry in entries) { if (zipEntry.IncludedInMostRecentSave) { zipEntry.WriteCentralDirectoryEntry(memoryStream); } } byte[] array = memoryStream.ToArray(); s.Write(array, 0, array.Length); num = (long)array.Length; } CountingStream countingStream = s as CountingStream; long num2 = (countingStream != null) ? countingStream.ComputedPosition : s.Position; long num3 = num2 - num; uint num4 = (zipSegmentedStream != null) ? zipSegmentedStream.CurrentSegment : 0u; long num5 = num2 - num3; int num6 = ZipOutput.CountEntries(entries); bool flag = zip64 == Zip64Option.Always || num6 >= 65535 || num5 > (long)((ulong)-1) || num3 > (long)((ulong)-1); byte[] array3; if (flag) { if (zip64 == Zip64Option.Default) { StackFrame stackFrame = new StackFrame(1); if (stackFrame.GetMethod().DeclaringType == typeof(ZipFile)) { throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property."); } throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property."); } else { byte[] array2 = ZipOutput.GenZip64EndOfCentralDirectory(num3, num2, num6, numSegments); array3 = ZipOutput.GenCentralDirectoryFooter(num3, num2, zip64, num6, comment, container); if (num4 != 0u) { uint value = zipSegmentedStream.ComputeSegment(array2.Length + array3.Length); int num7 = 16; Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4); num7 += 4; Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4); num7 = 60; Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4); num7 += 4; num7 += 8; Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4); } s.Write(array2, 0, array2.Length); } } else { array3 = ZipOutput.GenCentralDirectoryFooter(num3, num2, zip64, num6, comment, container); } if (num4 != 0u) { ushort value2 = (ushort)zipSegmentedStream.ComputeSegment(array3.Length); int num8 = 4; Array.Copy(BitConverter.GetBytes(value2), 0, array3, num8, 2); num8 += 2; Array.Copy(BitConverter.GetBytes(value2), 0, array3, num8, 2); num8 += 2; } s.Write(array3, 0, array3.Length); if (zipSegmentedStream != null) { zipSegmentedStream.ContiguousWrite = false; } return(flag); }
private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, ZipContainer container) { Encoding encoding = GetEncoding(container, comment); int num = 0; int num2 = 22; byte[] array = null; short num3 = 0; if (comment != null && comment.Length != 0) { array = encoding.GetBytes(comment); num3 = (short)array.Length; } num2 += num3; byte[] array2 = new byte[num2]; int num4 = 0; byte[] bytes = BitConverter.GetBytes(101010256u); Array.Copy(bytes, 0, array2, num4, 4); num4 += 4; array2[num4++] = 0; array2[num4++] = 0; array2[num4++] = 0; array2[num4++] = 0; if (entryCount >= 65535 || zip64 == Zip64Option.Always) { for (num = 0; num < 4; num++) { array2[num4++] = byte.MaxValue; } } else { array2[num4++] = (byte)(entryCount & 0xFF); array2[num4++] = (byte)((entryCount & 0xFF00) >> 8); array2[num4++] = (byte)(entryCount & 0xFF); array2[num4++] = (byte)((entryCount & 0xFF00) >> 8); } long num5 = EndOfCentralDirectory - StartOfCentralDirectory; if (num5 >= uint.MaxValue || StartOfCentralDirectory >= uint.MaxValue) { for (num = 0; num < 8; num++) { array2[num4++] = byte.MaxValue; } } else { array2[num4++] = (byte)(num5 & 0xFF); array2[num4++] = (byte)((num5 & 0xFF00) >> 8); array2[num4++] = (byte)((num5 & 0xFF0000) >> 16); array2[num4++] = (byte)((num5 & 4278190080u) >> 24); array2[num4++] = (byte)(StartOfCentralDirectory & 0xFF); array2[num4++] = (byte)((StartOfCentralDirectory & 0xFF00) >> 8); array2[num4++] = (byte)((StartOfCentralDirectory & 0xFF0000) >> 16); array2[num4++] = (byte)((StartOfCentralDirectory & 4278190080u) >> 24); } if (comment == null || comment.Length == 0) { array2[num4++] = 0; array2[num4++] = 0; } else { if (num3 + num4 + 2 > array2.Length) { num3 = (short)(array2.Length - num4 - 2); } array2[num4++] = (byte)(num3 & 0xFF); array2[num4++] = (byte)((num3 & 0xFF00) >> 8); if (num3 != 0) { for (num = 0; num < num3 && num4 + num < array2.Length; num++) { array2[num4 + num] = array[num]; } num4 += num; } } return(array2); }
/// <summary> /// Pass in either basedir or s, but not both. /// In other words, you can extract to a stream or to a directory (filesystem), but not both! /// The Password param is required for encrypted entries. /// </summary> void InternalExtractToBaseDir(string baseDir, string password, ZipContainer zipContainer, ZipEntrySource zipEntrySource, string fileName) { if (baseDir == null) throw new ArgumentNullException("baseDir"); // workitem 7958 if (zipContainer == null) throw new BadStateException("This entry is an orphan"); // workitem 10355 if (zipContainer.ZipFile == null) throw new InvalidOperationException("Use Extract() only with ZipFile."); zipContainer.ZipFile.Reset(false); if (zipEntrySource != ZipEntrySource.ZipFile) throw new BadStateException("You must call ZipFile.Save before calling any Extract method"); OnBeforeExtract(this, baseDir, zipContainer.ZipFile); _ioOperationCanceled = false; var fileExistsBeforeExtraction = false; var checkLaterForResetDirTimes = false; string targetFileName = null; try { ValidateCompression(_CompressionMethod_FromZipFile, fileName, GetUnsupportedCompressionMethod(_CompressionMethod)); ValidateEncryption(Encryption, fileName, _UnsupportedAlgorithmId); if (IsDoneWithOutputToBaseDir(baseDir, out targetFileName)) { WriteStatus("extract dir {0}...", targetFileName); // if true, then the entry was a directory and has been created. // We need to fire the Extract Event. OnAfterExtract(baseDir); return; } // workitem 10639 // do we want to extract to a regular filesystem file? // Check for extracting to a previously existing file. The user // can specify bejavior for that case: overwrite, don't // overwrite, and throw. Also, if the file exists prior to // extraction, it affects exception handling: whether to delete // the target of extraction or not. This check needs to be done // before the password check is done, because password check may // throw a BadPasswordException, which triggers the catch, // wherein the existing file may be deleted if not flagged as // pre-existing. if (File.Exists(targetFileName)) { fileExistsBeforeExtraction = true; int rc = CheckExtractExistingFile(baseDir, targetFileName); if (rc == 2) goto ExitTry; // cancel if (rc == 1) return; // do not overwrite } // If no password explicitly specified, use the password on the entry itself, // or on the zipfile itself. if (_Encryption_FromZipFile != EncryptionAlgorithm.None) EnsurePassword(password); // set up the output stream var tmpName = Path.GetRandomFileName(); var tmpPath = Path.Combine(Path.GetDirectoryName(targetFileName), tmpName); WriteStatus("extract file {0}...", targetFileName); using (var output = OpenFileStream(tmpPath, ref checkLaterForResetDirTimes)) { if (ExtractToStream(ArchiveStream, output, Encryption, _Crc32)) goto ExitTry; output.Close(); } MoveFileInPlace(fileExistsBeforeExtraction, targetFileName, tmpPath, checkLaterForResetDirTimes); OnAfterExtract(baseDir); ExitTry: ; } catch (Exception) { _ioOperationCanceled = true; throw; } finally { if (_ioOperationCanceled && targetFileName != null) { // An exception has occurred. If the file exists, check // to see if it existed before we tried extracting. If // it did not, attempt to remove the target file. There // is a small possibility that the existing file has // been extracted successfully, overwriting a previously // existing file, and an exception was thrown after that // but before final completion (setting times, etc). In // that case the file will remain, even though some // error occurred. Nothing to be done about it. if (File.Exists(targetFileName) && !fileExistsBeforeExtraction) File.Delete(targetFileName); } } }
// build the TOC by reading each entry in the file. private static void ReadIntoInstance_Orig(ZipFile zf) { zf.OnReadStarted(); //zf._entries = new System.Collections.Generic.List<ZipEntry>(); zf._entries = new System.Collections.Generic.Dictionary <String, ZipEntry>(); ZipEntry e; if (zf.Verbose) { if (zf.Name == null) { zf.StatusMessageTextWriter.WriteLine("Reading zip from stream..."); } else { zf.StatusMessageTextWriter.WriteLine("Reading zip {0}...", zf.Name); } } // work item 6647: PK00 (packed to removable disk) bool firstEntry = true; ZipContainer zc = new ZipContainer(zf); while ((e = ZipEntry.ReadEntry(zc, firstEntry)) != null) { if (zf.Verbose) { zf.StatusMessageTextWriter.WriteLine(" {0}", e.FileName); } zf._entries.Add(e.FileName, e); firstEntry = false; } // read the zipfile's central directory structure here. // workitem 9912 // But, because it may be corrupted, ignore errors. try { ZipEntry de; while ((de = ZipEntry.ReadDirEntry(zf)) != null) { // Housekeeping: Since ZipFile exposes ZipEntry elements in the enumerator, // we need to copy the comment that we grab from the ZipDirEntry // into the ZipEntry, so the application can access the comment. // Also since ZipEntry is used to Write zip files, we need to copy the // file attributes to the ZipEntry as appropriate. ZipEntry e1 = zf._entries[de.FileName]; if (e1 != null) { e1._Comment = de.Comment; if (de.IsDirectory) { e1.MarkAsDirectory(); } } } // workitem 8299 if (zf._locEndOfCDS > 0) { zf.ReadStream.Seek(zf._locEndOfCDS, SeekOrigin.Begin); } ReadCentralDirectoryFooter(zf); if (zf.Verbose && !String.IsNullOrEmpty(zf.Comment)) { zf.StatusMessageTextWriter.WriteLine("Zip file Comment: {0}", zf.Comment); } } catch { } zf.OnReadCompleted(); }
public static bool WriteCentralDirectoryStructure(Stream s, ICollection <ZipEntry> entries, uint numSegments, Zip64Option zip64, String comment, ZipContainer container) { var zss = s as ZipSegmentedStream; if (zss != null) { zss.ContiguousWrite = true; } // write to a memory stream in order to keep the // CDR contiguous Int64 aLength = 0; using (var ms = new MemoryStream()) { foreach (ZipEntry e in entries) { if (e.IncludedInMostRecentSave) { // this writes a ZipDirEntry corresponding to the ZipEntry e.WriteCentralDirectoryEntry(ms); } } var a = ms.ToArray(); s.Write(a, 0, a.Length); aLength = a.Length; } // We need to keep track of the start and // Finish of the Central Directory Structure. // Cannot always use WriteStream.Length or Position; some streams do // not support these. (eg, ASP.NET Response.OutputStream) In those // cases we have a CountingStream. // Also, we cannot just set Start as s.Position bfore the write, and Finish // as s.Position after the write. In a split zip, the write may actually // flip to the next segment. In that case, Start will be zero. But we // don't know that til after we know the size of the thing to write. So the // answer is to compute the directory, then ask the ZipSegmentedStream which // segment that directory would fall in, it it were written. Then, include // that data into the directory, and finally, write the directory to the // output stream. var output = s as CountingStream; long Finish = (output != null) ? output.ComputedPosition : s.Position; // BytesWritten long Start = Finish - aLength; // need to know which segment the EOCD record starts in UInt32 startSegment = (zss != null) ? zss.CurrentSegment : 0; Int64 SizeOfCentralDirectory = Finish - Start; int countOfEntries = CountEntries(entries); bool needZip64CentralDirectory = zip64 == Zip64Option.Always || countOfEntries >= 0xFFFF || SizeOfCentralDirectory > 0xFFFFFFFF || Start > 0xFFFFFFFF; byte[] a2 = null; // emit ZIP64 extensions as required if (needZip64CentralDirectory) { if (zip64 == Zip64Option.Never) { #if NETCF throw new ZipException("The archive requires a ZIP64 Central Directory. Consider enabling ZIP64 extensions."); #else System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(1); if (sf.GetMethod().DeclaringType == typeof(ZipFile)) { throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property."); } else { throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property."); } #endif } var a = GenZip64EndOfCentralDirectory(Start, Finish, countOfEntries, numSegments); a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container); if (startSegment != 0) { UInt32 thisSegment = zss.ComputeSegment(a.Length + a2.Length); int i = 16; // number of this disk Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i += 4; // number of the disk with the start of the central directory //Array.Copy(BitConverter.GetBytes(startSegment), 0, a, i, 4); Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i = 60; // offset 60 // number of the disk with the start of the zip64 eocd Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i += 4; i += 8; // offset 72 // total number of disks Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); } s.Write(a, 0, a.Length); } else { a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container); } // now, the regular footer if (startSegment != 0) { // The assumption is the central directory is never split across // segment boundaries. UInt16 thisSegment = (UInt16)zss.ComputeSegment(a2.Length); int i = 4; // number of this disk Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2); i += 2; // number of the disk with the start of the central directory //Array.Copy(BitConverter.GetBytes((UInt16)startSegment), 0, a2, i, 2); Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2); i += 2; } s.Write(a2, 0, a2.Length); // reset the contiguous write property if necessary if (zss != null) { zss.ContiguousWrite = false; } return(needZip64CentralDirectory); }
public static bool WriteCentralDirectoryStructure(Stream s, ICollection<ZipEntry> entries, uint numSegments, Zip64Option zip64, String comment, ZipContainer container) { var zss = s as ZipSegmentedStream; if (zss != null) zss.ContiguousWrite = true; // write to a memory stream in order to keep the // CDR contiguous Int64 aLength = 0; using (var ms = new MemoryStream()) { foreach (ZipEntry e in entries) { if (e.IncludedInMostRecentSave) { // this writes a ZipDirEntry corresponding to the ZipEntry e.WriteCentralDirectoryEntry(ms); } } var a = ms.ToArray(); s.Write(a, 0, a.Length); aLength = a.Length; } // We need to keep track of the start and // Finish of the Central Directory Structure. // Cannot always use WriteStream.Length or Position; some streams do // not support these. (eg, ASP.NET Response.OutputStream) In those // cases we have a CountingStream. // Also, we cannot just set Start as s.Position bfore the write, and Finish // as s.Position after the write. In a split zip, the write may actually // flip to the next segment. In that case, Start will be zero. But we // don't know that til after we know the size of the thing to write. So the // answer is to compute the directory, then ask the ZipSegmentedStream which // segment that directory would fall in, it it were written. Then, include // that data into the directory, and finally, write the directory to the // output stream. var output = s as CountingStream; long Finish = (output != null) ? output.ComputedPosition : s.Position; // BytesWritten long Start = Finish - aLength; // need to know which segment the EOCD record starts in UInt32 startSegment = (zss != null) ? zss.CurrentSegment : 0; Int64 SizeOfCentralDirectory = Finish - Start; int countOfEntries = CountEntries(entries); bool needZip64CentralDirectory = zip64 == Zip64Option.Always || countOfEntries >= 0xFFFF || SizeOfCentralDirectory > 0xFFFFFFFF || Start > 0xFFFFFFFF; byte[] a2 = null; // emit ZIP64 extensions as required if (needZip64CentralDirectory) { if (zip64 == Zip64Option.Never) { #if NETCF throw new ZipException("The archive requires a ZIP64 Central Directory. Consider enabling ZIP64 extensions."); #else System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(1); if (sf.GetMethod().DeclaringType == typeof(ZipFile)) throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property."); else throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property."); #endif } var a = GenZip64EndOfCentralDirectory(Start, Finish, countOfEntries, numSegments); a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container); if (startSegment != 0) { UInt32 thisSegment = zss.ComputeSegment(a.Length + a2.Length); int i = 16; // number of this disk Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i += 4; // number of the disk with the start of the central directory //Array.Copy(BitConverter.GetBytes(startSegment), 0, a, i, 4); Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i = 60; // offset 60 // number of the disk with the start of the zip64 eocd Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i += 4; i += 8; // offset 72 // total number of disks Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); } s.Write(a, 0, a.Length); } else a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container); // now, the regular footer if (startSegment != 0) { // The assumption is the central directory is never split across // segment boundaries. UInt16 thisSegment = (UInt16) zss.ComputeSegment(a2.Length); int i = 4; // number of this disk Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2); i += 2; // number of the disk with the start of the central directory //Array.Copy(BitConverter.GetBytes((UInt16)startSegment), 0, a2, i, 2); Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2); i += 2; } s.Write(a2, 0, a2.Length); // reset the contiguous write property if necessary if (zss != null) zss.ContiguousWrite = false; return needZip64CentralDirectory; }
private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, ZipContainer container) { System.Text.Encoding encoding = GetEncoding(container, comment); int j = 0; int bufferLength = 22; byte[] block = null; Int16 commentLength = 0; if ((comment != null) && (comment.Length != 0)) { block = encoding.GetBytes(comment); commentLength = (Int16)block.Length; } bufferLength += commentLength; byte[] bytes = new byte[bufferLength]; int i = 0; // signature byte[] sig = BitConverter.GetBytes(ZipConstants.EndOfCentralDirectorySignature); Array.Copy(sig, 0, bytes, i, 4); i += 4; // number of this disk // (this number may change later) bytes[i++] = 0; bytes[i++] = 0; // number of the disk with the start of the central directory // (this number may change later) bytes[i++] = 0; bytes[i++] = 0; // handle ZIP64 extensions for the end-of-central-directory if (entryCount >= 0xFFFF || zip64 == Zip64Option.Always) { // the ZIP64 version. for (j = 0; j < 4; j++) { bytes[i++] = 0xFF; } } else { // the standard version. // total number of entries in the central dir on this disk bytes[i++] = (byte)(entryCount & 0x00FF); bytes[i++] = (byte)((entryCount & 0xFF00) >> 8); // total number of entries in the central directory bytes[i++] = (byte)(entryCount & 0x00FF); bytes[i++] = (byte)((entryCount & 0xFF00) >> 8); } // size of the central directory Int64 SizeOfCentralDirectory = EndOfCentralDirectory - StartOfCentralDirectory; if (SizeOfCentralDirectory >= 0xFFFFFFFF || StartOfCentralDirectory >= 0xFFFFFFFF) { // The actual data is in the ZIP64 central directory structure for (j = 0; j < 8; j++) { bytes[i++] = 0xFF; } } else { // size of the central directory (we just get the low 4 bytes) bytes[i++] = (byte)(SizeOfCentralDirectory & 0x000000FF); bytes[i++] = (byte)((SizeOfCentralDirectory & 0x0000FF00) >> 8); bytes[i++] = (byte)((SizeOfCentralDirectory & 0x00FF0000) >> 16); bytes[i++] = (byte)((SizeOfCentralDirectory & 0xFF000000) >> 24); // offset of the start of the central directory (we just get the low 4 bytes) bytes[i++] = (byte)(StartOfCentralDirectory & 0x000000FF); bytes[i++] = (byte)((StartOfCentralDirectory & 0x0000FF00) >> 8); bytes[i++] = (byte)((StartOfCentralDirectory & 0x00FF0000) >> 16); bytes[i++] = (byte)((StartOfCentralDirectory & 0xFF000000) >> 24); } // zip archive comment if ((comment == null) || (comment.Length == 0)) { // no comment! bytes[i++] = (byte)0; bytes[i++] = (byte)0; } else { // the size of our buffer defines the max length of the comment we can write if (commentLength + i + 2 > bytes.Length) { commentLength = (Int16)(bytes.Length - i - 2); } bytes[i++] = (byte)(commentLength & 0x00FF); bytes[i++] = (byte)((commentLength & 0xFF00) >> 8); if (commentLength != 0) { // now actually write the comment itself into the byte buffer for (j = 0; (j < commentLength) && (i + j < bytes.Length); j++) { bytes[i + j] = block[j]; } i += j; } } // s.Write(bytes, 0, i); return(bytes); }
private static System.Text.Encoding GetEncoding(ZipContainer container, string t) { switch (container.AlternateEncodingUsage) { case ZipOption.Always: return container.AlternateEncoding; case ZipOption.Never: return container.DefaultEncoding; } // AsNecessary is in force var e = container.DefaultEncoding; if (t == null) return e; var bytes = e.GetBytes(t); var t2 = e.GetString(bytes,0,bytes.Length); if (t2.Equals(t)) return e; return container.AlternateEncoding; }
private void _Init(Stream stream, bool leaveOpen, string name) { _inputStream = stream; if (!_inputStream.CanRead) throw new ZipException("The stream must be readable."); _container= new ZipContainer(this); _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437"); _leaveUnderlyingStreamOpen = leaveOpen; _findRequired= true; _name = name ?? "(stream)"; }
private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, ZipContainer container) { System.Text.Encoding encoding = GetEncoding(container, comment); int j = 0; int bufferLength = 22; byte[] block = null; Int16 commentLength = 0; if ((comment != null) && (comment.Length != 0)) { block = encoding.GetBytes(comment); commentLength = (Int16)block.Length; } bufferLength += commentLength; byte[] bytes = new byte[bufferLength]; int i = 0; // signature byte[] sig = BitConverter.GetBytes(ZipConstants.EndOfCentralDirectorySignature); Array.Copy(sig, 0, bytes, i, 4); i+=4; // number of this disk // (this number may change later) bytes[i++] = 0; bytes[i++] = 0; // number of the disk with the start of the central directory // (this number may change later) bytes[i++] = 0; bytes[i++] = 0; // handle ZIP64 extensions for the end-of-central-directory if (entryCount >= 0xFFFF || zip64 == Zip64Option.Always) { // the ZIP64 version. for (j = 0; j < 4; j++) bytes[i++] = 0xFF; } else { // the standard version. // total number of entries in the central dir on this disk bytes[i++] = (byte)(entryCount & 0x00FF); bytes[i++] = (byte)((entryCount & 0xFF00) >> 8); // total number of entries in the central directory bytes[i++] = (byte)(entryCount & 0x00FF); bytes[i++] = (byte)((entryCount & 0xFF00) >> 8); } // size of the central directory Int64 SizeOfCentralDirectory = EndOfCentralDirectory - StartOfCentralDirectory; if (SizeOfCentralDirectory >= 0xFFFFFFFF || StartOfCentralDirectory >= 0xFFFFFFFF) { // The actual data is in the ZIP64 central directory structure for (j = 0; j < 8; j++) bytes[i++] = 0xFF; } else { // size of the central directory (we just get the low 4 bytes) bytes[i++] = (byte)(SizeOfCentralDirectory & 0x000000FF); bytes[i++] = (byte)((SizeOfCentralDirectory & 0x0000FF00) >> 8); bytes[i++] = (byte)((SizeOfCentralDirectory & 0x00FF0000) >> 16); bytes[i++] = (byte)((SizeOfCentralDirectory & 0xFF000000) >> 24); // offset of the start of the central directory (we just get the low 4 bytes) bytes[i++] = (byte)(StartOfCentralDirectory & 0x000000FF); bytes[i++] = (byte)((StartOfCentralDirectory & 0x0000FF00) >> 8); bytes[i++] = (byte)((StartOfCentralDirectory & 0x00FF0000) >> 16); bytes[i++] = (byte)((StartOfCentralDirectory & 0xFF000000) >> 24); } // zip archive comment if ((comment == null) || (comment.Length == 0)) { // no comment! bytes[i++] = (byte)0; bytes[i++] = (byte)0; } else { // the size of our buffer defines the max length of the comment we can write if (commentLength + i + 2 > bytes.Length) commentLength = (Int16)(bytes.Length - i - 2); bytes[i++] = (byte)(commentLength & 0x00FF); bytes[i++] = (byte)((commentLength & 0xFF00) >> 8); if (commentLength != 0) { // now actually write the comment itself into the byte buffer for (j = 0; (j < commentLength) && (i + j < bytes.Length); j++) { bytes[i + j] = block[j]; } i += j; } } // s.Write(bytes, 0, i); return bytes; }
/// <summary> /// Extract to a stream /// In other words, you can extract to a stream or to a directory (filesystem), but not both! /// The Password param is required for encrypted entries. /// </summary> void InternalExtractToStream(Stream outStream, string password, ZipContainer zipContainer, ZipEntrySource zipEntrySource, string fileName) { // workitem 7958 if (zipContainer == null) throw new BadStateException("This entry is an orphan"); // workitem 10355 if (zipContainer.ZipFile == null) throw new InvalidOperationException("Use Extract() only with ZipFile."); zipContainer.ZipFile.Reset(false); if (zipEntrySource != ZipEntrySource.ZipFile) throw new BadStateException("You must call ZipFile.Save before calling any Extract method"); OnBeforeExtract(this, null, zipContainer.ZipFile); _ioOperationCanceled = false; try { ValidateCompression(_CompressionMethod_FromZipFile, fileName, GetUnsupportedCompressionMethod(_CompressionMethod)); ValidateEncryption(Encryption, fileName, _UnsupportedAlgorithmId); if (IsDoneWithOutputToStream()) { WriteStatus("extract dir {0}...", null); // if true, then the entry was a directory and has been created. // We need to fire the Extract Event. OnAfterExtract(null); return; } // If no password explicitly specified, use the password on the entry itself, // or on the zipfile itself. if (_Encryption_FromZipFile != EncryptionAlgorithm.None) EnsurePassword(password); WriteStatus("extract entry {0} to stream...", fileName); var archiveStream = ArchiveStream; if (ExtractToStream(archiveStream, outStream, Encryption, _Crc32)) goto ExitTry; OnAfterExtract(null); ExitTry: ; } catch (Exception) { _ioOperationCanceled = true; throw; } }
public static bool WriteCentralDirectoryStructure(Stream s, ICollection <ZipEntry> entries, uint numSegments, Zip64Option zip64, String comment, ZipContainer container) { var zss = s as ZipSegmentedStream; if (zss != null) { zss.ContiguousWrite = true; } // write to a memory stream in order to keep the // CDR contiguous Int64 aLength = 0; using (var ms = new MemoryStream()) { foreach (ZipEntry e in entries) { if (e.IncludedInMostRecentSave) { // this writes a ZipDirEntry corresponding to the ZipEntry e.WriteCentralDirectoryEntry(ms); } } var a = ms.ToArray(); s.Write(a, 0, a.Length); aLength = a.Length; } var output = s as CountingStream; long Finish = (output != null) ? output.ComputedPosition : s.Position; // BytesWritten long Start = Finish - aLength; // need to know which segment the EOCD record starts in UInt32 startSegment = (zss != null) ? zss.CurrentSegment : 0; Int64 SizeOfCentralDirectory = Finish - Start; int countOfEntries = CountEntries(entries); bool needZip64CentralDirectory = zip64 == Zip64Option.Always || countOfEntries >= 0xFFFF || SizeOfCentralDirectory > 0xFFFFFFFF || Start > 0xFFFFFFFF; byte[] a2 = null; // emit ZIP64 extensions as required if (needZip64CentralDirectory) { if (zip64 == Zip64Option.Never) { System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(1); if (sf.GetMethod().DeclaringType == typeof(ZipFile)) { throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property."); } else { throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property."); } } var a = GenZip64EndOfCentralDirectory(Start, Finish, countOfEntries, numSegments); a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container); if (startSegment != 0) { UInt32 thisSegment = zss.ComputeSegment(a.Length + a2.Length); int i = 16; // number of this disk Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i += 4; // number of the disk with the start of the central directory //Array.Copy(BitConverter.GetBytes(startSegment), 0, a, i, 4); Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i = 60; // offset 60 // number of the disk with the start of the zip64 eocd Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); i += 4; i += 8; // offset 72 // total number of disks Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); } s.Write(a, 0, a.Length); } else { a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container); } // now, the regular footer if (startSegment != 0) { // The assumption is the central directory is never split across // segment boundaries. UInt16 thisSegment = (UInt16)zss.ComputeSegment(a2.Length); int i = 4; // number of this disk Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2); i += 2; // number of the disk with the start of the central directory //Array.Copy(BitConverter.GetBytes((UInt16)startSegment), 0, a2, i, 2); Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2); i += 2; } s.Write(a2, 0, a2.Length); // reset the contiguous write property if necessary if (zss != null) { zss.ContiguousWrite = false; } return(needZip64CentralDirectory); }