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