Ejemplo n.º 1
0
        void ReadFrom(Stream zipStream)
        {
            while (zipStream.Position < zipStream.Length)
            {
                var reader = new BinaryReader(zipStream, Encoding.ASCII);
                uint localFileHeaderSignature = reader.ReadUInt32();
                if (localFileHeaderSignature != LOCAL_FILE_HEADER_SIGNATURE)
                {
                    // Local file entries are finished, next records are central directory records
                    break;
                }
                ushort versionNeededToExtract = reader.ReadUInt16();
                ushort generalPurposeBitFlag = reader.ReadUInt16();
                ushort compressionMethod = reader.ReadUInt16();
                if (compressionMethod != COMPRESSION_DEFLATE && compressionMethod != COMPRESSION_STORE)
                {
                    throw new NotSupportedException(ARCHIVE_FORMAT_NOT_SUPPORTED_STRING);
                }
                uint lastModifiedDateTime = reader.ReadUInt32();
                uint crc32 = reader.ReadUInt32();
                uint compressedSize = reader.ReadUInt32();
                uint uncompressedSize = reader.ReadUInt32();
                ushort fileNameLength = reader.ReadUInt16();
                ushort extraFieldLength = reader.ReadUInt16();
                //if (extraFieldLength != 0)
                //{
                //    throw new NotSupportedException(ARCHIVE_FORMAT_NOT_SUPPORTED_STRING);
                //}

                var fileNameBytes = reader.ReadBytes(fileNameLength);
                Encoding fileNameEncoding = (generalPurposeBitFlag & UTF8_FILE_NAME_ENCODING_FLAG) != 0
                                                    ? new UTF8Encoding()
                                                    : Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage);

                var fileName = new string(fileNameEncoding.GetChars(fileNameBytes));

                // According to ZIP specification, ZIP archives generally 
                // contain forward slashes so make Windows file name
                fileName = fileName.Replace('/', Path.DirectorySeparatorChar);

                ZipEntry entry;
                if (uncompressedSize != 0)
                {
                    var fileData = reader.ReadBytes((int)compressedSize);
                    var fileDataStream = new MemoryStream(fileData);
                    var fileEntry = new ZipFileEntry(fileName, fileDataStream);
                    if (compressionMethod == COMPRESSION_DEFLATE)
                    {
                        fileDataStream.Position = 0;
                        var deflateStream = new DeflateStream(fileDataStream, CompressionMode.Decompress);

                        var uncompressedFileData = new byte[uncompressedSize];

                        deflateStream.Read(uncompressedFileData, 0, (int)uncompressedSize);
                        fileEntry.Data = new MemoryStream(uncompressedFileData);
                    }
                    entry = fileEntry;
                }
                else if (fileName.EndsWith(@"\"))
                {
                    entry = new ZipDirectoryEntry(fileName);
                }
                else
                {
                    entry = new ZipFileEntry(fileName, null);
                }

                _entries.Add(entry);
                reader.ReadBytes(extraFieldLength);
            }
        }