Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Zip / ZipIOCentralDirectoryFileHeader.cs / 1305600 / ZipIOCentralDirectoryFileHeader.cs
//------------------------------------------------------------------------------ //------------- *** WARNING *** //------------- This file is part of a legally monitored development project. //------------- Do not check in changes to this project. Do not raid bugs on this //------------- code in the main PS database. Do not contact the owner of this //------------- code directly. Contact the legal team at ‘ZSLegal’ for assistance. //------------- *** WARNING *** //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // This is an internal class that enables interactions with Zip archives // for OPC scenarios // // History: // 11/19/2004: IgorBel: Initial creation. // //----------------------------------------------------------------------------- using System; using System.IO; using System.Diagnostics; using System.Text; using System.Collections; using System.Runtime.Serialization; using System.Windows; using MS.Internal.WindowsBase; namespace MS.Internal.IO.Zip { internal class ZipIOCentralDirectoryFileHeader { internal static ZipIOCentralDirectoryFileHeader CreateNew(Encoding encoding, ZipIOLocalFileBlock fileBlock) { ZipIOCentralDirectoryFileHeader header = new ZipIOCentralDirectoryFileHeader(encoding); // initialize fields that are not duplicated in the local file block(header) header._fileCommentLength =0; header._fileComment = null; header._diskNumberStart = 0; header._internalFileAttributes = 0; header._externalFileAttributes = 0; header._versionMadeBy = (ushort)ZipIOVersionNeededToExtract.Zip64FileFormat; header._extraField = ZipIOExtraField.CreateNew(false /* no padding */); // update the rest of the fields based on the local file header header.UpdateFromLocalFileBlock(fileBlock); return header; } internal static ZipIOCentralDirectoryFileHeader ParseRecord(BinaryReader reader, Encoding encoding) { ZipIOCentralDirectoryFileHeader header = new ZipIOCentralDirectoryFileHeader(encoding); header._signature = reader.ReadUInt32(); header._versionMadeBy = reader.ReadUInt16(); header._versionNeededToExtract = reader.ReadUInt16(); header._generalPurposeBitFlag = reader.ReadUInt16(); header._compressionMethod = reader.ReadUInt16(); header._lastModFileDateTime = reader.ReadUInt32(); header._crc32 = reader.ReadUInt32(); header._compressedSize = reader.ReadUInt32(); header._uncompressedSize = reader.ReadUInt32(); header._fileNameLength = reader.ReadUInt16(); header._extraFieldLength = reader.ReadUInt16(); header._fileCommentLength = reader.ReadUInt16(); header._diskNumberStart = reader.ReadUInt16(); header._internalFileAttributes = reader.ReadUInt16(); header._externalFileAttributes = reader.ReadUInt32(); header._relativeOffsetOfLocalHeader = reader.ReadUInt32(); header._fileName = reader.ReadBytes(header._fileNameLength); // check for the ZIP 64 version and escaped values ZipIOZip64ExtraFieldUsage zip64extraFieldUsage = ZipIOZip64ExtraFieldUsage.None; if (header._versionNeededToExtract >= (ushort)ZipIOVersionNeededToExtract.Zip64FileFormat) { if (header._compressedSize == UInt32.MaxValue) { zip64extraFieldUsage |= ZipIOZip64ExtraFieldUsage.CompressedSize; } if (header._uncompressedSize == UInt32.MaxValue) { zip64extraFieldUsage |= ZipIOZip64ExtraFieldUsage.UncompressedSize; } if (header._relativeOffsetOfLocalHeader == UInt32.MaxValue) { zip64extraFieldUsage |= ZipIOZip64ExtraFieldUsage.OffsetOfLocalHeader; } if (header._diskNumberStart == UInt16.MaxValue) { zip64extraFieldUsage |= ZipIOZip64ExtraFieldUsage.DiskNumber; } } // if the ZIP 64 record is missing the zip64extraFieldUsage value will be ignored header._extraField = ZipIOExtraField.ParseRecord(reader, zip64extraFieldUsage, header._extraFieldLength); header._fileComment = reader.ReadBytes(header._fileCommentLength); //populate frequently used field with user friendly data representations header._stringFileName = ZipIOBlockManager.ValidateNormalizeFileName(encoding.GetString(header._fileName)); header.Validate(); return header; } internal void Save(BinaryWriter writer) { writer.Write(_signatureConstant); writer.Write(_versionMadeBy); writer.Write(_versionNeededToExtract); writer.Write(_generalPurposeBitFlag); writer.Write(_compressionMethod); writer.Write(_lastModFileDateTime); writer.Write(_crc32); writer.Write(_compressedSize); writer.Write(_uncompressedSize); writer.Write(_fileNameLength); writer.Write(_extraField.Size); writer.Write(_fileCommentLength); writer.Write(_diskNumberStart); writer.Write(_internalFileAttributes); writer.Write(_externalFileAttributes); writer.Write(_relativeOffsetOfLocalHeader); Debug.Assert(_fileNameLength > 0); // we validate this for both parsing and API entry points writer.Write(_fileName, 0, _fileNameLength); _extraField.Save(writer); if (_fileCommentLength > 0) { writer.Write(_fileComment , 0, _fileCommentLength); } } internal bool UpdateIfNeeded(ZipIOLocalFileBlock fileBlock) { if (CheckIfUpdateNeeded(fileBlock)) { UpdateFromLocalFileBlock(fileBlock); return true; } else { return false; } } internal string FileName { get { return _stringFileName; } // set method if needed will have to update both the _stringFileName and // _fileName } internal UInt16 VersionNeededToExtract { get { return _versionNeededToExtract; } } internal UInt16 GeneralPurposeBitFlag { get { return _generalPurposeBitFlag; } } internal CompressionMethodEnum CompressionMethod { get { // cast is safe because the value is validated in Validate() return (CompressionMethodEnum)_compressionMethod; } } internal long Size { get { return checked(_fixedMinimalRecordSize + _fileNameLength + _extraField.Size + _fileCommentLength); } } internal long OffsetOfLocalHeader { get { if ((_extraField.Zip64ExtraFieldUsage & ZipIOZip64ExtraFieldUsage.OffsetOfLocalHeader) != 0) { // zip 64 extra field is there return _extraField.OffsetOfLocalHeader; } else { // 32 bit case return _relativeOffsetOfLocalHeader; } } } internal long CompressedSize { get { if ((_extraField.Zip64ExtraFieldUsage & ZipIOZip64ExtraFieldUsage.CompressedSize) != 0) { // zip 64 extra field is there return _extraField.CompressedSize; } else { // 32 bit case return _compressedSize; } } } internal long UncompressedSize { get { if ((_extraField.Zip64ExtraFieldUsage & ZipIOZip64ExtraFieldUsage.UncompressedSize) != 0) { // zip 64 extra field is there return _extraField.UncompressedSize; } else { // 32 bit case return _uncompressedSize; } } } internal UInt32 Crc32 { get { return _crc32; } } internal UInt32 DiskNumberStart { get { if ((_extraField.Zip64ExtraFieldUsage & ZipIOZip64ExtraFieldUsage.DiskNumber) != 0) { // zip 64 extra field is there (32 bit value returned) return _extraField.DiskNumberOfFileStart; } else { // 16 bit case return _diskNumberStart;; } } } internal bool FolderFlag { get { // The upper byte of version made by indicates the compatibility of the file attribute information. // If the external file attributes are compatible with MS-DOS then this value // will be zero. // lower byte of the external file attribute is the the MS-DOS directory attribute byte // // 0x20 5 file has been changed since last backup // 0x10 4 entry represents a subdirectory XXXXXXXXX // 0x08 3 entry represents a volume label // 0x04 2 system file // 0x02 1 hidden file // 0x01 0 read-only return ((_versionMadeBy & 0xFF00) == _constantUpperVersionMadeByMsDos) && ((_externalFileAttributes & 0x10) != 0); } } internal bool VolumeLabelFlag { get { // The upper byte of version made by indicates the compatibility of the file attribute information. // If the external file attributes are compatible with MS-DOS then this value // will be zero. // lower byte of the external file attribute is the the MS-DOS directory attribute byte // // 0x20 5 file has been changed since last backup // 0x10 4 entry represents a subdirectory // 0x08 3 entry represents a volume label XXXXXXXXX // 0x04 2 system file // 0x02 1 hidden file // 0x01 0 read-only return ((_versionMadeBy & 0xFF00) == _constantUpperVersionMadeByMsDos) && ((_externalFileAttributes & 0x08) != 0); } } // this function is called by the Central Dir in order to notify us that // the appropriate file item was shifted (as detected by the shift in the Raw Data Block) // holding given file item. // for us it means that although all the size characteristics are preserved (local file header // wasn't even parsed if it still in the Raw). But the offset could have changed which // might result in Zip64 struicture. internal void MoveReference(long shiftSize) { UpdateZip64Structures(CompressedSize, UncompressedSize, checked(OffsetOfLocalHeader +shiftSize)); } // this function is sets the sizes into the either 64 or 32 bit structures based on values of the fields // It used in 2 places by the MoveReference and by the UpdateFromLocalFileBlock private void UpdateZip64Structures (long compressedSize, long uncompressedSize, long offset) { Debug.Assert((compressedSize >= 0) && (uncompressedSize>=0) && (offset >=0)); // according to the appnote central directory extra field might be a mix of any values based on escaping // we will fully (without disk number) use it every time we are building a ZIP 64 arhichive // we also trying to stay on the safe side and treeat the boundary case of 32 escape values // as a zip 64 scenrio if ((compressedSize >= UInt32.MaxValue) || (uncompressedSize >= UInt32.MaxValue) || (offset >= UInt32.MaxValue)) { // Zip 64 case _extraField.CompressedSize = compressedSize; _extraField.UncompressedSize = uncompressedSize; _extraField.OffsetOfLocalHeader = offset; //set proper escape values _compressedSize = UInt32.MaxValue; _uncompressedSize = UInt32.MaxValue; _relativeOffsetOfLocalHeader = UInt32.MaxValue; // update version needed to extract to 4.5 _versionNeededToExtract = (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat; } else { // 32 bit case _compressedSize = checked((UInt32)compressedSize); _uncompressedSize = checked((UInt32)uncompressedSize); _relativeOffsetOfLocalHeader = checked((UInt32)offset); // reset the extra ZIP 64 field to empty _extraField.Zip64ExtraFieldUsage = ZipIOZip64ExtraFieldUsage.None; // version needed to extract needs to be recalculated from scratch based on compression _versionNeededToExtract = (UInt16)ZipIOBlockManager.CalcVersionNeededToExtractFromCompression ((CompressionMethodEnum)_compressionMethod); } } private void UpdateFromLocalFileBlock(ZipIOLocalFileBlock fileBlock) { Debug.Assert(DiskNumberStart == 0); _signature = _signatureConstant; _generalPurposeBitFlag = fileBlock.GeneralPurposeBitFlag; _compressionMethod = (UInt16)fileBlock.CompressionMethod; _lastModFileDateTime = fileBlock.LastModFileDateTime; _crc32 = fileBlock.Crc32; // file name is easy to copy _fileNameLength = (UInt16)fileBlock.FileName.Length; // this is safe cast as file name is always validate for size _fileName = _encoding.GetBytes(fileBlock.FileName); _stringFileName = fileBlock.FileName; // this will properly update the 32 or zip 64 fields UpdateZip64Structures(fileBlock.CompressedSize, fileBlock.UncompressedSize, fileBlock.Offset); // Previous instruction may determine that we don't really need 4.5, but we // want to ensure that the version is identical with what is stored in the local file header. Debug.Assert(_versionNeededToExtract <= fileBlock.VersionNeededToExtract, "Should never be making this smaller"); _versionNeededToExtract = fileBlock.VersionNeededToExtract; // These fields are intentionally ignored, as they are not present in the local header //_fileCommentLength; //_fileComment; //_diskNumberStart; //_internalFileAttributes; //_externalFileAttributes; } private bool CheckIfUpdateNeeded(ZipIOLocalFileBlock fileBlock) { // there is a special case for the _generalPurposeBitFlag.Bit #3 // it could be set in the local file header indicating streaming // creation, while it doesn't need to be set in the Central directory // so having // (fileBlock.GeneralPurposeBitFlag == 8 && and _generalPurposeBitFlag == 0) // is a valid case when update is not required // let's compare the 3rd bit of the general purpose bit flag bool localFileHeaderStreamingFlag = (0 != (fileBlock.GeneralPurposeBitFlag & _streamingBitMask)); bool centralDirStreamingFlag = (0 != (_generalPurposeBitFlag & _streamingBitMask)); if (!localFileHeaderStreamingFlag && centralDirStreamingFlag) { // the mismatch if local file header in non streaming but the central directory is in streaming mode // all the other combinations do not require an update and valid as is // this includes scenario when local file header is in streaming and central dir is not return true; } Debug.Assert(String.CompareOrdinal(_stringFileName, fileBlock.FileName) == 0); return (_signature != _signatureConstant) || (_versionNeededToExtract != fileBlock.VersionNeededToExtract) || (_generalPurposeBitFlag != fileBlock.GeneralPurposeBitFlag) || (_compressionMethod != (UInt16)fileBlock.CompressionMethod) || (_crc32 != fileBlock.Crc32) || (CompressedSize != fileBlock.CompressedSize) || (UncompressedSize != fileBlock.UncompressedSize) || (OffsetOfLocalHeader != fileBlock.Offset); // These fields are intentionally ignored, as they are not present in the local header //_fileCommentLength; //_fileComment; //_diskNumberStart; //_internalFileAttributes; //_externalFileAttributes; } private ZipIOCentralDirectoryFileHeader(Encoding encoding) { _encoding = encoding; } private void Validate () { if (_signature != _signatureConstant) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } if (DiskNumberStart != 0) { throw new NotSupportedException(SR.Get(SRID.NotSupportedMultiDisk)); } if (_fileNameLength != _fileName.Length) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } if (_extraFieldLength != _extraField.Size) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } ZipArchive.VerifyVersionNeededToExtract(_versionNeededToExtract); // if verson is below 4.5 make sure that ZIP 64 extra filed isn't present // if it is it might be a security concern if ((_versionNeededToExtract < (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat) && (_extraField.Zip64ExtraFieldUsage != ZipIOZip64ExtraFieldUsage.None)) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } if (_fileCommentLength != _fileComment.Length) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } if ((_compressionMethod != (UInt16)CompressionMethodEnum.Stored) && (_compressionMethod != (UInt16)CompressionMethodEnum.Deflated)) { throw new NotSupportedException(SR.Get(SRID.ZipNotSupportedCompressionMethod)); } } private Encoding _encoding; private const int _fixedMinimalRecordSize = 46; private const byte _constantUpperVersionMadeByMsDos = 0x0; private const UInt16 _streamingBitMask = 0x08; // bit #3 private const UInt32 _signatureConstant = 0x02014b50; private UInt32 _signature = _signatureConstant; // we expect all variables to be initialized to 0 private UInt16 _versionMadeBy; private UInt16 _versionNeededToExtract; private UInt16 _generalPurposeBitFlag; private UInt16 _compressionMethod; private UInt32 _lastModFileDateTime; private UInt32 _crc32; private UInt32 _compressedSize; private UInt32 _uncompressedSize; private UInt16 _fileNameLength; private UInt16 _extraFieldLength; private UInt16 _fileCommentLength; private UInt16 _diskNumberStart; private UInt16 _internalFileAttributes; private UInt32 _externalFileAttributes; private UInt32 _relativeOffsetOfLocalHeader; private byte[] _fileName; private ZipIOExtraField _extraField; private byte[] _fileComment; //duplicate dat for fast access private string _stringFileName; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ //------------- *** WARNING *** //------------- This file is part of a legally monitored development project. //------------- Do not check in changes to this project. Do not raid bugs on this //------------- code in the main PS database. Do not contact the owner of this //------------- code directly. Contact the legal team at ‘ZSLegal’ for assistance. //------------- *** WARNING *** //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // This is an internal class that enables interactions with Zip archives // for OPC scenarios // // History: // 11/19/2004: IgorBel: Initial creation. // //----------------------------------------------------------------------------- using System; using System.IO; using System.Diagnostics; using System.Text; using System.Collections; using System.Runtime.Serialization; using System.Windows; using MS.Internal.WindowsBase; namespace MS.Internal.IO.Zip { internal class ZipIOCentralDirectoryFileHeader { internal static ZipIOCentralDirectoryFileHeader CreateNew(Encoding encoding, ZipIOLocalFileBlock fileBlock) { ZipIOCentralDirectoryFileHeader header = new ZipIOCentralDirectoryFileHeader(encoding); // initialize fields that are not duplicated in the local file block(header) header._fileCommentLength =0; header._fileComment = null; header._diskNumberStart = 0; header._internalFileAttributes = 0; header._externalFileAttributes = 0; header._versionMadeBy = (ushort)ZipIOVersionNeededToExtract.Zip64FileFormat; header._extraField = ZipIOExtraField.CreateNew(false /* no padding */); // update the rest of the fields based on the local file header header.UpdateFromLocalFileBlock(fileBlock); return header; } internal static ZipIOCentralDirectoryFileHeader ParseRecord(BinaryReader reader, Encoding encoding) { ZipIOCentralDirectoryFileHeader header = new ZipIOCentralDirectoryFileHeader(encoding); header._signature = reader.ReadUInt32(); header._versionMadeBy = reader.ReadUInt16(); header._versionNeededToExtract = reader.ReadUInt16(); header._generalPurposeBitFlag = reader.ReadUInt16(); header._compressionMethod = reader.ReadUInt16(); header._lastModFileDateTime = reader.ReadUInt32(); header._crc32 = reader.ReadUInt32(); header._compressedSize = reader.ReadUInt32(); header._uncompressedSize = reader.ReadUInt32(); header._fileNameLength = reader.ReadUInt16(); header._extraFieldLength = reader.ReadUInt16(); header._fileCommentLength = reader.ReadUInt16(); header._diskNumberStart = reader.ReadUInt16(); header._internalFileAttributes = reader.ReadUInt16(); header._externalFileAttributes = reader.ReadUInt32(); header._relativeOffsetOfLocalHeader = reader.ReadUInt32(); header._fileName = reader.ReadBytes(header._fileNameLength); // check for the ZIP 64 version and escaped values ZipIOZip64ExtraFieldUsage zip64extraFieldUsage = ZipIOZip64ExtraFieldUsage.None; if (header._versionNeededToExtract >= (ushort)ZipIOVersionNeededToExtract.Zip64FileFormat) { if (header._compressedSize == UInt32.MaxValue) { zip64extraFieldUsage |= ZipIOZip64ExtraFieldUsage.CompressedSize; } if (header._uncompressedSize == UInt32.MaxValue) { zip64extraFieldUsage |= ZipIOZip64ExtraFieldUsage.UncompressedSize; } if (header._relativeOffsetOfLocalHeader == UInt32.MaxValue) { zip64extraFieldUsage |= ZipIOZip64ExtraFieldUsage.OffsetOfLocalHeader; } if (header._diskNumberStart == UInt16.MaxValue) { zip64extraFieldUsage |= ZipIOZip64ExtraFieldUsage.DiskNumber; } } // if the ZIP 64 record is missing the zip64extraFieldUsage value will be ignored header._extraField = ZipIOExtraField.ParseRecord(reader, zip64extraFieldUsage, header._extraFieldLength); header._fileComment = reader.ReadBytes(header._fileCommentLength); //populate frequently used field with user friendly data representations header._stringFileName = ZipIOBlockManager.ValidateNormalizeFileName(encoding.GetString(header._fileName)); header.Validate(); return header; } internal void Save(BinaryWriter writer) { writer.Write(_signatureConstant); writer.Write(_versionMadeBy); writer.Write(_versionNeededToExtract); writer.Write(_generalPurposeBitFlag); writer.Write(_compressionMethod); writer.Write(_lastModFileDateTime); writer.Write(_crc32); writer.Write(_compressedSize); writer.Write(_uncompressedSize); writer.Write(_fileNameLength); writer.Write(_extraField.Size); writer.Write(_fileCommentLength); writer.Write(_diskNumberStart); writer.Write(_internalFileAttributes); writer.Write(_externalFileAttributes); writer.Write(_relativeOffsetOfLocalHeader); Debug.Assert(_fileNameLength > 0); // we validate this for both parsing and API entry points writer.Write(_fileName, 0, _fileNameLength); _extraField.Save(writer); if (_fileCommentLength > 0) { writer.Write(_fileComment , 0, _fileCommentLength); } } internal bool UpdateIfNeeded(ZipIOLocalFileBlock fileBlock) { if (CheckIfUpdateNeeded(fileBlock)) { UpdateFromLocalFileBlock(fileBlock); return true; } else { return false; } } internal string FileName { get { return _stringFileName; } // set method if needed will have to update both the _stringFileName and // _fileName } internal UInt16 VersionNeededToExtract { get { return _versionNeededToExtract; } } internal UInt16 GeneralPurposeBitFlag { get { return _generalPurposeBitFlag; } } internal CompressionMethodEnum CompressionMethod { get { // cast is safe because the value is validated in Validate() return (CompressionMethodEnum)_compressionMethod; } } internal long Size { get { return checked(_fixedMinimalRecordSize + _fileNameLength + _extraField.Size + _fileCommentLength); } } internal long OffsetOfLocalHeader { get { if ((_extraField.Zip64ExtraFieldUsage & ZipIOZip64ExtraFieldUsage.OffsetOfLocalHeader) != 0) { // zip 64 extra field is there return _extraField.OffsetOfLocalHeader; } else { // 32 bit case return _relativeOffsetOfLocalHeader; } } } internal long CompressedSize { get { if ((_extraField.Zip64ExtraFieldUsage & ZipIOZip64ExtraFieldUsage.CompressedSize) != 0) { // zip 64 extra field is there return _extraField.CompressedSize; } else { // 32 bit case return _compressedSize; } } } internal long UncompressedSize { get { if ((_extraField.Zip64ExtraFieldUsage & ZipIOZip64ExtraFieldUsage.UncompressedSize) != 0) { // zip 64 extra field is there return _extraField.UncompressedSize; } else { // 32 bit case return _uncompressedSize; } } } internal UInt32 Crc32 { get { return _crc32; } } internal UInt32 DiskNumberStart { get { if ((_extraField.Zip64ExtraFieldUsage & ZipIOZip64ExtraFieldUsage.DiskNumber) != 0) { // zip 64 extra field is there (32 bit value returned) return _extraField.DiskNumberOfFileStart; } else { // 16 bit case return _diskNumberStart;; } } } internal bool FolderFlag { get { // The upper byte of version made by indicates the compatibility of the file attribute information. // If the external file attributes are compatible with MS-DOS then this value // will be zero. // lower byte of the external file attribute is the the MS-DOS directory attribute byte // // 0x20 5 file has been changed since last backup // 0x10 4 entry represents a subdirectory XXXXXXXXX // 0x08 3 entry represents a volume label // 0x04 2 system file // 0x02 1 hidden file // 0x01 0 read-only return ((_versionMadeBy & 0xFF00) == _constantUpperVersionMadeByMsDos) && ((_externalFileAttributes & 0x10) != 0); } } internal bool VolumeLabelFlag { get { // The upper byte of version made by indicates the compatibility of the file attribute information. // If the external file attributes are compatible with MS-DOS then this value // will be zero. // lower byte of the external file attribute is the the MS-DOS directory attribute byte // // 0x20 5 file has been changed since last backup // 0x10 4 entry represents a subdirectory // 0x08 3 entry represents a volume label XXXXXXXXX // 0x04 2 system file // 0x02 1 hidden file // 0x01 0 read-only return ((_versionMadeBy & 0xFF00) == _constantUpperVersionMadeByMsDos) && ((_externalFileAttributes & 0x08) != 0); } } // this function is called by the Central Dir in order to notify us that // the appropriate file item was shifted (as detected by the shift in the Raw Data Block) // holding given file item. // for us it means that although all the size characteristics are preserved (local file header // wasn't even parsed if it still in the Raw). But the offset could have changed which // might result in Zip64 struicture. internal void MoveReference(long shiftSize) { UpdateZip64Structures(CompressedSize, UncompressedSize, checked(OffsetOfLocalHeader +shiftSize)); } // this function is sets the sizes into the either 64 or 32 bit structures based on values of the fields // It used in 2 places by the MoveReference and by the UpdateFromLocalFileBlock private void UpdateZip64Structures (long compressedSize, long uncompressedSize, long offset) { Debug.Assert((compressedSize >= 0) && (uncompressedSize>=0) && (offset >=0)); // according to the appnote central directory extra field might be a mix of any values based on escaping // we will fully (without disk number) use it every time we are building a ZIP 64 arhichive // we also trying to stay on the safe side and treeat the boundary case of 32 escape values // as a zip 64 scenrio if ((compressedSize >= UInt32.MaxValue) || (uncompressedSize >= UInt32.MaxValue) || (offset >= UInt32.MaxValue)) { // Zip 64 case _extraField.CompressedSize = compressedSize; _extraField.UncompressedSize = uncompressedSize; _extraField.OffsetOfLocalHeader = offset; //set proper escape values _compressedSize = UInt32.MaxValue; _uncompressedSize = UInt32.MaxValue; _relativeOffsetOfLocalHeader = UInt32.MaxValue; // update version needed to extract to 4.5 _versionNeededToExtract = (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat; } else { // 32 bit case _compressedSize = checked((UInt32)compressedSize); _uncompressedSize = checked((UInt32)uncompressedSize); _relativeOffsetOfLocalHeader = checked((UInt32)offset); // reset the extra ZIP 64 field to empty _extraField.Zip64ExtraFieldUsage = ZipIOZip64ExtraFieldUsage.None; // version needed to extract needs to be recalculated from scratch based on compression _versionNeededToExtract = (UInt16)ZipIOBlockManager.CalcVersionNeededToExtractFromCompression ((CompressionMethodEnum)_compressionMethod); } } private void UpdateFromLocalFileBlock(ZipIOLocalFileBlock fileBlock) { Debug.Assert(DiskNumberStart == 0); _signature = _signatureConstant; _generalPurposeBitFlag = fileBlock.GeneralPurposeBitFlag; _compressionMethod = (UInt16)fileBlock.CompressionMethod; _lastModFileDateTime = fileBlock.LastModFileDateTime; _crc32 = fileBlock.Crc32; // file name is easy to copy _fileNameLength = (UInt16)fileBlock.FileName.Length; // this is safe cast as file name is always validate for size _fileName = _encoding.GetBytes(fileBlock.FileName); _stringFileName = fileBlock.FileName; // this will properly update the 32 or zip 64 fields UpdateZip64Structures(fileBlock.CompressedSize, fileBlock.UncompressedSize, fileBlock.Offset); // Previous instruction may determine that we don't really need 4.5, but we // want to ensure that the version is identical with what is stored in the local file header. Debug.Assert(_versionNeededToExtract <= fileBlock.VersionNeededToExtract, "Should never be making this smaller"); _versionNeededToExtract = fileBlock.VersionNeededToExtract; // These fields are intentionally ignored, as they are not present in the local header //_fileCommentLength; //_fileComment; //_diskNumberStart; //_internalFileAttributes; //_externalFileAttributes; } private bool CheckIfUpdateNeeded(ZipIOLocalFileBlock fileBlock) { // there is a special case for the _generalPurposeBitFlag.Bit #3 // it could be set in the local file header indicating streaming // creation, while it doesn't need to be set in the Central directory // so having // (fileBlock.GeneralPurposeBitFlag == 8 && and _generalPurposeBitFlag == 0) // is a valid case when update is not required // let's compare the 3rd bit of the general purpose bit flag bool localFileHeaderStreamingFlag = (0 != (fileBlock.GeneralPurposeBitFlag & _streamingBitMask)); bool centralDirStreamingFlag = (0 != (_generalPurposeBitFlag & _streamingBitMask)); if (!localFileHeaderStreamingFlag && centralDirStreamingFlag) { // the mismatch if local file header in non streaming but the central directory is in streaming mode // all the other combinations do not require an update and valid as is // this includes scenario when local file header is in streaming and central dir is not return true; } Debug.Assert(String.CompareOrdinal(_stringFileName, fileBlock.FileName) == 0); return (_signature != _signatureConstant) || (_versionNeededToExtract != fileBlock.VersionNeededToExtract) || (_generalPurposeBitFlag != fileBlock.GeneralPurposeBitFlag) || (_compressionMethod != (UInt16)fileBlock.CompressionMethod) || (_crc32 != fileBlock.Crc32) || (CompressedSize != fileBlock.CompressedSize) || (UncompressedSize != fileBlock.UncompressedSize) || (OffsetOfLocalHeader != fileBlock.Offset); // These fields are intentionally ignored, as they are not present in the local header //_fileCommentLength; //_fileComment; //_diskNumberStart; //_internalFileAttributes; //_externalFileAttributes; } private ZipIOCentralDirectoryFileHeader(Encoding encoding) { _encoding = encoding; } private void Validate () { if (_signature != _signatureConstant) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } if (DiskNumberStart != 0) { throw new NotSupportedException(SR.Get(SRID.NotSupportedMultiDisk)); } if (_fileNameLength != _fileName.Length) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } if (_extraFieldLength != _extraField.Size) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } ZipArchive.VerifyVersionNeededToExtract(_versionNeededToExtract); // if verson is below 4.5 make sure that ZIP 64 extra filed isn't present // if it is it might be a security concern if ((_versionNeededToExtract < (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat) && (_extraField.Zip64ExtraFieldUsage != ZipIOZip64ExtraFieldUsage.None)) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } if (_fileCommentLength != _fileComment.Length) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } if ((_compressionMethod != (UInt16)CompressionMethodEnum.Stored) && (_compressionMethod != (UInt16)CompressionMethodEnum.Deflated)) { throw new NotSupportedException(SR.Get(SRID.ZipNotSupportedCompressionMethod)); } } private Encoding _encoding; private const int _fixedMinimalRecordSize = 46; private const byte _constantUpperVersionMadeByMsDos = 0x0; private const UInt16 _streamingBitMask = 0x08; // bit #3 private const UInt32 _signatureConstant = 0x02014b50; private UInt32 _signature = _signatureConstant; // we expect all variables to be initialized to 0 private UInt16 _versionMadeBy; private UInt16 _versionNeededToExtract; private UInt16 _generalPurposeBitFlag; private UInt16 _compressionMethod; private UInt32 _lastModFileDateTime; private UInt32 _crc32; private UInt32 _compressedSize; private UInt32 _uncompressedSize; private UInt16 _fileNameLength; private UInt16 _extraFieldLength; private UInt16 _fileCommentLength; private UInt16 _diskNumberStart; private UInt16 _internalFileAttributes; private UInt32 _externalFileAttributes; private UInt32 _relativeOffsetOfLocalHeader; private byte[] _fileName; private ZipIOExtraField _extraField; private byte[] _fileComment; //duplicate dat for fast access private string _stringFileName; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SelectionChangedEventArgs.cs
- DependencyObjectPropertyDescriptor.cs
- WSHttpBinding.cs
- BCLDebug.cs
- BuildProviderInstallComponent.cs
- MultiTrigger.cs
- ListChangedEventArgs.cs
- Array.cs
- ActivityInstance.cs
- DataGridDefaultColumnWidthTypeConverter.cs
- XmlnsCache.cs
- WinInetCache.cs
- FlowDocumentScrollViewer.cs
- TreeBuilder.cs
- PropertyGridView.cs
- CompositeActivityMarkupSerializer.cs
- ToolStripPanelDesigner.cs
- AspCompat.cs
- TypeSystemProvider.cs
- ZipIOFileItemStream.cs
- XD.cs
- ProfilePropertySettings.cs
- PrivilegeNotHeldException.cs
- TabControlCancelEvent.cs
- DetailsViewUpdatedEventArgs.cs
- LoginUtil.cs
- PathData.cs
- SplitContainer.cs
- FixedSOMLineRanges.cs
- ZipIOExtraFieldZip64Element.cs
- DataException.cs
- ObjectTokenCategory.cs
- SqlConnectionPoolGroupProviderInfo.cs
- Freezable.cs
- RequestResizeEvent.cs
- PasswordPropertyTextAttribute.cs
- GenericTypeParameterBuilder.cs
- WinEventWrap.cs
- ObjectHandle.cs
- SqlConnectionPoolProviderInfo.cs
- X509CertificateStore.cs
- AuthorizationContext.cs
- DoubleAnimationBase.cs
- OdbcParameter.cs
- ButtonStandardAdapter.cs
- PropertyOverridesDialog.cs
- StringUtil.cs
- HMACMD5.cs
- Style.cs
- IndexerNameAttribute.cs
- Executor.cs
- HandlerBase.cs
- KeyConstraint.cs
- TextServicesProperty.cs
- PathSegmentCollection.cs
- EmptyReadOnlyDictionaryInternal.cs
- InvalidPropValue.cs
- DataGridViewCellCollection.cs
- HandledMouseEvent.cs
- ShutDownListener.cs
- TextEditorTyping.cs
- StylusPlugin.cs
- DataBindingCollection.cs
- HtmlInputButton.cs
- EventProxy.cs
- QueryRewriter.cs
- FacetEnabledSchemaElement.cs
- LinqDataSource.cs
- NativeMethods.cs
- VisualTarget.cs
- BulletedList.cs
- Compiler.cs
- Dispatcher.cs
- SafeNativeMethods.cs
- BitStack.cs
- SessionKeyExpiredException.cs
- OleAutBinder.cs
- XPathArrayIterator.cs
- ExponentialEase.cs
- ItemsPresenter.cs
- BinaryEditor.cs
- DataGridHeadersVisibilityToVisibilityConverter.cs
- XmlUtf8RawTextWriter.cs
- BitmapImage.cs
- BinaryObjectReader.cs
- DateTimeUtil.cs
- TagPrefixAttribute.cs
- MetadataFile.cs
- TextRunCacheImp.cs
- UserNameSecurityTokenAuthenticator.cs
- TransactionState.cs
- AudioLevelUpdatedEventArgs.cs
- SQLDateTime.cs
- Stylus.cs
- XmlDataImplementation.cs
- WebServiceEnumData.cs
- PenContext.cs
- TreeNodeClickEventArgs.cs
- AuthorizationRuleCollection.cs
- TextEditorSelection.cs