示例#1
0
        private static bool ReadHeader(Stream s, ZipEntry ze)
        {
            var signature = Shared.ReadSignature(s);

            // return null if this is not a local file header signature
            if (SignatureIsNotValid(signature))
            {
                s.Seek(-4, SeekOrigin.Current);
                if (ze._Debug)
                {
                    Console.WriteLine("  ZipEntry::Read(): Bad signature ({0:X8}) at position {1}", signature,
                                      s.Position);
                }
                return(false);
            }

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

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

            var 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;
            }

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

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

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

            // transform the time data into something usable
            ze.LastModified = Shared.PackedToDateTime(ze._LastModDateTime);

            // actually get the compressed size and CRC if necessary
            if ((ze.BitField & 0x0008) == 0x0008)
            {
                var posn           = s.Position;
                var SizeOfDataRead = Shared.FindSignature(s, 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, SeekOrigin.Begin);
            }

            return(true);
        }