예제 #1
0
        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");
                }
            }
        }
예제 #4
0
        /// <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);
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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();
        }
예제 #10
0
        /// <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;
        }
예제 #11
0
        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;
        }
예제 #12
0
        /// <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;
        }
예제 #13
0
        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));
                }
            }
        }
예제 #14
0
        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));
                    }
                }
            }
        }
예제 #15
0
        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);
                }
            }
        }
예제 #16
0
        // 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();
        }
예제 #17
0
        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);
                }
            }
        }
예제 #18
0
        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);
 }
예제 #20
0
        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;
            }
        }
예제 #21
0
        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);
        }
예제 #22
0
        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);
        }
예제 #23
0
        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);
            }
        }
예제 #24
0
        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?
            }
        }
예제 #25
0
        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.");
                }
            }
        }
예제 #26
0
        [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;
        }
예제 #27
0
        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.");
            }
        }
예제 #28
0
        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));
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #29
0
        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);
            }
        }
예제 #30
0
        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.");
        }