/// <summary> /// Auxiliary function of IPersistFile.Load. /// </summary> /// <returns> /// <value>A MemoryStream of the package file or a FileStream if the file is too big.</value> /// </returns> /// <remarks> /// <para>Use this method to load a package file completely to a memory buffer. /// After loading the file we can close the file, thus we can release the file /// lock quickly. However, there is a size limit on the file. If the /// file is too big (greater than _maxMemoryStreamBuffer), we cannot allow /// this method to consume too much memory. So we simply return the fileStream.</para> /// <para>Mode, access and sharing have already been checked or adjusted and can be assumed /// to be compatible with the goal of reading from the file.</para> /// </remarks> private static Stream FileToStream( string filePath, FileMode fileMode, FileAccess fileAccess, FileShare fileSharing, long maxMemoryStream) { FileInfo fi = new FileInfo(filePath); long byteCount = fi.Length; Stream s = new FileStream(filePath, fileMode, fileAccess, fileSharing); // There is a size limit of the file that we allow to be uploaded to a // memory stream. If the file size is bigger than the limit, simply return the fileStream. if (byteCount < maxMemoryStream) { // unchecked cast is safe because _maxMemoryStreamBuffer is less than Int32.Max MemoryStream ms = new MemoryStream(unchecked ((int)byteCount)); using (s) { PackagingUtilities.CopyStream(s, ms, byteCount, 0x1000); } s = ms; } return(s); }
//------------------------------------------------------ // // Protected Methods // //------------------------------------------------------ protected override void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // Non-standard pattern - call base.Dispose() first. // This is required because the base class is a stream and we cannot // delete the underlying file storage before it has a chance to close // and release it. base.Dispose(disposing); if (_path != null) { PackagingUtilities.DeleteIsolatedStorageFile(_path); _path = null; } //Decrement the count of files _folder.DecRef(); _folder = null; GC.SuppressFinalize(this); } _disposed = true; } }
/// <summary> /// Parse the DigestMethod tag /// </summary> /// <param name="reader"></param> private static string ParseDigestAlgorithmTag(XmlReader reader) { // verify namespace and lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) > 1 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || reader.Depth != 3) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } // get the Algorithm attribute string hashAlgorithm = null; if (reader.HasAttributes) { hashAlgorithm = reader.GetAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); } if (hashAlgorithm == null || hashAlgorithm.Length == 0) { throw new XmlException(SR.Get(SRID.UnsupportedHashAlgorithm)); } return(hashAlgorithm); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ /// <summary> /// Certificate to associate with this Certificate Part /// </summary> /// <value></value> /// <exception cref="FileFormatException">stream is too large</exception> internal X509Certificate2 GetCertificate() { // lazy init if (_certificate == null) { // obtain from the part using (Stream s = _part.GetStream()) { if (s.Length > 0) { // throw if stream is beyond any reasonable length if (s.Length > _maximumCertificateStreamLength) { throw new FileFormatException(SR.CorruptedData); } // X509Certificate constructor desires a byte array Byte[] byteArray = new Byte[s.Length]; PackagingUtilities.ReliableRead(s, byteArray, 0, (int)s.Length); _certificate = new X509Certificate2(byteArray); } } } return(_certificate); }
private void SwitchModeIfNecessary() { if (_isolatedStorageMode) { Debug.Assert(_memoryStreamList.Count == 0); // it must be empty in isolated storage mode // if we are in isolated storage mode we need to check the Low Water Mark crossing if (_isolatedStorageStream.Length < _lowWaterMark) { if (_isolatedStorageStream.Length > 0) { //build memory stream MemoryStreamBlock newMemStreamBlock = new MemoryStreamBlock (_trackingMemoryStreamFactory.Create((int)_isolatedStorageStream.Length), 0); //copy data from iso storage to memory stream _isolatedStorageStream.Seek(0, SeekOrigin.Begin); newMemStreamBlock.Stream.Seek(0, SeekOrigin.Begin); PackagingUtilities.CopyStream(_isolatedStorageStream, newMemStreamBlock.Stream, Int64.MaxValue /*bytes to copy*/, 0x80000 /*512K buffer size */); Debug.Assert(newMemStreamBlock.Stream.Length > 0); _memoryStreamList.Add(newMemStreamBlock); } //switch mode _isolatedStorageMode = false; // release isolated storage disk space by setting its length to 0 // This way we don't have to re-open the isolated storage again if the memory consumption // goes above the High Water Mark _isolatedStorageStream.SetLength(0); _isolatedStorageStream.Flush(); } } else { // if we are in Memory Stream mode we need to check the High Water Mark crossing if (_trackingMemoryStreamFactory.CurrentMemoryConsumption > _highWaterMark) { //copy data to isolated storage EnsureIsolatedStoreStream(); CopyMemoryBlocksToStream(_isolatedStorageStream); //switch mode _isolatedStorageMode = true; //release memory stream resources foreach (MemoryStreamBlock memStreamBlock in _memoryStreamList) { // this will report the appropriate Memory usage back to the ITrackingMemoryStreamFactory memStreamBlock.Stream.Close(); } _memoryStreamList.Clear(); } } }
private void EnsureIsolatedStoreStream() { if (_isolatedStorageStream == null) { _isolatedStorageStream = PackagingUtilities.CreateUserScopedIsolatedStorageFileStreamWithRandomName( 3, out _isolatedStorageStreamFileName); } }
//------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Stream Methods /// <summary> /// Return the bytes requested from the container /// </summary> /// <param name="buffer">destination buffer</param> /// <param name="offset">offset to write into that buffer</param> /// <param name="count">how many bytes requested</param> /// <returns>how many bytes were written into <paramref name="buffer" />.</returns> /// <remarks> /// The underlying stream, expected to be an IsolatedStorageFileStream, /// is trusted to leave the IO position unchanged in case of an exception. /// </remarks> public override int Read(byte[] buffer, int offset, int count) { CheckDisposed(); PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); return(_tempStream.Read(buffer, offset, count)); }
//------------------------------------------------------ // // Public Methods // //------------------------------------------------------ /// <summary> /// Return the bytes requested. /// </summary> /// <param name="buffer">Destination buffer.</param> /// <param name="offset"> /// The zero-based byte offset in buffer at which to begin storing the data read /// from the current stream. /// </param> /// <param name="count">How many bytes requested.</param> /// <returns>How many bytes were written into buffer.</returns> public override int Read(byte[] buffer, int offset, int count) { CheckClosed(); // Check arguments. PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); // Leave capability and FileAccess checks up to the underlying stream(s). // Reading 0 bytes is a no-op. if (count == 0) { return(0); } int pieceNumber = GetCurrentPieceNumber(); int totalBytesRead = 0; Stream pieceStream = _dir.GetStream(pieceNumber); checked { //Seek to the correct location in the underlying stream for the current piece pieceStream.Seek(_currentOffset - _dir.GetStartOffset(pieceNumber), SeekOrigin.Begin); while (totalBytesRead < count) { int numBytesRead = pieceStream.Read( buffer, offset + totalBytesRead, count - totalBytesRead); // End of the current stream: try to move to the next stream. if (numBytesRead == 0) { if (_dir.IsLastPiece(pieceNumber)) { break; } ++pieceNumber; Invariant.Assert(_dir.GetStartOffset(pieceNumber) == _currentOffset + totalBytesRead); pieceStream = _dir.GetStream(pieceNumber); //Seek inorder to set the correct pointer for the next piece stream pieceStream.Seek(0, SeekOrigin.Begin); } totalBytesRead += numBytesRead; } // Advance current position now we know the operation completed successfully. _currentOffset += totalBytesRead; } return(totalBytesRead); }
/// <summary> /// Parse the Relationship-specific Transform /// </summary> /// <param name="reader"></param> /// <param name="partUri"></param> /// <param name="relationshipSelectors">may be allocated but will never be empty</param> private static void ParseRelationshipsTransform(XmlReader reader, Uri partUri, ref List <PackageRelationshipSelector> relationshipSelectors) { Uri owningPartUri = PackUriHelper.GetSourcePartUriFromRelationshipPartUri(partUri); // find all of the Relationship tags of form: // <RelationshipReference SourceId="abc123" /> // or // <RelationshipsGroupReference SourceType="reference-type-of-the-week" /> while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element) && reader.Depth == 5) { // both types have no children, a single required attribute and belong to the OPC namespace if (reader.IsEmptyElement && PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1 && (String.CompareOrdinal(reader.NamespaceURI, XTable.Get(XTable.ID.OpcSignatureNamespace)) == 0)) { // <RelationshipReference>? if (String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.RelationshipReferenceTagName)) == 0) { // RelationshipReference tags are legal and these must be empty with a single SourceId attribute // get the SourceId attribute string id = reader.GetAttribute(XTable.Get(XTable.ID.SourceIdAttrName)); if (id != null && id.Length > 0) { if (relationshipSelectors == null) { relationshipSelectors = new List <PackageRelationshipSelector>(); } // we found a legal SourceId so create a selector and continue searching relationshipSelectors.Add(new PackageRelationshipSelector(owningPartUri, PackageRelationshipSelectorType.Id, id)); continue; } } // <RelationshipsGroupReference>? else if ((String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.RelationshipsGroupReferenceTagName)) == 0)) { // RelationshipsGroupReference tags must be empty with a single SourceType attribute string type = reader.GetAttribute(XTable.Get(XTable.ID.SourceTypeAttrName)); if (type != null && type.Length > 0) { // lazy init if (relationshipSelectors == null) { relationshipSelectors = new List <PackageRelationshipSelector>(); } // got a legal SourceType attribute relationshipSelectors.Add(new PackageRelationshipSelector(owningPartUri, PackageRelationshipSelectorType.Type, type)); continue; } } } // if we get to here, we have not found a legal tag so we throw throw new XmlException(SR.Get(SRID.UnexpectedXmlTag, reader.LocalName)); } }
/// <summary> /// Write /// </summary> public override void Write(byte[] buffer, int offset, int count) { CheckDisposed(); PackagingUtilities.VerifyStreamWriteArgs(this, buffer, offset, count); // no-op if (count == 0) { return; } _tempStream.Write(buffer, offset, count); _dirty = true; }
// Token: 0x06006CB1 RID: 27825 RVA: 0x001F44D8 File Offset: 0x001F26D8 private static Stream FileToStream(string filePath, FileMode fileMode, FileAccess fileAccess, FileShare fileSharing, long maxMemoryStream) { FileInfo fileInfo = new FileInfo(filePath); long length = fileInfo.Length; Stream stream = new FileStream(filePath, fileMode, fileAccess, fileSharing); if (length < maxMemoryStream) { MemoryStream memoryStream = new MemoryStream((int)length); using (stream) { PackagingUtilities.CopyStream(stream, memoryStream, length, 4096); } stream = memoryStream; } return(stream); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ /// <summary> /// WriteToStream(Stream stream) writes the sparse Memory stream to the Stream provided as parameter /// starting at the current position in the stream /// </summary> internal void WriteToStream(Stream stream) { checked { if (_isolatedStorageMode) { _isolatedStorageStream.Seek(0, SeekOrigin.Begin); PackagingUtilities.CopyStream(_isolatedStorageStream, stream, Int64.MaxValue /*bytes to copy*/, 0x80000 /*512K buffer size */); } else { CopyMemoryBlocksToStream(stream); } } }
/// <summary> /// Parse the DigestValue tag /// </summary> /// <param name="reader"></param> private static string ParseDigestValueTag(XmlReader reader) { Debug.Assert(reader != null); // verify namespace and lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) > 0 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || reader.Depth != 3) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } // there are no legal attributes and the only content must be text if (reader.HasAttributes || (reader.Read() && reader.MoveToContent() != XmlNodeType.Text)) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } // get the Value return(reader.ReadString()); }
//------------------------------------------------------ // // Public Methods // //------------------------------------------------------ /// <summary> /// Return the bytes requested. /// </summary> /// <param name="buffer">Destination buffer.</param> /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param> /// <param name="count">How many bytes requested.</param> /// <returns>How many bytes were written into buffer.</returns> public unsafe override int Read(byte[] buffer, int offset, int count) { ThrowIfStreamDisposed(); // Check arguments. PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); // Reading 0 bytes is a no-op. if (count == 0) { return(0); } // Prepare location of return value and call the COM object. int bytesRead; IntPtr pBytesRead = new IntPtr(&bytesRead); // Prepare to restore position in case the read fails. long positionBeforeReadAttempt = this.Position; try { // Pin the array wrt GC while using an address in it. fixed(byte *bufferPointer = &buffer[offset]) { _oleStream.Read(new IntPtr(bufferPointer), count, pBytesRead); } } catch (COMException comException) { this.Position = positionBeforeReadAttempt; throw new IOException("Read", comException); } catch (IOException ioException) { this.Position = positionBeforeReadAttempt; throw new IOException("Read", ioException); } return(bytesRead); }
override public void Write(byte[] buffer, int offset, int count) { CheckDisposed(); #if DEBUG DebugAssertConsistentArrayStructure(); #endif PackagingUtilities.VerifyStreamWriteArgs(this, buffer, offset, count); Debug.Assert(_currentStreamPosition >= 0); if (count == 0) { return; } checked { if (_isolatedStorageMode) { lock (PackagingUtilities.IsolatedStorageFileLock) { _isolatedStorageStream.Seek(_currentStreamPosition, SeekOrigin.Begin); _isolatedStorageStream.Write(buffer, offset, count); } _currentStreamPosition += count; } else { WriteAndCollapseBlocks(buffer, offset, count); } _currentStreamLength = Math.Max(_currentStreamLength, _currentStreamPosition); } // this can potentially affect memory consumption SwitchModeIfNecessary(); #if DEBUG DebugAssertConsistentArrayStructure(); #endif }
// Token: 0x06006C85 RID: 27781 RVA: 0x001F3B74 File Offset: 0x001F1D74 public unsafe override int Read(byte[] buffer, int offset, int count) { this.ThrowIfStreamDisposed(); PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); if (count == 0) { return(0); } int result; IntPtr refToNumBytesRead = new IntPtr((void *)(&result)); long position = this.Position; try { try { fixed(byte *ptr = &buffer[offset]) { this._oleStream.Read(new IntPtr((void *)ptr), count, refToNumBytesRead); } } finally { byte *ptr = null; } } catch (COMException innerException) { this.Position = position; throw new IOException("Read", innerException); } catch (IOException innerException2) { this.Position = position; throw new IOException("Read", innerException2); } return(result); }
/// <summary> /// Get the part uri and it's content type from the current Reference tag /// </summary> /// <param name="reader"></param> /// <param name="contentType">contentType extracted from the query portion of the Uri</param> /// <returns>PackagePart uri and contentType</returns> private static Uri ParsePartUri(XmlReader reader, out ContentType contentType) { // should be a relative Package uri with a query portion that contains the ContentType contentType = ContentType.Empty; Uri partUri = null; // must be one and only one attribute if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1) { string uriAttrValue = reader.GetAttribute(XTable.Get(XTable.ID.UriAttrName)); if (uriAttrValue != null) { partUri = ParsePartUriAttribute(uriAttrValue, out contentType); } } // will be null if we had no success if (partUri == null) { throw new XmlException(SR.Get(SRID.RequiredXmlAttributeMissing, XTable.Get(XTable.ID.UriAttrName))); } return(partUri); }
// Deserialize properties part. private void ParseCorePropertyPart(PackagePart part) { Stream stream = part.GetStream(FileMode.Open, FileAccess.Read); // Create a reader that uses _nameTable so as to use the set of tag literals // in effect as a set of atomic identifiers. XmlTextReader reader = new XmlTextReader(stream, _nameTable); //Prohibit DTD from the markup as per the OPC spec reader.ProhibitDtd = true; //This method expects the reader to be in ReadState.Initial. //It will make the first read call. PackagingUtilities.PerformInitailReadAndVerifyEncoding(reader); //Note: After the previous method call the reader should be at the first tag in the markup. //MoveToContent - Skips over the following - ProcessingInstruction, DocumentType, Comment, Whitespace, or SignificantWhitespace //If the reader is currently at a content node then this function call is a no-op if (reader.MoveToContent() != XmlNodeType.Element || (object)reader.NamespaceURI != PackageXmlStringTable.GetXmlStringAsObject(PackageXmlEnum.PackageCorePropertiesNamespace) || (object)reader.LocalName != PackageXmlStringTable.GetXmlStringAsObject(PackageXmlEnum.CoreProperties)) { throw new XmlException(SR.Get(SRID.CorePropertiesElementExpected), null, reader.LineNumber, reader.LinePosition); } // The schema is closed and defines no attributes on the root element. if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) != 0) { throw new XmlException(SR.Get(SRID.PropertyWrongNumbOfAttribsDefinedOn, reader.Name), null, reader.LineNumber, reader.LinePosition); } // Iterate through property elements until EOF. Note the proper closing of all // open tags is checked by the reader itself. // This loop deals only with depth-1 start tags. Handling of element content // is delegated to dedicated functions. int attributesCount; while (reader.Read() && reader.MoveToContent() != XmlNodeType.None) { // Ignore end-tags. We check element errors on opening tags. if (reader.NodeType == XmlNodeType.EndElement) { continue; } // Any content markup that is not an element here is unexpected. if (reader.NodeType != XmlNodeType.Element) { throw new XmlException(SR.Get(SRID.PropertyStartTagExpected), null, reader.LineNumber, reader.LinePosition); } // Any element below the root should open at level 1 exclusively. if (reader.Depth != 1) { throw new XmlException(SR.Get(SRID.NoStructuredContentInsideProperties), null, reader.LineNumber, reader.LinePosition); } attributesCount = PackagingUtilities.GetNonXmlnsAttributeCount(reader); // Property elements can occur in any order (xsd:all). object localName = reader.LocalName; PackageXmlEnum xmlStringIndex = PackageXmlStringTable.GetEnumOf(localName); String valueType = PackageXmlStringTable.GetValueType(xmlStringIndex); if (Array.IndexOf(_validProperties, xmlStringIndex) == -1) // An unexpected element is an error. { throw new XmlException( SR.Get(SRID.InvalidPropertyNameInCorePropertiesPart, reader.LocalName), null, reader.LineNumber, reader.LinePosition); } // Any element not in the valid core properties namespace is unexpected. // The following is an object comparison, not a string comparison. if ((object)reader.NamespaceURI != PackageXmlStringTable.GetXmlStringAsObject(PackageXmlStringTable.GetXmlNamespace(xmlStringIndex))) { throw new XmlException(SR.Get(SRID.UnknownNamespaceInCorePropertiesPart), null, reader.LineNumber, reader.LinePosition); } if (String.CompareOrdinal(valueType, "String") == 0) { // The schema is closed and defines no attributes on this type of element. if (attributesCount != 0) { throw new XmlException(SR.Get(SRID.PropertyWrongNumbOfAttribsDefinedOn, reader.Name), null, reader.LineNumber, reader.LinePosition); } RecordNewBinding(xmlStringIndex, GetStringData(reader), true /*initializing*/, reader); } else if (String.CompareOrdinal(valueType, "DateTime") == 0) { int allowedAttributeCount = (object)reader.NamespaceURI == PackageXmlStringTable.GetXmlStringAsObject(PackageXmlEnum.DublinCoreTermsNamespace) ? 1 : 0; // The schema is closed and defines no attributes on this type of element. if (attributesCount != allowedAttributeCount) { throw new XmlException(SR.Get(SRID.PropertyWrongNumbOfAttribsDefinedOn, reader.Name), null, reader.LineNumber, reader.LinePosition); } if (allowedAttributeCount != 0) { ValidateXsiType(reader, PackageXmlStringTable.GetXmlStringAsObject(PackageXmlEnum.DublinCoreTermsNamespace), _w3cdtf); } RecordNewBinding(xmlStringIndex, GetDateData(reader), true /*initializing*/, reader); } else // An unexpected element is an error. { Invariant.Assert(false, "Unknown value type for properties"); } } }
/// <summary> /// Parse PackageRelationship Stream /// </summary> /// <param name="part">relationship part</param> /// <exception cref="XmlException">Thrown if XML is malformed</exception> private void ParseRelationshipPart(PackagePart part) { //We can safely open the stream as FileAccess.Read, as this code //should only be invoked if the Package has been opened in Read or ReadWrite mode. Debug.Assert(_package.FileOpenAccess == FileAccess.Read || _package.FileOpenAccess == FileAccess.ReadWrite, "This method should only be called when FileAccess is Read or ReadWrite"); using (Stream s = part.GetStream(FileMode.Open, FileAccess.Read)) { // load from the relationship part associated with the given part using (XmlTextReader baseReader = new XmlTextReader(s)) { baseReader.WhitespaceHandling = WhitespaceHandling.None; //Prohibit DTD from the markup as per the OPC spec baseReader.ProhibitDtd = true; using (XmlCompatibilityReader reader = new XmlCompatibilityReader(baseReader, RelationshipKnownNamespaces)) { //This method expects the reader to be in ReadState.Initial. //It will make the first read call. PackagingUtilities.PerformInitailReadAndVerifyEncoding(baseReader); //Note: After the previous method call the reader should be at the first tag in the markup. //MoveToContent - Skips over the following - ProcessingInstruction, DocumentType, Comment, Whitespace, or SignificantWhitespace //If the reader is currently at a content node then this function call is a no-op reader.MoveToContent(); // look for our tag and namespace pair - throw if other elements are encountered // Make sure that the current node read is an Element if (reader.NodeType == XmlNodeType.Element && (reader.Depth == 0) && (String.CompareOrdinal(RelationshipsTagName, reader.LocalName) == 0) && (String.CompareOrdinal(PackagingUtilities.RelationshipNamespaceUri, reader.NamespaceURI) == 0)) { ThrowIfXmlBaseAttributeIsPresent(reader); //There should be a namespace Attribute present at this level. //Also any other attribute on the <Relationships> tag is an error including xml: and xsi: attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) > 0) { throw new XmlException(SR.Get(SRID.RelationshipsTagHasExtraAttributes), null, reader.LineNumber, reader.LinePosition); } // start tag encountered for Relationships // now parse individual Relationship tags while (reader.Read()) { //Skips over the following - ProcessingInstruction, DocumentType, Comment, Whitespace, or SignificantWhitespace //If the reader is currently at a content node then this function call is a no-op reader.MoveToContent(); //If MoveToContent() takes us to the end of the content if (reader.NodeType == XmlNodeType.None) { continue; } if (reader.NodeType == XmlNodeType.Element && (reader.Depth == 1) && (String.CompareOrdinal(RelationshipTagName, reader.LocalName) == 0) && (String.CompareOrdinal(PackagingUtilities.RelationshipNamespaceUri, reader.NamespaceURI) == 0)) { ThrowIfXmlBaseAttributeIsPresent(reader); int expectedAttributesCount = 3; string targetModeAttributeValue = reader.GetAttribute(TargetModeAttributeName); if (targetModeAttributeValue != null) { expectedAttributesCount++; } //check if there are expected number of attributes. //Also any other attribute on the <Relationship> tag is an error including xml: and xsi: attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == expectedAttributesCount) { ProcessRelationshipAttributes(reader); //Skip the EndElement for Relationship if (!reader.IsEmptyElement) { ProcessEndElementForRelationshipTag(reader); } } else { throw new XmlException(SR.Get(SRID.RelationshipTagDoesntMatchSchema), null, reader.LineNumber, reader.LinePosition); } } else if (!(String.CompareOrdinal(RelationshipsTagName, reader.LocalName) == 0 && (reader.NodeType == XmlNodeType.EndElement))) { throw new XmlException(SR.Get(SRID.UnknownTagEncountered), null, reader.LineNumber, reader.LinePosition); } } } else { throw new XmlException(SR.Get(SRID.ExpectedRelationshipsElementTag), null, reader.LineNumber, reader.LinePosition); } } } } }
/// <summary> /// Parses Transforms tag /// </summary> /// <param name="reader">node to parse</param> /// <param name="partUri">Part Uri for the part owning the relationships</param> /// <param name="relationshipSelectors">allocates and returns a list of /// PackageRelationshipSelectors if Relationship transform</param> /// <returns>ordered list of Transform names</returns> private static List <String> ParseTransformsTag(XmlReader reader, Uri partUri, ref List <PackageRelationshipSelector> relationshipSelectors) { // # reference that signs multiple PackageRelationships // <Reference URI="/shared/_rels/image.jpg.rels?ContentType=image/jpg"> // <Transforms> // <Transform Algorithm="http://schemas.openxmlformats.org/package/2006/RelationshipTransform"> // <RelationshipReference SourceId="1" /> // <RelationshipReference SourceId="2" /> // <RelationshipReference SourceId="8" /> // </Transform> // <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /> // </Transforms> // <DigestMethod Algorithm="sha1" /> // <DigestValue>... </DigestValue> // </Reference> // verify lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) != 0) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } List <String> transforms = null; bool relationshipTransformFound = false; int transformsCountWhenRelationshipTransformFound = 0; // Look for transforms. // There are currently only 3 legal transforms which can be arranged in any // combination. while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element)) { String transformName = null; // at this level, all tags must be Transform tags if (reader.Depth != 4 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.TransformTagName)) != 0) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } // inspect the Algorithm attribute to determine the type of transform if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1) { transformName = reader.GetAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); } // legal transform name? if ((transformName != null) && (transformName.Length > 0)) { // what type of transform? if (String.CompareOrdinal(transformName, XTable.Get(XTable.ID.RelationshipsTransformName)) == 0) { if (!relationshipTransformFound) { // relationship transform ParseRelationshipsTransform(reader, partUri, ref relationshipSelectors); if (transforms == null) { transforms = new List <String>(); } transforms.Add(transformName); relationshipTransformFound = true; transformsCountWhenRelationshipTransformFound = transforms.Count; continue; // success } else { throw new XmlException(SR.Get(SRID.MultipleRelationshipTransformsFound)); } } else { // non-Relationship transform should have no children if (reader.IsEmptyElement) { if (transforms == null) { transforms = new List <String>(); } if (XmlDigitalSignatureProcessor.IsValidXmlCanonicalizationTransform(transformName)) { transforms.Add(transformName); // return it continue; // success } else { throw new InvalidOperationException(SR.Get(SRID.UnsupportedTransformAlgorithm)); } } } } throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } if (transforms.Count == 0) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } //If we found another transform after the Relationship transform, it will be validated earlier //in this method to make sure that its a supported xml canonicalization algorithm and so we can //simplify this test condition - As per the OPC spec - Relationship transform must be followed //by a canonicalization algorithm. if (relationshipTransformFound && (transforms.Count == transformsCountWhenRelationshipTransformFound)) { throw new XmlException(SR.Get(SRID.RelationshipTransformNotFollowedByCanonicalizationTransform)); } return(transforms); }
//----------------------------------------------------------------------------- // // Private Methods // //----------------------------------------------------------------------------- /// <summary> /// Parse the SignatureTime tag /// </summary> /// <param name="reader">NodeReader positioned at the SignatureProperty tag</param> /// <param name="timeFormat">format found</param> /// <exception cref="XmlException">illegal format</exception> /// <returns>signing time</returns> private static DateTime ParseSignatureTimeTag(XmlReader reader, out String timeFormat) { //There are no attributes on all the three tags that we parse in this method //<SignatureTime>, <Format>, <Value> int expectedAttributeCount = 0; string opcSignatureNameSpace = XTable.Get(XTable.ID.OpcSignatureNamespace); string signaturePropertyTag = XTable.Get(XTable.ID.SignaturePropertyTagName); string signatureTimeTag = XTable.Get(XTable.ID.SignatureTimeTagName); string timeValueTagName = XTable.Get(XTable.ID.SignatureTimeValueTagName); string timeFormatTagName = XTable.Get(XTable.ID.SignatureTimeFormatTagName); // <SignatureTime> must be one of <Format> or <Time> timeFormat = null; string timeValue = null; //Look for <SignatureTime> Tag if (reader.Read() && reader.MoveToContent() == XmlNodeType.Element && (String.CompareOrdinal(reader.NamespaceURI, opcSignatureNameSpace) == 0) && (String.CompareOrdinal(reader.LocalName, signatureTimeTag) == 0) && reader.Depth == 3 && PackagingUtilities.GetNonXmlnsAttributeCount(reader) == expectedAttributeCount) { while (reader.Read()) { if (String.CompareOrdinal(reader.NamespaceURI, opcSignatureNameSpace) == 0 && reader.MoveToContent() == XmlNodeType.Element && reader.Depth == 4) { // which tag do we have? if ((String.CompareOrdinal(reader.LocalName, timeValueTagName) == 0) && PackagingUtilities.GetNonXmlnsAttributeCount(reader) == expectedAttributeCount) { if (timeValue == null && reader.Read() && reader.MoveToContent() == XmlNodeType.Text && reader.Depth == 5) { //After reading the content, the reader progresses to the next element. //So after this method is called, the reader is positioned at the //EndElement corresponding to Value tag - </Value> // Note: ReadContentAsString will return String.Empty but never null timeValue = reader.ReadContentAsString(); Debug.Assert(reader.NodeType == XmlNodeType.EndElement); } else { //This would happen if we found more than one Value tags or if there //are other nested elements of if they are of a different XmlNodeType type throw new XmlException(SR.PackageSignatureCorruption); } } else if ((String.CompareOrdinal(reader.LocalName, timeFormatTagName) == 0) && PackagingUtilities.GetNonXmlnsAttributeCount(reader) == expectedAttributeCount) { if (timeFormat == null && reader.Read() && reader.MoveToContent() == XmlNodeType.Text && reader.Depth == 5) { //After reading the content, the reader progresses to the next element. //So after this method is called, the reader is positioned at the //EndElement corresponding to Format tag - </Format> // Note: ReadContentAsString will return String.Empty but never null timeFormat = reader.ReadContentAsString(); Debug.Assert(reader.NodeType == XmlNodeType.EndElement); } else { //This would happen if we found more than one Format tags or if there //are other nested elements of if they are of a different XmlNodeType type throw new XmlException(SR.PackageSignatureCorruption); } } else { //If we encounter any tag other than <Format> or <Time> nested within the <SignatureTime> tag throw new XmlException(SR.PackageSignatureCorruption); } } else //If we have encountered the end tag for the <SignatureTime> tag //then we are done parsing the tag, and we can stop the parsing. if (String.CompareOrdinal(signatureTimeTag, reader.LocalName) == 0 && (reader.NodeType == XmlNodeType.EndElement)) { //We must find a </SignatureProperty> tag at this point, //else it could be that there are more SignatureTime or //other tags nested here and that is an error. if (reader.Read() && reader.MoveToContent() == XmlNodeType.EndElement && String.CompareOrdinal(signaturePropertyTag, reader.LocalName) == 0) { break; } else { throw new XmlException(SR.PackageSignatureCorruption); } } else { // if we do not find the nested elements as expected throw new XmlException(SR.PackageSignatureCorruption); } } } else { throw new XmlException(SR.Format(SR.RequiredTagNotFound, signatureTimeTag)); } // generate an equivalent DateTime object if (timeValue != null && timeFormat != null) { return(XmlFormattedTimeToDateTime(timeValue, timeFormat)); } else { throw new XmlException(SR.PackageSignatureCorruption); } }
/// <summary> /// Write. Distribute the bytes to write across several contiguous streams if needed. /// </summary> /// <remarks> /// Zip streams can be assumed seekable so the length will be available for chaining /// pieces. /// </remarks> public override void Write(byte[] buffer, int offset, int count) { CheckClosed(); // Check arguments. PackagingUtilities.VerifyStreamWriteArgs(this, buffer, offset, count); // No check for FileAccess and stream capability (CanWrite). This is the responsibility // of the underlying stream(s). // A no-op if zero bytes to write. if (count == 0) { return; } // Write into piece streams, preserving all lengths in non-terminal pieces. int totalBytesWritten = 0; int pieceNumber = GetCurrentPieceNumber(); Stream pieceStream = _dir.GetStream(pieceNumber); checked { //Seek to the correct location in the underlying stream for the current piece pieceStream.Seek(_currentOffset - _dir.GetStartOffset(pieceNumber), SeekOrigin.Begin); while (totalBytesWritten < count) { // Compute the number of bytes to write into pieceStream. int numBytesToWriteInCurrentPiece = count - totalBytesWritten; if (!_dir.IsLastPiece(pieceNumber)) { // The write should not change the length of an intermediate piece. long currentPosition = _currentOffset + totalBytesWritten; long maxPosition = _dir.GetStartOffset(pieceNumber + 1) - 1; if (numBytesToWriteInCurrentPiece > (maxPosition - currentPosition + 1)) { // Cast from long to cast is safe in so far as *count*, which is the // absolute max for all byte counts, is a positive int. numBytesToWriteInCurrentPiece = checked ((int)(maxPosition - currentPosition + 1)); } } // Do the write. pieceStream.Write(buffer, offset + totalBytesWritten, numBytesToWriteInCurrentPiece); // Update the tally. totalBytesWritten += numBytesToWriteInCurrentPiece; // If there is more data to write, get the next piece stream if (!_dir.IsLastPiece(pieceNumber) && totalBytesWritten < count) { // The next write, should involve the next piece. ++pieceNumber; pieceStream = _dir.GetStream(pieceNumber); //Seek inorder to set the correct pointer for the next piece stream pieceStream.Seek(0, SeekOrigin.Begin); } } // Now we know the operation has completed, the current position can be updated. Invariant.Assert(totalBytesWritten == count); _currentOffset += totalBytesWritten; } }
/// <summary> /// Write /// </summary> /// <remarks>Note that zero length write to deflate stream actually results in a stream containing 2 bytes. This is /// required to maintain compatibility with the standard.</remarks> public override void Write(byte[] buffer, int offset, int count) { CheckDisposed(); PackagingUtilities.VerifyStreamWriteArgs(this, buffer, offset, count); // no-op if (count == 0) { return; } checked { switch (_mode) { case Mode.Start: // enter WritePassThrough mode if possible { // Special case: If stream has existing content, we need to go straight // to Emulation mode otherwise we'll potentially destroy existing data. // Don't bother entering WritePassThroughMode if position is non-zero because // we'll just enter emulation later. if (_position == 0 && IsDeflateStreamEmpty(_baseStream)) { ChangeMode(Mode.WritePassThrough); } else { ChangeMode(Mode.Emulation); } break; } case Mode.WritePassThrough: // continue in Write mode case Mode.Emulation: // continue to read from existing emulation stream { break; } case Mode.ReadPassThrough: // enter Emulation mode { ChangeMode(Mode.Emulation); break; } default: Debug.Assert(false, "Illegal state for CompressStream - logic error"); break; } _current.Write(buffer, offset, count); _position += count; } // keep track of the current length in case someone asks for it if (_mode == Mode.WritePassThrough) { CachedLength = _position; } _dirtyForFlushing = true; _dirtyForClosing = true; }
//------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Stream Methods /// <summary> /// Return the bytes requested from the container /// </summary> /// <param name="buffer">destination buffer</param> /// <param name="offset">offset to write into that buffer</param> /// <param name="count">how many bytes requested</param> /// <returns>how many bytes were written into <paramref name="buffer" />.</returns> /// <remarks> /// The underlying stream, expected to be a DeflateStream or a CompressEmulationStream, /// is in charge of leaving the IO position unchanged in case of an exception. /// </remarks> public override int Read(byte[] buffer, int offset, int count) { CheckDisposed(); PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); // no-op if (count == 0) { return(0); } checked // catch any integer overflows { switch (_mode) { case Mode.Start: { // skip to the correct logical position if necessary (DeflateStream starts at position zero) if (_position == 0) { // enter ReadPassThrough mode if it is efficient ChangeMode(Mode.ReadPassThrough); } else { ChangeMode(Mode.Emulation); } break; } case Mode.ReadPassThrough: // continue in ReadPassThrough mode case Mode.Emulation: // continue to read from existing emulation stream { break; } case Mode.WritePassThrough: // enter Emulation mode { // optimization - if they are trying to jump back to the start to read, simply jump to ReadPassThrough mode if (_position == 0) { ChangeMode(Mode.ReadPassThrough); } else { ChangeMode(Mode.Emulation); } break; } default: Debug.Assert(false, "Illegal state for CompressStream - logic error"); break; } // we might be in Start mode now if we are beyond the end of stream - just return zero if (_current == null) { return(0); } int bytesRead = _current.Read(buffer, offset, count); // optimization for ReadPassThrough mode - we actually know the length because we ran out of bytes if (_mode == Mode.ReadPassThrough && bytesRead == 0) { // possible first chance to set and verify length from header against real data length UpdateUncompressedDataLength(_position); // since we've exhausted the deflateStream, discard it to reduce working set ChangeMode(Mode.Start); } // Stream contract - don't update position until we are certain that no exceptions have occurred _position += bytesRead; return(bytesRead); } }
override public int Read(byte[] buffer, int offset, int count) { CheckDisposed(); PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); Debug.Assert(_currentStreamPosition >= 0); if (count == 0) { return(0); } if (_currentStreamLength <= _currentStreamPosition) { // we are past the end of the stream so let's just return 0 return(0); } // No need to use checked{} since _currentStreamLength > _currentStreamPosition int bytesToRead = (int)Math.Min((long)count, _currentStreamLength - _currentStreamPosition); checked { Debug.Assert(bytesToRead > 0); int bytesRead; // how much data we actually were able to read if (_isolatedStorageMode) { lock (PackagingUtilities.IsolatedStorageFileLock) { _isolatedStorageStream.Seek(_currentStreamPosition, SeekOrigin.Begin); bytesRead = _isolatedStorageStream.Read(buffer, offset, bytesToRead); } } else { // let's reset data to 0 first, so that gaps will be filled with 0s // this is required for consistent behavior between the read calls used by the CRC Calculator // and the WriteToStream calls used by the Flush/Save routines Array.Clear(buffer, offset, bytesToRead); int index = _memoryStreamList.BinarySearch(GetSearchBlockForOffset(_currentStreamPosition)); if (index < 0) // the head of new write block does not overlap with any existing blocks // ~startIndex represents the insertion position { index = ~index; } for ( ; index < _memoryStreamList.Count; ++index) { MemoryStreamBlock memStreamBlock = _memoryStreamList[index]; long overlapBlockOffset; long overlapBlockSize; // let's check for overlap and fill up appropriate data PackagingUtilities.CalculateOverlap(memStreamBlock.Offset, (int)memStreamBlock.Stream.Length, _currentStreamPosition, bytesToRead, out overlapBlockOffset, out overlapBlockSize); if (overlapBlockSize > 0) { // we got an overlap let's copy data over to the target buffer // _currentStreamPosition is not updated in this foreach loop; it will be updated later Array.Copy(memStreamBlock.Stream.GetBuffer(), (int)(overlapBlockOffset - memStreamBlock.Offset), buffer, (int)(offset + overlapBlockOffset - _currentStreamPosition), (int)overlapBlockSize); } else { break; } } // for memory stream case we get as much as we asked for bytesRead = bytesToRead; } _currentStreamPosition += bytesRead; return(bytesRead); } }