internal static ZipIOLocalFileHeader ParseRecord(BinaryReader reader, Encoding encoding) { ZipIOLocalFileHeader header = new ZipIOLocalFileHeader(); header._signature = reader.ReadUInt32(); 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._fileName = reader.ReadBytes(header._fileNameLength); ZipIOZip64ExtraFieldUsage none = ZipIOZip64ExtraFieldUsage.None; if (header._versionNeededToExtract >= 0x2d) { if (header._compressedSize == uint.MaxValue) { none |= ZipIOZip64ExtraFieldUsage.CompressedSize; } if (header._uncompressedSize == uint.MaxValue) { none |= ZipIOZip64ExtraFieldUsage.UncompressedSize; } } header._extraField = ZipIOExtraField.ParseRecord(reader, none, header._extraFieldLength); header._stringFileName = ZipIOBlockManager.ValidateNormalizeFileName(encoding.GetString(header._fileName)); header.Validate(); 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 static ZipIOExtraField ParseRecord(BinaryReader reader, ZipIOZip64ExtraFieldUsage zip64extraFieldUsage, ushort expectedExtraFieldSize) { if (expectedExtraFieldSize == 0) { if (zip64extraFieldUsage != ZipIOZip64ExtraFieldUsage.None) { throw new FileFormatException(SR.Get("CorruptedData")); } return(CreateNew(false)); } ZipIOExtraField field = new ZipIOExtraField(); while (expectedExtraFieldSize > 0) { if (expectedExtraFieldSize < ZipIOExtraFieldElement.MinimumSize) { throw new FileFormatException(SR.Get("CorruptedData")); } ZipIOExtraFieldElement element = ZipIOExtraFieldElement.Parse(reader, zip64extraFieldUsage); ZipIOExtraFieldZip64Element element3 = element as ZipIOExtraFieldZip64Element; ZipIOExtraFieldPaddingElement element2 = element as ZipIOExtraFieldPaddingElement; if (element3 != null) { if (field._zip64Element != null) { throw new FileFormatException(SR.Get("CorruptedData")); } field._zip64Element = element3; } else if (element2 != null) { if (field._paddingElement != null) { throw new FileFormatException(SR.Get("CorruptedData")); } field._paddingElement = element2; } else { if (field._extraFieldElements == null) { field._extraFieldElements = new ArrayList(3); } field._extraFieldElements.Add(element); } expectedExtraFieldSize = (ushort)(expectedExtraFieldSize - element.Size); } if (expectedExtraFieldSize != 0) { throw new FileFormatException(SR.Get("CorruptedData")); } if (field._zip64Element == null) { field._zip64Element = ZipIOExtraFieldZip64Element.CreateNew(); } return(field); }
internal static ZipIOExtraFieldElement Parse(BinaryReader reader, ZipIOZip64ExtraFieldUsage zip64extraFieldUsage) { // we can safely parse the Id and Size here // since the minimum size is checked from the caller (ZipIoExtraField) UInt16 id = reader.ReadUInt16(); UInt16 size = reader.ReadUInt16(); ZipIOExtraFieldElement newElement; if (id == ZipIOExtraFieldZip64Element.ConstantFieldId) // Found Zip64 Extra Field element { newElement = new ZipIOExtraFieldZip64Element(); ((ZipIOExtraFieldZip64Element)newElement).Zip64ExtraFieldUsage = zip64extraFieldUsage; } else if (id == ZipIOExtraFieldPaddingElement.ConstantFieldId) // Found potential Padding Extra Field element { // Even if the id matches Padding Extra Element id, we cannot be sure if it is Microsoft defined one // until its signature is verified // This extra field matches Padding Extra Element id, but it is not big enough to be ours if (size < ZipIOExtraFieldPaddingElement.MinimumFieldDataSize) { // Treat it as an unknown Extra Field element newElement = new ZipIOExtraFieldElement(id); } else { // Sniff bytes to check it it matches our Padding extra field signature byte[] sniffedBytes = reader.ReadBytes(ZipIOExtraFieldPaddingElement.SignatureSize); if (ZipIOExtraFieldPaddingElement.MatchesPaddingSignature(sniffedBytes)) { // Signature matches the Padding Extra Field signature newElement = new ZipIOExtraFieldPaddingElement(); } else { // Signature doesn't match; treat it a an unknown Extra Field element newElement = new ZipIOExtraFieldElement(id, sniffedBytes); } } } else { newElement = new ZipIOExtraFieldElement(id); } // Parse the data field of the Extra Field element newElement.ParseDataField(reader, size); return(newElement); }
internal static ZipIOExtraFieldElement Parse(BinaryReader reader, ZipIOZip64ExtraFieldUsage zip64extraFieldUsage) { // we can safely parse the Id and Size here // since the minimum size is checked from the caller (ZipIoExtraField) UInt16 id = reader.ReadUInt16(); UInt16 size = reader.ReadUInt16(); ZipIOExtraFieldElement newElement; if (id == ZipIOExtraFieldZip64Element.ConstantFieldId) // Found Zip64 Extra Field element { newElement = new ZipIOExtraFieldZip64Element(); ((ZipIOExtraFieldZip64Element) newElement).Zip64ExtraFieldUsage = zip64extraFieldUsage; } else if (id == ZipIOExtraFieldPaddingElement.ConstantFieldId) // Found potential Padding Extra Field element { // Even if the id matches Padding Extra Element id, we cannot be sure if it is Microsoft defined one // until its signature is verified // This extra field matches Padding Extra Element id, but it is not big enough to be ours if (size < ZipIOExtraFieldPaddingElement.MinimumFieldDataSize) { // Treat it as an unknown Extra Field element newElement = new ZipIOExtraFieldElement(id); } else { // Sniff bytes to check it it matches our Padding extra field signature byte[] sniffedBytes = reader.ReadBytes(ZipIOExtraFieldPaddingElement.SignatureSize); if (ZipIOExtraFieldPaddingElement.MatchesPaddingSignature(sniffedBytes)) { // Signature matches the Padding Extra Field signature newElement = new ZipIOExtraFieldPaddingElement(); } else { // Signature doesn't match; treat it a an unknown Extra Field element newElement = new ZipIOExtraFieldElement(id, sniffedBytes); } } } else { newElement = new ZipIOExtraFieldElement(id); } // Parse the data field of the Extra Field element newElement.ParseDataField(reader, size); return newElement; }
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); ZipIOZip64ExtraFieldUsage none = ZipIOZip64ExtraFieldUsage.None; if (header._versionNeededToExtract >= 0x2d) { if (header._compressedSize == uint.MaxValue) { none |= ZipIOZip64ExtraFieldUsage.CompressedSize; } if (header._uncompressedSize == uint.MaxValue) { none |= ZipIOZip64ExtraFieldUsage.UncompressedSize; } if (header._relativeOffsetOfLocalHeader == uint.MaxValue) { none |= ZipIOZip64ExtraFieldUsage.OffsetOfLocalHeader; } if (header._diskNumberStart == 0xffff) { none |= ZipIOZip64ExtraFieldUsage.DiskNumber; } } header._extraField = ZipIOExtraField.ParseRecord(reader, none, header._extraFieldLength); header._fileComment = reader.ReadBytes(header._fileCommentLength); header._stringFileName = ZipIOBlockManager.ValidateNormalizeFileName(encoding.GetString(header._fileName)); header.Validate(); return(header); }
internal static ZipIOExtraFieldElement Parse(BinaryReader reader, ZipIOZip64ExtraFieldUsage zip64extraFieldUsage) { ZipIOExtraFieldElement element; ushort id = reader.ReadUInt16(); ushort size = reader.ReadUInt16(); if (id == ZipIOExtraFieldZip64Element.ConstantFieldId) { element = new ZipIOExtraFieldZip64Element(); ((ZipIOExtraFieldZip64Element)element).Zip64ExtraFieldUsage = zip64extraFieldUsage; } else if (id == ZipIOExtraFieldPaddingElement.ConstantFieldId) { if (size < ZipIOExtraFieldPaddingElement.MinimumFieldDataSize) { element = new ZipIOExtraFieldElement(id); } else { byte[] sniffiedBytes = reader.ReadBytes(ZipIOExtraFieldPaddingElement.SignatureSize); if (ZipIOExtraFieldPaddingElement.MatchesPaddingSignature(sniffiedBytes)) { element = new ZipIOExtraFieldPaddingElement(); } else { element = new ZipIOExtraFieldElement(id, sniffiedBytes); } } } else { element = new ZipIOExtraFieldElement(id); } element.ParseDataField(reader, size); return(element); }
// Methods internal ZipIOExtraFieldZip64Element() : base(1) { this._zip64ExtraFieldUsage = ZipIOZip64ExtraFieldUsage.None; }
internal static ZipIOExtraField ParseRecord(BinaryReader reader, ZipIOZip64ExtraFieldUsage zip64extraFieldUsage, ushort expectedExtraFieldSize) { // most of the files are not ZIP 64, and instead of trying to parse it we should create new empty record if (expectedExtraFieldSize == 0) { if (zip64extraFieldUsage != ZipIOZip64ExtraFieldUsage.None) { // in case there is an expectation by the caller for a non empty record we should throw throw new FileFormatException(SR.Get(SRID.CorruptedData)); } // We are creating Extra Fields for the existing Local File Header, // so no need to create a new padding field return(CreateNew(false)); } ZipIOExtraField extraField = new ZipIOExtraField(); // Parse all Extra elements from Extra Field while (expectedExtraFieldSize > 0) { if (expectedExtraFieldSize < ZipIOExtraFieldElement.MinimumSize) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } ZipIOExtraFieldElement newElement = ZipIOExtraFieldElement.Parse(reader, zip64extraFieldUsage); ZipIOExtraFieldZip64Element zip64Element = newElement as ZipIOExtraFieldZip64Element; ZipIOExtraFieldPaddingElement paddingElement = newElement as ZipIOExtraFieldPaddingElement; // if we have found the Zip 64 record. let's remember it if (zip64Element != null) { if (extraField._zip64Element != null) { // multiple ZIP 64 extra fields are not allowed throw new FileFormatException(SR.Get(SRID.CorruptedData)); } extraField._zip64Element = zip64Element; } else if (paddingElement != null) { if (extraField._paddingElement != null) { // multiple padding extra fields are not allowed throw new FileFormatException(SR.Get(SRID.CorruptedData)); } extraField._paddingElement = paddingElement; } else { if (extraField._extraFieldElements == null) { extraField._extraFieldElements = new ArrayList(3); // we expect to see a few records there, as it sould have been produced by other authoring systems. } // any other instances of extra fields with the same id are allowed extraField._extraFieldElements.Add(newElement); } checked { expectedExtraFieldSize -= newElement.Size; } } // if we didn't end up at the exact expected position, we are treating this as a corrupted file if (expectedExtraFieldSize != 0) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } // As we treat the ZIP 64 extra field as optional for all version >= 4.5 // we need to explicitly consider a case when it is missing if (extraField._zip64Element == null) { extraField._zip64Element = ZipIOExtraFieldZip64Element.CreateNew(); } ///////////////////////////////////////////////////////////////////// // extraField.Validate(); // an instance Validate function is removed to fix FxCop violation, please add it back // if extra validation steps are required // // we are checking for uniqueness of the Zip 64 header ID in the Parse function. // Although it might be a good idea to check for record id uniqueness in general, // we are treating the rest of the field as a bag of bits, so it is probably not worth it to // search for other duplicate ID especially as appnote considers ID duplication a possibility // and even suggest a work around for file producers. ///////////////////////////////////////////////////////////////////// return(extraField); }
internal static ZipIOExtraField ParseRecord(BinaryReader reader, ZipIOZip64ExtraFieldUsage zip64extraFieldUsage, ushort expectedExtraFieldSize) { // most of the files are not ZIP 64, and instead of trying to parse it we should create new empty record if (expectedExtraFieldSize == 0) { if (zip64extraFieldUsage != ZipIOZip64ExtraFieldUsage.None) { // in case there is an expectation by the caller for a non empty record we should throw throw new FileFormatException(SR.Get(SRID.CorruptedData)); } // We are creating Extra Fields for the existing Local File Header, // so no need to create a new padding field return CreateNew(false); } ZipIOExtraField extraField = new ZipIOExtraField(); // Parse all Extra elements from Extra Field while (expectedExtraFieldSize > 0) { if (expectedExtraFieldSize < ZipIOExtraFieldElement.MinimumSize) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } ZipIOExtraFieldElement newElement = ZipIOExtraFieldElement.Parse(reader, zip64extraFieldUsage); ZipIOExtraFieldZip64Element zip64Element = newElement as ZipIOExtraFieldZip64Element; ZipIOExtraFieldPaddingElement paddingElement = newElement as ZipIOExtraFieldPaddingElement; // if we have found the Zip 64 record. let's remember it if (zip64Element != null) { if (extraField._zip64Element != null) { // multiple ZIP 64 extra fields are not allowed throw new FileFormatException(SR.Get(SRID.CorruptedData)); } extraField._zip64Element = zip64Element; } else if (paddingElement != null) { if (extraField._paddingElement != null) { // multiple padding extra fields are not allowed throw new FileFormatException(SR.Get(SRID.CorruptedData)); } extraField._paddingElement = paddingElement; } else { if (extraField._extraFieldElements == null) extraField._extraFieldElements = new ArrayList(3); // we expect to see a few records there, as it sould have been produced by other authoring systems. // any other instances of extra fields with the same id are allowed extraField._extraFieldElements.Add(newElement); } checked { expectedExtraFieldSize -= newElement.Size; } } // if we didn't end up at the exact expected position, we are treating this as a corrupted file if (expectedExtraFieldSize != 0) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } // As we treat the ZIP 64 extra field as optional for all version >= 4.5 // we need to explicitly consider a case when it is missing if (extraField._zip64Element == null) { extraField._zip64Element = ZipIOExtraFieldZip64Element.CreateNew(); } ///////////////////////////////////////////////////////////////////// // extraField.Validate(); // an instance Validate function is removed to fix FxCop violation, please add it back // if extra validation steps are required // // we are checking for uniqueness of the Zip 64 header ID in the Parse function. // Although it might be a good idea to check for record id uniqueness in general, // we are treating the rest of the field as a bag of bits, so it is probably not worth it to // search for other duplicate ID especially as appnote considers ID duplication a possibility // and even suggest a work around for file producers. ///////////////////////////////////////////////////////////////////// return extraField; }