Exemple #1
0
        private static void InitCompressionStreamCreators()
        {
            if (ZipEngine.compressionStreamCreators == null)
            {
                ZipEngine.compressionStreamCreators = new
                                                      Dictionary <ZipCompressionMethod, Converter <Stream, Stream> >();
                ZipEngine.decompressionStreamCreators = new
                                                        Dictionary <ZipCompressionMethod, Converter <Stream, Stream> >();

                ZipEngine.RegisterCompressionStreamCreator(
                    ZipCompressionMethod.Store,
                    CompressionMode.Compress,
                    delegate(Stream stream) {
                    return(stream);
                });
                ZipEngine.RegisterCompressionStreamCreator(
                    ZipCompressionMethod.Deflate,
                    CompressionMode.Compress,
                    delegate(Stream stream) {
                    return(new DeflateStream(stream, CompressionMode.Compress, true));
                });
                ZipEngine.RegisterCompressionStreamCreator(
                    ZipCompressionMethod.Store,
                    CompressionMode.Decompress,
                    delegate(Stream stream) {
                    return(stream);
                });
                ZipEngine.RegisterCompressionStreamCreator(
                    ZipCompressionMethod.Deflate,
                    CompressionMode.Decompress,
                    delegate(Stream stream) {
                    return(new DeflateStream(stream, CompressionMode.Decompress, true));
                });
            }
        }
Exemple #2
0
 /// <summary>
 /// Registers a delegate that can create a warpper stream for
 /// compressing or uncompressing the data of a source stream.
 /// </summary>
 /// <param name="compressionMethod">Compression method being registered.</param>
 /// <param name="compressionMode">Indicates registration for ether
 /// compress or decompress mode.</param>
 /// <param name="creator">Delegate being registered.</param>
 /// <remarks>
 /// For compression, the delegate accepts a stream that writes to the archive
 /// and returns a wrapper stream that compresses bytes as they are written.
 /// For decompression, the delegate accepts a stream that reads from the archive
 /// and returns a wrapper stream that decompresses bytes as they are read.
 /// This wrapper stream model follows the design used by
 /// System.IO.Compression.DeflateStream, and indeed that class is used
 /// to implement the Deflate compression method by default.
 /// <para>To unregister a delegate, call this method again and pass
 /// null for the delegate parameter.</para>
 /// </remarks>
 /// <example>
 /// When the ZipEngine class is initialized, the Deflate compression method
 /// is automatically registered like this:
 /// <code>
 ///        ZipEngine.RegisterCompressionStreamCreator(
 ///            ZipCompressionMethod.Deflate,
 ///            CompressionMode.Compress,
 ///            delegate(Stream stream) {
 ///                return new DeflateStream(stream, CompressionMode.Compress, true);
 ///            });
 ///        ZipEngine.RegisterCompressionStreamCreator(
 ///            ZipCompressionMethod.Deflate,
 ///            CompressionMode.Decompress,
 ///            delegate(Stream stream) {
 ///                return new DeflateStream(stream, CompressionMode.Decompress, true);
 ///            });
 /// </code></example>
 public static void RegisterCompressionStreamCreator(
     ZipCompressionMethod compressionMethod,
     CompressionMode compressionMode,
     Converter <Stream, Stream> creator)
 {
     ZipEngine.InitCompressionStreamCreators();
     if (compressionMode == CompressionMode.Compress)
     {
         ZipEngine.compressionStreamCreators[compressionMethod] = creator;
     }
     else
     {
         ZipEngine.decompressionStreamCreators[compressionMethod] = creator;
     }
 }
Exemple #3
0
 /// <summary>
 /// Creates a new instance of the zip engine.
 /// </summary>
 public ZipEngine()
     : base()
 {
     ZipEngine.InitCompressionStreamCreators();
 }
Exemple #4
0
        private IList<ArchiveFileInfo> RunZipPackUnpack(int fileCount, long fileSize,
            long maxArchiveSize, CompressionLevel compLevel)
        {
            Console.WriteLine("Creating zip archive with {0} files of size {1}",
                fileCount, fileSize);
            Console.WriteLine("MaxArchiveSize={0}, CompressionLevel={1}", maxArchiveSize, compLevel);

            string dirA = String.Format("{0}-{1}-A", fileCount, fileSize);
            if (Directory.Exists(dirA)) Directory.Delete(dirA, true);
            Directory.CreateDirectory(dirA);
            string dirB = String.Format("{0}-{1}-B", fileCount, fileSize);
            if (Directory.Exists(dirB)) Directory.Delete(dirB, true);
            Directory.CreateDirectory(dirB);

            string[] files = new string[fileCount];
            for (int iFile = 0; iFile < fileCount; iFile++)
            {
                files[iFile] = TEST_FILENAME_PREFIX + iFile + ".txt";
                CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[iFile]), iFile, fileSize);
            }

            string[] archiveNames = new string[1000];
            for (int i = 0; i < archiveNames.Length; i++)
            {
                if (i < 100)
                {
                    archiveNames[i] = String.Format(
                        (i == 0 ? "{0}-{1}.zip" : "{0}-{1}.z{2:d02}"),
                        fileCount, fileSize, i);
                }
                else
                {
                    archiveNames[i] = String.Format(
                         "{0}-{1}.{2:d03}", fileCount, fileSize, i);
                }
            }

            string progressTextFile = String.Format("progress_{0}-{1}.txt", fileCount, fileSize);
            CompressionTestUtil testUtil = new CompressionTestUtil(progressTextFile);

            IList<ArchiveFileInfo> fileInfo;
            using (ZipEngine zipEngine = new ZipEngine())
            {
                zipEngine.CompressionLevel = compLevel;

                File.AppendAllText(progressTextFile,
                    "\r\n\r\n====================================================\r\nCREATE\r\n\r\n");
                zipEngine.Progress += testUtil.PrintArchiveProgress;

                OptionStreamContext streamContext = new OptionStreamContext(archiveNames, dirA, null);
                streamContext.OptionHandler =
                    delegate(string optionName, object[] parameters)
                    {
                        // For testing purposes, force zip64 for only moderately large files.
                        switch (optionName)
                        {
                            case  "forceZip64":
                                return fileSize > UInt16.MaxValue;
                            default:
                                return null;
                        }
                    };

                zipEngine.Pack(streamContext, files, maxArchiveSize);

                string checkArchiveName = archiveNames[0];
                if (File.Exists(archiveNames[1])) checkArchiveName = archiveNames[1];
                using (Stream archiveStream = File.OpenRead(checkArchiveName))
                {
                    bool isArchive = zipEngine.IsArchive(archiveStream);
                    Assert.IsTrue(isArchive, "Checking that created archive appears valid.");
                }

                IList<string> createdArchiveNames = new List<string>(archiveNames.Length);
                for (int i = 0; i < archiveNames.Length; i++)
                {
                    if (File.Exists(archiveNames[i]))
                    {
                        createdArchiveNames.Add(archiveNames[i]);
                    }
                    else
                    {
                        break;
                    }
                }

                Assert.AreNotEqual<int>(0, createdArchiveNames.Count);

                Console.WriteLine("Listing zip archive with {0} files of size {1}",
                    fileCount, fileSize);
                File.AppendAllText(progressTextFile, "\r\n\r\nLIST\r\n\r\n");
                fileInfo = zipEngine.GetFileInfo(
                    new ArchiveFileStreamContext(createdArchiveNames, null, null), null);

                Assert.AreEqual<int>(fileCount, fileInfo.Count);

                Console.WriteLine("Extracting zip archive with {0} files of size {1}",
                    fileCount, fileSize);
                File.AppendAllText(progressTextFile, "\r\n\r\nEXTRACT\r\n\r\n");
                zipEngine.Unpack(new ArchiveFileStreamContext(createdArchiveNames, dirB, null), null);
            }

            bool directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
            Assert.IsTrue(directoryMatch,
                "Testing whether zip output directory matches input directory.");

            return fileInfo;
        }
Exemple #5
0
        public void ZipBadUnpackStreamContexts()
        {
            int txtSize = 40960;
            ZipInfo zipInfo = new ZipInfo("test2.zip");
            CompressionTestUtil.GenerateRandomFile("ziptest-0.txt", 0, txtSize);
            CompressionTestUtil.GenerateRandomFile("ziptest-1.txt", 1, txtSize);
            zipInfo.PackFiles(null, new string[] { "ziptest-0.txt", "ziptest-1.txt" }, null);

            using (ZipEngine zipEngine = new ZipEngine())
            {
                CompressionTestUtil.TestBadUnpackStreamContexts(zipEngine, "test2.zip");
            }
        }
Exemple #6
0
        public void ZipBadPackStreamContexts()
        {
            string[] testFiles = new string[] { "test.txt" };
            CompressionTestUtil.GenerateRandomFile(testFiles[0], 0, 20000);

            using (ZipEngine zipEngine = new ZipEngine())
            {
                zipEngine.CompressionLevel = CompressionLevel.None;

                CompressionTestUtil.TestBadPackStreamContexts(zipEngine, "test.zip", testFiles);
            }
        }
Exemple #7
0
        public void ZipEngineNullParams()
        {
            string[] testFiles = new string[] { "test.txt" };
            ArchiveFileStreamContext streamContext = new ArchiveFileStreamContext("test.zip", null, null);

            using (ZipEngine zipEngine = new ZipEngine())
            {
                zipEngine.CompressionLevel = CompressionLevel.None;

                CompressionTestUtil.TestCompressionEngineNullParams(zipEngine, streamContext, testFiles);
            }
        }
Exemple #8
0
        /// <summary>
        /// Unpacks a single file from an archive or archive chain.
        /// </summary>
        private void UnpackOneFile(
            IUnpackStreamContext streamContext,
            ZipFileHeader header,
            ref Stream archiveStream)
        {
            ZipFileInfo fileInfo   = null;
            Stream      fileStream = null;

            try
            {
                Converter <Stream, Stream> compressionStreamCreator;
                if (!ZipEngine.decompressionStreamCreators.TryGetValue(
                        header.compressionMethod, out compressionStreamCreator))
                {
                    // Silently skip files of an unsupported compression method.
                    return;
                }

                long compressedSize;
                long uncompressedSize;
                long localHeaderOffset;
                int  archiveNumber;
                uint crc;
                header.GetZip64Fields(
                    out compressedSize,
                    out uncompressedSize,
                    out localHeaderOffset,
                    out archiveNumber,
                    out crc);

                if (this.currentArchiveNumber != archiveNumber + 1)
                {
                    if (archiveStream != null)
                    {
                        streamContext.CloseArchiveReadStream(
                            this.currentArchiveNumber,
                            String.Empty,
                            archiveStream);
                        archiveStream = null;

                        this.OnProgress(ArchiveProgressType.FinishArchive);
                        this.currentArchiveName = null;
                    }

                    this.currentArchiveNumber         = (short)(archiveNumber + 1);
                    this.currentArchiveBytesProcessed = 0;
                    this.currentArchiveTotalBytes     = 0;

                    archiveStream = this.OpenArchive(
                        streamContext, this.currentArchiveNumber);

                    FileStream archiveFileStream = archiveStream as FileStream;
                    this.currentArchiveName = (archiveFileStream != null ?
                                               Path.GetFileName(archiveFileStream.Name) : null);

                    this.currentArchiveTotalBytes = archiveStream.Length;
                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.StartArchive);
                    this.currentArchiveNumber++;
                }

                archiveStream.Seek(localHeaderOffset, SeekOrigin.Begin);

                ZipFileHeader localHeader = new ZipFileHeader();
                if (!localHeader.Read(archiveStream, false) ||
                    !ZipEngine.AreFilePathsEqual(localHeader.fileName, header.fileName))
                {
                    string msg = "Could not read file: " + header.fileName;
                    throw new ZipException(msg);
                }

                fileInfo = header.ToZipFileInfo();

                fileStream = streamContext.OpenFileWriteStream(
                    fileInfo.FullName,
                    fileInfo.Length,
                    fileInfo.LastWriteTime);

                if (fileStream != null)
                {
                    this.currentFileName           = header.fileName;
                    this.currentFileBytesProcessed = 0;
                    this.currentFileTotalBytes     = fileInfo.Length;
                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.StartFile);
                    this.currentArchiveNumber++;

                    this.UnpackFileBytes(
                        streamContext,
                        fileInfo.FullName,
                        fileInfo.CompressedLength,
                        fileInfo.Length,
                        header.crc32,
                        fileStream,
                        compressionStreamCreator,
                        ref archiveStream);
                }
            }
            finally
            {
                if (fileStream != null)
                {
                    streamContext.CloseFileWriteStream(
                        fileInfo.FullName,
                        fileStream,
                        fileInfo.Attributes,
                        fileInfo.LastWriteTime);

                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.FinishFile);
                    this.currentArchiveNumber++;
                }
            }
        }