Ejemplo n.º 1
0
        private void UpdateCrcAndSizes(ref ZipFileEntry _zfe)
        {
            /* CRC32 algorithm
            The 'magic number' for the CRC is 0xdebb20e3.
            The proper CRC pre and post conditioning
            is used, meaning that the CRC register is
            pre-conditioned with all ones (a starting value
            of 0xffffffff) and the value is post-conditioned by
            taking the one's complement of the CRC residual.
            If bit 3 of the general purpose flag is set, this
            field is set to zero in the local header and the correct
            value is put in the data descriptor and in the central
            directory.
            */
            long lastPos = this.ZipFileStream.Position;

            this.ZipFileStream.Position = _zfe.HeaderOffset + 8;
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2);

            this.ZipFileStream.Position = _zfe.HeaderOffset + 14;
            this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.Crc32), 0, 4);
            this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.CompressedSize), 0, 4);
            this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.FileSize), 0, 4);

            this.ZipFileStream.Position = lastPos;
        }
Ejemplo n.º 2
0
 public void DisposeStream(ZipFileEntry _zfe, Stream s)
 {
     if (_zfe.Method == Compression.Deflate) s.Dispose();
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Copy the contents of a stored file into a physical file.
        /// </summary>
        /// <param name="zipFileEntry">Entry information of file to extract.</param>
        /// <param name="destinationFileName">Name of file to store uncompressed data.</param>
        /// <returns><see langword="true"/> if the file is successfully extracted; otherwise, <see langword="false"/>.</returns>
        /// <remarks>Unique compression methods are Store and Deflate.</remarks>
        public bool ExtractFile(ZipFileEntry zipFileEntry, string destinationFileName)
        {
            // Make sure the parent directory exist
            string path = System.IO.Path.GetDirectoryName(destinationFileName);

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            // Check it is directory. If so, do nothing
            if (Directory.Exists(destinationFileName))
            {
                return true;
            }

            bool result = false;
            using (Stream output = new FileStream(destinationFileName, FileMode.Create, FileAccess.Write))
            {
                result = this.ExtractFile(zipFileEntry, output);
            }

            File.SetCreationTime(destinationFileName, zipFileEntry.ModifyTime);
            File.SetLastWriteTime(destinationFileName, zipFileEntry.ModifyTime);

            return result;
        }
Ejemplo n.º 4
0
 public bool ExtractFile(ZipFileEntry _zfe, Stream _stream)
 {
     return ExtractFile(_zfe, _stream, 0);
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Copy the contents of a stored file into a physical file
        /// </summary>
        /// <param name="zfe">Entry information of file to extract</param>
        /// <param name="targetFileName">Name of file to store uncompressed data</param>
        /// <returns>True if success, false if not.</returns>
        /// <remarks>Unique compression methods are Store and Deflate</remarks>
        public bool ExtractFile( ZipFileEntry zfe, [NotNull] string targetFileName ) {
            if( fileName == null ) throw new ArgumentNullException( "targetFileName" );
            // Make sure the parent directory exist
            string path = Path.GetDirectoryName( fileName );
            if( path == null ) throw new NotImplementedException();

            if( !Directory.Exists( path ) ) {
                Directory.CreateDirectory( path );
            }
            // Check it is directory. If so, do nothing
            if( Directory.Exists( fileName ) ) {
                return true;
            }

            Stream output = new FileStream( fileName, FileMode.Create, FileAccess.Write );
            bool result = ExtractFile( zfe, output );
            if( result )
                output.Close();

            File.SetCreationTime( fileName, zfe.ModifyTime );
            File.SetLastWriteTime( fileName, zfe.ModifyTime );

            return result;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Copy the contents of a stored file into an opened stream
        /// </summary>
        /// <param name="_zfe">Entry information of file to extract</param>
        /// <param name="_stream">Stream to store the uncompressed data</param>
        /// <returns>True if success, false if not.</returns>
        /// <remarks>Unique compression methods are Store and Deflate</remarks>
        public bool ExtractFile(ZipFileEntry _zfe, Stream _stream)
        {
            if (!_stream.CanWrite)
                 throw new InvalidOperationException("Stream cannot be written");

             // check signature
             byte[] signature = new byte[4];
             this.ZipFileStream.Seek(_zfe.HeaderOffset, SeekOrigin.Begin);
             this.ZipFileStream.Read(signature, 0, 4);
             if (BitConverter.ToUInt32(signature, 0) != 0x04034b50)
                 return false;

             // Select input stream for inflating or just reading
             Stream inStream;
             if (_zfe.Method == Compression.Store)
                 inStream = this.ZipFileStream;
             else if (_zfe.Method == Compression.Deflate)
                 inStream = new DeflateStream(this.ZipFileStream, CompressionMode.Decompress, true);
             else
                 return false;

             // Buffered copy
             byte[] buffer = new byte[16384];
             this.ZipFileStream.Seek(_zfe.FileOffset, SeekOrigin.Begin);
             uint bytesPending = _zfe.FileSize;
             while (bytesPending > 0)
             {
                 int bytesRead = inStream.Read(buffer, 0, (int)Math.Min(bytesPending, buffer.Length));
                 _stream.Write(buffer, 0, bytesRead);
                 bytesPending -= (uint)bytesRead;
             }
             _stream.Flush();

             if (_zfe.Method == Compression.Deflate)
                 inStream.Dispose();
             return true;
        }
Ejemplo n.º 7
0
        /* Central directory's File header:
             central file header signature   4 bytes  (0x02014b50)
             version made by                 2 bytes
             version needed to extract       2 bytes
             general purpose bit flag        2 bytes
             compression method              2 bytes
             last mod file time              2 bytes
             last mod file date              2 bytes
             crc-32                          4 bytes
             compressed size                 4 bytes
             uncompressed size               4 bytes
             filename length                 2 bytes
             extra field length              2 bytes
             file comment length             2 bytes
             disk number start               2 bytes
             internal file attributes        2 bytes
             external file attributes        4 bytes
             relative offset of local header 4 bytes

             filename (variable size)
             extra field (variable size)
             file comment (variable size)
         */
        private void WriteCentralDirRecord(ZipFileEntry _zfe)
        {
            Encoding encoder = _zfe.EncodeUTF8 ? Encoding.UTF8 : DefaultEncoding;
             byte[] encodedFilename = encoder.GetBytes(_zfe.FilenameInZip);
             byte[] encodedComment = encoder.GetBytes(_zfe.Comment);

             this.ZipFileStream.Write(new byte[] { 80, 75, 1, 2, 23, 0xB, 20, 0 }, 0, 8);
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)(_zfe.EncodeUTF8 ? 0x0800 : 0)), 0, 2); // filename and comment encoding
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2);  // zipping method
             this.ZipFileStream.Write(BitConverter.GetBytes(DateTimeToDosTime(_zfe.ModifyTime)), 0, 4);  // zipping date and time
             this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.Crc32), 0, 4); // file CRC
             this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.CompressedSize), 0, 4); // compressed file size
             this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.FileSize), 0, 4); // uncompressed file size
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedFilename.Length), 0, 2); // Filename in zip
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // extra length
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedComment.Length), 0, 2);

             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // disk=0
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // file type: binary
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // Internal file attributes
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0x8100), 0, 2); // External file attributes (normal/readable)
             this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.HeaderOffset), 0, 4);  // Offset of header

             this.ZipFileStream.Write(encodedFilename, 0, encodedFilename.Length);
             this.ZipFileStream.Write(encodedComment, 0, encodedComment.Length);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Read all the file records in the central directory
        /// </summary>
        /// <returns>List of all entries in directory</returns>
        private IEnumerable <ZipFileEntry> ReadCentralDir()
        {
            if (CentralDirImage == null)
            {
                throw new InvalidOperationException("Central directory currently does not exist");
            }

            for (int pointer = 0; pointer < CentralDirImage.Length;)
            {
                uint signature = BitConverter.ToUInt32(CentralDirImage, pointer);
                if (signature != 0x02014b50)
                {
                    CentralDirImage = null;
                    yield break;
                }

                bool   encodeUTF8   = (BitConverter.ToUInt16(CentralDirImage, pointer + 8) & 0x0800) != 0;
                ushort method       = BitConverter.ToUInt16(CentralDirImage, pointer + 10);
                uint   modifyTime   = BitConverter.ToUInt32(CentralDirImage, pointer + 12);
                uint   crc32        = BitConverter.ToUInt32(CentralDirImage, pointer + 16);
                ulong  comprSize    = BitConverter.ToUInt32(CentralDirImage, pointer + 20);
                ulong  fileSize     = BitConverter.ToUInt32(CentralDirImage, pointer + 24);
                ushort filenameSize = BitConverter.ToUInt16(CentralDirImage, pointer + 28);
                ushort extraSize    = BitConverter.ToUInt16(CentralDirImage, pointer + 30);
                ushort commentSize  = BitConverter.ToUInt16(CentralDirImage, pointer + 32);
                ulong  headerOffset = BitConverter.ToUInt32(CentralDirImage, pointer + 42);
                uint   headerSize   = (uint)(46 + filenameSize + extraSize + commentSize);

                Encoding encoder = encodeUTF8 ? Encoding.UTF8 : DefaultEncoding;

                if (extraSize >= 4)
                {
                    int extraPtr = pointer + 46 + filenameSize;
                    // Find ZIP64 extra field record
                    while (extraPtr < pointer + 46 + filenameSize + extraSize)
                    {
                        ushort headerId = BitConverter.ToUInt16(CentralDirImage, extraPtr);
                        ushort length   = BitConverter.ToUInt16(CentralDirImage, extraPtr + 2);
                        if (headerId == 1)
                        {
                            extraPtr += 4;
                            if (fileSize == 0xffffffff)
                            {
                                fileSize  = BitConverter.ToUInt64(CentralDirImage, extraPtr);
                                extraPtr += 8;
                            }
                            if (comprSize == 0xffffffff)
                            {
                                comprSize = BitConverter.ToUInt64(CentralDirImage, extraPtr);
                                extraPtr += 8;
                            }
                            if (headerOffset == 0xffffffff)
                            {
                                headerOffset = BitConverter.ToUInt64(CentralDirImage, extraPtr);
                                extraPtr    += 8;
                            }
                            break;
                        }
                        else
                        {
                            extraPtr += (4 + length);
                        }
                    }
                }

                ZipFileEntry zfe = new ZipFileEntry
                {
                    Method         = (Compression)method,
                    FilenameInZip  = encoder.GetString(CentralDirImage, pointer + 46, filenameSize),
                    FileSize       = fileSize,
                    CompressedSize = comprSize,
                    HeaderOffset   = headerOffset,
                    HeaderSize     = headerSize,
                    FileOffset     = GetFileOffset(headerOffset),
                    Crc32          = crc32,
                    ModifyTime     = DosTimeToDateTime(modifyTime) ?? DateTime.Now
                };

                if (commentSize > 0)
                {
                    zfe.Comment = encoder.GetString(CentralDirImage, pointer + 46 + filenameSize + extraSize, commentSize);
                }

                pointer += (46 + filenameSize + extraSize + commentSize);
                yield return(zfe);
            }

            CentralDirImage = null;
        }
Ejemplo n.º 9
0
        private void LoadHeader(ZipFileEntry entryHeader, Stream stream)
        {
            if (FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.Encrypted))
            {
                if (!entryHeader.IsDirectory && entryHeader.CompressedSize == 0 &&
                    FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.UsePostDataDescriptor))
                {
                    throw new NotSupportedException("SharpCompress cannot currently read non-seekable Zip Streams with encrypted data that has been written in a non-seekable manner.");
                }

                if (password == null)
                {
                    throw new CryptographicException("No password supplied for encrypted zip.");
                }

                entryHeader.Password = password;

                if (entryHeader.CompressionMethod == ZipCompressionMethod.WinzipAes)
                {
#if NO_CRYPTO
                    throw new NotSupportedException("Cannot decrypt Winzip AES with Silverlight or WP7.");
#else
                    ExtraData data = entryHeader.Extra.SingleOrDefault(x => x.Type == ExtraDataType.WinZipAes);
                    if (data != null)
                    {
                        var keySize = (WinzipAesKeySize)data.DataBytes[4];

                        var salt = new byte[WinzipAesEncryptionData.KeyLengthInBytes(keySize) / 2];
                        var passwordVerifyValue = new byte[2];
                        stream.Read(salt, 0, salt.Length);
                        stream.Read(passwordVerifyValue, 0, 2);
                        entryHeader.WinzipAesEncryptionData =
                            new WinzipAesEncryptionData(keySize, salt, passwordVerifyValue, password);

                        entryHeader.CompressedSize -= (uint)(salt.Length + 2);
                    }
#endif
                }
            }

            if (entryHeader.IsDirectory)
            {
                return;
            }

            //if (FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.UsePostDataDescriptor))
            //{
            //    entryHeader.PackedStream = new ReadOnlySubStream(stream);
            //}
            //else
            //{
            switch (mode)
            {
            case StreamingMode.Seekable:
            {
                entryHeader.DataStartPosition = stream.Position;
                stream.Position += entryHeader.CompressedSize;
                break;
            }

            case StreamingMode.Streaming:
            {
                entryHeader.PackedStream = stream;
                break;
            }

            default:
            {
                throw new InvalidFormatException("Invalid StreamingMode");
            }
            }

            //}
        }
Ejemplo n.º 10
0
        ExtractFileAsync(ZipFileEntry _zfe, Stream _stream)
        {
            if (!_stream.CanWrite)
            {
                throw new InvalidOperationException("Stream cannot be written");
            }

            // check signature
            byte[] signature = new byte[4];
            this.ZipFileStream.Seek(_zfe.HeaderOffset, SeekOrigin.Begin);

#if NOASYNC
            this.ZipFileStream.Read(signature, 0, 4);
#else
            await this.ZipFileStream.ReadAsync(signature, 0, 4);
#endif

            if (BitConverter.ToUInt32(signature, 0) != 0x04034b50)
            {
                return(false);
            }

            // Select input stream for inflating or just reading
            Stream inStream;

            if (_zfe.Method == Compression.Store)
            {
                inStream = this.ZipFileStream;
            }
            else if (_zfe.Method == Compression.Deflate)
            {
                inStream = new DeflateStream(this.ZipFileStream, CompressionMode.Decompress, true);
            }
            else
            {
                return(false);
            }

            // Buffered copy
            byte[] buffer = new byte[65535];
            this.ZipFileStream.Seek(_zfe.FileOffset, SeekOrigin.Begin);
            long bytesPending = _zfe.FileSize;

            while (bytesPending > 0)
            {
#if NOASYNC
                int bytesRead = inStream.Read(buffer, 0, (int)Math.Min(bytesPending, buffer.Length));
                _stream.Write(buffer, 0, bytesRead);
#else
                int bytesRead = await inStream.ReadAsync(buffer, 0, (int)Math.Min(bytesPending, buffer.Length));

                await _stream.WriteAsync(buffer, 0, bytesRead);
#endif

                bytesPending -= (uint)bytesRead;
            }
            _stream.Flush();

            if (_zfe.Method == Compression.Deflate)
            {
                inStream.Dispose();
            }

            return(true);
        }
Ejemplo n.º 11
0
        Store(ZipFileEntry _zfe, Stream _source)
        {
            byte[] buffer = new byte[16384];
            int    bytesRead;
            uint   totalRead = 0;
            Stream outStream;

            long posStart    = this.ZipFileStream.Position;
            long sourceStart = _source.CanSeek ? _source.Position : 0;

            if (_zfe.Method == Compression.Store)
            {
                outStream = this.ZipFileStream;
            }
            else
            {
                outStream = new DeflateStream(this.ZipFileStream, CompressionMode.Compress, true);
            }

            _zfe.Crc32 = 0 ^ 0xffffffff;

            do
            {
#if NOASYNC
                bytesRead = _source.Read(buffer, 0, buffer.Length);
                if (bytesRead > 0)
                {
                    outStream.Write(buffer, 0, bytesRead);
                }
#else
                bytesRead = await _source.ReadAsync(buffer, 0, buffer.Length);

                if (bytesRead > 0)
                {
                    await outStream.WriteAsync(buffer, 0, bytesRead);
                }
#endif

                for (uint i = 0; i < bytesRead; i++)
                {
                    _zfe.Crc32 = ZipStorer.CrcTable[(_zfe.Crc32 ^ buffer[i]) & 0xFF] ^ (_zfe.Crc32 >> 8);
                }

                totalRead += (uint)bytesRead;
            } while (bytesRead > 0);

            outStream.Flush();

            if (_zfe.Method == Compression.Deflate)
            {
                outStream.Dispose();
            }

            _zfe.Crc32         ^= 0xFFFFFFFF;
            _zfe.FileSize       = totalRead;
            _zfe.CompressedSize = (uint)(this.ZipFileStream.Position - posStart);

            // Verify for real compression
            if (_zfe.Method == Compression.Deflate && !this.ForceDeflating && _source.CanSeek && _zfe.CompressedSize > _zfe.FileSize)
            {
                // Start operation again with Store algorithm
                _zfe.Method = Compression.Store;
                this.ZipFileStream.Position = posStart;
                this.ZipFileStream.SetLength(posStart);
                _source.Position = sourceStart;

#if NOASYNC
                return(this.Store(_zfe, _source));
#else
                return(await this.Store(_zfe, _source));
#endif
            }

            return(_zfe.Method);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Read all the file records in the central directory
        /// </summary>
        /// <returns>List of all entries in directory</returns>
        public List <ZipFileEntry> ReadCentralDir()
        {
            if (this.CentralDirImage == null)
            {
                throw new InvalidOperationException("Central directory currently does not exist");
            }

            List <ZipFileEntry> result = new List <ZipFileEntry>();

            for (int pointer = 0; pointer < this.CentralDirImage.Length;)
            {
                uint signature = BitConverter.ToUInt32(CentralDirImage, pointer);
                if (signature != 0x02014b50)
                {
                    break;
                }

                bool     encodeUTF8   = (BitConverter.ToUInt16(CentralDirImage, pointer + 8) & 0x0800) != 0;
                ushort   method       = BitConverter.ToUInt16(CentralDirImage, pointer + 10);
                uint     modifyTime   = BitConverter.ToUInt32(CentralDirImage, pointer + 12);
                uint     crc32        = BitConverter.ToUInt32(CentralDirImage, pointer + 16);
                long     comprSize    = BitConverter.ToUInt32(CentralDirImage, pointer + 20);
                long     fileSize     = BitConverter.ToUInt32(CentralDirImage, pointer + 24);
                ushort   filenameSize = BitConverter.ToUInt16(CentralDirImage, pointer + 28);
                ushort   extraSize    = BitConverter.ToUInt16(CentralDirImage, pointer + 30);
                ushort   commentSize  = BitConverter.ToUInt16(CentralDirImage, pointer + 32);
                uint     headerOffset = BitConverter.ToUInt32(CentralDirImage, pointer + 42);
                uint     headerSize   = (uint)(46 + filenameSize + extraSize + commentSize);
                DateTime modifyTimeDT = DosTimeToDateTime(modifyTime) ?? DateTime.Now;

                Encoding encoder = encodeUTF8 ? Encoding.UTF8 : DefaultEncoding;

                ZipFileEntry zfe = new ZipFileEntry()
                {
                    Method         = (Compression)method,
                    FilenameInZip  = encoder.GetString(CentralDirImage, pointer + 46, filenameSize),
                    FileOffset     = GetFileOffset(headerOffset),
                    FileSize       = fileSize,
                    CompressedSize = comprSize,
                    HeaderOffset   = headerOffset,
                    HeaderSize     = headerSize,
                    Crc32          = crc32,
                    ModifyTime     = modifyTimeDT,
                    CreationTime   = modifyTimeDT,
                    AccessTime     = DateTime.Now,
                };

                if (commentSize > 0)
                {
                    zfe.Comment = encoder.GetString(CentralDirImage, pointer + 46 + filenameSize + extraSize, commentSize);
                }

                if (extraSize > 0)
                {
                    this.ReadExtraInfo(CentralDirImage, pointer + 46 + filenameSize, zfe);
                }

                result.Add(zfe);
                pointer += (46 + filenameSize + extraSize + commentSize);
            }

            return(result);
        }
Ejemplo n.º 13
0
        // Copies all source file into storage file
        void Store(ref ZipFileEntry zfe, [NotNull] Stream source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            while (true)
            {
                byte[] buffer = new byte[16384];
                int    bytesRead;
                uint   totalRead = 0;
                Stream outStream;

                long posStart    = zipFileStream.Position;
                long sourceStart = source.Position;

                if (zfe.Method == Compression.Store)
                {
                    outStream = zipFileStream;
                }
                else
                {
                    outStream = new DeflateStream(zipFileStream, CompressionMode.Compress, true);
                }

                zfe.Crc32 = 0 ^ 0xffffffff;

                do
                {
                    bytesRead  = source.Read(buffer, 0, buffer.Length);
                    totalRead += (uint)bytesRead;
                    if (bytesRead > 0)
                    {
                        outStream.Write(buffer, 0, bytesRead);

                        for (uint i = 0; i < bytesRead; i++)
                        {
                            zfe.Crc32 = CrcTable[(zfe.Crc32 ^ buffer[i]) & 0xFF] ^ (zfe.Crc32 >> 8);
                        }
                    }
                } while (bytesRead == buffer.Length);

                if (totalRead > 0)
                {
                    outStream.Flush(); // fix for "Internal error Flush" under Mono
                }

                if (zfe.Method == Compression.Deflate)
                {
                    outStream.Dispose();
                }

                zfe.Crc32         ^= 0xffffffff;
                zfe.FileSize       = totalRead;
                zfe.CompressedSize = (uint)(zipFileStream.Position - posStart);

                // Verify for real compression
                if (zfe.Method == Compression.Deflate && !ForceDeflating && source.CanSeek &&
                    zfe.CompressedSize > zfe.FileSize)
                {
                    // Start operation again with Store algorithm
                    zfe.Method             = Compression.Store;
                    zipFileStream.Position = posStart;
                    zipFileStream.SetLength(posStart);
                    source.Position = sourceStart;
                    continue;
                }
                break;
            }
        }
Ejemplo n.º 14
0
        // Copies all source file into storage file
        private void Store(ref ZipFileEntry _zfe, Stream _source)
        {
            byte[] buffer = new byte[16384];
            int    bytesRead;
            uint   totalRead = 0;
            Stream outStream;

            long posStart    = ZipFileStream.Position;
            long sourceStart = _source.Position;

            if (_zfe.Method == Compression.Store)
            {
                outStream = ZipFileStream;
            }
            else
            {
                outStream = new DeflateStream(ZipFileStream,
                                              CompressionMode.Compress,
                                              true);
            }

            _zfe.Crc32 = 0 ^ 0xffffffff;

            do
            {
                bytesRead = _source.Read(buffer,
                                         0,
                                         buffer.Length);
                totalRead += (uint)bytesRead;
                if (bytesRead > 0)
                {
                    outStream.Write(buffer,
                                    0,
                                    bytesRead);

                    for (uint i = 0; i < bytesRead; i++)
                    {
                        _zfe.Crc32 = CrcTable[(_zfe.Crc32 ^ buffer[i]) & 0xFF] ^ (_zfe.Crc32 >> 8);
                    }
                }
            } while (bytesRead == buffer.Length);
            outStream.Flush();

            if (_zfe.Method == Compression.Deflate)
            {
                outStream.Dispose();
            }

            _zfe.Crc32         ^= 0xffffffff;
            _zfe.FileSize       = totalRead;
            _zfe.CompressedSize = (uint)(ZipFileStream.Position - posStart);

            // Verify for real compression
            if (_zfe.Method == Compression.Deflate && !ForceDeflating && _source.CanSeek && _zfe.CompressedSize > _zfe.FileSize)
            {
                // Start operation again with Store algorithm
                _zfe.Method            = Compression.Store;
                ZipFileStream.Position = posStart;
                ZipFileStream.SetLength(posStart);
                _source.Position = sourceStart;
                Store(ref _zfe,
                      _source);
            }
        }
Ejemplo n.º 15
0
        private void WriteLocalHeader(ref ZipFileEntry _zfe)
        {
            /* Local file header:
            local file header signature     4 bytes  (0x04034b50)
            version needed to extract       2 bytes
            general purpose bit flag        2 bytes
            compression method              2 bytes
            last mod file time              2 bytes
            last mod file date              2 bytes
            crc-32                          4 bytes
            compressed size                 4 bytes
            uncompressed size               4 bytes
            filename length                 2 bytes
            extra field length              2 bytes

            filename (variable size)
            extra field (variable size)
            */
            long pos = this.ZipFileStream.Position;
            Encoding encoder = _zfe.EncodeUTF8 ? Encoding.UTF8 : DefaultEncoding;
            byte[] encodedFilename = encoder.GetBytes(_zfe.FilenameInZip);

            this.ZipFileStream.Write(new byte[] { 80, 75, 3, 4, 20, 0}, 0, 6);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)(_zfe.EncodeUTF8 ? 0x0800 : 0)), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes(DateTimeToDosTime(_zfe.ModifyTime)), 0, 4);
            this.ZipFileStream.Write(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 12);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedFilename.Length), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);

            this.ZipFileStream.Write(encodedFilename, 0, encodedFilename.Length);
            _zfe.HeaderSize = (uint)(this.ZipFileStream.Position - pos);
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ZipStream"/> class.
 /// </summary>
 /// <param name="innerStream">
 /// The inner stream.
 /// </param>
 /// <param name="zipFileEntry">
 /// The zip file entry.
 /// </param>
 public ZipStream(Stream innerStream, ZipFileEntry zipFileEntry)
 {
     this.innerStream  = innerStream;
     this.zipFileEntry = zipFileEntry;
 }
Ejemplo n.º 17
0
        /// <summary>
        /// Add full contents of a stream into the Zip storage
        /// </summary>
        /// <param name="_method">Compression method</param>
        /// <param name="_filenameInZip">Filename and path as desired in Zip directory</param>
        /// <param name="_source">Stream object containing the data to store in Zip</param>
        /// <param name="_modTime">Modification time of the data to store</param>
        /// <param name="_comment">Comment for stored file</param>
        public void AddStream(Compression _method, string _filenameInZip, Stream _source, DateTime _modTime, string _comment)
        {
            if (Access == FileAccess.Read)
                 throw new InvalidOperationException("Writing is not alowed");

             long offset;
             if (this.Files.Count == 0)
                 offset = 0;
             else
             {
                 ZipFileEntry last = this.Files[this.Files.Count - 1];
                 offset = last.HeaderOffset + last.HeaderSize;
             }

             // Prepare the fileinfo
             ZipFileEntry zfe = new ZipFileEntry();
             zfe.Method = _method;
             zfe.EncodeUTF8 = this.EncodeUTF8;
             zfe.FilenameInZip = NormalizedFilename(_filenameInZip);
             zfe.Comment = (_comment == null ? "" : _comment);

             // Even though we write the header now, it will have to be rewritten, since we don't know compressed size or crc.
             zfe.Crc32 = 0;  // to be updated later
             zfe.HeaderOffset = (uint)this.ZipFileStream.Position;  // offset within file of the start of this local record
             zfe.ModifyTime = _modTime;

             // Write local header
             WriteLocalHeader(ref zfe);
             zfe.FileOffset = (uint)this.ZipFileStream.Position;

             // Write file to zip (store)
             Store(ref zfe, _source);
             _source.Close();

             this.UpdateCrcAndSizes(ref zfe);

             Files.Add(zfe);
        }
Ejemplo n.º 18
0
        private void LoadHeader(ZipFileEntry entryHeader, Stream stream)
        {
            if (FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.Encrypted))
            {
                if (!entryHeader.IsDirectory &&
                    entryHeader.CompressedSize == 0 &&
                    FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.UsePostDataDescriptor))
                {
                    throw new NotSupportedException(
                              "TF.Common.SharpCompress cannot currently read non-seekable Zip Streams with encrypted data that has been written in a non-seekable manner.");
                }
                if (password == null)
                {
                    throw new CryptographicException("No password supplied for encrypted zip.");
                }
                if (entryHeader.CompressionMethod != ZipCompressionMethod.WinzipAes)
                {
                    byte[] buffer = new byte[12];
                    stream.Read(buffer, 0, 12);
                    entryHeader.PkwareTraditionalEncryptionData = PkwareTraditionalEncryptionData.ForRead(password,
                                                                                                          entryHeader,
                                                                                                          buffer);
                    entryHeader.CompressedSize -= 12;
                }
                else
                {
#if PORTABLE || NETFX_CORE
                    throw new NotSupportedException("Cannot decrypt Winzip AES with Silverlight or WP7.");
#else
                    var data = entryHeader.Extra.Where(x => x.Type == ExtraDataType.WinZipAes).SingleOrDefault();
                    WinzipAesKeySize keySize = (WinzipAesKeySize)data.DataBytes[4];

                    byte[] salt = new byte[WinzipAesEncryptionData.KeyLengthInBytes(keySize) / 2];
                    byte[] passwordVerifyValue = new byte[2];
                    stream.Read(salt, 0, salt.Length);
                    stream.Read(passwordVerifyValue, 0, 2);
                    entryHeader.WinzipAesEncryptionData = new WinzipAesEncryptionData(keySize, salt, passwordVerifyValue,
                                                                                      password);
                    entryHeader.CompressedSize -= (uint)(salt.Length + 2);
#endif
                }
            }
            if (entryHeader.IsDirectory)
            {
                return;
            }
            //if (FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.UsePostDataDescriptor))
            //{
            //    entryHeader.PackedStream = new ReadOnlySubStream(stream);
            //}
            //else
            //{
            switch (mode)
            {
            case StreamingMode.Seekable:
            {
                entryHeader.DataStartPosition = stream.Position;
                stream.Position += entryHeader.CompressedSize;
            }
            break;

            case StreamingMode.Streaming:
            {
                entryHeader.PackedStream = stream;
            }
            break;

            default:
            {
                throw new InvalidFormatException("Invalid StreamingMode");
            }
            }
            //}
        }
Ejemplo n.º 19
0
        // Copies all source file into storage file
        private void Store(ref ZipFileEntry _zfe, Stream _source)
        {
            byte[] buffer = new byte[16384];
             int bytesRead;
             uint totalRead = 0;
             Stream outStream;

             long posStart = this.ZipFileStream.Position;
             long sourceStart = _source.Position;

             if (_zfe.Method == Compression.Store)
                 outStream = this.ZipFileStream;
             else
                 outStream = new DeflateStream(this.ZipFileStream, CompressionMode.Compress, true);

             _zfe.Crc32 = 0 ^ 0xffffffff;

             do
             {
                 bytesRead = _source.Read(buffer, 0, buffer.Length);
                 totalRead += (uint)bytesRead;
                 if (bytesRead > 0)
                 {
                     outStream.Write(buffer, 0, bytesRead);

                     for (uint i = 0; i < bytesRead; i++)
                     {
                         _zfe.Crc32 = ZipStorer.CrcTable[(_zfe.Crc32 ^ buffer[i]) & 0xFF] ^ (_zfe.Crc32 >> 8);
                     }
                 }
             } while (bytesRead == buffer.Length);
             outStream.Flush();

             if (_zfe.Method == Compression.Deflate)
                 outStream.Dispose();

             _zfe.Crc32 ^= 0xffffffff;
             _zfe.FileSize = totalRead;
             _zfe.CompressedSize = (uint)(this.ZipFileStream.Position - posStart);

             // Verify for real compression
             if (_zfe.Method == Compression.Deflate && !this.ForceDeflating && _source.CanSeek && _zfe.CompressedSize > _zfe.FileSize)
             {
                 // Start operation again with Store algorithm
                 _zfe.Method = Compression.Store;
                 this.ZipFileStream.Position = posStart;
                 this.ZipFileStream.SetLength(posStart);
                 _source.Position = sourceStart;
                 this.Store(ref _zfe, _source);
             }
        }
Ejemplo n.º 20
0
 internal ZipFilePart(ZipFileEntry header, Stream stream)
 {
     Header      = header;
     header.Part = this;
     BaseStream  = stream;
 }
Ejemplo n.º 21
0
        /* Central directory's File header:
         *  central file header signature   4 bytes  (0x02014b50)
         *  version made by                 2 bytes
         *  version needed to extract       2 bytes
         *  general purpose bit flag        2 bytes
         *  compression method              2 bytes
         *  last mod file time              2 bytes
         *  last mod file date              2 bytes
         *  crc-32                          4 bytes
         *  compressed size                 4 bytes
         *  uncompressed size               4 bytes
         *  filename length                 2 bytes
         *  extra field length              2 bytes
         *  file comment length             2 bytes
         *  disk number start               2 bytes
         *  internal file attributes        2 bytes
         *  external file attributes        4 bytes
         *  relative offset of local header 4 bytes
         *
         *  filename (variable size)
         *  extra field (variable size)
         *  file comment (variable size)
         */

        private void WriteCentralDirRecord(ZipFileEntry _zfe)
        {
            Encoding encoder = _zfe.EncodeUTF8 ? Encoding.UTF8 : DefaultEncoding;

            byte[] encodedFilename = encoder.GetBytes(_zfe.FilenameInZip);
            byte[] encodedComment  = encoder.GetBytes(_zfe.Comment);

            ZipFileStream.Write(new byte[] { 80, 75, 1, 2, 23, 0xB, 20, 0 },
                                0,
                                8);
            ZipFileStream.Write(BitConverter.GetBytes((ushort)(_zfe.EncodeUTF8 ? 0x0800 : 0)),
                                0,
                                2); // filename and comment encoding
            ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method),
                                0,
                                2); // zipping method
            ZipFileStream.Write(BitConverter.GetBytes(DateTimeToDosTime(_zfe.ModifyTime)),
                                0,
                                4); // zipping date and time
            ZipFileStream.Write(BitConverter.GetBytes(_zfe.Crc32),
                                0,
                                4); // file CRC
            ZipFileStream.Write(BitConverter.GetBytes(_zfe.CompressedSize),
                                0,
                                4); // compressed file size
            ZipFileStream.Write(BitConverter.GetBytes(_zfe.FileSize),
                                0,
                                4); // uncompressed file size
            ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedFilename.Length),
                                0,
                                2); // Filename in zip
            ZipFileStream.Write(BitConverter.GetBytes((ushort)0),
                                0,
                                2); // extra length
            ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedComment.Length),
                                0,
                                2);

            ZipFileStream.Write(BitConverter.GetBytes((ushort)0),
                                0,
                                2); // disk=0
            ZipFileStream.Write(BitConverter.GetBytes((ushort)0),
                                0,
                                2); // file type: binary
            ZipFileStream.Write(BitConverter.GetBytes((ushort)0),
                                0,
                                2); // Internal file attributes
            ZipFileStream.Write(BitConverter.GetBytes((ushort)0x8100),
                                0,
                                2); // External file attributes (normal/readable)
            ZipFileStream.Write(BitConverter.GetBytes(_zfe.HeaderOffset),
                                0,
                                4); // Offset of header

            ZipFileStream.Write(encodedFilename,
                                0,
                                encodedFilename.Length);
            ZipFileStream.Write(encodedComment,
                                0,
                                encodedComment.Length);
        }
Ejemplo n.º 22
0
        /* CRC32 algorithm
          The 'magic number' for the CRC is 0xdebb20e3.  
          The proper CRC pre and post conditioning
          is used, meaning that the CRC register is
          pre-conditioned with all ones (a starting value
          of 0xffffffff) and the value is post-conditioned by
          taking the one's complement of the CRC residual.
          If bit 3 of the general purpose flag is set, this
          field is set to zero in the local header and the correct
          value is put in the data descriptor and in the central
          directory.
        */
        private void UpdateCrcAndSizes(ref ZipFileEntry zfe)
        {
            long lastPos = this.ZipFileStream.Position;  // remember position

            zfe.Crc32 = 0 ^ 0xffffffff;
            this.ZipFileStream.Position = zfe.FileOffset;
            for (uint i = 0; i < zfe.FileSize; i++)
            {
                byte b = (byte)this.ZipFileStream.ReadByte();
                zfe.Crc32 = ZipStorer.CrcTable[(zfe.Crc32 ^ b) & 0xff] ^ (zfe.Crc32 >> 8);
            }
            zfe.Crc32 ^= 0xffffffff;

            this.ZipFileStream.Position = zfe.HeaderOffset + 14;
            this.ZipFileStream.Write(BitConverter.GetBytes(zfe.Crc32), 0, 4);  // Update CRC
            this.ZipFileStream.Write(BitConverter.GetBytes(zfe.FileSize), 0, 4);  // Compressed size
            this.ZipFileStream.Write(BitConverter.GetBytes(zfe.FileSize), 0, 4);  // Uncompressed size

            this.ZipFileStream.Position = lastPos;  // restore position
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Add full contents of a stream into the Zip storage
        /// </summary>
        /// <param name="method">Compression method</param>
        /// <param name="fileNameInZip">File name and path as desired in Zip directory</param>
        /// <param name="source">Stream object containing the data to store in Zip</param>
        /// <param name="modTime">Modification time of the data to store</param>
        /// <param name="fileComment">Comment for stored file</param>
        public void AddStream( Compression method, [NotNull] string fileNameInZip, [NotNull] Stream source,
                               DateTime modTime, [CanBeNull] string fileComment ) {
            if( fileNameInZip == null ) throw new ArgumentNullException( "fileNameInZip" );
            if( source == null ) throw new ArgumentNullException( "source" );
            if( access == FileAccess.Read )
                throw new InvalidOperationException( "Writing is not alowed" );

            /*long offset;
            if( Files.Count == 0 )
                offset = 0;
            else {
                ZipFileEntry last = Files[Files.Count - 1];
                offset = last.HeaderOffset + last.HeaderSize;
            }*/

            // Prepare the fileinfo
            ZipFileEntry zfe = new ZipFileEntry {
                Method = method,
                EncodeUTF8 = EncodeUTF8,
                FileNameInZip = NormalizedFileName( fileNameInZip ),
                Comment = (fileComment ?? ""),
                Crc32 = 0,
                HeaderOffset = (uint)zipFileStream.Position,
                ModifyTime = modTime
            };

            // Even though we write the header now, it will have to be rewritten, since we don't know compressed size or crc.

            // Write local header
            WriteLocalHeader( ref zfe );
            zfe.FileOffset = (uint)zipFileStream.Position;

            // Write file to zip (store)
            Store( ref zfe, source );
            source.Close();

            UpdateCrcAndSizes( ref zfe );

            files.Add( zfe );
        }
Ejemplo n.º 24
0
        /// <summary>
        ///     Add full contents of a stream into the Zip storage
        /// </summary>
        /// <param name="method">Compression method</param>
        /// <param name="filenameInZip">Filename and path as desired in Zip directory</param>
        /// <param name="source">Stream object containing the data to store in Zip</param>
        /// <param name="modTime">Modification time of the data to store</param>
        /// <param name="comment">Comment for stored file</param>
        public void AddStream(Compression method, string filenameInZip, Stream source, DateTime modTime, string comment)
        {
            if (_access == FileAccess.Read)
                throw new InvalidOperationException("Writing is not alowed");

            // Prepare the fileinfo
            var zfe = new ZipFileEntry
                {
                    Method = method,
                    EncodeUTF8 = EncodeUTF8,
                    FilenameInZip = NormalizedFilename(filenameInZip),
                    Comment = (comment ?? string.Empty),
                    Crc32 = 0,
                    HeaderOffset = (uint) _zipFileStream.Position,
                    ModifyTime = modTime
                };

            // Even though we write the header now, it will have to be rewritten, since we don't know compressed size or crc.

            // Write local header
            WriteLocalHeader(ref zfe);
            zfe.FileOffset = (uint) _zipFileStream.Position;

            // Write file to zip (store)
            Store(ref zfe, source);
            source.Close();

            UpdateCrcAndSizes(ref zfe);

            _files.Add(zfe);
        }
Ejemplo n.º 25
0
        // Copies all source file into storage file
        private void Store( ref ZipFileEntry zfe, Stream source ) {
            byte[] buffer = new byte[16384];
            int bytesRead;
            uint totalRead = 0;
            Stream outStream;

            long posStart = zipFileStream.Position;
            long sourceStart = source.Position;

            if( zfe.Method == Compression.Store )
                outStream = zipFileStream;
            else
                outStream = new DeflateStream( zipFileStream, CompressionMode.Compress, true );

            zfe.Crc32 = 0 ^ 0xffffffff;

            do {
                bytesRead = source.Read( buffer, 0, buffer.Length );
                totalRead += (uint)bytesRead;
                if( bytesRead > 0 ) {
                    outStream.Write( buffer, 0, bytesRead );

                    for( uint i = 0; i < bytesRead; i++ ) {
                        zfe.Crc32 = CrcTable[(zfe.Crc32 ^ buffer[i]) & 0xFF] ^ (zfe.Crc32 >> 8);
                    }
                }
            } while( bytesRead == buffer.Length );

            if( totalRead > 0 )
                outStream.Flush(); // fix for "Internal error Flush" under Mono

            if( zfe.Method == Compression.Deflate )
                outStream.Dispose();

            zfe.Crc32 ^= 0xffffffff;
            zfe.FileSize = totalRead;
            zfe.CompressedSize = (uint)(zipFileStream.Position - posStart);

            // Verify for real compression
            if( zfe.Method == Compression.Deflate && !ForceDeflating && source.CanSeek && zfe.CompressedSize > zfe.FileSize ) {
                // Start operation again with Store algorithm
                zfe.Method = Compression.Store;
                zipFileStream.Position = posStart;
                zipFileStream.SetLength( posStart );
                source.Position = sourceStart;
                Store( ref zfe, source );
            }
        }
Ejemplo n.º 26
0
        /// <summary>
        ///     Copy the contents of a stored file into an opened stream
        /// </summary>
        /// <param name="zfe">Entry information of file to extract</param>
        /// <param name="stream">Stream to store the uncompressed data</param>
        /// <returns>True if success, false if not.</returns>
        /// <remarks>Unique compression methods are Store and Deflate</remarks>
        public bool ExtractFile(ZipFileEntry zfe, Stream stream)
        {
            if (!stream.CanWrite)
                throw new InvalidOperationException("Stream cannot be written");

            // check signature
            var signature = new byte[4];
            _zipFileStream.Seek(zfe.HeaderOffset, SeekOrigin.Begin);
            _zipFileStream.Read(signature, 0, 4);
            if (BitConverter.ToUInt32(signature, 0) != 0x04034b50)
                return false;

            // Select input stream for inflating or just reading
            Stream inStream;
            switch (zfe.Method)
            {
                case Compression.Store:
                    inStream = _zipFileStream;
                    break;
                case Compression.Deflate:
                    inStream = new DeflateStream(_zipFileStream, CompressionMode.Decompress, true);
                    break;
                default:
                    return false;
            }

            // Buffered copy
            var buffer = new byte[16384];
            _zipFileStream.Seek(zfe.FileOffset, SeekOrigin.Begin);
            var bytesPending = zfe.FileSize;
            while (bytesPending > 0)
            {
                var bytesRead = inStream.Read(buffer, 0, (int) Math.Min(bytesPending, buffer.Length));
                stream.Write(buffer, 0, bytesRead);
                bytesPending -= (uint) bytesRead;
            }
            stream.Flush();

            if (zfe.Method == Compression.Deflate)
                inStream.Dispose();
            return true;
        }
Ejemplo n.º 27
0
        public Stream GetStream(ZipFileEntry _zfe)
        {
            // check signature
            byte[] signature = new byte[4];
            this.ZipFileStream.Seek(_zfe.HeaderOffset, SeekOrigin.Begin);
            this.ZipFileStream.Read(signature, 0, 4);
            if (BitConverter.ToUInt32(signature, 0) != 0x04034b50) throw new Exception("Bad signature");

            // Select input stream for inflating or just reading
            Stream inStream = null;
            if (_zfe.Method == Compression.Store) inStream = this.ZipFileStream;
            else if (_zfe.Method == Compression.Deflate) inStream = new DeflateStream(this.ZipFileStream, CompressionMode.Decompress, true); else throw new Exception("Unsupoorted comprension");
            this.ZipFileStream.Seek(_zfe.FileOffset, SeekOrigin.Begin);
            return inStream;
        }
Ejemplo n.º 28
0
        /// <summary>
        ///     Read all the file records in the central directory
        /// </summary>
        /// <returns>List of all entries in directory</returns>
        public List<ZipFileEntry> ReadCentralDir()
        {
            if (_centralDirImage == null)
                throw new InvalidOperationException("Central directory currently does not exist");

            var result = new List<ZipFileEntry>();

            for (var pointer = 0; pointer < _centralDirImage.Length;)
            {
                var signature = BitConverter.ToUInt32(_centralDirImage, pointer);
                if (signature != 0x02014b50)
                    break;

                var encodeUTF8 = (BitConverter.ToUInt16(_centralDirImage, pointer + 8) & 0x0800) != 0;
                var method = BitConverter.ToUInt16(_centralDirImage, pointer + 10);
                var modifyTime = BitConverter.ToUInt32(_centralDirImage, pointer + 12);
                var crc32 = BitConverter.ToUInt32(_centralDirImage, pointer + 16);
                var comprSize = BitConverter.ToUInt32(_centralDirImage, pointer + 20);
                var fileSize = BitConverter.ToUInt32(_centralDirImage, pointer + 24);
                var filenameSize = BitConverter.ToUInt16(_centralDirImage, pointer + 28);
                var extraSize = BitConverter.ToUInt16(_centralDirImage, pointer + 30);
                var commentSize = BitConverter.ToUInt16(_centralDirImage, pointer + 32);
                var headerOffset = BitConverter.ToUInt32(_centralDirImage, pointer + 42);
                var headerSize = (uint) (46 + filenameSize + extraSize + commentSize);

                var encoder = encodeUTF8 ? Encoding.UTF8 : DefaultEncoding;

                var zfe = new ZipFileEntry
                    {
                        Method = (Compression) method,
                        FilenameInZip = encoder.GetString(_centralDirImage, pointer + 46, filenameSize),
                        FileOffset = GetFileOffset(headerOffset),
                        FileSize = fileSize,
                        CompressedSize = comprSize,
                        HeaderOffset = headerOffset,
                        HeaderSize = headerSize,
                        Crc32 = crc32,
                        ModifyTime = DosTimeToDateTime(modifyTime)
                    };
                if (commentSize > 0)
                    zfe.Comment = encoder.GetString(_centralDirImage, pointer + 46 + filenameSize + extraSize,
                                                    commentSize);

                result.Add(zfe);
                pointer += (46 + filenameSize + extraSize + commentSize);
            }

            return result;
        }
Ejemplo n.º 29
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="_method"></param>
        /// <param name="_filenameInZip"></param>
        /// <param name="_source"></param>
        /// <param name="_modTime"></param>
        /// <param name="_comment"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public void AddStream(Compression _method, string _filenameInZip, Stream _source, DateTime _modTime, string _comment)
        {
            if (Access == FileAccess.Read)
                throw new InvalidOperationException("Writing is not allowed.");

            long offset;
            if (this.Files.Count==0)
                offset = 0;
            else
            {
                ZipFileEntry last = this.Files[this.Files.Count-1];
                offset = last.HeaderOffset + last.HeaderSize;
            }

            ZipFileEntry zfe = new ZipFileEntry();
            zfe.Method = _method;
            zfe.EncodeUTF8 = this.EncodeUTF8;
            zfe.FilenameInZip = NormalizedFilename(_filenameInZip);
            zfe.Comment = (_comment == null ? "" : _comment);
            zfe.Crc32 = 0;
            zfe.HeaderOffset = (uint)this.ZipFileStream.Position;
            zfe.ModifyTime = _modTime;

            WriteLocalHeader(ref zfe);
            zfe.FileOffset = (uint)this.ZipFileStream.Position;

            Store(ref zfe, _source);
            _source.Close();

            this.UpdateCrcAndSizes(ref zfe);

            Files.Add(zfe);
        }
Ejemplo n.º 30
0
        // Copies all source file into storage file
        private void Store(ref ZipFileEntry zfe, Stream source)
        {
            var buffer = new byte[16384];
            int bytesRead;
            uint totalRead = 0;

            var posStart = _zipFileStream.Position;
            var sourceStart = source.Position;

            Stream outStream = zfe.Method == Compression.Store ? _zipFileStream : new DeflateStream(_zipFileStream, CompressionMode.Compress, true);

            zfe.Crc32 = 0 ^ 0xffffffff;

            do
            {
                bytesRead = source.Read(buffer, 0, buffer.Length);
                totalRead += (uint) bytesRead;
                if (bytesRead <= 0)
                    continue;
                outStream.Write(buffer, 0, bytesRead);

                for (uint i = 0; i < bytesRead; i++)
                    zfe.Crc32 = CrcTable[(zfe.Crc32 ^ buffer[i]) & 0xFF] ^ (zfe.Crc32 >> 8);
            } while (bytesRead == buffer.Length);
            outStream.Flush();

            if (zfe.Method == Compression.Deflate)
                outStream.Dispose();

            zfe.Crc32 ^= 0xffffffff;
            zfe.FileSize = totalRead;
            zfe.CompressedSize = (uint) (_zipFileStream.Position - posStart);

            // Verify for real compression
            if (zfe.Method != Compression.Deflate || ForceDeflating || !source.CanSeek || zfe.CompressedSize <= zfe.FileSize)
                return;
            // Start operation again with Store algorithm
            zfe.Method = Compression.Store;
            _zipFileStream.Position = posStart;
            _zipFileStream.SetLength(posStart);
            source.Position = sourceStart;
            Store(ref zfe, source);
        }
Ejemplo n.º 31
0
        private void WriteCentralDirRecord(ZipFileEntry _zfe)
        {
            /* Central directory's File header:
            central file header signature   4 bytes  (0x02014b50)
            version made by                 2 bytes
            version needed to extract       2 bytes
            general purpose bit flag        2 bytes
            compression method              2 bytes
            last mod file time              2 bytes
            last mod file date              2 bytes
            crc-32                          4 bytes
            compressed size                 4 bytes
            uncompressed size               4 bytes
            filename length                 2 bytes
            extra field length              2 bytes
            file comment length             2 bytes
            disk number start               2 bytes
            internal file attributes        2 bytes
            external file attributes        4 bytes
            relative offset of local header 4 bytes

            filename (variable size)
            extra field (variable size)
            file comment (variable size)
            */
            Encoding encoder = _zfe.EncodeUTF8 ? Encoding.UTF8 : DefaultEncoding;
            byte[] encodedFilename = encoder.GetBytes(_zfe.FilenameInZip);
            byte[] encodedComment = encoder.GetBytes(_zfe.Comment);

            this.ZipFileStream.Write(new byte[] { 80, 75, 1, 2, 23, 0xB, 20, 0 }, 0, 8);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)(_zfe.EncodeUTF8 ? 0x0800 : 0)), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes(DateTimeToDosTime(_zfe.ModifyTime)), 0, 4);
            this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.Crc32), 0, 4);
            this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.CompressedSize), 0, 4);
            this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.FileSize), 0, 4);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedFilename.Length), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedComment.Length), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0x8100), 0, 2);
            this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.HeaderOffset), 0, 4);

            this.ZipFileStream.Write(encodedFilename, 0, encodedFilename.Length);
            this.ZipFileStream.Write(encodedComment, 0, encodedComment.Length);
        }
Ejemplo n.º 32
0
        /* CRC32 algorithm
          The 'magic number' for the CRC is 0xdebb20e3.
          The proper CRC pre and post conditioning
          is used, meaning that the CRC register is
          pre-conditioned with all ones (a starting value
          of 0xffffffff) and the value is post-conditioned by
          taking the one's complement of the CRC residual.
          If bit 3 of the general purpose flag is set, this
          field is set to zero in the local header and the correct
          value is put in the data descriptor and in the central
          directory.
        */
        private void UpdateCrcAndSizes(ref ZipFileEntry zfe)
        {
            var lastPos = _zipFileStream.Position; // remember position

            _zipFileStream.Position = zfe.HeaderOffset + 8;
            _zipFileStream.Write(BitConverter.GetBytes((ushort) zfe.Method), 0, 2); // zipping method

            _zipFileStream.Position = zfe.HeaderOffset + 14;
            _zipFileStream.Write(BitConverter.GetBytes(zfe.Crc32), 0, 4); // Update CRC
            _zipFileStream.Write(BitConverter.GetBytes(zfe.CompressedSize), 0, 4); // Compressed size
            _zipFileStream.Write(BitConverter.GetBytes(zfe.FileSize), 0, 4); // Uncompressed size

            _zipFileStream.Position = lastPos; // restore position
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ZipStream"/> class.
 /// </summary>
 /// <param name="innerStream">
 /// The inner stream.
 /// </param>
 /// <param name="zipFileEntry">
 /// The zip file entry.
 /// </param>
 public ZipStream(Stream innerStream, ZipFileEntry zipFileEntry)
 {
     this.innerStream = innerStream;
     this.zipFileEntry = zipFileEntry;
 }
Ejemplo n.º 34
0
        /// <summary>
        /// Copy the contents of a stored file into a physical file
        /// </summary>
        /// <param name="_zfe">Entry information of file to extract</param>
        /// <param name="_filename">Name of file to store uncompressed data</param>
        /// <returns>True if success, false if not.</returns>
        /// <remarks>Unique compression methods are Store and Deflate</remarks>
        public bool ExtractStoredFile(ZipFileEntry _zfe, string _filename)
        {
            // check signature
            byte[] signature = new byte[4];
            this.ZipFileStream.Seek(_zfe.HeaderOffset, SeekOrigin.Begin);
            this.ZipFileStream.Read(signature, 0, 4);
            if (BitConverter.ToUInt32(signature, 0) != 0x04034b50)
                return false;

            // Select input stream for inflating or just reading
            Stream inStream;
            if (_zfe.Method == Compression.Store)
                inStream = this.ZipFileStream;
            else if (_zfe.Method == Compression.Deflate)
                inStream = new DeflateStream(this.ZipFileStream, CompressionMode.Decompress, true);
            else
                return false;

            // Make sure the parent directory exist
            string path = System.IO.Path.GetDirectoryName(_filename);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            // Check it is directory. If so, do nothing
            if (Directory.Exists(_filename))
                return true;

            FileStream output = new FileStream(_filename, FileMode.Create, FileAccess.Write);

            // Buffered copy
            byte[] buffer = new byte[16384];
            this.ZipFileStream.Seek(_zfe.FileOffset, SeekOrigin.Begin);
            uint bytesPending = _zfe.FileSize;
            while (bytesPending > 0)
            {
                int bytesRead = inStream.Read(buffer, 0, (int)Math.Min(bytesPending, buffer.Length));
                output.Write(buffer, 0, bytesRead);
                bytesPending -= (uint)bytesRead;
            }
            output.Close();
            if (_zfe.Method == Compression.Deflate)
                inStream.Dispose();
            return true;
        }
Ejemplo n.º 35
0
        /// <summary>
        /// Copy the contents of a stored file into a physical file
        /// </summary>
        /// <param name="_zfe">Entry information of file to extract</param>
        /// <param name="_filename">Name of file to store uncompressed data</param>
        /// <returns>True if success, false if not.</returns>
        /// <remarks>Unique compression methods are Store and Deflate</remarks>
        public bool ExtractFile(ZipFileEntry _zfe, string _filename)
        {
            // Make sure the parent directory exist
             string path = System.IO.Path.GetDirectoryName(_filename);

             if (!Directory.Exists(path))
                 Directory.CreateDirectory(path);
             // Check it is directory. If so, do nothing
             if (Directory.Exists(_filename))
                 return true;

             Stream output = new FileStream(_filename, FileMode.Create, FileAccess.Write);
             bool result = ExtractFile(_zfe, output);
             if (result)
                 output.Close();

             File.SetCreationTime(_filename, _zfe.ModifyTime);
             File.SetLastWriteTime(_filename, _zfe.ModifyTime);

             return result;
        }
Ejemplo n.º 36
0
        // Copies all source file into storage file
        private void Store(ref ZipFileEntry zfe, Stream source)
        {
            byte[] buffer = new byte[16384];
            int bytesRead;
            uint totalRead = 0;
            Stream outStream;
            long posStart = this.ZipFileStream.Position;

            if (zfe.Method == Compression.Store)
                outStream = this.ZipFileStream;
            else
                outStream = new DeflateStream(this.ZipFileStream, CompressionMode.Compress, true);

            zfe.Crc32 = 0 ^ 0xffffffff;

            do
            {
                bytesRead = source.Read(buffer, 0, buffer.Length);
                totalRead += (uint)bytesRead;
                if (bytesRead > 0)
                {
                    outStream.Write(buffer, 0, bytesRead);

                    for (uint i = 0; i < bytesRead; i++)
                    {
                        zfe.Crc32 = ZipStorer.CrcTable[(zfe.Crc32 ^ buffer[i]) & 0xFF] ^ (zfe.Crc32 >> 8);
                    }
                }
            } while (bytesRead == buffer.Length);
            outStream.Flush();

            if (zfe.Method == Compression.Deflate)
                outStream.Dispose();

            zfe.Crc32 ^= 0xffffffff;
            zfe.FileSize = totalRead;
            zfe.CompressedSize = (uint)(this.ZipFileStream.Position - posStart);
        }
Ejemplo n.º 37
0
        /// <summary>
        /// Read all the file records in the central directory 
        /// </summary>
        /// <returns>List of all entries in directory</returns>
        public List<ZipFileEntry> ReadCentralDir()
        {
            if (this.CentralDirImage == null)
                 throw new InvalidOperationException("Central directory currently does not exist");

             List<ZipFileEntry> result = new List<ZipFileEntry>();

             for (int pointer = 0; pointer < this.CentralDirImage.Length; )
             {
                 uint signature = BitConverter.ToUInt32(CentralDirImage, pointer);
                 if (signature != 0x02014b50)
                     break;

                 bool encodeUTF8 = (BitConverter.ToUInt16(CentralDirImage, pointer + 8) & 0x0800) != 0;
                 ushort method = BitConverter.ToUInt16(CentralDirImage, pointer + 10);
                 uint modifyTime = BitConverter.ToUInt32(CentralDirImage, pointer + 12);
                 uint crc32 = BitConverter.ToUInt32(CentralDirImage, pointer + 16);
                 uint comprSize = BitConverter.ToUInt32(CentralDirImage, pointer + 20);
                 uint fileSize = BitConverter.ToUInt32(CentralDirImage, pointer + 24);
                 ushort filenameSize = BitConverter.ToUInt16(CentralDirImage, pointer + 28);
                 ushort extraSize = BitConverter.ToUInt16(CentralDirImage, pointer + 30);
                 ushort commentSize = BitConverter.ToUInt16(CentralDirImage, pointer + 32);
                 uint headerOffset = BitConverter.ToUInt32(CentralDirImage, pointer + 42);
                 uint headerSize = (uint)(46 + filenameSize + extraSize + commentSize);

                 Encoding encoder = encodeUTF8 ? Encoding.UTF8 : DefaultEncoding;

                 ZipFileEntry zfe = new ZipFileEntry();
                 zfe.Method = (Compression)method;
                 zfe.FilenameInZip = encoder.GetString(CentralDirImage, pointer + 46, filenameSize);
                 zfe.FileOffset = GetFileOffset(headerOffset);
                 zfe.FileSize = fileSize;
                 zfe.CompressedSize = comprSize;
                 zfe.HeaderOffset = headerOffset;
                 zfe.HeaderSize = headerSize;
                 zfe.Crc32 = crc32;
                 zfe.ModifyTime = DosTimeToDateTime(modifyTime);
                 if (commentSize > 0)
                     zfe.Comment = encoder.GetString(CentralDirImage, pointer + 46 + filenameSize + extraSize, commentSize);

                 result.Add(zfe);
                 pointer += (46 + filenameSize + extraSize + commentSize);
             }

             return result;
        }
Ejemplo n.º 38
0
        /* Local file header:
            local file header signature     4 bytes  (0x04034b50)
            version needed to extract       2 bytes
            general purpose bit flag        2 bytes
            compression method              2 bytes
            last mod file time              2 bytes
            last mod file date              2 bytes
            crc-32                          4 bytes
            compressed size                 4 bytes
            uncompressed size               4 bytes
            filename length                 2 bytes
            extra field length              2 bytes

            filename (variable size)
            extra field (variable size)
        */
        private void WriteLocalHeader(ref ZipFileEntry zfe)
        {
            long pos = this.ZipFileStream.Position;
            byte[] encodedFilename = FilenameEncoder.GetBytes(zfe.FilenameInZip);

            this.ZipFileStream.Write(new byte[] { 80, 75, 3, 4, 20, 0, 0, 0 }, 0, 8); // No extra header
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)zfe.Method), 0, 2);  // zipping method
            this.ZipFileStream.Write(BitConverter.GetBytes(DosTime(zfe.ModifyTime)), 0, 4); // zipping date and time
            this.ZipFileStream.Write(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 12); // unused CRC, un/compressed size, updated later
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedFilename.Length), 0, 2); // filename length
            this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // extra length

            this.ZipFileStream.Write(encodedFilename, 0, encodedFilename.Length);
            zfe.HeaderSize = (uint)(this.ZipFileStream.Position - pos);
        }
Ejemplo n.º 39
0
        /* CRC32 algorithm
        656           The 'magic number' for the CRC is 0xdebb20e3.
        657           The proper CRC pre and post conditioning
        658           is used, meaning that the CRC register is
        659           pre-conditioned with all ones (a starting value
        660           of 0xffffffff) and the value is post-conditioned by
        661           taking the one's complement of the CRC residual.
        662           If bit 3 of the general purpose flag is set, this
        663           field is set to zero in the local header and the correct
        664           value is put in the data descriptor and in the central
        665           directory.
        666         */
        private void UpdateCrcAndSizes(ref ZipFileEntry _zfe)
        {
            long lastPos = this.ZipFileStream.Position;  // remember position

             this.ZipFileStream.Position = _zfe.HeaderOffset + 8;
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2);  // zipping method

             this.ZipFileStream.Position = _zfe.HeaderOffset + 14;
             this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.Crc32), 0, 4);  // Update CRC
             this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.CompressedSize), 0, 4);  // Compressed size
             this.ZipFileStream.Write(BitConverter.GetBytes(_zfe.FileSize), 0, 4);  // Uncompressed size

             this.ZipFileStream.Position = lastPos;  // restore position
        }
Ejemplo n.º 40
0
 public bool ExtractFile(ZipFileEntry _zfe, string _filename)
 {
     return ExtractFile(_zfe, _filename, 0);
 }
Ejemplo n.º 41
0
        /* Local file header:
             local file header signature     4 bytes  (0x04034b50)
             version needed to extract       2 bytes
             general purpose bit flag        2 bytes
             compression method              2 bytes
             last mod file time              2 bytes
             last mod file date              2 bytes
             crc-32                          4 bytes
             compressed size                 4 bytes
             uncompressed size               4 bytes
             filename length                 2 bytes
             extra field length              2 bytes

             filename (variable size)
             extra field (variable size)
         */
        private void WriteLocalHeader(ref ZipFileEntry _zfe)
        {
            long pos = this.ZipFileStream.Position;
             Encoding encoder = _zfe.EncodeUTF8 ? Encoding.UTF8 : DefaultEncoding;
             byte[] encodedFilename = encoder.GetBytes(_zfe.FilenameInZip);

             this.ZipFileStream.Write(new byte[] { 80, 75, 3, 4, 20, 0 }, 0, 6); // No extra header
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)(_zfe.EncodeUTF8 ? 0x0800 : 0)), 0, 2); // filename and comment encoding
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)_zfe.Method), 0, 2);  // zipping method
             this.ZipFileStream.Write(BitConverter.GetBytes(DateTimeToDosTime(_zfe.ModifyTime)), 0, 4); // zipping date and time
             this.ZipFileStream.Write(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 12); // unused CRC, un/compressed size, updated later
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)encodedFilename.Length), 0, 2); // filename length
             this.ZipFileStream.Write(BitConverter.GetBytes((ushort)0), 0, 2); // extra length

             this.ZipFileStream.Write(encodedFilename, 0, encodedFilename.Length);
             _zfe.HeaderSize = (uint)(this.ZipFileStream.Position - pos);
        }
Ejemplo n.º 42
0
 internal StreamingZipFilePart(ZipFileEntry header, Stream stream)
     : base(header, stream)
 {
 }