public void UpdateZip_RemoveAllEntries() { string password = "******" + TestUtilities.GenerateRandomLowerString(7); string filename = null; int entriesToBeAdded = 0; string repeatedLine = null; int j; // select the name of the zip file string zipFileToCreate = Path.Combine(TopLevelDir, "UpdateZip_RemoveAllEntries.zip"); // create the subdirectory string subdir = Path.Combine(TopLevelDir, "A"); Directory.CreateDirectory(subdir); // create the files int numFilesToCreate = _rnd.Next(13) + 14; for (j = 0; j < numFilesToCreate; j++) { filename = String.Format("file{0:D3}.txt", j); repeatedLine = String.Format("This line is repeated over and over and over in file {0}", filename); TestUtilities.CreateAndFillFileText(Path.Combine(subdir, filename), repeatedLine, _rnd.Next(34000) + 5000); entriesToBeAdded++; } // Add the files to the zip, save the zip Directory.SetCurrentDirectory(TopLevelDir); using (ZipFile zip = new ZipFile()) { String[] filenames = Directory.GetFiles("A"); zip.Password = password; foreach (String f in filenames) zip.AddFile(f, ""); zip.Comment = "UpdateTests::UpdateZip_RemoveAllEntries(): This archive will be updated."; zip.Save(zipFileToCreate); } // Verify the files are in the zip Assert.AreEqual<int>(entriesToBeAdded, TestUtilities.CountEntries(zipFileToCreate), "The Zip file has the wrong number of entries."); // remove all the entries from the zip archive using (ZipFile zip2 = ZipFile.Read(zipFileToCreate)) { zip2.RemoveSelectedEntries("*.*"); zip2.Comment = "This archive has been modified. All the entries have been removed."; zip2.Save(); } // Verify the files are in the zip Assert.AreEqual<int>(0, TestUtilities.CountEntries(zipFileToCreate), "The Zip file has the wrong number of entries."); }
public void Password_Extract_WrongPassword() { string ZipFileToCreate = Path.Combine(TopLevelDir, "MultipleEntriesDifferentPasswords.zip"); Assert.IsFalse(File.Exists(ZipFileToCreate), "The temporary zip file '{0}' already exists.", ZipFileToCreate); string SourceDir = CurrentDir; for (int i = 0; i < 3; i++) SourceDir = Path.GetDirectoryName(SourceDir); Directory.SetCurrentDirectory(TopLevelDir); string[] filenames = { Path.Combine(SourceDir, "Tools\\Zipit\\bin\\Debug\\Zipit.exe"), Path.Combine(SourceDir, "Zip\\bin\\Debug\\Ionic.Zip.xml"), }; string[] passwords = { "12345678", "0987654321", }; int j = 0; using (ZipFile zip = new ZipFile(ZipFileToCreate)) { for (j = 0; j < filenames.Length; j++) { zip.Password = passwords[j]; zip.AddFile(filenames[j], ""); } zip.Save(); } // now try to extract using (ZipFile zip = new ZipFile(ZipFileToCreate)) { for (j = 0; j < filenames.Length; j++) zip[Path.GetFileName(filenames[j])].ExtractWithPassword("unpack", ExtractExistingFileAction.OverwriteSilently, "WrongPassword"); } }
public void Password_BasicAddAndExtract() { int i; string[] Passwords = { null, "Password!", TestUtilities.GenerateRandomPassword(), "A" }; Alienlab.Zlib.CompressionLevel[] compressionLevelOptions = { Alienlab.Zlib.CompressionLevel.None, Alienlab.Zlib.CompressionLevel.BestSpeed, Alienlab.Zlib.CompressionLevel.Default, Alienlab.Zlib.CompressionLevel.BestCompression, }; for (int k = 0; k < compressionLevelOptions.Length; k++) { for (int j = 0; j < Passwords.Length; j++) { TestContext.WriteLine("\n\n===================\nTrial ({0}) pw({1})", j, Passwords[j]); string ZipFileToCreate = Path.Combine(TopLevelDir, String.Format("Password_BasicAddAndExtract-{0}-{1}.zip", k, j)); Assert.IsFalse(File.Exists(ZipFileToCreate), "The temporary zip file '{0}' already exists.", ZipFileToCreate); Directory.SetCurrentDirectory(TopLevelDir); string DirToZip = String.Format("zipthis-{0}-{1}", k, j); Directory.CreateDirectory(DirToZip); TestContext.WriteLine("\n---------------------creating files and computing checksums..."); int NumFilesToCreate = _rnd.Next(10) + 10; string[] filenames = new string[NumFilesToCreate]; var checksums = new Dictionary<string, string>(); for (i = 0; i < NumFilesToCreate; i++) { filenames[i] = Path.Combine(DirToZip, String.Format("file{0:D3}.txt", i)); int sz = _rnd.Next(22000) + 3000; //int sz = 1000; var repeatedLine = String.Format("Line to Repeat... {0} {1} {2} filename: {3}", i, k, j, filenames[i]); TestUtilities.CreateAndFillFileText(filenames[i], repeatedLine, sz); string key = Path.GetFileName(filenames[i]); checksums.Add(key, TestUtilities.GetCheckSumString(filenames[i])); TestContext.WriteLine(" chk[{0}]={1}", key, checksums[key]); } TestContext.WriteLine("\n---------------------adding files to the archive..."); var sw = new StringWriter(); using (ZipFile zip = new ZipFile(ZipFileToCreate, sw)) { zip.CompressionLevel = compressionLevelOptions[k]; zip.Password = Passwords[j]; zip.AddDirectory(Path.GetFileName(DirToZip)); zip.Save(); } TestContext.WriteLine(sw.ToString()); Assert.AreEqual<int>(TestUtilities.CountEntries(ZipFileToCreate), NumFilesToCreate, "The Zip file has an unexpected number of entries."); TestContext.WriteLine("\n---------------------verifying checksums..."); using (ZipFile zip = ZipFile.Read(ZipFileToCreate)) { foreach (ZipEntry e in zip) TestContext.WriteLine("found entry: {0}", e.FileName); var extractDir = String.Format("extract-{0}-{1}", k, j); TestContext.WriteLine(" Extract with pw({0})", Passwords[j]); foreach (ZipEntry e in zip) { e.ExtractWithPassword(extractDir, ExtractExistingFileAction.OverwriteSilently, Passwords[j]); if (!e.IsDirectory) { byte[] c2 = TestUtilities.ComputeChecksum(Path.Combine(extractDir, e.FileName)); Assert.AreEqual<string>(checksums[e.FileName], TestUtilities.CheckSumToString(c2), "The checksum of the extracted file is incorrect."); } } } TestContext.WriteLine("\n"); } } }
/// <summary> /// Reads one entry from the zip directory structure in the zip file. /// </summary> /// /// <param name="zf"> /// The zipfile for which a directory entry will be read. From this param, the /// method gets the ReadStream and the expected text encoding /// (ProvisionalAlternateEncoding) which is used if the entry is not marked /// UTF-8. /// </param> /// /// <param name="previouslySeen"> /// a list of previously seen entry names; used to prevent duplicates. /// </param> /// /// <returns>the entry read from the archive.</returns> internal static ZipEntry ReadDirEntry(ZipFile zf, Dictionary<String,Object> previouslySeen) { System.IO.Stream s = zf.ReadStream; System.Text.Encoding expectedEncoding = (zf.AlternateEncodingUsage == ZipOption.Always) ? zf.AlternateEncoding : ZipFile.DefaultEncoding; int signature = Alienlab.Zip.SharedUtilities.ReadSignature(s); // return null if this is not a local file header signature if (IsNotValidZipDirEntrySig(signature)) { s.Seek(-4, System.IO.SeekOrigin.Current); // workitem 10178 Alienlab.Zip.SharedUtilities.Workaround_Ladybug318918(s); // Getting "not a ZipDirEntry signature" here is not always wrong or an // error. This can happen when walking through a zipfile. After the // last ZipDirEntry, we expect to read an // EndOfCentralDirectorySignature. When we get this is how we know // we've reached the end of the central directory. if (signature != ZipConstants.EndOfCentralDirectorySignature && signature != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature && signature != ZipConstants.ZipEntrySignature // workitem 8299 ) { throw new BadReadException(String.Format(" Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, s.Position)); } return null; } int bytesRead = 42 + 4; byte[] block = new byte[42]; int n = s.Read(block, 0, block.Length); if (n != block.Length) return null; int i = 0; ZipEntry zde = new ZipEntry(); zde.AlternateEncoding = expectedEncoding; zde._Source = ZipEntrySource.ZipFile; zde._container = new ZipContainer(zf); unchecked { zde._VersionMadeBy = (short)(block[i++] + block[i++] * 256); zde._VersionNeeded = (short)(block[i++] + block[i++] * 256); zde._BitField = (short)(block[i++] + block[i++] * 256); zde._CompressionMethod = (Int16)(block[i++] + block[i++] * 256); zde._TimeBlob = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; zde._LastModified = Alienlab.Zip.SharedUtilities.PackedToDateTime(zde._TimeBlob); zde._timestamp |= ZipEntryTimestamp.DOS; zde._Crc32 = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; zde._CompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); zde._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); } // preserve zde._CompressionMethod_FromZipFile = zde._CompressionMethod; zde._filenameLength = (short)(block[i++] + block[i++] * 256); zde._extraFieldLength = (short)(block[i++] + block[i++] * 256); zde._commentLength = (short)(block[i++] + block[i++] * 256); zde._diskNumber = (UInt32)(block[i++] + block[i++] * 256); zde._InternalFileAttrs = (short)(block[i++] + block[i++] * 256); zde._ExternalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; zde._RelativeOffsetOfLocalHeader = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); // workitem 7801 zde.IsText = ((zde._InternalFileAttrs & 0x01) == 0x01); block = new byte[zde._filenameLength]; n = s.Read(block, 0, block.Length); bytesRead += n; if ((zde._BitField & 0x0800) == 0x0800) { // UTF-8 is in use zde._FileNameInArchive = Alienlab.Zip.SharedUtilities.Utf8StringFromBuffer(block); } else { zde._FileNameInArchive = Alienlab.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding); } // workitem 10330 // insure unique entry names while (previouslySeen.ContainsKey(zde._FileNameInArchive)) { zde._FileNameInArchive = CopyHelper.AppendCopyToFileName(zde._FileNameInArchive); zde._metadataChanged = true; } if (zde.AttributesIndicateDirectory) zde.MarkAsDirectory(); // may append a slash to filename if nec. // workitem 6898 else if (zde._FileNameInArchive.EndsWith("/")) zde.MarkAsDirectory(); zde._CompressedFileDataSize = zde._CompressedSize; if ((zde._BitField & 0x01) == 0x01) { // this may change after processing the Extra field zde._Encryption_FromZipFile = zde._Encryption = EncryptionAlgorithm.PkzipWeak; zde._sourceIsEncrypted = true; } if (zde._extraFieldLength > 0) { zde._InputUsesZip64 = (zde._CompressedSize == 0xFFFFFFFF || zde._UncompressedSize == 0xFFFFFFFF || zde._RelativeOffsetOfLocalHeader == 0xFFFFFFFF); // Console.WriteLine(" Input uses Z64?: {0}", zde._InputUsesZip64); bytesRead += zde.ProcessExtraField(s, zde._extraFieldLength); zde._CompressedFileDataSize = zde._CompressedSize; } // we've processed the extra field, so we know the encryption method is set now. if (zde._Encryption == EncryptionAlgorithm.PkzipWeak) { // the "encryption header" of 12 bytes precedes the file data zde._CompressedFileDataSize -= 12; } #if AESCRYPTO else if (zde.Encryption == EncryptionAlgorithm.WinZipAes128 || zde.Encryption == EncryptionAlgorithm.WinZipAes256) { zde._CompressedFileDataSize = zde.CompressedSize - (ZipEntry.GetLengthOfCryptoHeaderBytes(zde.Encryption) + 10); zde._LengthOfTrailer = 10; } #endif // tally the trailing descriptor if ((zde._BitField & 0x0008) == 0x0008) { // sig, CRC, Comp and Uncomp sizes if (zde._InputUsesZip64) zde._LengthOfTrailer += 24; else zde._LengthOfTrailer += 16; } // workitem 12744 zde.AlternateEncoding = ((zde._BitField & 0x0800) == 0x0800) ? System.Text.Encoding.UTF8 :expectedEncoding; zde.AlternateEncodingUsage = ZipOption.Always; if (zde._commentLength > 0) { block = new byte[zde._commentLength]; n = s.Read(block, 0, block.Length); bytesRead += n; if ((zde._BitField & 0x0800) == 0x0800) { // UTF-8 is in use zde._Comment = Alienlab.Zip.SharedUtilities.Utf8StringFromBuffer(block); } else { zde._Comment = Alienlab.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding); } } //zde._LengthOfDirEntry = bytesRead; return zde; }
public void Password_UnsetEncryptionAfterSetPassword_wi13909_ZF() { // Verify that unsetting the Encryption property after // setting a Password results in no encryption being used. // This method tests ZipFile. string unusedPassword = TestUtilities.GenerateRandomPassword(); int numTotalEntries = _rnd.Next(46)+653; string zipFileToCreate = "UnsetEncryption.zip"; using (var zip = new ZipFile()) { zip.Password = unusedPassword; zip.Encryption = EncryptionAlgorithm.None; for (int i=0; i < numTotalEntries; i++) { if (_rnd.Next(7)==0) { string entryName = String.Format("{0:D5}", i); zip.AddDirectoryByName(entryName); } else { string entryName = String.Format("{0:D5}.txt", i); if (_rnd.Next(12)==0) { var block = TestUtilities.GenerateRandomAsciiString() + " "; string contentBuffer = String.Format("This is the content for entry {0}", i); int n = _rnd.Next(6) + 2; for (int j=0; j < n; j++) contentBuffer += block; byte[] buffer = System.Text.Encoding.ASCII.GetBytes(contentBuffer); zip.AddEntry(entryName, contentBuffer); } else zip.AddEntry(entryName, Stream.Null); } } zip.Save(zipFileToCreate); } BasicVerifyZip(zipFileToCreate); }
private void _Internal_AddEntry_WriteDelegate(string[] files, EncryptionAlgorithm crypto, bool seekable, int cycle, string format, int ignored) { int bufferSize = 2048; byte[] buffer = new byte[bufferSize]; int n; for (int k = 0; k < compLevels.Length; k++) { string zipFileToCreate = Path.Combine(TopLevelDir, String.Format(format, compLevels[k].ToString())); string password = TestUtilities.GenerateRandomPassword(); using (var zip = new ZipFile()) { TestContext.WriteLine("================================="); TestContext.WriteLine("Creating {0}...", Path.GetFileName(zipFileToCreate)); TestContext.WriteLine("Encryption({0}) Compression({1}) pw({2})", crypto.ToString(), compLevels[k].ToString(), password); zip.Password = password; zip.Encryption = crypto; zip.CompressionLevel = compLevels[k]; foreach (var file in files) { zip.AddEntry(file, (name, output) => { using (var input = File.OpenRead(name)) { while ((n = input.Read(buffer, 0, buffer.Length)) != 0) { output.Write(buffer, 0, n); } } }); } if (!seekable) { // conditionally use a non-seekable output stream using (var raw = File.Create(zipFileToCreate)) { using (var ns = new Alienlab.Zip.Tests.NonSeekableOutputStream(raw)) { zip.Save(ns); } } } else zip.Save(zipFileToCreate); } BasicVerifyZip(Path.GetFileName(zipFileToCreate), password); Assert.AreEqual<int>(files.Length, TestUtilities.CountEntries(zipFileToCreate), "Trial ({0},{1}): The zip file created has the wrong number of entries.", cycle, k); } }
public void Progress_AddFiles() { Directory.SetCurrentDirectory(TopLevelDir); string zipFileToCreate = Path.Combine(TopLevelDir, "Progress_AddFiles.zip"); string dirToZip = Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); var files = TestUtilities.GenerateFilesFlat(dirToZip); var sw = new StringWriter(); using (ZipFile zip = new ZipFile(zipFileToCreate, sw)) { zip.AddProgress += AddProgress1; zip.AddFiles(files); zip.Save(); } TestContext.WriteLine(sw.ToString()); int count = TestUtilities.CountEntries(zipFileToCreate); Assert.AreEqual<Int32>(count, files.Length); }
private static void Zip64SeekToCentralDirectory(ZipFile zf) { Stream s = zf.ReadStream; byte[] block = new byte[16]; // seek back to find the ZIP64 EoCD. // I think this might not work for .NET CF ? s.Seek(-40, SeekOrigin.Current); s.Read(block, 0, 16); Int64 offset64 = BitConverter.ToInt64(block, 8); zf._OffsetOfCentralDirectory = 0xFFFFFFFF; zf._OffsetOfCentralDirectory64 = offset64; // change for workitem 8098 s.Seek(offset64, SeekOrigin.Begin); //zf.SeekFromOrigin(Offset64); uint datum = (uint)Alienlab.Zip.SharedUtilities.ReadInt(s); if (datum != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature) throw new BadReadException(String.Format(" Bad signature (0x{0:X8}) looking for ZIP64 EoCD Record at position 0x{1:X8}", datum, s.Position)); s.Read(block, 0, 8); Int64 Size = BitConverter.ToInt64(block, 0); block = new byte[Size]; s.Read(block, 0, block.Length); offset64 = BitConverter.ToInt64(block, 36); // change for workitem 8098 s.Seek(offset64, SeekOrigin.Begin); //zf.SeekFromOrigin(Offset64); }
private static void ReadCentralDirectory(ZipFile zf) { // We must have the central directory footer record, in order to properly // read zip dir entries from the central directory. This because the logic // knows when to open a spanned file when the volume number for the central // directory differs from the volume number for the zip entry. The // _diskNumberWithCd was set when originally finding the offset for the // start of the Central Directory. // workitem 9214 bool inputUsesZip64 = false; ZipEntry de; // in lieu of hashset, use a dictionary var previouslySeen = new Dictionary<String,object>(); while ((de = ZipEntry.ReadDirEntry(zf, previouslySeen)) != null) { de.ResetDirEntry(); zf.OnReadEntry(true, null); if (zf.Verbose) zf.StatusMessageTextWriter.WriteLine("entry {0}", de.FileName); zf._entries.Add(de.FileName,de); // workitem 9214 if (de._InputUsesZip64) inputUsesZip64 = true; previouslySeen.Add(de.FileName, null); // to prevent dupes } // workitem 9214; auto-set the zip64 flag if (inputUsesZip64) zf.UseZip64WhenSaving = Zip64Option.Always; // 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); // We keep the read stream open after reading. if (zf.Verbose) zf.StatusMessageTextWriter.WriteLine("read in {0} entries.", zf._entries.Count); zf.OnReadCompleted(); }
/// <summary> /// Reads a zip archive from a stream, using the specified text Encoding, the /// specified TextWriter for status messages, /// and the specified ReadProgress event handler. /// </summary> /// /// <remarks> /// <para> /// Reading of zip content begins at the current position in the stream. This /// means if you have a stream that concatenates regular data and zip data, if /// you position the open, readable stream at the start of the zip data, you /// will be able to read the zip archive using this constructor, or any of the /// ZipFile constructors that accept a <see cref="System.IO.Stream" /> as /// input. Some examples of where this might be useful: the zip content is /// concatenated at the end of a regular EXE file, as some self-extracting /// archives do. (Note: SFX files produced by DotNetZip do not work this /// way). Another example might be a stream being read from a database, where /// the zip content is embedded within an aggregate stream of data. /// </para> /// </remarks> /// /// <param name="zipStream">the stream containing the zip data.</param> /// /// <param name="statusMessageWriter"> /// The <c>System.IO.TextWriter</c> to which verbose status messages are written /// during operations on the <c>ZipFile</c>. For example, in a console /// application, System.Console.Out works, and will get a message for each entry /// added to the ZipFile. If the TextWriter is <c>null</c>, no verbose messages /// are written. /// </param> /// /// <param name="encoding"> /// The text encoding to use when reading entries that do not have the UTF-8 /// encoding bit set. Be careful specifying the encoding. If the value you use /// here is not the same as the Encoding used when the zip archive was created /// (possibly by a different archiver) you will get unexpected results and /// possibly exceptions. See the <see cref="ProvisionalAlternateEncoding"/> /// property for more information. /// </param> /// /// <param name="readProgress"> /// An event handler for Read operations. /// </param> /// /// <returns>an instance of ZipFile</returns> private static ZipFile Read(Stream zipStream, TextWriter statusMessageWriter, System.Text.Encoding encoding, EventHandler<ReadProgressEventArgs> readProgress) { if (zipStream == null) throw new ArgumentNullException("zipStream"); ZipFile zf = new ZipFile(); zf._StatusMessageTextWriter = statusMessageWriter; zf._alternateEncoding = encoding ?? ZipFile.DefaultEncoding; zf._alternateEncodingUsage = ZipOption.Always; if (readProgress != null) zf.ReadProgress += readProgress; zf._readstream = (zipStream.Position == 0L) ? zipStream : new OffsetStream(zipStream); zf._ReadStreamIsOurs = false; if (zf.Verbose) zf._StatusMessageTextWriter.WriteLine("reading from stream..."); ReadIntoInstance(zf); return zf; }
private static void ReadIntoInstance(ZipFile zf) { Stream s = zf.ReadStream; try { zf._readName = zf._name; // workitem 13915 if (!s.CanSeek) { ReadIntoInstance_Orig(zf); return; } zf.OnReadStarted(); // change for workitem 8098 //zf._originPosition = s.Position; // Try reading the central directory, rather than scanning the file. uint datum = ReadFirstFourBytes(s); if (datum == ZipConstants.EndOfCentralDirectorySignature) return; // start at the end of the file... // seek backwards a bit, then look for the EoCD signature. int nTries = 0; bool success = false; // The size of the end-of-central-directory-footer plus 2 bytes is 18. // This implies an archive comment length of 0. We'll add a margin of // safety and start "in front" of that, when looking for the // EndOfCentralDirectorySignature long posn = s.Length - 64; long maxSeekback = Math.Max(s.Length - 0x4000, 10); do { if (posn < 0) posn = 0; // BOF s.Seek(posn, SeekOrigin.Begin); long bytesRead = SharedUtilities.FindSignature(s, (int)ZipConstants.EndOfCentralDirectorySignature); if (bytesRead != -1) success = true; else { if (posn==0) break; // started at the BOF and found nothing nTries++; // Weird: with NETCF, negative offsets from SeekOrigin.End DO // NOT WORK. So rather than seek a negative offset, we seek // from SeekOrigin.Begin using a smaller number. posn -= (32 * (nTries + 1) * nTries); } } while (!success && posn > maxSeekback); if (success) { // workitem 8299 zf._locEndOfCDS = s.Position - 4; byte[] block = new byte[16]; s.Read(block, 0, block.Length); zf._diskNumberWithCd = BitConverter.ToUInt16(block, 2); if (zf._diskNumberWithCd == 0xFFFF) throw new ZipException("Spanned archives with more than 65534 segments are not supported at this time."); zf._diskNumberWithCd++; // I think the number in the file differs from reality by 1 int i = 12; uint offset32 = (uint) BitConverter.ToUInt32(block, i); if (offset32 == 0xFFFFFFFF) { Zip64SeekToCentralDirectory(zf); } else { zf._OffsetOfCentralDirectory = offset32; // change for workitem 8098 s.Seek(offset32, SeekOrigin.Begin); } ReadCentralDirectory(zf); } else { // Could not find the central directory. // Fallback to the old method. // workitem 8098: ok //s.Seek(zf._originPosition, SeekOrigin.Begin); s.Seek(0L, SeekOrigin.Begin); ReadIntoInstance_Orig(zf); } } catch (Exception ex1) { if (zf._ReadStreamIsOurs && zf._readstream != null) { try { #if NETCF zf._readstream.Close(); #else zf._readstream.Dispose(); #endif zf._readstream = null; } finally { } } throw new ZipException("Cannot read that as a ZipFile", ex1); } // the instance has been read in zf._contentsChanged = false; }
/// <summary> /// Reads a zip file archive using the specified text encoding, the specified /// TextWriter for status messages, and the specified ReadProgress event handler, /// and returns the instance. /// </summary> /// /// <param name="fileName"> /// The name of the zip archive to open. /// This can be a fully-qualified or relative pathname. /// </param> /// /// <param name="readProgress"> /// An event handler for Read operations. /// </param> /// /// <param name="statusMessageWriter"> /// The <c>System.IO.TextWriter</c> to use for writing verbose status messages /// during operations on the zip archive. A console application may wish to /// pass <c>System.Console.Out</c> to get messages on the Console. A graphical /// or headless application may wish to capture the messages in a different /// <c>TextWriter</c>, such as a <c>System.IO.StringWriter</c>. /// </param> /// /// <param name="encoding"> /// The <c>System.Text.Encoding</c> to use when reading in the zip archive. Be /// careful specifying the encoding. If the value you use here is not the same /// as the Encoding used when the zip archive was created (possibly by a /// different archiver) you will get unexpected results and possibly exceptions. /// </param> /// /// <returns>The instance read from the zip archive.</returns> /// private static ZipFile Read(string fileName, TextWriter statusMessageWriter, System.Text.Encoding encoding, EventHandler<ReadProgressEventArgs> readProgress) { ZipFile zf = new ZipFile(); zf.AlternateEncoding = encoding ?? DefaultEncoding; zf.AlternateEncodingUsage = ZipOption.Always; zf._StatusMessageTextWriter = statusMessageWriter; zf._name = fileName; if (readProgress != null) zf.ReadProgress = readProgress; if (zf.Verbose) zf._StatusMessageTextWriter.WriteLine("reading from {0}...", fileName); ReadIntoInstance(zf); zf._fileAlreadyExists = true; return zf; }
public void UpdateZip_UpdateItem() { string filename = null; int entriesAdded = 0; string repeatedLine = null; int j; // select the name of the zip file string zipFileToCreate = Path.Combine(TopLevelDir, "UpdateZip_UpdateItem.zip"); // create the subdirectory string subdir = Path.Combine(TopLevelDir, "A"); Directory.CreateDirectory(subdir); // create a bunch of files int numFilesToCreate = _rnd.Next(10) + 8; for (j = 0; j < numFilesToCreate; j++) { filename = Path.Combine(subdir, String.Format("file{0:D3}.txt", j)); repeatedLine = String.Format("Content for Original file {0}", Path.GetFileName(filename)); TestUtilities.CreateAndFillFileText(filename, repeatedLine, _rnd.Next(34000) + 5000); entriesAdded++; } // Create the zip file Directory.SetCurrentDirectory(TopLevelDir); using (ZipFile zip1 = new ZipFile()) { String[] filenames = Directory.GetFiles("A"); foreach (String f in filenames) zip1.AddFile(f, ""); zip1.Comment = "UpdateTests::UpdateZip_UpdateItem(): This archive will be updated."; zip1.Save(zipFileToCreate); } // Verify the files are in the zip Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), entriesAdded, "The Zip file has the wrong number of entries."); // create another subdirectory subdir = Path.Combine(TopLevelDir, "B"); Directory.CreateDirectory(subdir); // create a bunch more files int newFileCount = numFilesToCreate + _rnd.Next(3) + 3; for (j = 0; j < newFileCount; j++) { filename = Path.Combine(subdir, String.Format("file{0:D3}.txt", j)); repeatedLine = String.Format("Content for the updated file {0} {1}", Path.GetFileName(filename), System.DateTime.Now.ToString("yyyy-MM-dd")); TestUtilities.CreateAndFillFileText(filename, repeatedLine, _rnd.Next(1000) + 2000); entriesAdded++; } // Update those files in the zip file Directory.SetCurrentDirectory(TopLevelDir); using (ZipFile zip1 = new ZipFile()) { String[] filenames = Directory.GetFiles("B"); foreach (String f in filenames) zip1.UpdateItem(f, ""); zip1.Comment = "UpdateTests::UpdateZip_UpdateItem(): This archive has been updated."; zip1.Save(zipFileToCreate); } // Verify the number of files in the zip Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), newFileCount, "The Zip file has the wrong number of entries."); // now extract the files and verify their contents using (ZipFile zip3 = ZipFile.Read(zipFileToCreate)) { foreach (string s in zip3.EntryFileNames) { repeatedLine = String.Format("Content for the updated file {0} {1}", s, System.DateTime.Now.ToString("yyyy-MM-dd")); zip3[s].Extract("extract"); // verify the content of the updated file. var sr = new StreamReader(Path.Combine("extract", s)); string sLine = sr.ReadLine(); sr.Close(); Assert.AreEqual<string>(repeatedLine, sLine, String.Format("The content of the Updated file ({0}) in the zip archive is incorrect.", s)); } } }
public void UpdateZip_AddFile_OldEntriesWithPassword() { string password = "******"; string filename = null; int entriesAdded = 0; string repeatedLine = null; int j; // select the name of the zip file string zipFileToCreate = Path.Combine(TopLevelDir, "UpdateZip_AddFile_OldEntriesWithPassword.zip"); // create the subdirectory string subdir = Path.Combine(TopLevelDir, "A"); Directory.CreateDirectory(subdir); // create the files int numFilesToCreate = _rnd.Next(10) + 8; for (j = 0; j < numFilesToCreate; j++) { filename = Path.Combine(subdir, String.Format("file{0:D3}.txt", j)); repeatedLine = String.Format("This line is repeated over and over and over in file {0}", Path.GetFileName(filename)); TestUtilities.CreateAndFillFileText(filename, repeatedLine, _rnd.Next(34000) + 5000); entriesAdded++; } // Create the zip file Directory.SetCurrentDirectory(TopLevelDir); using (ZipFile zip1 = new ZipFile()) { zip1.Password = password; String[] filenames = Directory.GetFiles("A"); foreach (String f in filenames) zip1.AddFile(f, ""); zip1.Comment = "UpdateTests::UpdateZip_AddFile_OldEntriesWithPassword(): This archive will be updated."; zip1.Save(zipFileToCreate); } // Verify the files are in the zip Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), entriesAdded, "The Zip file has the wrong number of entries."); // Create a bunch of new files... var addedFiles = new List<string>(); int numToUpdate = _rnd.Next(numFilesToCreate - 4); for (j = 0; j < numToUpdate; j++) { // select a new, uniquely named file to create filename = String.Format("newfile{0:D3}.txt", j); // create a new file, and fill that new file with text data repeatedLine = String.Format("**UPDATED** This file ({0}) has been updated on {1}.", filename, System.DateTime.Now.ToString("yyyy-MM-dd")); TestUtilities.CreateAndFillFileText(Path.Combine(subdir, filename), repeatedLine, _rnd.Next(34000) + 5000); addedFiles.Add(filename); } // add each one of those new files in the zip archive using (ZipFile zip2 = ZipFile.Read(zipFileToCreate)) { foreach (string s in addedFiles) zip2.AddFile(Path.Combine(subdir, s), ""); zip2.Comment = "UpdateTests::UpdateZip_AddFile_OldEntriesWithPassword(): This archive has been updated."; zip2.Save(); } // Verify the number of files in the zip Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), entriesAdded + addedFiles.Count, "The Zip file has the wrong number of entries."); // now extract the newly-added files and verify their contents using (ZipFile zip3 = ZipFile.Read(zipFileToCreate)) { foreach (string s in addedFiles) { repeatedLine = String.Format("**UPDATED** This file ({0}) has been updated on {1}.", s, System.DateTime.Now.ToString("yyyy-MM-dd")); zip3[s].Extract("extract"); // verify the content of the updated file. var sr = new StreamReader(Path.Combine("extract", s)); string sLine = sr.ReadLine(); sr.Close(); Assert.AreEqual<string>(repeatedLine, sLine, String.Format("The content of the Updated file ({0}) in the zip archive is incorrect.", s)); } } // extract all the other files and verify their contents using (ZipFile zip4 = ZipFile.Read(zipFileToCreate)) { foreach (string s1 in zip4.EntryFileNames) { bool addedLater = false; foreach (string s2 in addedFiles) { if (s2 == s1) addedLater = true; } if (!addedLater) { zip4[s1].ExtractWithPassword("extract", password); repeatedLine = String.Format("This line is repeated over and over and over in file {0}", s1); // verify the content of the updated file. var sr = new StreamReader(Path.Combine("extract", s1)); string sLine = sr.ReadLine(); sr.Close(); Assert.AreEqual<string>(repeatedLine, sLine, String.Format("The content of the originally added file ({0}) in the zip archive is incorrect.", s1)); } } } }
public void _Internal_Streams_ZipInput_Encryption(int fodderOption, int fileReadOption) { byte[] buffer = new byte[2048]; int n; int[] fileCounts = { 1, 2, _rnd.Next(8) + 6, _rnd.Next(18) + 16, _rnd.Next(48) + 56 }; for (int m = 0; m < fileCounts.Length; m++) { string password = TestUtilities.GenerateRandomPassword(); string dirToZip = String.Format("trial{0:D2}", m); if (!Directory.Exists(dirToZip)) Directory.CreateDirectory(dirToZip); int fileCount = fileCounts[m]; TestContext.WriteLine("====="); TestContext.WriteLine("Trial {0} filecount={1}", m, fileCount); var files = (new Func<string[]>( () => { if (fodderOption == 0) { // zero length files var a = new string[fileCount]; for (int i = 0; i < fileCount; i++) a[i] = CreateZeroLengthFile(i, dirToZip); return a; } if (fodderOption == 1) return TestUtilities.GenerateFilesFlat(dirToZip, fileCount, 100, 72000); // mixed = some zero and some not var b = new string[fileCount]; for (int i = 0; i < fileCount; i++) { if (_rnd.Next(3) == 0) b[i] = CreateZeroLengthFile(i, dirToZip); else { b[i] = Path.Combine(dirToZip, String.Format("nonzero{0:D4}.txt", i)); TestUtilities.CreateAndFillFileText(b[i], _rnd.Next(60000) + 100); } } return b; }))(); for (int i = 0; i < crypto.Length; i++) { EncryptionAlgorithm c = crypto[i]; string zipFileToCreate = Path.Combine(TopLevelDir, String.Format("ZIS_Crypto.{0}.count.{1:D2}.{2}.zip", c.ToString(), fileCounts[m], fodderOption)); // Create the zip archive using (var zip = new ZipFile()) { zip.Password = password; zip.Encryption = c; if (fodderOption > 2) { zip.AddDirectoryByName("subdir"); zip.AddDirectory(dirToZip, "subdir"); } else zip.AddDirectory(dirToZip); zip.Save(zipFileToCreate); } // Verify the number of files in the zip Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), files.Length, "Incorrect number of entries in the zip file."); // extract the files string extractDir = String.Format("extract{0:D2}.{1:D2}", m, i); TestContext.WriteLine("Extract to: {0}", extractDir); Directory.CreateDirectory(extractDir); var input = (new Func<ZipInputStream>( () => { if (fileReadOption == 0) { var raw = File.OpenRead(zipFileToCreate); return new ZipInputStream(raw); } return new ZipInputStream(zipFileToCreate); }))(); using (input) { // set password if necessary if (crypto[i] != EncryptionAlgorithm.None) input.Password = password; ZipEntry e; while ((e = input.GetNextEntry()) != null) { TestContext.WriteLine("entry: {0}", e.FileName); string outputPath = Path.Combine(extractDir, e.FileName); if (e.IsDirectory) { // create the directory Directory.CreateDirectory(outputPath); } else { // emit the file using (var output = File.Create(outputPath)) { while ((n = input.Read(buffer, 0, buffer.Length)) > 0) { output.Write(buffer, 0, n); } } } } } string[] filesUnzipped = (fodderOption > 2) ? Directory.GetFiles(Path.Combine(extractDir, "subdir")) : Directory.GetFiles(extractDir); // Verify the number of files extracted Assert.AreEqual<int>(files.Length, filesUnzipped.Length, "Incorrect number of files extracted. ({0}!={1})", files.Length, filesUnzipped.Length); } } }
// 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(); }
public void AddEntry_JitProvided() { for (int i = 0; i < crypto.Length; i++) { for (int k = 0; k < compLevels.Length; k++) { string zipFileToCreate = String.Format("AddEntry_JitProvided.{0}.{1}.zip", i, k); string dirToZip = Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); var files = TestUtilities.GenerateFilesFlat(dirToZip); string password = Path.GetRandomFileName(); using (var zip = new ZipFile()) { TestContext.WriteLine("================================="); TestContext.WriteLine("Creating {0}...", Path.GetFileName(zipFileToCreate)); TestContext.WriteLine("Encryption({0}) Compression({1}) pw({2})", crypto[i].ToString(), compLevels[k].ToString(), password); zip.Password = password; zip.Encryption = crypto[i]; zip.CompressionLevel = compLevels[k]; foreach (var file in files) zip.AddEntry(file, (name) => File.OpenRead(name), (name, stream) => stream.Close() ); zip.Save(zipFileToCreate); } if (crypto[i] == EncryptionAlgorithm.None) BasicVerifyZip(zipFileToCreate); else BasicVerifyZip(zipFileToCreate, password); Assert.AreEqual<int>(files.Length, TestUtilities.CountEntries(zipFileToCreate), "Trial ({0},{1}): The zip file created has the wrong number of entries.", i, k); } } }
private static void ReadCentralDirectoryFooter(ZipFile zf) { Stream s = zf.ReadStream; int signature = Alienlab.Zip.SharedUtilities.ReadSignature(s); byte[] block = null; int j = 0; if (signature == ZipConstants.Zip64EndOfCentralDirectoryRecordSignature) { // We have a ZIP64 EOCD // This data block is 4 bytes sig, 8 bytes size, 44 bytes fixed data, // followed by a variable-sized extension block. We have read the sig already. // 8 - datasize (64 bits) // 2 - version made by // 2 - version needed to extract // 4 - number of this disk // 4 - number of the disk with the start of the CD // 8 - total number of entries in the CD on this disk // 8 - total number of entries in the CD // 8 - size of the CD // 8 - offset of the CD // ----------------------- // 52 bytes block = new byte[8 + 44]; s.Read(block, 0, block.Length); Int64 DataSize = BitConverter.ToInt64(block, 0); // == 44 + the variable length if (DataSize < 44) throw new ZipException("Bad size in the ZIP64 Central Directory."); zf._versionMadeBy = BitConverter.ToUInt16(block, j); j += 2; zf._versionNeededToExtract = BitConverter.ToUInt16(block, j); j += 2; zf._diskNumberWithCd = BitConverter.ToUInt32(block, j); j += 2; //zf._diskNumberWithCd++; // hack!! // read the extended block block = new byte[DataSize - 44]; s.Read(block, 0, block.Length); // discard the result signature = Alienlab.Zip.SharedUtilities.ReadSignature(s); if (signature != ZipConstants.Zip64EndOfCentralDirectoryLocatorSignature) throw new ZipException("Inconsistent metadata in the ZIP64 Central Directory."); block = new byte[16]; s.Read(block, 0, block.Length); // discard the result signature = Alienlab.Zip.SharedUtilities.ReadSignature(s); } // Throw if this is not a signature for "end of central directory record" // This is a sanity check. if (signature != ZipConstants.EndOfCentralDirectorySignature) { s.Seek(-4, SeekOrigin.Current); throw new BadReadException(String.Format("Bad signature ({0:X8}) at position 0x{1:X8}", signature, s.Position)); } // read the End-of-Central-Directory-Record block = new byte[16]; zf.ReadStream.Read(block, 0, block.Length); // off sz data // ------------------------------------------------------- // 0 4 end of central dir signature (0x06054b50) // 4 2 number of this disk // 6 2 number of the disk with start of the central directory // 8 2 total number of entries in the central directory on this disk // 10 2 total number of entries in the central directory // 12 4 size of the central directory // 16 4 offset of start of central directory with respect to the starting disk number // 20 2 ZIP file comment length // 22 ?? ZIP file comment if (zf._diskNumberWithCd == 0) { zf._diskNumberWithCd = BitConverter.ToUInt16(block, 2); //zf._diskNumberWithCd++; // hack!! } // read the comment here ReadZipFileComment(zf); }
public ZipContainer(Object o) { _zf = (o as ZipFile); _zos = (o as ZipOutputStream); _zis = (o as ZipInputStream); }
private static void ReadZipFileComment(ZipFile zf) { // read the comment here byte[] block = new byte[2]; zf.ReadStream.Read(block, 0, block.Length); Int16 commentLength = (short)(block[0] + block[1] * 256); if (commentLength > 0) { block = new byte[commentLength]; zf.ReadStream.Read(block, 0, block.Length); // workitem 10392 - prefer ProvisionalAlternateEncoding, // first. The fix for workitem 6513 tried to use UTF8 // only as necessary, but that is impossible to test // for, in this direction. There's no way to know what // characters the already-encoded bytes refer // to. Therefore, must do what the user tells us. string s1 = zf.AlternateEncoding.GetString(block, 0, block.Length); zf.Comment = s1; } }
public void Progress_ReadFile() { Directory.SetCurrentDirectory(TopLevelDir); string zipFileToCreate = Path.Combine(TopLevelDir, "Progress_ReadFile.zip"); string dirToZip = Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); var files = TestUtilities.GenerateFilesFlat(dirToZip); using (ZipFile zip = new ZipFile()) { zip.AddFiles(files); zip.Save(zipFileToCreate); } int count = TestUtilities.CountEntries(zipFileToCreate); Assert.IsTrue(count>0); var options = new ReadOptions { StatusMessageWriter = new StringWriter(), ReadProgress = ReadProgress1 }; using (ZipFile zip = ZipFile.Read(zipFileToCreate, options)) { // this should be fine zip.RemoveEntry(zip[1]); zip.Save(); } TestContext.WriteLine(options.StatusMessageWriter.ToString()); Assert.AreEqual<Int32>(count, TestUtilities.CountEntries(zipFileToCreate)+1); }
public void ZipFile_JitStream_CloserTwice_wi10489() { int fileCount = 20 + _rnd.Next(20); string zipFileToCreate = "CloserTwice.zip"; string dirToZip = "fodder"; var files = TestUtilities.GenerateFilesFlat(dirToZip, fileCount, 100, 72000); OpenDelegate opener = (name) => { TestContext.WriteLine("Opening {0}", name); Stream s = File.OpenRead(Path.Combine(dirToZip,name)); return s; }; CloseDelegate closer = (e, s) => { TestContext.WriteLine("Closing {0}", e); s.Dispose(); }; TestContext.WriteLine("Creating zipfile {0}", zipFileToCreate); using (var zip = new ZipFile()) { foreach (var file in files) { zip.AddEntry(Path.GetFileName(file),opener,closer); } zip.Save(zipFileToCreate); } Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), files.Length); BasicVerifyZip(zipFileToCreate); }
public void Password_CheckZipPassword_wi13664() { string[] passwords = { null, "Password!", TestUtilities.GenerateRandomPassword(), "_" }; string dirToZip = Path.Combine(TopLevelDir, "zipthis"); int subdirCount; int entries = TestUtilities.GenerateFilesOneLevelDeep (TestContext, "wi13664", dirToZip, null, out subdirCount); string[] filesToZip = Directory.GetFiles("zipthis", "*.*", SearchOption.AllDirectories); Assert.AreEqual<int>(filesToZip.Length, entries, "Incorrect number of entries in the directory."); for (int j = 0; j < passwords.Length; j++) { string zipFileToCreate = Path.Combine(TopLevelDir, String.Format("Password_CheckZipPassword_wi13664-{0}.zip", j)); // Create the zip archive using (ZipFile zip1 = new ZipFile()) { zip1.Password = passwords[j]; zip1.AddFiles(filesToZip, true, ""); zip1.Save(zipFileToCreate); } var r = ZipFile.CheckZipPassword(zipFileToCreate, passwords[j]); Assert.IsTrue(r, "Bad password in round {0}", j); } }
public void JitStream_Update_wi13899() { int fileCount = 12 + _rnd.Next(16); string dirToZip = "fodder"; var files = TestUtilities.GenerateFilesFlat(dirToZip, fileCount, 100, 72000); OpenDelegate opener = (name) => { TestContext.WriteLine("Opening {0}", name); Stream s = File.OpenRead(Path.Combine(dirToZip,name)); return s; }; CloseDelegate closer = (e, s) => { TestContext.WriteLine("Closing {0}", e); s.Dispose(); }; // Two passes: first to call UpdateEntry() when no prior entry exists. // Second to call UpdateEntry when a prior entry exists. for (int j=0; j < 2; j++) { string zipFileToCreate = String.Format("wi13899-{0}.zip", j); TestContext.WriteLine(""); TestContext.WriteLine("Creating zipfile {0}", zipFileToCreate); if (j!=0) { using (var zip = new ZipFile(zipFileToCreate)) { foreach (var file in files) { zip.AddEntry(Path.GetFileName(file), "This is the content for file " + file); } zip.Save(); } Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), files.Length); BasicVerifyZip(zipFileToCreate); TestContext.WriteLine("Updating zipfile {0}", zipFileToCreate); } using (var zip = new ZipFile(zipFileToCreate)) { foreach (var file in files) { zip.UpdateEntry(Path.GetFileName(file), opener, closer); } zip.Save(); } BasicVerifyZip(zipFileToCreate); // verify checksum here? } }
public void Password_MultipleEntriesDifferentPasswords() { string ZipFileToCreate = Path.Combine(TopLevelDir, "Password_MultipleEntriesDifferentPasswords.zip"); Assert.IsFalse(File.Exists(ZipFileToCreate), "The temporary zip file '{0}' already exists.", ZipFileToCreate); string SourceDir = CurrentDir; for (int i = 0; i < 3; i++) SourceDir = Path.GetDirectoryName(SourceDir); Directory.SetCurrentDirectory(TopLevelDir); string[] filenames = { Path.Combine(SourceDir, "Tools\\Zipit\\bin\\Debug\\Zipit.exe"), Path.Combine(SourceDir, "Zip\\bin\\Debug\\Ionic.Zip.xml"), }; string[] checksums = { TestUtilities.GetCheckSumString(filenames[0]), TestUtilities.GetCheckSumString(filenames[1]), }; string[] passwords = { "12345678", "0987654321", }; int j = 0; using (ZipFile zip = new ZipFile(ZipFileToCreate)) { for (j = 0; j < filenames.Length; j++) { zip.Password = passwords[j]; zip.AddFile(filenames[j], ""); } zip.Save(); } Assert.AreEqual<int>(TestUtilities.CountEntries(ZipFileToCreate), filenames.Length, "The zip file created has the wrong number of entries."); using (ZipFile zip = new ZipFile(ZipFileToCreate)) { for (j = 0; j < filenames.Length; j++) { zip[Path.GetFileName(filenames[j])].ExtractWithPassword("unpack", ExtractExistingFileAction.OverwriteSilently, passwords[j]); string newpath = Path.Combine("unpack", filenames[j]); string chk = TestUtilities.GetCheckSumString(newpath); Assert.AreEqual<string>(checksums[j], chk, "File checksums do not match."); } } }
[TestMethod, Timeout(30 * 60 * 1000)] // in ms. 30*60*100 == 30min public void ZipFile_PDOS_LeakTest_wi10030() { // Test memory growth over many many cycles. // There was a leak in the ParallelDeflateOutputStream, where // the PDOS was not being GC'd. This test checks for that. // // If the error is present, this test will either timeout or // throw an InsufficientMemoryException (or whatever). The // timeout occurs because GC begins to get verrrrry // sloooooow. IF the error is not present, this test will // complete successfully, in about 20 minutes. // string zipFileToCreate = "ZipFile_PDOS_LeakTest_wi10030.zip"; int nCycles = 4096; int nFiles = 3; int sizeBase = 384 * 1024; int sizeRange = 32 * 1024; int count = 0; byte[] buffer = new byte[1024]; int n; // fill a couple memory streams with random text MemoryStream[] ms = new MemoryStream[nFiles]; for (int i = 0; i < ms.Length; i++) { ms[i] = new MemoryStream(); int sz = sizeBase + _rnd.Next(sizeRange); using (Stream rtg = new Alienlab.Zip.Tests.Utilities.RandomTextInputStream(sz)) { while ((n = rtg.Read(buffer, 0, buffer.Length)) > 0) { ms[i].Write(buffer, 0, n); } } } buffer = null; OpenDelegate opener = (x) => { Stream s = ms[count % ms.Length]; s.Seek(0L, SeekOrigin.Begin); count++; return s; }; CloseDelegate closer = (e, s) => { //s.Close(); }; string txrxLabel = "PDOS Leak Test"; _txrx = TestUtilities.StartProgressMonitor("ZipFile_PDOS_LeakTest_wi10030", txrxLabel, "starting up..."); TestContext.WriteLine("Testing for leaks...."); _txrx.Send(String.Format("pb 0 max {0}", nCycles)); _txrx.Send("pb 0 value 0"); for (int x = 0; x < nCycles; x++) { if (x != 0 && x % 16 == 0) { TestContext.WriteLine("Cycle {0}...", x); string status = String.Format("status Cycle {0}/{1} {2:N0}%", x + 1, nCycles, ((x+1)/(0.01 * nCycles))); _txrx.Send(status); } using (ZipFile zip = new ZipFile()) { zip.ParallelDeflateThreshold = 128 * 1024; zip.CompressionLevel = Alienlab.Zlib.CompressionLevel.BestCompression; //zip.SaveProgress += streams_SaveProgress; for (int y = 0; y < nFiles; y++) { zip.AddEntry("Entry" + y + ".txt", opener, closer); } zip.Comment = "Produced at " + System.DateTime.UtcNow.ToString("G"); zip.Save(zipFileToCreate); } _txrx.Send("pb 0 step"); } for (int i = 0; i < ms.Length; i++) { ms[i].Dispose(); ms[i] = null; } ms = null; }
public void Password_AddEntryWithPasswordToExistingZip() { string zipFileToCreate = "AddEntryWithPasswordToExistingZip.zip"; string dnzDir = CurrentDir; for (int i = 0; i < 3; i++) dnzDir = Path.GetDirectoryName(dnzDir); string[] filenames = { Path.Combine(dnzDir, "Tools\\Zipit\\bin\\Debug\\Zipit.exe"), Path.Combine(dnzDir, "Zip\\bin\\Debug\\Ionic.Zip.xml"), }; string[] checksums = { TestUtilities.GetCheckSumString(filenames[0]), TestUtilities.GetCheckSumString(filenames[1]), }; int j = 0; using (ZipFile zip = new ZipFile(zipFileToCreate)) { for (j = 0; j < filenames.Length; j++) zip.AddFile(filenames[j], ""); zip.Save(); } Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), 2, "wrong number of entries."); string fileX = Path.Combine(dnzDir, "Tools\\Unzip\\bin\\debug\\unzip.exe"); string checksumX = TestUtilities.GetCheckSumString(fileX); string password = TestUtilities.GenerateRandomPassword() + "!"; using (ZipFile zip = new ZipFile(zipFileToCreate)) { zip.Password = password; zip.AddFile(fileX, ""); zip.Save(); } Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), 3, "wrong number of entries."); string unpackDir = "unpack"; string newpath, chk, baseName; using (ZipFile zip = new ZipFile(zipFileToCreate)) { for (j = 0; j < filenames.Length; j++) { baseName = Path.GetFileName(filenames[j]); zip[baseName].Extract(unpackDir, ExtractExistingFileAction.OverwriteSilently); newpath = Path.Combine(unpackDir, filenames[j]); chk = TestUtilities.GetCheckSumString(newpath); Assert.AreEqual<string>(checksums[j], chk, "Checksums do not match."); } baseName = Path.GetFileName(fileX); zip[baseName].ExtractWithPassword(unpackDir, ExtractExistingFileAction.OverwriteSilently, password); newpath = Path.Combine(unpackDir, fileX); chk = TestUtilities.GetCheckSumString(newpath); Assert.AreEqual<string>(checksumX, chk, "Checksums do not match."); } }
public void ReadZip_OpenReader() { string[] passwords = { null, Path.GetRandomFileName(), "EE", "***()" }; for (int j = 0; j < compLevels.Length; j++) { for (int k = 0; k < passwords.Length; k++) { string zipFileToCreate = String.Format("ReadZip_OpenReader-{0}-{1}.zip", j, k); //int entriesAdded = 0; //String filename = null; string dirToZip = String.Format("dirToZip.{0}.{1}", j, k); var files = TestUtilities.GenerateFilesFlat(dirToZip); using (ZipFile zip1 = new ZipFile()) { zip1.CompressionLevel = compLevels[j]; zip1.Password = passwords[k]; zip1.AddDirectory(dirToZip,dirToZip); zip1.Save(zipFileToCreate); } // Verify the files are in the zip Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), files.Length, String.Format("Trial ({0},{1})", j, k)); int i = 0; ZipEntry e1 = null; Func<Ionic.Crc.CrcCalculatorStream> opener = () => { if (i == 0) return e1.OpenReader(); if (i == 1) return e1.OpenReader(passwords[k]); e1.Password = passwords[k]; return e1.OpenReader(); }; // now extract the files and verify their contents using (ZipFile zip2 = ZipFile.Read(zipFileToCreate)) { for (i = 0; i < 3; i++) { // try once with Password set on ZipFile, // another with password on the entry, and // a third time with password passed into the OpenReader() method. if (i == 0) zip2.Password = passwords[k]; foreach (string eName in zip2.EntryFileNames) { e1 = zip2[eName]; if (e1.IsDirectory) continue; using (var s = opener()) { string outFile = String.Format("{0}.{1}.out", eName, i); int totalBytesRead = 0; using (var output = File.Create(outFile)) { byte[] buffer = new byte[4096]; int n; while ((n = s.Read(buffer, 0, buffer.Length)) > 0) { totalBytesRead += n; output.Write(buffer, 0, n); } } TestContext.WriteLine("CRC expected({0:X8}) actual({1:X8})", e1.Crc, s.Crc); Assert.AreEqual<Int32>(s.Crc, e1.Crc, string.Format("{0} :: CRC Mismatch", eName)); Assert.AreEqual<Int32>(totalBytesRead, (int)e1.UncompressedSize, string.Format("We read an unexpected number of bytes. ({0})", eName)); } } } } } } }
public void SilentDeletion_wi10639() { string zipFileToCreate = "SilentDeletion.zip"; string dirToZip = "dirToZip"; string extractDir = "extracted"; string password = TestUtilities.GenerateRandomPassword(); string wrongPassword = "******"; var files = TestUtilities.GenerateFilesFlat(dirToZip); TestContext.WriteLine("Creating the zip."); using (var zip = new ZipFile()) { zip.Password = password; zip.AddFiles(files, dirToZip); zip.Save(zipFileToCreate); } TestContext.WriteLine("Extract one file with wrong password."); // pick a random entry to extract int ix = -1; string extractedFile = null; // perform two passes: first with correct password to extract the // file. 2nd with incorrect password to see if the file is // deleted. Directory.CreateDirectory(extractDir); for (int i=0; i < 2; i++) { try { using (var zip = ZipFile.Read(zipFileToCreate)) { if (i==0) { do { ix = this._rnd.Next(zip.Entries.Count); } while (zip[ix].IsDirectory); TestContext.WriteLine("Selected entry: {0}", zip[ix].FileName); extractedFile = Path.Combine(extractDir, zip[ix].FileName.Replace("/","\\")); TestContext.WriteLine("name for extracted file: {0}", extractedFile); Assert.IsFalse(File.Exists(extractedFile), "The file exists."); } TestContext.WriteLine("Cycle {0}: ExtractWithPassword()", i); zip[ix].ExtractWithPassword(extractDir, ExtractExistingFileAction.OverwriteSilently, (i==0)? password : wrongPassword); } } catch (Ionic.Zip.BadPasswordException bpe1) { // only swallow exceptions on the first go-round if (i==0) throw; } Assert.IsTrue(File.Exists(extractedFile), "Cycle {0}: The extracted file does not exist.", i); } }
public void UpdateZip_RemoveEntry_ViaIndexer_WithPassword() { string password = TestUtilities.GenerateRandomPassword(); string filename = null; int entriesToBeAdded = 0; string repeatedLine = null; int j; // select the name of the zip file string zipFileToCreate = Path.Combine(TopLevelDir, "UpdateZip_RemoveEntry_ViaIndexer_WithPassword.zip"); // create the subdirectory string subdir = Path.Combine(TopLevelDir, "A"); Directory.CreateDirectory(subdir); // create the files int numFilesToCreate = _rnd.Next(13) + 14; for (j = 0; j < numFilesToCreate; j++) { filename = String.Format("file{0:D3}.txt", j); repeatedLine = String.Format("This line is repeated over and over and over in file {0}", filename); TestUtilities.CreateAndFillFileText(Path.Combine(subdir, filename), repeatedLine, _rnd.Next(34000) + 5000); entriesToBeAdded++; } // Add the files to the zip, save the zip Directory.SetCurrentDirectory(TopLevelDir); using (ZipFile zip = new ZipFile()) { String[] filenames = Directory.GetFiles("A"); zip.Password = password; foreach (String f in filenames) zip.AddFile(f, ""); zip.Comment = "UpdateTests::UpdateZip_OpenForUpdate_Password_RemoveViaIndexer(): This archive will be updated."; zip.Save(zipFileToCreate); } // Verify the files are in the zip Assert.AreEqual<int>(entriesToBeAdded, TestUtilities.CountEntries(zipFileToCreate), "The Zip file has the wrong number of entries."); // selectively remove a few files in the zip archive var filesToRemove = new List<string>(); int numToRemove = _rnd.Next(numFilesToCreate - 4); using (ZipFile zip2 = ZipFile.Read(zipFileToCreate)) { for (j = 0; j < numToRemove; j++) { // select a new, uniquely named file to create do { filename = String.Format("file{0:D3}.txt", _rnd.Next(numFilesToCreate)); } while (filesToRemove.Contains(filename)); // add this file to the list filesToRemove.Add(filename); // remove the file from the zip archive zip2.RemoveEntry(filename); } zip2.Comment = "This archive has been modified. Some files have been removed."; zip2.Save(); } // extract all files, verify none should have been removed, // and verify the contents of those that remain using (ZipFile zip3 = ZipFile.Read(zipFileToCreate)) { foreach (string s1 in zip3.EntryFileNames) { Assert.IsFalse(filesToRemove.Contains(s1), String.Format("File ({0}) was not expected.", s1)); zip3[s1].ExtractWithPassword("extract", password); repeatedLine = String.Format("This line is repeated over and over and over in file {0}", s1); // verify the content of the updated file. var sr = new StreamReader(Path.Combine("extract", s1)); string sLine = sr.ReadLine(); sr.Close(); Assert.AreEqual<string>(repeatedLine, sLine, String.Format("The content of the originally added file ({0}) in the zip archive is incorrect.", s1)); } } // Verify the files are in the zip Assert.AreEqual<int>(TestUtilities.CountEntries(zipFileToCreate), entriesToBeAdded - filesToRemove.Count, "The updated Zip file has the wrong number of entries."); }