コード例 #1
0
ファイル: ZipOutputStream.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Starts a new Zip entry. It automatically closes the previous
        /// entry if present.
        /// All entry elements bar name are optional, but must be correct if present.
        /// If the compression method is stored and the output is not patchable
        /// the compression for that entry is automatically changed to deflate level 0
        /// </summary>
        /// <param name="entry">
        /// the entry.
        /// </param>
        /// <exception cref="System.IO.IOException">
        /// if an I/O error occured.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// if stream was finished
        /// </exception>
        /// <exception cref="ZipException">
        /// Too many entries in the Zip file<br/>
        /// Entry name is too long<br/>
        /// Finish has already been called<br/>
        /// </exception>
        public void PutNextEntry(ZipEntry entry)
        {
            if (entries == null) {
                throw new InvalidOperationException("ZipOutputStream was finished");
            }

            if (curEntry != null) {
                CloseEntry();
            }

            if (entries.Count >= 0xffff) {
                throw new ZipException("Too many entries for Zip file");
            }

            CompressionMethod method = entry.CompressionMethod;
            int compressionLevel = defaultCompressionLevel;

            entry.Flags = 0;
            patchEntryHeader = false;
            bool headerInfoAvailable = true;

            if (method == CompressionMethod.Stored) {
                if (entry.CompressedSize >= 0) {
                    if (entry.Size < 0) {
                        entry.Size = entry.CompressedSize;
                    } else if (entry.Size != entry.CompressedSize) {
                        throw new ZipException("Method STORED, but compressed size != size");
                    }
                } else {
                    if (entry.Size >= 0) {
                        entry.CompressedSize = entry.Size;
                    }
                }

                if (entry.Size < 0 || entry.Crc < 0) {
                    if (CanPatchEntries == true) {
                        headerInfoAvailable = false;
                    }
                    else {
                        method = CompressionMethod.Deflated;
                        compressionLevel = 0;
                    }
                }
            }

            if (method == CompressionMethod.Deflated) {
                if (entry.Size == 0) {
                    entry.CompressedSize = entry.Size;
                    entry.Crc = 0;
                    method = CompressionMethod.Stored;
                } else if (entry.CompressedSize < 0 || entry.Size < 0 || entry.Crc < 0) {
                    headerInfoAvailable = false;
                }
            }

            if (headerInfoAvailable == false) {
                if (CanPatchEntries == false) {
                    entry.Flags |= 8;
                } else {
                    patchEntryHeader = true;
                }
            }

            if (Password != null) {
                entry.IsCrypted = true;
                if (entry.Crc < 0) {
                    entry.Flags |= 8;
                }
            }
            entry.Offset = (int)offset;
            entry.CompressionMethod = (CompressionMethod)method;

            curMethod    = method;

            // Write the local file header
            WriteLeInt(ZipConstants.LOCSIG);

            WriteLeShort(entry.Version);
            WriteLeShort(entry.Flags);
            WriteLeShort((byte)method);
            WriteLeInt((int)entry.DosTime);
            if (headerInfoAvailable == true) {
                WriteLeInt((int)entry.Crc);
                WriteLeInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CRYPTO_HEADER_SIZE : (int)entry.CompressedSize);
                WriteLeInt((int)entry.Size);
            } else {
                if (patchEntryHeader == true) {
                    headerPatchPos = baseOutputStream.Position;
                }
                WriteLeInt(0);	// Crc
                WriteLeInt(0);	// Compressed size
                WriteLeInt(0);	// Uncompressed size
            }

            byte[] name = ZipConstants.ConvertToArray(entry.Name);

            if (name.Length > 0xFFFF) {
                throw new ZipException("Entry name too long.");
            }

            byte[] extra = entry.ExtraData;
            if (extra == null) {
                extra = new byte[0];
            }

            if (extra.Length > 0xFFFF) {
                throw new ZipException("Extra data too long.");
            }

            WriteLeShort(name.Length);
            WriteLeShort(extra.Length);
            baseOutputStream.Write(name, 0, name.Length);
            baseOutputStream.Write(extra, 0, extra.Length);

            offset += ZipConstants.LOCHDR + name.Length + extra.Length;

            // Activate the entry.
            curEntry = entry;
            crc.Reset();
            if (method == CompressionMethod.Deflated) {
                def.Reset();
                def.SetLevel(compressionLevel);
            }
            size = 0;

            if (entry.IsCrypted == true) {
                if (entry.Crc < 0) {			// so testing Zip will says its ok
                    WriteEncryptionHeader(entry.DosTime << 16);
                } else {
                    WriteEncryptionHeader(entry.Crc);
                }
            }
        }
コード例 #2
0
ファイル: ZipEntry.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Creates a copy of the given zip entry.
        /// </summary>
        /// <param name="e">
        /// The entry to copy.
        /// </param>
        public ZipEntry(ZipEntry e)
        {
            known                  = e.known;
            name                   = e.name;
            size                   = e.size;
            compressedSize         = e.compressedSize;
            crc                    = e.crc;
            dosTime                = e.dosTime;
            method                 = e.method;
            ExtraData              = e.ExtraData;     // Note use of property ensuring data is unique
            comment                = e.comment;
            versionToExtract       = e.versionToExtract;
            versionMadeBy          = e.versionMadeBy;
            externalFileAttributes = e.externalFileAttributes;
            flags                  = e.flags;

            zipFileIndex           = -1;
            offset                 = 0;
        }
コード例 #3
0
ファイル: ZipOutputStream.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Closes the current entry, updating header and footer information as required
        /// </summary>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurs.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// No entry is active.
        /// </exception>
        public void CloseEntry()
        {
            if (curEntry == null) {
                throw new InvalidOperationException("No open entry");
            }

            // First finish the deflater, if appropriate
            if (curMethod == CompressionMethod.Deflated) {
                base.Finish();
            }

            long csize = curMethod == CompressionMethod.Deflated ? def.TotalOut : size;

            if (curEntry.Size < 0) {
                curEntry.Size = size;
            } else if (curEntry.Size != size) {
                throw new ZipException("size was " + size + ", but I expected " + curEntry.Size);
            }

            if (curEntry.CompressedSize < 0) {
                curEntry.CompressedSize = csize;
            } else if (curEntry.CompressedSize != csize) {
                throw new ZipException("compressed size was " + csize + ", but I expected " + curEntry.CompressedSize);
            }

            if (curEntry.Crc < 0) {
                curEntry.Crc = crc.Value;
            } else if (curEntry.Crc != crc.Value) {
                throw new ZipException("crc was " + crc.Value +	", but I expected " + curEntry.Crc);
            }

            offset += csize;

            if (offset > 0xffffffff) {
                throw new ZipException("Maximum Zip file size exceeded");
            }

            if (curEntry.IsCrypted == true) {
                curEntry.CompressedSize += ZipConstants.CRYPTO_HEADER_SIZE;
            }

            // Patch the header if possible
            if (patchEntryHeader == true) {
                long curPos = baseOutputStream.Position;
                baseOutputStream.Seek(headerPatchPos, SeekOrigin.Begin);
                WriteLeInt((int)curEntry.Crc);
                WriteLeInt((int)curEntry.CompressedSize);
                WriteLeInt((int)curEntry.Size);
                baseOutputStream.Seek(curPos, SeekOrigin.Begin);
                patchEntryHeader = false;
            }

            // Add data descriptor if flagged as required
            if ((curEntry.Flags & 8) != 0) {
                WriteLeInt(ZipConstants.EXTSIG);
                WriteLeInt((int)curEntry.Crc);
                WriteLeInt((int)curEntry.CompressedSize);
                WriteLeInt((int)curEntry.Size);
                offset += ZipConstants.EXTHDR;
            }

            entries.Add(curEntry);
            curEntry = null;
        }
コード例 #4
0
ファイル: ZipInputStream.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Advances to the next entry in the archive
        /// </summary>
        /// <returns>
        /// The next <see cref="ZipEntry">entry</see> in the archive or null if there are no more entries.
        /// </returns>
        /// <remarks>
        /// If the previous entry is still open <see cref="CloseEntry">CloseEntry</see> is called.
        /// </remarks>
        /// <exception cref="InvalidOperationException">
        /// Input stream is closed
        /// </exception>
        /// <exception cref="ZipException">
        /// Password is not set, password is invalid, compression method is invalid, 
        /// version required to extract is not supported
        /// </exception>
        public ZipEntry GetNextEntry()
        {
            if (crc == null) {
                throw new InvalidOperationException("Closed.");
            }

            if (entry != null) {
                CloseEntry();
            }

            if (this.cryptbuffer != null) {

                if (avail == 0 && inf.RemainingInput != 0) {
                    avail = inf.RemainingInput - 16;
                    inf.Reset();
                }
                baseInputStream.Position -= this.len;
                baseInputStream.Read(this.buf, 0, this.len);

            }

            if (avail <= 0) {
                FillBuf(ZipConstants.LOCHDR);
            }

            int header = ReadLeInt();

            if (header == ZipConstants.CENSIG ||
                header == ZipConstants.ENDSIG ||
                header == ZipConstants.CENDIGITALSIG ||
                header == ZipConstants.CENSIG64) {
                // No more individual entries exist
                Close();
                return null;
            }

            // -jr- 07-Dec-2003 Ignore spanning temporary signatures if found
            // SPANNINGSIG is same as descriptor signature and is untested as yet.
            if (header == ZipConstants.SPANTEMPSIG || header == ZipConstants.SPANNINGSIG) {
                header = ReadLeInt();
            }

            if (header != ZipConstants.LOCSIG) {
                throw new ZipException("Wrong Local header signature: 0x" + String.Format("{0:X}", header));
            }

            short versionRequiredToExtract = (short)ReadLeShort();

            flags          = ReadLeShort();
            method         = ReadLeShort();
            uint dostime   = (uint)ReadLeInt();
            int crc2       = ReadLeInt();
            csize          = ReadLeInt();
            size           = ReadLeInt();
            int nameLen    = ReadLeShort();
            int extraLen   = ReadLeShort();

            bool isCrypted = (flags & 1) == 1;

            byte[] buffer = new byte[nameLen];
            ReadFully(buffer);

            string name = ZipConstants.ConvertToString(buffer);

            entry = new ZipEntry(name, versionRequiredToExtract);
            entry.Flags = flags;

            if (method == (int)CompressionMethod.Stored && (!isCrypted && csize != size || (isCrypted && csize - ZipConstants.CRYPTO_HEADER_SIZE != size))) {
                throw new ZipException("Stored, but compressed != uncompressed");
            }

            if (method != (int)CompressionMethod.Stored && method != (int)CompressionMethod.Deflated) {
                throw new ZipException("unknown compression method " + method);
            }

            entry.CompressionMethod = (CompressionMethod)method;

            if ((flags & 8) == 0) {
                entry.Crc  = crc2 & 0xFFFFFFFFL;
                entry.Size = size & 0xFFFFFFFFL;
                entry.CompressedSize = csize & 0xFFFFFFFFL;
                BufferReadSize = 0;
            } else {

                if (isCrypted) {
                    BufferReadSize = 1;
                } else {
                    BufferReadSize = 0;
                }

                // This allows for GNU, WinZip and possibly other archives, the PKZIP spec says these are zero
                // under these circumstances.
                if (crc2 != 0) {
                    entry.Crc = crc2 & 0xFFFFFFFFL;
                }

                if (size != 0) {
                    entry.Size = size & 0xFFFFFFFFL;
                }
                if (csize != 0) {
                    entry.CompressedSize = csize & 0xFFFFFFFFL;
                }
            }

            entry.DosTime = dostime;

            if (extraLen > 0) {
                byte[] extra = new byte[extraLen];
                ReadFully(extra);
                entry.ExtraData = extra;
            }

            // TODO How to handle this?
            // This library cannot handle versions greater than 20
            // Throwing an exception precludes getting at later possibly useable entries.
            // Could also skip this entry entirely
            // Letting it slip past here isnt so great as it wont work
            if (versionRequiredToExtract > 20) {
                throw new ZipException("Libray cannot extract this entry version required (" + versionRequiredToExtract.ToString() + ")");
            }

            // test for encryption
            if (isCrypted) {
                if (password == null) {
                    throw new ZipException("No password set.");
                }
                InitializePassword(password);
                cryptbuffer = new byte[ZipConstants.CRYPTO_HEADER_SIZE];
                ReadFully(cryptbuffer);
                DecryptBlock(cryptbuffer, 0, cryptbuffer.Length);

                if ((flags & 8) == 0) {
                    if (cryptbuffer[ZipConstants.CRYPTO_HEADER_SIZE - 1] != (byte)(crc2 >> 24)) {
                        throw new ZipException("Invalid password");
                    }
                }
                else {
                    if (cryptbuffer[ZipConstants.CRYPTO_HEADER_SIZE - 1] != (byte)((dostime >> 8) & 0xff)) {
                        throw new ZipException("Invalid password");
                    }
                }

                if (csize >= ZipConstants.CRYPTO_HEADER_SIZE) {
                    csize -= ZipConstants.CRYPTO_HEADER_SIZE;
                }
            } else {
                cryptbuffer = null;
            }

            if (method == (int)CompressionMethod.Deflated && avail > 0) {
                System.Array.Copy(buf, len - (int)avail, buf, 0, (int)avail);
                len = (int)avail;
                avail = 0;
                if (isCrypted) {
                    DecryptBlock(buf, 0, Math.Min((int)csize, len));
                }
                inf.SetInput(buf, 0, len);
            }

            return entry;
        }
コード例 #5
0
ファイル: ZipInputStream.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Reads a block of bytes from the current zip entry.
        /// </summary>
        /// <returns>
        /// The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream.
        /// </returns>
        /// <exception name="IOException">
        /// An i/o error occured.
        /// </exception>
        /// <exception cref="ZipException">
        /// The deflated stream is corrupted.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// The stream is not open.
        /// </exception>
        public override int Read(byte[] b, int off, int len)
        {
            if (crc == null) {
                throw new InvalidOperationException("Closed.");
            }

            if (entry == null) {
                return 0;
            }

            bool finished = false;

            switch (method) {
                case (int)CompressionMethod.Deflated:
                    len = base.Read(b, off, len);
                    if (len <= 0) {
                        if (!inf.IsFinished) {
                            throw new ZipException("Inflater not finished!?");
                        }
                        avail = inf.RemainingInput;

                        if ((flags & 8) == 0 && (inf.TotalIn != csize || inf.TotalOut != size)) {
                            throw new ZipException("size mismatch: " + csize + ";" + size + " <-> " + inf.TotalIn + ";" + inf.TotalOut);
                        }
                        inf.Reset();
                        finished = true;
                    }
                    break;

                case (int)CompressionMethod.Stored:
                    if (len > csize && csize >= 0) {
                        len = (int)csize;
                    }
                    len = ReadBuf(b, off, len);
                    if (len > 0) {
                        csize -= len;
                        size -= len;
                    }

                    if (csize == 0) {
                        finished = true;
                    } else {
                        if (len < 0) {
                            throw new ZipException("EOF in stored block");
                        }
                    }

                    // cipher text needs decrypting
                    if (cryptbuffer != null) {
                        DecryptBlock(b, off, len);
                    }

                    break;
            }

            if (len > 0) {
                crc.Update(b, off, len);
            }

            if (finished) {
                StopDecrypting();
                if ((flags & 8) != 0) {
                    ReadDataDescriptor();
                }

                if ((crc.Value & 0xFFFFFFFFL) != entry.Crc && entry.Crc != -1) {
                    throw new ZipException("CRC mismatch");
                }
                crc.Reset();
                entry = null;
            }
            return len;
        }
コード例 #6
0
ファイル: ZipInputStream.cs プロジェクト: plamikcho/xbrlpoc
 /// <summary>
 /// Closes the zip input stream
 /// </summary>
 public override void Close()
 {
     base.Close();
     crc = null;
     entry = null;
 }
コード例 #7
0
ファイル: ZipInputStream.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Closes the current zip entry and moves to the next one.
        /// </summary>
        /// <exception cref="InvalidOperationException">
        /// The stream is closed
        /// </exception>
        /// <exception cref="ZipException">
        /// The Zip stream ends early
        /// </exception>
        public void CloseEntry()
        {
            if (crc == null) {
                throw new InvalidOperationException("Closed.");
            }

            if (entry == null) {
                return;
            }

            if (method == (int)CompressionMethod.Deflated) {
                if ((flags & 8) != 0) {
                    // We don't know how much we must skip, read until end.
                    byte[] tmp = new byte[2048];
                    while (Read(tmp, 0, tmp.Length) > 0)
                        ;
                    // read will close this entry
                    return;
                }
                csize -= inf.TotalIn;
                avail = inf.RemainingInput;
            }

            if (avail > csize && csize >= 0) {
                avail -= csize;
            } else {
                csize -= avail;
                avail = 0;
                while (csize != 0) {
                    int skipped = (int)base.Skip(csize & 0xFFFFFFFFL);

                    if (skipped <= 0) {
                        throw new ZipException("Zip archive ends early.");
                    }

                    csize -= skipped;
                }
            }

            size = 0;
            crc.Reset();
            if (method == (int)CompressionMethod.Deflated) {
                inf.Reset();
            }
            entry = null;
        }
コード例 #8
0
ファイル: ZipFile.cs プロジェクト: plamikcho/xbrlpoc
 public ZipEntryEnumeration(ZipEntry[] arr)
 {
     array = arr;
 }
コード例 #9
0
ファイル: ZIPUtilities.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Zips and compresses files.
        /// You should give the full path for the zipFileName.
        /// You should give the full path for the rootDirectoryName.
        /// You should give relative path for the names of the files to zip. Relative to the root
        ///		Example: ZipCompressUtility.TryZipAndCompressFiles( "C:\Aucent\Folio1.zip",
        ///						"C:\DirectoryWithHtmlFiles\Folio1",
        ///						new string[]{"index.html", "DependentHoppers\hopper.html"} );
        /// </summary>
        /// <param name="zipFileName">Set to the name that you want the zip file to be. (e.g. C:\Aucent\SalesFolio.zip)</param>
        /// <param name="rootDirectoryName">The root directory to start looking for files and directories in.</param>
        /// <param name="filesToZip">List of all the files you want to zip.</param>
        /// <returns></returns>
        public static bool TryZipAndCompressFiles(string zipFileName, string rootDirectoryName, string[] filesToZip)
        {
            bool ok = false;
            using (ZipOutputStream s = new ZipOutputStream(File.Create(zipFileName)))
            {
                try
                {
                    if (rootDirectoryName[rootDirectoryName.Length - 1] != Path.DirectorySeparatorChar)
                    {
                        // append directory separator char
                        rootDirectoryName += Path.DirectorySeparatorChar;
                    }

                    s.SetLevel(9); // 0 - store only to 9 - means best compression

                    if (filesToZip != null)
                    {
                        foreach (string file in filesToZip)
                        {
                            byte[] buffer = FileUtilities.ReadFileToByteArray(rootDirectoryName + file);
                            if (buffer != null)
                            {
                                ZipEntry entry = new ZipEntry(file);
                                s.PutNextEntry(entry);
                                s.Write(buffer, 0, buffer.Length);
                            }
                        }
                    }

                    ok = true;
                }
                catch
                {
                    ok = false;
                }
            }
            return ok;
        }
コード例 #10
0
ファイル: ZipFile.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Search for and read the central directory of a zip file filling the entries
        /// array.  This is called exactly once by the constructors.
        /// </summary>
        /// <exception cref="System.IO.IOException">
        /// An i/o error occurs.
        /// </exception>
        /// <exception cref="Aucent.MAX.AXE.Common.ZipCompressDecompress.Zip.ZipException">
        /// The central directory is malformed or cannot be found
        /// </exception>
        void ReadEntries()
        {
            // Search for the End Of Central Directory.  When a zip comment is
            // present the directory may start earlier.
            //
            // TODO: The search is limited to 64K which is the maximum size of a trailing comment field to aid speed.
            // This should be compatible with both SFX and ZIP files but has only been tested for Zip files
            // Need to confirm this is valid in all cases.
            // Could also speed this up by reading memory in larger blocks?

            if (baseStream.CanSeek == false) {
                throw new ZipException("ZipFile stream must be seekable");
            }

            long pos = baseStream.Length - ZipConstants.ENDHDR;
            if (pos <= 0) {
                throw new ZipException("File is too small to be a Zip file");
            }

            long giveUpMarker = Math.Max(pos - 0x10000, 0);

            do {
                if (pos < giveUpMarker) {
                    throw new ZipException("central directory not found, probably not a zip file");
                }
                baseStream.Seek(pos--, SeekOrigin.Begin);
            } while (ReadLeInt() != ZipConstants.ENDSIG);

            int thisDiskNumber            = ReadLeShort();
            int startCentralDirDisk       = ReadLeShort();
            int entriesForThisDisk        = ReadLeShort();
            int entriesForWholeCentralDir = ReadLeShort();
            int centralDirSize            = ReadLeInt();
            int offsetOfCentralDir        = ReadLeInt();
            int commentSize               = ReadLeShort();

            byte[] zipComment = new byte[commentSize];
            baseStream.Read(zipComment, 0, zipComment.Length);
            comment = ZipConstants.ConvertToString(zipComment);

            /* Its seems possible that this is too strict, more digging required.
            if (thisDiskNumber != 0 || startCentralDirDisk != 0 || entriesForThisDisk != entriesForWholeCentralDir) {
                throw new ZipException("Spanned archives are not currently handled");
            }
            */

            entries = new ZipEntry[entriesForWholeCentralDir];
            baseStream.Seek(offsetOfCentralDir, SeekOrigin.Begin);

            for (int i = 0; i < entriesForWholeCentralDir; i++) {
                if (ReadLeInt() != ZipConstants.CENSIG) {
                    throw new ZipException("Wrong Central Directory signature");
                }

                int versionMadeBy      = ReadLeShort();
                int versionToExtract   = ReadLeShort();
                int bitFlags           = ReadLeShort();
                int method             = ReadLeShort();
                int dostime            = ReadLeInt();
                int crc                = ReadLeInt();
                int csize              = ReadLeInt();
                int size               = ReadLeInt();
                int nameLen            = ReadLeShort();
                int extraLen           = ReadLeShort();
                int commentLen         = ReadLeShort();

                int diskStartNo        = ReadLeShort();  // Not currently used
                int internalAttributes = ReadLeShort();  // Not currently used

                int externalAttributes = ReadLeInt();
                int offset             = ReadLeInt();

                byte[] buffer = new byte[Math.Max(nameLen, commentLen)];

                baseStream.Read(buffer, 0, nameLen);
                string name = ZipConstants.ConvertToString(buffer, nameLen);

                ZipEntry entry = new ZipEntry(name, versionToExtract, versionMadeBy);
                entry.CompressionMethod = (CompressionMethod)method;
                entry.Crc = crc & 0xffffffffL;
                entry.Size = size & 0xffffffffL;
                entry.CompressedSize = csize & 0xffffffffL;
                entry.Flags = bitFlags;
                entry.DosTime = (uint)dostime;

                if (extraLen > 0) {
                    byte[] extra = new byte[extraLen];
                    baseStream.Read(extra, 0, extraLen);
                    entry.ExtraData = extra;
                }

                if (commentLen > 0) {
                    baseStream.Read(buffer, 0, commentLen);
                    entry.Comment = ZipConstants.ConvertToString(buffer, commentLen);
                }

                entry.ZipFileIndex           = i;
                entry.Offset                 = offset;
                entry.ExternalFileAttributes = externalAttributes;

                entries[i] = entry;
            }
        }
コード例 #11
0
ファイル: ZipFile.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Checks, if the local header of the entry at index i matches the
        /// central directory, and returns the offset to the data.
        /// </summary>
        /// <returns>
        /// The start offset of the (compressed) data.
        /// </returns>
        /// <exception cref="System.IO.EndOfStreamException">
        /// The stream ends prematurely
        /// </exception>
        /// <exception cref="Aucent.MAX.AXE.Common.ZipCompressDecompress.Zip.ZipException">
        /// The local header signature is invalid, the entry and central header file name lengths are different
        /// or the local and entry compression methods dont match
        /// </exception>
        long CheckLocalHeader(ZipEntry entry)
        {
            lock(baseStream) {
                baseStream.Seek(entry.Offset, SeekOrigin.Begin);
                if (ReadLeInt() != ZipConstants.LOCSIG) {
                    throw new ZipException("Wrong Local header signature");
                }

                short shortValue = (short)ReadLeShort();     // version required to extract
                if (shortValue > ZipConstants.VERSION_MADE_BY) {
                    throw new ZipException(string.Format("Version required to extract this entry not supported ({0})", shortValue));
                }

                shortValue = (short)ReadLeShort();                  // general purpose bit flags.
                if ((shortValue & 0x30) != 0) {
                    throw new ZipException("The library doesnt support the zip version required to extract this entry");
                }

                if (entry.CompressionMethod != (CompressionMethod)ReadLeShort()) {
                    throw new ZipException("Compression method mismatch");
                }

                // Skip time, crc, size and csize
                long oldPos = baseStream.Position;
                baseStream.Position += ZipConstants.LOCNAM - ZipConstants.LOCTIM;

                if (baseStream.Position - oldPos != ZipConstants.LOCNAM - ZipConstants.LOCTIM) {
                    throw new ZipException("End of stream");
                }

                // TODO make test more correct...  cant compare lengths as was done originally as this can fail for MBCS strings
                int storedNameLength = ReadLeShort();
                if (entry.Name.Length > storedNameLength) {
                    throw new ZipException("file name length mismatch");
                }

                int extraLen = storedNameLength + ReadLeShort();
                return entry.Offset + ZipConstants.LOCHDR + extraLen;
            }
        }
コード例 #12
0
ファイル: ZipFile.cs プロジェクト: plamikcho/xbrlpoc
        /// <summary>
        /// Creates an input stream reading the given zip entry as
        /// uncompressed data.  Normally zip entry should be an entry
        /// returned by GetEntry().
        /// </summary>
        /// <returns>
        /// the input stream.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// The ZipFile has already been closed
        /// </exception>
        /// <exception cref="Aucent.MAX.AXE.Common.ZipCompressDecompress.Zip.ZipException">
        /// The compression method for the entry is unknown
        /// </exception>
        /// <exception cref="IndexOutOfRangeException">
        /// The entry is not found in the ZipFile
        /// </exception>
        public Stream GetInputStream(ZipEntry entry)
        {
            if (entries == null) {
                throw new InvalidOperationException("ZipFile has closed");
            }

            int index = entry.ZipFileIndex;
            if (index < 0 || index >= entries.Length || entries[index].Name != entry.Name) {
                index = FindEntry(entry.Name, true);
                if (index < 0) {
                    throw new IndexOutOfRangeException();
                }
            }
            return GetInputStream(index);
        }
コード例 #13
0
        /// <summary>
        /// Search for and read the central directory of a zip file filling the entries
        /// array.  This is called exactly once by the constructors.
        /// </summary>
        /// <exception cref="System.IO.IOException">
        /// An i/o error occurs.
        /// </exception>
        /// <exception cref="Aucent.MAX.AXE.Common.ZipCompressDecompress.Zip.ZipException">
        /// The central directory is malformed or cannot be found
        /// </exception>
        void ReadEntries()
        {
            // Search for the End Of Central Directory.  When a zip comment is
            // present the directory may start earlier.
            //
            // TODO: The search is limited to 64K which is the maximum size of a trailing comment field to aid speed.
            // This should be compatible with both SFX and ZIP files but has only been tested for Zip files
            // Need to confirm this is valid in all cases.
            // Could also speed this up by reading memory in larger blocks?


            if (baseStream.CanSeek == false)
            {
                throw new ZipException("ZipFile stream must be seekable");
            }

            long pos = baseStream.Length - ZipConstants.ENDHDR;

            if (pos <= 0)
            {
                throw new ZipException("File is too small to be a Zip file");
            }

            long giveUpMarker = Math.Max(pos - 0x10000, 0);

            do
            {
                if (pos < giveUpMarker)
                {
                    throw new ZipException("central directory not found, probably not a zip file");
                }
                baseStream.Seek(pos--, SeekOrigin.Begin);
            } while (ReadLeInt() != ZipConstants.ENDSIG);

            int thisDiskNumber            = ReadLeShort();
            int startCentralDirDisk       = ReadLeShort();
            int entriesForThisDisk        = ReadLeShort();
            int entriesForWholeCentralDir = ReadLeShort();
            int centralDirSize            = ReadLeInt();
            int offsetOfCentralDir        = ReadLeInt();
            int commentSize = ReadLeShort();

            byte[] zipComment = new byte[commentSize];
            baseStream.Read(zipComment, 0, zipComment.Length);
            comment = ZipConstants.ConvertToString(zipComment);

/* Its seems possible that this is too strict, more digging required.
 *                      if (thisDiskNumber != 0 || startCentralDirDisk != 0 || entriesForThisDisk != entriesForWholeCentralDir) {
 *                              throw new ZipException("Spanned archives are not currently handled");
 *                      }
 */

            entries = new ZipEntry[entriesForWholeCentralDir];
            baseStream.Seek(offsetOfCentralDir, SeekOrigin.Begin);

            for (int i = 0; i < entriesForWholeCentralDir; i++)
            {
                if (ReadLeInt() != ZipConstants.CENSIG)
                {
                    throw new ZipException("Wrong Central Directory signature");
                }

                int versionMadeBy    = ReadLeShort();
                int versionToExtract = ReadLeShort();
                int bitFlags         = ReadLeShort();
                int method           = ReadLeShort();
                int dostime          = ReadLeInt();
                int crc        = ReadLeInt();
                int csize      = ReadLeInt();
                int size       = ReadLeInt();
                int nameLen    = ReadLeShort();
                int extraLen   = ReadLeShort();
                int commentLen = ReadLeShort();

                int diskStartNo        = ReadLeShort();                  // Not currently used
                int internalAttributes = ReadLeShort();                  // Not currently used

                int externalAttributes = ReadLeInt();
                int offset             = ReadLeInt();

                byte[] buffer = new byte[Math.Max(nameLen, commentLen)];

                baseStream.Read(buffer, 0, nameLen);
                string name = ZipConstants.ConvertToString(buffer, nameLen);

                ZipEntry entry = new ZipEntry(name, versionToExtract, versionMadeBy);
                entry.CompressionMethod = (CompressionMethod)method;
                entry.Crc            = crc & 0xffffffffL;
                entry.Size           = size & 0xffffffffL;
                entry.CompressedSize = csize & 0xffffffffL;
                entry.Flags          = bitFlags;
                entry.DosTime        = (uint)dostime;

                if (extraLen > 0)
                {
                    byte[] extra = new byte[extraLen];
                    baseStream.Read(extra, 0, extraLen);
                    entry.ExtraData = extra;
                }

                if (commentLen > 0)
                {
                    baseStream.Read(buffer, 0, commentLen);
                    entry.Comment = ZipConstants.ConvertToString(buffer, commentLen);
                }

                entry.ZipFileIndex           = i;
                entry.Offset                 = offset;
                entry.ExternalFileAttributes = externalAttributes;

                entries[i] = entry;
            }
        }
コード例 #14
0
ファイル: ZipFileInfo.cs プロジェクト: plamikcho/xbrlpoc
 /// <summary>
 /// Creates a new <see cref="ZipFileInfo"/> instance with the given zip
 /// entry as the base.
 /// </summary>
 /// <param name="zip">The base <see cref="ZipEntry"/> upon which to
 /// create an instance.</param>
 public ZipFileInfo( ZipEntry zip )
 {
     this._length = zip.Size;
     this.Name = zip.Name;
 }