/// <summary> /// Executes the logic for this workflow activity /// </summary> protected override void InternalExecute() { if (!string.IsNullOrEmpty(this.UseZip64WhenSaving.Get(this.ActivityContext))) { this.useZip64WhenSaving = (Zip64Option)Enum.Parse(typeof(Zip64Option), this.UseZip64WhenSaving.Get(this.ActivityContext)); } switch (this.Action) { case ZipAction.Create: this.Create(); break; case ZipAction.Extract: this.Extract(); break; case ZipAction.AddFiles: this.AddFiles(); break; default: throw new ArgumentException("Action not supported"); } }
private void _Init(Stream stream, bool leaveOpen, string name) { _outputStream = (stream.CanRead ? stream : new CountingStream(stream)); CompressionLevel = CompressionLevel.Default; CompressionMethod = CompressionMethod.Deflate; _encryption = EncryptionAlgorithm.None; _entriesWritten = new Dictionary <string, ZipEntry>(StringComparer.Ordinal); _zip64 = Zip64Option.Default; _leaveUnderlyingStreamOpen = leaveOpen; Strategy = CompressionStrategy.Default; _name = (name ?? "(stream)"); }
private void _Init(Stream stream, bool leaveOpen, string name) { this._outputStream = ((!stream.CanRead) ? new CountingStream(stream) : stream); this.CompressionLevel = CompressionLevel.Default; this.CompressionMethod = CompressionMethod.Deflate; this._encryption = EncryptionAlgorithm.None; this._entriesWritten = new Dictionary <string, ZipEntry>(StringComparer.Ordinal); this._zip64 = Zip64Option.Default; this._leaveUnderlyingStreamOpen = leaveOpen; this.Strategy = CompressionStrategy.Default; this._name = (name ?? "(stream)"); this.ParallelDeflateThreshold = -1L; }
private void Test_SpannedZip64_Unzip_Compatibility( long fileSize, long spanSize, Zip64Option zip64Option, Action <string, string> unzipAction) { TestContext.WriteLine("Creating fodder files... {0}", DateTime.Now.ToString("G")); CreateSomeFiles(); var file1Path = Path.Combine(_fodderDir, "1.dat"); var file2Path = Path.Combine(_fodderDir, "2.dat"); foreach (var filePath in new[] { file1Path, file2Path }) { using (var file = File.Create(filePath)) { file.Seek(fileSize, SeekOrigin.Begin); file.Write(new byte[] { 1 }, 0, 1); } } Directory.CreateDirectory("zip-output"); var zipFilePath = Path.Combine("zip-output", "archive.zip"); using (var zipFile = new ZipFile()) { zipFile.UseZip64WhenSaving = zip64Option; // disable compression to make sure out 0-filled files would keep their size zipFile.CompressionLevel = Zlib.CompressionLevel.None; zipFile.MaxOutputSegmentSize64 = spanSize; zipFile.AddFile(file1Path, ""); zipFile.AddFile(file2Path, ""); zipFile.Save(zipFilePath); } var extractDir = "extract"; Directory.CreateDirectory(extractDir); unzipAction(zipFilePath, extractDir); string[] filesUnzipped = Directory.GetFiles(extractDir); Assert.AreEqual(2, filesUnzipped.Length, "Incorrect number of files extracted"); }
public static bool WriteCentralDirectoryStructure(Stream s, ICollection<ZipEntry> entries, uint numSegments, Zip64Option zip64, String comment, System.Text.Encoding encoding) { var zss = s as ZipSegmentedStream; if (zss != null) zss.ContiguousWrite = true; // write to a memory stream in order to keep the // CDR contiguous 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); // 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 - a.Length; // 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 } a = GenZip64EndOfCentralDirectory(Start, Finish, countOfEntries, numSegments); a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, encoding); 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, encoding); // 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); }
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 void _ZOS_z64Over65534Entries (Zip64Option z64option, EncryptionAlgorithm encryption, Ionic.Zlib.CompressionLevel compression) { TestContext.WriteLine("_ZOS_z64Over65534Entries hello: {0}", DateTime.Now.ToString("G")); int fileCount = _rnd.Next(14616) + 65536; //int fileCount = _rnd.Next(146) + 5536; TestContext.WriteLine("entries: {0}", fileCount); var txrxLabel = String.Format("ZOS #{0} 64({3}) E({1}) C({2})", fileCount, encryption.ToString(), compression.ToString(), z64option.ToString()); TestContext.WriteLine("label: {0}", txrxLabel); string zipFileToCreate = String.Format("ZOS.Zip64.over65534.{0}.{1}.{2}.zip", z64option.ToString(), encryption.ToString(), compression.ToString()); TestContext.WriteLine("zipFileToCreate: {0}", zipFileToCreate); _txrx = TestUtilities.StartProgressMonitor(zipFileToCreate, txrxLabel, "starting up..."); TestContext.WriteLine("generating {0} entries ", fileCount); _txrx.Send("pb 0 max 3"); // 2 stages: Write, Count, Verify _txrx.Send("pb 0 value 0"); string password = Path.GetRandomFileName(); string statusString = String.Format("status Encryption:{0} Compression:{1}", encryption.ToString(), compression.ToString()); _txrx.Send(statusString); int dirCount = 0; using (FileStream fs = File.Create(zipFileToCreate)) { using (var output = new ZipOutputStream(fs)) { _txrx.Send("test " + txrxLabel); System.Threading.Thread.Sleep(400); _txrx.Send("pb 1 max " + fileCount); _txrx.Send("pb 1 value 0"); output.Password = password; output.Encryption = encryption; output.CompressionLevel = compression; output.EnableZip64 = z64option; for (int k = 0; k < fileCount; k++) { if (_rnd.Next(7) == 0) { // make it a directory string entryName = String.Format("{0:D4}/", k); output.PutNextEntry(entryName); dirCount++; } else { string entryName = String.Format("{0:D4}.txt", k); output.PutNextEntry(entryName); // only a few entries are non-empty if (_rnd.Next(18) == 0) { var block = TestUtilities.GenerateRandomAsciiString(); string content = String.Format("This is the content for entry #{0}.\n", k); int n = _rnd.Next(4) + 1; for (int j=0; j < n; j++) content+= block; byte[] buffer = System.Text.Encoding.ASCII.GetBytes(content); output.Write(buffer, 0, buffer.Length); } } if (k % 1024 == 0) _txrx.Send(String.Format("status saving ({0}/{1}) {2:N0}%", k, fileCount, ((double)k) / (0.01 * fileCount))); else if (k % 256 == 0) _txrx.Send("pb 1 value " + k); } } } _txrx.Send("pb 1 max 1"); _txrx.Send("pb 1 value 1"); _txrx.Send("pb 0 step"); System.Threading.Thread.Sleep(400); TestContext.WriteLine("Counting entries ... " + DateTime.Now.ToString("G")); _txrx.Send("status Counting entries..."); Assert.AreEqual<int> (fileCount - dirCount, TestUtilities.CountEntries(zipFileToCreate), "{0}: The zip file created has the wrong number of entries.", zipFileToCreate); _txrx.Send("pb 0 step"); System.Threading.Thread.Sleep(140); // basic verify. The output is really large, so we pass emitOutput=false . _txrx.Send("status Verifying..."); TestContext.WriteLine("Verifying ... " + DateTime.Now.ToString("G")); _numExtracted = 0; _numFilesToExtract = fileCount; _txrx.Send("pb 1 max " + fileCount); System.Threading.Thread.Sleep(200); _txrx.Send("pb 1 value 0"); BasicVerifyZip(zipFileToCreate, password, false, Streams_ExtractProgress); _txrx.Send("pb 0 step"); System.Threading.Thread.Sleep(800); TestContext.WriteLine("Done ... " + DateTime.Now.ToString("G")); }
// 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: 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); }
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); }
private void _Init(Stream stream, bool leaveOpen) { // workitem 9307 _outputStream = stream.CanRead ? stream : new CountingStream(stream); CompressionLevel = Ionic.Zlib.CompressionLevel.Default; _encryption = EncryptionAlgorithm.None; _entriesWritten = new Dictionary<String, ZipEntry>(StringComparer.Ordinal); _zip64 = Zip64Option.Never; _leaveUnderlyingStreamOpen = leaveOpen; Strategy = Ionic.Zlib.CompressionStrategy.Default; _name = "unknown"; #if !NETCF ParallelDeflateThreshold = -1L; #endif }
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); }
private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, System.Text.Encoding encoding) { 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; }
void _Zip64_Over65534Entries(Zip64Option z64option, EncryptionAlgorithm encryption, Ionic.Zlib.CompressionLevel compression) { // Emitting a zip file with > 65534 entries requires the use of ZIP64 in // the central directory. int numTotalEntries = _rnd.Next(4616)+65534; //int numTotalEntries = _rnd.Next(461)+6534; //int numTotalEntries = _rnd.Next(46)+653; string enc = encryption.ToString(); if (enc.StartsWith("WinZip")) enc = enc.Substring(6); else if (enc.StartsWith("Pkzip")) enc = enc.Substring(0,5); string zipFileToCreate = String.Format("Zip64.ZF_Over65534.{0}.{1}.{2}.zip", z64option.ToString(), enc, compression.ToString()); _testTitle = String.Format("ZipFile #{0} 64({1}) E({2}), C({3})", numTotalEntries, z64option.ToString(), enc, compression.ToString()); _txrx = TestUtilities.StartProgressMonitor(zipFileToCreate, _testTitle, "starting up..."); _txrx.Send("pb 0 max 4"); // 3 stages: AddEntry, Save, Verify _txrx.Send("pb 0 value 0"); string password = Path.GetRandomFileName(); string statusString = String.Format("status Encrypt:{0} Compress:{1}...", enc, compression.ToString()); int numSaved = 0; var saveProgress = new EventHandler<SaveProgressEventArgs>( (sender, e) => { switch (e.EventType) { case ZipProgressEventType.Saving_Started: _txrx.Send("status saving..."); _txrx.Send("pb 1 max " + numTotalEntries); numSaved= 0; break; case ZipProgressEventType.Saving_AfterWriteEntry: numSaved++; if ((numSaved % 128) == 0) { _txrx.Send("pb 1 value " + numSaved); _txrx.Send(String.Format("status Saving entry {0}/{1} ({2:N0}%)", numSaved, numTotalEntries, numSaved / (0.01 * numTotalEntries) )); } break; case ZipProgressEventType.Saving_Completed: _txrx.Send("status Save completed"); _txrx.Send("pb 1 max 1"); _txrx.Send("pb 1 value 1"); break; } }); string contentFormatString = "This is the content for entry #{0}.\r\n\r\n" + "AAAAAAA BBBBBB AAAAA BBBBB AAAAA BBBBB AAAAA\r\n"+ "AAAAAAA BBBBBB AAAAA BBBBB AAAAA BBBBB AAAAA\r\n"; _txrx.Send(statusString); int dirCount= 0; using (var zip = new ZipFile()) { _txrx.Send(String.Format("pb 1 max {0}", numTotalEntries)); _txrx.Send("pb 1 value 0"); zip.Password = password; zip.Encryption = encryption; zip.CompressionLevel = compression; zip.SaveProgress += saveProgress; zip.UseZip64WhenSaving = z64option; // save space when saving the file: zip.EmitTimesInWindowsFormatWhenSaving = false; zip.EmitTimesInUnixFormatWhenSaving = false; // add files: for (int m=0; m<numTotalEntries; m++) { if (_rnd.Next(7)==0) { string entryName = String.Format("{0:D5}", m); zip.AddDirectoryByName(entryName); dirCount++; } else { string entryName = String.Format("{0:D5}.txt", m); if (_rnd.Next(12)==0) { string contentBuffer = String.Format(contentFormatString, m); byte[] buffer = System.Text.Encoding.ASCII.GetBytes(contentBuffer); zip.AddEntry(entryName, contentBuffer); } else zip.AddEntry(entryName, Stream.Null); } if (m % 1024 == 0) { _txrx.Send("pb 1 value " + m); string msg = String.Format("status adding entry {0}/{1} ({2:N0}%)", m, numTotalEntries, (m/(0.01*numTotalEntries))); _txrx.Send(msg); } } _txrx.Send("pb 0 step"); _txrx.Send(statusString + " Saving..."); zip.Save(zipFileToCreate); } _txrx.Send("pb 0 step"); _txrx.Send("pb 1 value 0"); _txrx.Send("status Reading..."); // verify the zip by unpacking. _numFilesToExtract = numTotalEntries; _numExtracted= 1; _pb1Set = false; verb = "verify"; BasicVerifyZip(zipFileToCreate, password, false, Zip64ExtractProgress); _txrx.Send("pb 0 step"); _txrx.Send("status successful extract, now doing final count..."); _txrx.Send("pb 1 value 0"); Assert.AreEqual<int>(numTotalEntries-dirCount, TestUtilities.CountEntries(zipFileToCreate)); _txrx.Send("pb 0 step"); }
// 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); }