예제 #1
0
        private static bool ReadHeader(System.IO.Stream s, ZipEntry ze)
        {
            int signature = SQLInstaller.Core.Zip.Shared.ReadSignature(s);

            // Return false if this is not a local file header signature.
            if (ZipEntry.IsNotValidSig(signature))
            {
                s.Seek(-4, System.IO.SeekOrigin.Current); // unread the signature
                // Getting "not a ZipEntry signature" is not always wrong or an error.
                // This can happen when walking through a zipfile.  After the last compressed entry,
                // we expect to read a ZipDirEntry signature.  When we get this is how we
                // know we've reached the end of the compressed entries.
                if (ZipDirEntry.IsNotValidSig(signature))
                {
                    throw new Exception(String.Format("  ZipEntry::Read(): Bad signature ({0:X8}) at position  0x{1:X8}", signature, s.Position));
                }
                return(false);
            }

            byte[] block = new byte[26];
            int    n     = s.Read(block, 0, block.Length);

            if (n != block.Length)
            {
                return(false);
            }

            int i = 0;

            ze._VersionNeeded     = (short)(block[i++] + block[i++] * 256);
            ze._BitField          = (short)(block[i++] + block[i++] * 256);
            ze._CompressionMethod = (short)(block[i++] + block[i++] * 256);
            ze._LastModDateTime   = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;

            // the PKZIP spec says that if bit 3 is set (0x0008), then the CRC, Compressed size, and uncompressed size
            // come directly after the file data.  The only way to find it is to scan the zip archive for the signature of
            // the Data Descriptor, and presume that that signature does not appear in the (compressed) data of the compressed file.

            if ((ze._BitField & 0x0008) != 0x0008)
            {
                ze._Crc32            = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                ze._CompressedSize   = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                ze._UncompressedSize = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            }
            else
            {
                // the CRC, compressed size, and uncompressed size are stored later in the stream.
                // here, we advance the pointer.
                i += 12;
            }

            Int16 filenameLength   = (short)(block[i++] + block[i++] * 256);
            Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256);

            block = new byte[filenameLength];
            n     = s.Read(block, 0, block.Length);
            ze._FileNameInArchive = SQLInstaller.Core.Zip.Shared.StringFromBuffer(block, 0, block.Length);

            // when creating an entry by reading, the LocalFileName is the same as the FileNameInArchivre
            ze._LocalFileName = ze._FileNameInArchive;

            ze._Extra = new byte[extraFieldLength];
            n         = s.Read(ze._Extra, 0, ze._Extra.Length);

            // transform the time data into something usable
            ze._LastModified = SQLInstaller.Core.Zip.Shared.PackedToDateTime(ze._LastModDateTime);

            // actually get the compressed size and CRC if necessary
            if ((ze._BitField & 0x0008) == 0x0008)
            {
                long posn           = s.Position;
                long SizeOfDataRead = SQLInstaller.Core.Zip.Shared.FindSignature(s, ZipConstants.ZipEntryDataDescriptorSignature);
                if (SizeOfDataRead == -1)
                {
                    return(false);
                }

                // read 3x 4-byte fields (CRC, Compressed Size, Uncompressed Size)
                block = new byte[12];
                n     = s.Read(block, 0, block.Length);
                if (n != 12)
                {
                    return(false);
                }
                i                    = 0;
                ze._Crc32            = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                ze._CompressedSize   = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                ze._UncompressedSize = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;

                if (SizeOfDataRead != ze._CompressedSize)
                {
                    throw new Exception("Data format error (bit 3 is set)");
                }

                // seek back to previous position, to read file data
                s.Seek(posn, System.IO.SeekOrigin.Begin);
            }

            return(true);
        }
예제 #2
0
        /// <summary>
        /// Reads one entry from the zip directory structure in the zip file.
        /// </summary>
        /// <param name="s">the stream from which to read.</param>
        /// <returns>the entry read from the archive.</returns>
        public static ZipDirEntry Read(System.IO.Stream s)
        {
            int signature = SQLInstaller.Core.Zip.Shared.ReadSignature(s);

            // return null if this is not a local file header signature
            if (ZipDirEntry.IsNotValidSig(signature))
            {
                s.Seek(-4, System.IO.SeekOrigin.Current);

                // Getting "not a ZipDirEntry signature" here is not always wrong or an error.
                // This can happen when walking through a zipfile.  After the last ZipDirEntry,
                // we expect to read an EndOfCentralDirectorySignature.  When we get this is how we
                // know we've reached the end of the central directory.
                if (signature != ZipConstants.EndOfCentralDirectorySignature)
                {
                    throw new Exception(String.Format("  ZipDirEntry::Read(): Bad signature ({0:X8}) at position 0x{1:X8}", signature, s.Position));
                }
                return(null);
            }

            byte[] block = new byte[42];
            int    n     = s.Read(block, 0, block.Length);

            if (n != block.Length)
            {
                return(null);
            }

            int         i   = 0;
            ZipDirEntry zde = new ZipDirEntry();

            zde._VersionMadeBy     = (short)(block[i++] + block[i++] * 256);
            zde._VersionNeeded     = (short)(block[i++] + block[i++] * 256);
            zde._BitField          = (short)(block[i++] + block[i++] * 256);
            zde._CompressionMethod = (short)(block[i++] + block[i++] * 256);
            zde._LastModDateTime   = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            zde._Crc32             = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            zde._CompressedSize    = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            zde._UncompressedSize  = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;

            zde._LastModified = SQLInstaller.Core.Zip.Shared.PackedToDateTime(zde._LastModDateTime);

            Int16 filenameLength   = (short)(block[i++] + block[i++] * 256);
            Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256);
            Int16 commentLength    = (short)(block[i++] + block[i++] * 256);
            Int16 diskNumber       = (short)(block[i++] + block[i++] * 256);

            zde._InternalFileAttrs = (short)(block[i++] + block[i++] * 256);
            zde._ExternalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            Int32 Offset = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;

            block         = new byte[filenameLength];
            n             = s.Read(block, 0, block.Length);
            zde._FileName = SQLInstaller.Core.Zip.Shared.StringFromBuffer(block, 0, block.Length);

            if (extraFieldLength > 0)
            {
                zde._Extra = new byte[extraFieldLength];
                n          = s.Read(zde._Extra, 0, zde._Extra.Length);
            }
            if (commentLength > 0)
            {
                block        = new byte[commentLength];
                n            = s.Read(block, 0, block.Length);
                zde._Comment = SQLInstaller.Core.Zip.Shared.StringFromBuffer(block, 0, block.Length);
            }
            return(zde);
        }