/// <summary>
        /// Creates a central file header from the information in a local file header.
        /// </summary>
        /// <param name="localFileHeader">Local file header to </param>
        public ZipFileHeader(ZipFileHeader localFileHeader)
        {
            if (localFileHeader.central)
            {
                throw new ArgumentException();
            }

            this.central           = true;
            this.compressionMethod = localFileHeader.compressionMethod;
            this.fileName          = localFileHeader.fileName;
            this.fileComment       = localFileHeader.fileComment;
            this.flags             = localFileHeader.flags;
            this.externalFileAttrs = localFileHeader.externalFileAttrs;
            this.internalFileAttrs = localFileHeader.internalFileAttrs;
            this.lastModDate       = localFileHeader.lastModDate;
            this.lastModTime       = localFileHeader.lastModTime;
            this.crc32             = localFileHeader.crc32;

            if (this.zip64)
            {
                this.versionMadeBy = 45;
                this.versionNeeded = 45;

                this.compressedSize   = UInt32.MaxValue;
                this.uncompressedSize = UInt32.MaxValue;
                this.diskStart        = UInt16.MaxValue;

                ZipExtraFileField field = new ZipExtraFileField();
                field.fieldType = ZipExtraFileFieldType.ZIP64;
                field.SetZip64Data(localFileHeader.compressedSize, localFileHeader.uncompressedSize, localFileHeader.localHeaderOffset, localFileHeader.diskStart);
                this.extraFields = new ZipExtraFileField[] { field };
            }
            else
            {
                this.versionMadeBy = 20;
                this.versionNeeded = 20;

                this.localHeaderOffset = localFileHeader.localHeaderOffset;
                this.compressedSize    = localFileHeader.compressedSize;
                this.uncompressedSize  = localFileHeader.uncompressedSize;
            }
        }
        public bool Read(Stream stream)
        {
            if (stream.Length - stream.Position < (this.central ? CFH_FIXEDSIZE : LFH_FIXEDSIZE))
            {
                return(false);
            }

            BinaryReader reader = new BinaryReader(stream);
            uint         sig    = reader.ReadUInt32();

            if (sig == SPANSIG || sig == SPANSIG2)
            {
                // Spanned zip files may optionally begin with a special marker.
                // Just ignore it and move on.
                sig = reader.ReadUInt32();
            }

            if (sig != (this.central ? CFHSIG : LFHSIG))
            {
                return(false);
            }

            this.versionMadeBy     = (this.central ? reader.ReadUInt16() : (ushort)0);
            this.versionNeeded     = reader.ReadUInt16();
            this.flags             = (ZipFileFlags)reader.ReadUInt16();
            this.compressionMethod = (ZipCompressionMethod)reader.ReadUInt16();
            this.lastModTime       = reader.ReadInt16();
            this.lastModDate       = reader.ReadInt16();
            this.crc32             = reader.ReadUInt32();
            this.compressedSize    = reader.ReadUInt32();
            this.uncompressedSize  = reader.ReadUInt32();

            this.zip64 = this.uncompressedSize == UInt32.MaxValue;

            int fileNameLength   = reader.ReadUInt16();
            int extraFieldLength = reader.ReadUInt16();
            int fileCommentLength;

            if (this.central)
            {
                fileCommentLength = reader.ReadUInt16();

                this.diskStart         = reader.ReadUInt16();
                this.internalFileAttrs = reader.ReadUInt16();
                this.externalFileAttrs = reader.ReadUInt32();
                this.localHeaderOffset = reader.ReadUInt32();
            }
            else
            {
                fileCommentLength      = 0;
                this.diskStart         = 0;
                this.internalFileAttrs = 0;
                this.externalFileAttrs = 0;
                this.localHeaderOffset = 0;
            }

            if (stream.Length - stream.Position < fileNameLength + extraFieldLength + fileCommentLength)
            {
                return(false);
            }

            Encoding headerEncoding = ((this.flags | ZipFileFlags.UTF8) != 0 ? Encoding.UTF8 : Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage));

            byte[] fileNameBytes = reader.ReadBytes(fileNameLength);
            this.fileName = headerEncoding.GetString(fileNameBytes);

            List <ZipExtraFileField> fields = new List <ZipExtraFileField>();

            while (extraFieldLength > 0)
            {
                ZipExtraFileField field = new ZipExtraFileField();
                if (!field.Read(stream, ref extraFieldLength))
                {
                    return(false);
                }
                fields.Add(field);
                if (field.fieldType == ZipExtraFileFieldType.ZIP64)
                {
                    this.zip64 = true;
                }
            }
            this.extraFields = fields.ToArray();

            byte[] fileCommentBytes = reader.ReadBytes(fileCommentLength);
            this.fileComment = headerEncoding.GetString(fileCommentBytes);

            return(true);
        }