Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Zip / ZipIOExtraField.cs / 1305600 / ZipIOExtraField.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 is used to implement parsing and // of the extra field optionally present in the fileHeader and Central Dir // // History: // 05/16/2005: IgorBel: Initial creation. // 03/23/2006: [....]: Added support for Padding Extra Field // //----------------------------------------------------------------------------- using System; using System.IO; using System.Diagnostics; using System.Collections; using System.Globalization; using System.Runtime.Serialization; using System.Windows; using MS.Internal.WindowsBase; namespace MS.Internal.IO.Zip { internal class ZipIOExtraField { internal static ZipIOExtraField CreateNew(bool createPadding) { // we have been asked to create a new record, current zip io implementation will add at most one Zip64 block ZipIOExtraField extraField = new ZipIOExtraField(); extraField._zip64Element = ZipIOExtraFieldZip64Element.CreateNew(); if (createPadding) { extraField._paddingElement = ZipIOExtraFieldPaddingElement.CreateNew(); } 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; } internal void Save(BinaryWriter writer) { // write Out the Zip 64 extra field first if (_zip64Element.SizeField > 0) { _zip64Element.Save(writer); } // write Out the padding field if (_paddingElement != null) { _paddingElement.Save(writer); } if (_extraFieldElements != null) { foreach (ZipIOExtraFieldElement extraFieldElement in _extraFieldElements) { extraFieldElement.Save(writer); } } } // Add or remove padding for the given size change internal void UpdatePadding(long size) { // If the local file header changed more than 100 bytes, it means // there are some logical errors Debug.Assert(Math.Abs(size) <= 100); // The header size change should be no more than what we can hold in UInt16 if (Math.Abs(size) > UInt16.MaxValue) return; // Header size increased; need to remove padding if there is an existing padding structure if (size > 0 && _paddingElement != null) { // There is enough padding left over to do size adjustment // No need to use checked{} since _paddingElement.PaddingSize >= size if (_paddingElement.PaddingSize >= size) _paddingElement.PaddingSize -= (UInt16) size; // The size of the whole padding structure exactly matches the size change else if (_paddingElement.Size == size) { // Then the padding structure can be completely removed // to accommodate the size change _paddingElement = null; } return; } // Header size decreased; need to add padding if (size < 0) { // Padding structure is not there but, the size change is big enough for one // to be created if (_paddingElement == null) { // No need to use checked{} since size is long type // and size < 0 // and (ZipIOExtraFieldPaddingElement.MinimumFieldDataSize + ZipIOExtraFieldElement.MinimumSize) // is small number that can not cause the overflow size += (ZipIOExtraFieldPaddingElement.MinimumFieldDataSize + ZipIOExtraFieldElement.MinimumSize); if (size >= 0) { _paddingElement = new ZipIOExtraFieldPaddingElement(); // No need to use checked{} since size > 0 and less than UInt16.MaxValue _paddingElement.PaddingSize = (UInt16) size; } } else { // Check if we hit the max padding allowed if ((_paddingElement.PaddingSize - size) > UInt16.MaxValue) return; // No need to use checked{} since we already check the overflow _paddingElement.PaddingSize = (UInt16) (_paddingElement.PaddingSize - size); } } } internal UInt16 Size { get { UInt16 size = 0; if (_extraFieldElements != null) { foreach (ZipIOExtraFieldElement extraFieldElement in _extraFieldElements) { checked{size += extraFieldElement.Size;} } } checked{size += _zip64Element.Size;} if (_paddingElement != null) { checked { size += _paddingElement.Size; } } return size; } } internal ZipIOZip64ExtraFieldUsage Zip64ExtraFieldUsage { get { return _zip64Element.Zip64ExtraFieldUsage; } set { _zip64Element.Zip64ExtraFieldUsage = value; } } internal UInt32 DiskNumberOfFileStart { get { return _zip64Element.DiskNumber; } } internal long OffsetOfLocalHeader { get { return _zip64Element.OffsetOfLocalHeader; } set { _zip64Element.OffsetOfLocalHeader = value; } } internal long CompressedSize { get { return _zip64Element.CompressedSize; } set { _zip64Element.CompressedSize = value; } } internal long UncompressedSize { get { return _zip64Element.UncompressedSize; } set { _zip64Element.UncompressedSize = value; } } private ZipIOExtraField() { } private ArrayList _extraFieldElements; private ZipIOExtraFieldZip64Element _zip64Element; private ZipIOExtraFieldPaddingElement _paddingElement; } } // 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 is used to implement parsing and // of the extra field optionally present in the fileHeader and Central Dir // // History: // 05/16/2005: IgorBel: Initial creation. // 03/23/2006: [....]: Added support for Padding Extra Field // //----------------------------------------------------------------------------- using System; using System.IO; using System.Diagnostics; using System.Collections; using System.Globalization; using System.Runtime.Serialization; using System.Windows; using MS.Internal.WindowsBase; namespace MS.Internal.IO.Zip { internal class ZipIOExtraField { internal static ZipIOExtraField CreateNew(bool createPadding) { // we have been asked to create a new record, current zip io implementation will add at most one Zip64 block ZipIOExtraField extraField = new ZipIOExtraField(); extraField._zip64Element = ZipIOExtraFieldZip64Element.CreateNew(); if (createPadding) { extraField._paddingElement = ZipIOExtraFieldPaddingElement.CreateNew(); } 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; } internal void Save(BinaryWriter writer) { // write Out the Zip 64 extra field first if (_zip64Element.SizeField > 0) { _zip64Element.Save(writer); } // write Out the padding field if (_paddingElement != null) { _paddingElement.Save(writer); } if (_extraFieldElements != null) { foreach (ZipIOExtraFieldElement extraFieldElement in _extraFieldElements) { extraFieldElement.Save(writer); } } } // Add or remove padding for the given size change internal void UpdatePadding(long size) { // If the local file header changed more than 100 bytes, it means // there are some logical errors Debug.Assert(Math.Abs(size) <= 100); // The header size change should be no more than what we can hold in UInt16 if (Math.Abs(size) > UInt16.MaxValue) return; // Header size increased; need to remove padding if there is an existing padding structure if (size > 0 && _paddingElement != null) { // There is enough padding left over to do size adjustment // No need to use checked{} since _paddingElement.PaddingSize >= size if (_paddingElement.PaddingSize >= size) _paddingElement.PaddingSize -= (UInt16) size; // The size of the whole padding structure exactly matches the size change else if (_paddingElement.Size == size) { // Then the padding structure can be completely removed // to accommodate the size change _paddingElement = null; } return; } // Header size decreased; need to add padding if (size < 0) { // Padding structure is not there but, the size change is big enough for one // to be created if (_paddingElement == null) { // No need to use checked{} since size is long type // and size < 0 // and (ZipIOExtraFieldPaddingElement.MinimumFieldDataSize + ZipIOExtraFieldElement.MinimumSize) // is small number that can not cause the overflow size += (ZipIOExtraFieldPaddingElement.MinimumFieldDataSize + ZipIOExtraFieldElement.MinimumSize); if (size >= 0) { _paddingElement = new ZipIOExtraFieldPaddingElement(); // No need to use checked{} since size > 0 and less than UInt16.MaxValue _paddingElement.PaddingSize = (UInt16) size; } } else { // Check if we hit the max padding allowed if ((_paddingElement.PaddingSize - size) > UInt16.MaxValue) return; // No need to use checked{} since we already check the overflow _paddingElement.PaddingSize = (UInt16) (_paddingElement.PaddingSize - size); } } } internal UInt16 Size { get { UInt16 size = 0; if (_extraFieldElements != null) { foreach (ZipIOExtraFieldElement extraFieldElement in _extraFieldElements) { checked{size += extraFieldElement.Size;} } } checked{size += _zip64Element.Size;} if (_paddingElement != null) { checked { size += _paddingElement.Size; } } return size; } } internal ZipIOZip64ExtraFieldUsage Zip64ExtraFieldUsage { get { return _zip64Element.Zip64ExtraFieldUsage; } set { _zip64Element.Zip64ExtraFieldUsage = value; } } internal UInt32 DiskNumberOfFileStart { get { return _zip64Element.DiskNumber; } } internal long OffsetOfLocalHeader { get { return _zip64Element.OffsetOfLocalHeader; } set { _zip64Element.OffsetOfLocalHeader = value; } } internal long CompressedSize { get { return _zip64Element.CompressedSize; } set { _zip64Element.CompressedSize = value; } } internal long UncompressedSize { get { return _zip64Element.UncompressedSize; } set { _zip64Element.UncompressedSize = value; } } private ZipIOExtraField() { } private ArrayList _extraFieldElements; private ZipIOExtraFieldZip64Element _zip64Element; private ZipIOExtraFieldPaddingElement _paddingElement; } } // 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
- CriticalFileToken.cs
- PEFileEvidenceFactory.cs
- FamilyCollection.cs
- BindToObject.cs
- TiffBitmapDecoder.cs
- BufferedGraphicsContext.cs
- DoubleIndependentAnimationStorage.cs
- ProgressiveCrcCalculatingStream.cs
- TransformConverter.cs
- VisualTreeUtils.cs
- CategoryGridEntry.cs
- SqlExpander.cs
- CornerRadius.cs
- EventListenerClientSide.cs
- TextBoxAutoCompleteSourceConverter.cs
- MimeXmlReflector.cs
- MailAddress.cs
- XmlCustomFormatter.cs
- PathFigureCollectionConverter.cs
- InstanceKey.cs
- EventProperty.cs
- BatchWriter.cs
- XmlSchemaIdentityConstraint.cs
- TabControlCancelEvent.cs
- NameNode.cs
- BasePropertyDescriptor.cs
- DecoderReplacementFallback.cs
- SemanticBasicElement.cs
- HtmlButton.cs
- CngAlgorithmGroup.cs
- CodeSnippetCompileUnit.cs
- DeploymentExceptionMapper.cs
- SafeArrayTypeMismatchException.cs
- TrackingMemoryStream.cs
- WebPartEventArgs.cs
- PenContext.cs
- NeutralResourcesLanguageAttribute.cs
- Renderer.cs
- SvcMapFile.cs
- ControlBindingsCollection.cs
- ObjectListCommand.cs
- IsolatedStorageFilePermission.cs
- VectorAnimationUsingKeyFrames.cs
- Certificate.cs
- Timer.cs
- StyleSheetRefUrlEditor.cs
- SaveFileDialogDesigner.cs
- APCustomTypeDescriptor.cs
- OdbcConnection.cs
- GroupBoxRenderer.cs
- HtmlInputImage.cs
- Accessible.cs
- HashMembershipCondition.cs
- configsystem.cs
- ComplexTypeEmitter.cs
- DesignerWithHeader.cs
- TablePattern.cs
- AttributeParameterInfo.cs
- TraceContext.cs
- DoubleConverter.cs
- CodeVariableReferenceExpression.cs
- StyleCollection.cs
- _DomainName.cs
- WebPartUserCapability.cs
- SoapWriter.cs
- RegionData.cs
- HttpHandlersSection.cs
- StylusPointPropertyInfo.cs
- EmptyEnumerable.cs
- BitmapEffectInput.cs
- RelatedCurrencyManager.cs
- _ShellExpression.cs
- ReflectionServiceProvider.cs
- WorkflowOwnershipException.cs
- PerfService.cs
- Crypto.cs
- DoubleUtil.cs
- ComboBox.cs
- StorageMappingFragment.cs
- GridViewItemAutomationPeer.cs
- SchemaDeclBase.cs
- ReadonlyMessageFilter.cs
- NavigationPropertyEmitter.cs
- TransportConfigurationTypeElement.cs
- StringUtil.cs
- SecurityContext.cs
- RemoteWebConfigurationHostStream.cs
- XslAstAnalyzer.cs
- TransformFinalBlockRequest.cs
- TemplateColumn.cs
- NumericUpDownAccelerationCollection.cs
- SizeAnimationClockResource.cs
- _UriSyntax.cs
- ValidationResult.cs
- TypeExtensionSerializer.cs
- ColorConvertedBitmapExtension.cs
- HtmlEncodedRawTextWriter.cs
- BitHelper.cs
- OrderedDictionary.cs
- DataDocumentXPathNavigator.cs