/// <summary>
 /// Returns a stream for the specified zip file entry.
 /// </summary>
 /// <param name="zfe">
 /// The zip file entry for which to fetch a stream.
 /// </param>
 /// <returns>
 /// A stream for the specified zip file entry.
 /// </returns>
 private Stream GetZipStream(ZipFileEntry zfe)
 {
     switch (zfe.Method)
     {
         case Compression.Store:
             return this.zipFileStream;
         case Compression.Deflate:
             return new DeflateStream(this.zipFileStream, CompressionMode.Decompress, true);
         default:
             return null;
     }
 }
        /// <summary>
        /// The matrix cursor.
        /// </summary>
        /// <param name="projection">
        /// The projection.
        /// </param>
        /// <param name="intProjection">
        /// The int projection.
        /// </param>
        /// <param name="entries">
        /// The entries.
        /// </param>
        /// <returns>
        /// The Android.Database.MatrixCursor.
        /// </returns>
        private static MatrixCursor MatrixCursor(
            string[] projection, ApezProjection[] intProjection, ZipFileEntry[] entries)
        {
            var mc = new MatrixCursor(projection, entries.Length);
            foreach (ZipFileEntry zer in entries)
            {
                MatrixCursor.RowBuilder rb = mc.NewRow();
                for (int i = 0; i < intProjection.Length; i++)
                {
                    switch (intProjection[i])
                    {
                        case ApezProjection.File:
                            rb.Add(i);
                            break;
                        case ApezProjection.FileName:
                            rb.Add(zer.FilenameInZip);
                            break;
                        case ApezProjection.ZipFile:
                            rb.Add(zer.ZipFileName);
                            break;
                        case ApezProjection.Modification:
                            rb.Add(ZipFile.DateTimeToDosTime(zer.ModifyTime));
                            break;
                        case ApezProjection.Crc:
                            rb.Add(zer.Crc32);
                            break;
                        case ApezProjection.CompressedLength:
                            rb.Add(zer.CompressedSize);
                            break;
                        case ApezProjection.UncompressedLength:
                            rb.Add(zer.FileSize);
                            break;
                        case ApezProjection.CompressionType:
                            rb.Add((int)zer.Method);
                            break;
                    }
                }
            }

            return mc;
        }
        /// <summary>
        /// Loads an entry from the zip file.
        /// </summary>
        /// <param name="pointer">
        /// The pointer.
        /// </param>
        /// <returns>
        /// An entry at this location
        /// </returns>
        private ZipFileEntry GetEntry(ref int pointer)
        {
            bool encodeUtf8 = (BitConverter.ToUInt16(this.centralDirImage, pointer + 8) & 0x0800) != 0;
            ushort method = BitConverter.ToUInt16(this.centralDirImage, pointer + 10);
            uint modifyTime = BitConverter.ToUInt32(this.centralDirImage, pointer + 12);
            uint crc32 = BitConverter.ToUInt32(this.centralDirImage, pointer + 16);
            uint comprSize = BitConverter.ToUInt32(this.centralDirImage, pointer + 20);
            uint fileSize = BitConverter.ToUInt32(this.centralDirImage, pointer + 24);
            ushort filenameSize = BitConverter.ToUInt16(this.centralDirImage, pointer + 28);
            ushort extraSize = BitConverter.ToUInt16(this.centralDirImage, pointer + 30);
            ushort commentSize = BitConverter.ToUInt16(this.centralDirImage, pointer + 32);
            uint headerOffset = BitConverter.ToUInt32(this.centralDirImage, pointer + 42);
            int commentsStart = 46 + filenameSize + extraSize;
            int headerSize = commentsStart + commentSize;
            Encoding encoder = encodeUtf8 ? Encoding.UTF8 : Encoding.Default;
            string comment = null;
            if (commentSize > 0)
            {
                comment = encoder.GetString(this.centralDirImage, pointer + commentsStart, commentSize);
            }

            var zfe = new ZipFileEntry
                {
                    Method = (Compression)method, 
                    FilenameInZip = encoder.GetString(this.centralDirImage, pointer + 46, filenameSize), 
                    FileOffset = this.GetFileOffset(headerOffset), 
                    FileSize = fileSize, 
                    CompressedSize = comprSize, 
                    HeaderOffset = headerOffset, 
                    HeaderSize = (uint)headerSize, 
                    Crc32 = crc32, 
                    ModifyTime = DosTimeToDateTime(modifyTime), 
                    Comment = comment ?? string.Empty, 
                    ZipFileName = this.FileName
                };
            pointer += headerSize;
            return zfe;
        }
        /// <summary>
        /// Copy the contents of a stored file into an opened stream
        /// </summary>
        /// <param name="zfe">
        /// Entry information of file to extract
        /// </param>
        /// <returns>
        /// Stream to store the uncompressed data
        /// </returns>
        /// <remarks>
        /// Unique compression methods are Store and Deflate
        /// </remarks>
        public Stream ReadFile(ZipFileEntry zfe)
        {
            // check signature
            var 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 InvalidOperationException("Not a valid zip entry.");
            }

            // Select input stream for inflating or just reading
            Stream inStream;
            switch (zfe.Method)
            {
                case Compression.Store:
                    inStream = this.zipFileStream;
                    break;
                case Compression.Deflate:
                    inStream = new DeflateStream(this.zipFileStream, CompressionMode.Decompress, true);
                    break;
                default:
                    throw new InvalidOperationException("Not a valid zip entry.");
            }

            this.zipFileStream.Seek(zfe.FileOffset, SeekOrigin.Begin);

            return new ZipStream(inStream, zfe);
        }
        /// <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];
            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 = this.GetZipStream(zfe);
            if (inStream == null)
            {
                return false;
            }

            // Buffered copy
            var 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;
        }
        /// <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 = Path.GetDirectoryName(filename);

            if (!string.IsNullOrWhiteSpace(path) && !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 = this.ExtractFile(zfe, output);
            if (result)
            {
                output.Close();
            }

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

            return result;
        }
Ejemplo n.º 7
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="buffer">
        /// 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, byte[] buffer)
        {
            // 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 = GetZipStream(zfe);
            if (inStream == null)
            {
                return false;
            }

            // Buffered copy
            zipFileStream.Seek(zfe.FileOffset, SeekOrigin.Begin);
            inStream.Read(buffer, 0, buffer.Length);

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

            return true;
        }