private static Uri ParsePartUriAttribute(String attrValue, out ContentType contentType) { // extract the query portion - do not ask the Uri class for it because it will escape // characters and we want to do a simple text comparison later contentType = ContentType.Empty; // out argument must always be set int index = attrValue.IndexOf('?'); Uri uri = null; if (index > 0) { try { // ensure it starts with the correct query prefix String query = attrValue.Substring(index); if ((query.Length > _contentTypeQueryStringPrefix.Length) && (query.StartsWith(_contentTypeQueryStringPrefix, StringComparison.Ordinal))) { // truncate the prefix and validate contentType = new ContentType(query.Substring(_contentTypeQueryStringPrefix.Length)); } // now construct the uri without the query uri = PackUriHelper.ValidatePartUri(new Uri(attrValue.Substring(0, index), UriKind.Relative)); } catch (ArgumentException ae) { // Content type or part uri is malformed so we have a bad signature. // Rethrow as XmlException so outer validation loop can catch it and return validation result. throw new XmlException(SR.Get(SRID.PartReferenceUriMalformed), ae); } } // throw if we failed if (contentType.ToString().Length <= 0) { throw new XmlException(SR.Get(SRID.PartReferenceUriMalformed)); } return(uri); }
/// <summary> /// Generates a Reference tag that contains a Relationship transform /// </summary> /// <param name="manager">manager</param> /// <param name="relationshipPartName">name of the relationship part</param> /// <param name="xDoc">current xml document</param> /// <param name="hashAlgorithm">hash algorithm = digest method</param> /// <param name="relationshipSelectors">relationshipSelectors that represent the relationships to sign </param> /// <remarks>ContentType is known and part name can be derived from the relationship collection</remarks> private static XmlNode GenerateRelationshipSigningReference( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, Uri relationshipPartName, IEnumerable <PackageRelationshipSelector> relationshipSelectors) { string relPartContentType = PackagingUtilities.RelationshipPartContentType.ToString(); // <Reference> XmlElement reference = xDoc.CreateElement(XTable.Get(XTable.ID.ReferenceTagName), SignedXml.XmlDsigNamespaceUrl); // add Uri // persist the Uri of the associated Relationship part String relationshipPartString; if (PackUriHelper.ComparePartUri(relationshipPartName, PackageRelationship.ContainerRelationshipPartName) == 0) { relationshipPartString = PackageRelationship.ContainerRelationshipPartName.ToString(); } else { relationshipPartString = PackUriHelper.GetStringForPartUri(relationshipPartName); } XmlAttribute uriAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.UriAttrName)); uriAttr.Value = relationshipPartString + _contentTypeQueryStringPrefix + relPartContentType; reference.Attributes.Append(uriAttr); // add transforms tag (always necessary) // <Transforms> XmlElement transforms = xDoc.CreateElement(XTable.Get(XTable.ID.TransformsTagName), SignedXml.XmlDsigNamespaceUrl); // add Relationship transform String opcNamespace = XTable.Get(XTable.ID.OpcSignatureNamespace); String opcNamespacePrefix = XTable.Get(XTable.ID.OpcSignatureNamespacePrefix); XmlElement transform = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl); XmlAttribute algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); algorithmAttr.Value = XTable.Get(XTable.ID.RelationshipsTransformName); transform.Attributes.Append(algorithmAttr); // <RelationshipReference SourceId="abc" /> or // <RelationshipGroupReference SourceType="xyz" /> foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectors) { switch (relationshipSelector.SelectorType) { case PackageRelationshipSelectorType.Id: { XmlNode relationshipNode = xDoc.CreateElement(opcNamespacePrefix, XTable.Get(XTable.ID.RelationshipReferenceTagName), opcNamespace); XmlAttribute idAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SourceIdAttrName)); idAttr.Value = relationshipSelector.SelectionCriteria; relationshipNode.Attributes.Append(idAttr); transform.AppendChild(relationshipNode); } break; case PackageRelationshipSelectorType.Type: { XmlNode relationshipNode = xDoc.CreateElement(opcNamespacePrefix, XTable.Get(XTable.ID.RelationshipsGroupReferenceTagName), opcNamespace); XmlAttribute typeAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SourceTypeAttrName)); typeAttr.Value = relationshipSelector.SelectionCriteria; relationshipNode.Attributes.Append(typeAttr); transform.AppendChild(relationshipNode); } break; default: Invariant.Assert(false, "This option should never be executed"); break; } } transforms.AppendChild(transform); // add non-Relationship transform (if any) String transformName = null; if (manager.TransformMapping.ContainsKey(relPartContentType)) { transformName = manager.TransformMapping[relPartContentType]; // let them override //Currently we only support two transforms and so we validate whether its //one of those if (transformName == null || transformName.Length == 0 || !XmlDigitalSignatureProcessor.IsValidXmlCanonicalizationTransform(transformName)) { throw new InvalidOperationException(SR.Get(SRID.UnsupportedTransformAlgorithm)); } // <Transform> transform = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl); algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); algorithmAttr.Value = transformName; transform.Attributes.Append(algorithmAttr); transforms.AppendChild(transform); } reference.AppendChild(transforms); // <DigestMethod> reference.AppendChild(GenerateDigestMethod(manager, xDoc)); // <DigestValue> - digest the virtual node list made from these Relationship tags using (Stream s = XmlDigitalSignatureProcessor.GenerateRelationshipNodeStream(GetRelationships(manager, relationshipSelectors))) // serialized node list { reference.AppendChild(GenerateDigestValueNode(xDoc, hashAlgorithm, s, transformName)); } return(reference); }
/// <summary> /// Add new relationship to the Collection /// </summary> /// <param name="targetUri">target</param> /// <param name="targetMode">Enumeration indicating the base uri for the target uri</param> /// <param name="relationshipType">relationship type that uniquely defines the role of the relationship</param> /// <param name="id">String that conforms to the xsd:ID datatype. Unique across the source's relationships. /// Null OK (ID will be generated).</param> /// <param name="parsing">Indicates whether the add call is made while parsing existing relationships /// from a relationship part, or we are adding a new relationship</param> private PackageRelationship Add(Uri targetUri, TargetMode targetMode, string relationshipType, string id, bool parsing) { if (targetUri == null) { throw new ArgumentNullException("targetUri"); } if (relationshipType == null) { throw new ArgumentNullException("relationshipType"); } ThrowIfInvalidRelationshipType(relationshipType); //Verify if the Enum value is valid if (targetMode < TargetMode.Internal || targetMode > TargetMode.External) { throw new ArgumentOutOfRangeException("targetMode"); } // don't accept absolute Uri's if targetMode is Internal. if (targetMode == TargetMode.Internal && targetUri.IsAbsoluteUri) { throw new ArgumentException(SR.Get(SRID.RelationshipTargetMustBeRelative), "targetUri"); } // don't allow relationships to relationships // This check should be made for following cases // 1. Uri is absolute and it is pack Uri // 2. Uri is NOT absolute and its target mode is internal (or NOT external) // Note: if the target is absolute uri and its not a pack scheme then we cannot determine if it is a rels part // Note: if the target is relative uri and target mode is external, we cannot determine if it is a rels part if ((!targetUri.IsAbsoluteUri && targetMode != TargetMode.External) || (targetUri.IsAbsoluteUri && targetUri.Scheme == PackUriHelper.UriSchemePack)) { Uri resolvedUri = GetResolvedTargetUri(targetUri, targetMode); //GetResolvedTargetUri returns a null if the target mode is external and the //target Uri is a packUri with no "part" component, so in that case we know that //its not a relationship part. if (resolvedUri != null) { if (PackUriHelper.IsRelationshipPartUri(resolvedUri)) { throw new ArgumentException(SR.Get(SRID.RelationshipToRelationshipIllegal), "targetUri"); } } } // Generate an ID if id is null. Throw exception if neither null nor a valid unique xsd:ID. if (id == null) { id = GenerateUniqueRelationshipId(); } else { ValidateUniqueRelationshipId(id); } //Ensure the relationship part EnsureRelationshipPart(); // create and add PackageRelationship relationship = new PackageRelationship(_package, _sourcePart, targetUri, targetMode, relationshipType, id); _relationships.Add(relationship); //If we are adding relationships as a part of Parsing the underlying relationship part, we should not set //the dirty flag to false. _dirty = !parsing; return(relationship); }
//------------------------------------------------------ // // Constructors // //------------------------------------------------------ /// <summary> /// Build a System.IO.Stream on a part that possibly consists of multiple files /// An InterleavedZipPartStream gets created by ZipPackagePart.GetStreamCore when the part /// is interleaved. It wraps one or more Zip streams (one per piece). /// (pieces). /// </summary> /// <param name="mode">Mode (create, etc.) in which piece streams should be opened</param> /// <param name="access">Access (read, write, etc.) with which piece streams should be opened</param> /// <param name="owningPart"> /// The part to build a stream on. It contains all ZipFileInfo descriptors for the part's pieces /// (see ZipPackage.GetPartsCore). /// </param> internal InterleavedZipPartStream(ZipPackagePart owningPart, FileMode mode, FileAccess access) : this(PackUriHelper.GetStringForPartUri(owningPart.Uri), owningPart.PieceDescriptors, mode, access) { }
/// <summary> /// rootElement == null: Load elements, validation of root element will occur in caller by checking object type or casting /// rootElement != null: Only perform validation, and expect rootElement at root of markup /// </summary> /// <param name="stream"></param> /// <param name="parentUri"></param> /// <param name="pc"></param> /// <param name="mimeType"></param> /// <param name="rootElement"></param> /// <returns></returns> private object Load(Stream stream, Uri parentUri, ParserContext pc, ContentType mimeType, string rootElement) { object obj = null; if (!DocumentMode) { // Loose XAML, just check against schema, don't check content type if (rootElement == null) { obj = XamlReader.Load(stream, pc); } } else { // inside an XPS Document. Perform maximum validation XpsSchema schema = XpsSchema.GetSchema(mimeType); Uri uri = pc.BaseUri; // Using PackUriHelper.ValidateAndGetPackUriComponents internal method // to get Package and Part Uri in one step Uri packageUri; Uri partUri; InternalPackUriHelper.ValidateAndGetPackUriComponents(uri, out packageUri, out partUri); Package package = PreloadedPackages.GetPackage(packageUri); Uri parentPackageUri = null; if (parentUri != null) { parentPackageUri = PackUriHelper.GetPackageUri(parentUri); if (!parentPackageUri.Equals(packageUri)) { throw new FileFormatException(SR.Get(SRID.XpsValidatingLoaderUriNotInSamePackage)); } } schema.ValidateRelationships(new SecurityCriticalData <Package>(package), packageUri, partUri, mimeType); if (schema.AllowsMultipleReferencesToSameUri(mimeType)) { _uniqueUriRef = null; } else { _uniqueUriRef = new Hashtable(11); } Hashtable validResources = (_validResources.Count > 0 ? _validResources.Peek() : null); if (schema.HasRequiredResources(mimeType)) { validResources = new Hashtable(11); PackagePart part = package.GetPart(partUri); PackageRelationshipCollection requiredResources = part.GetRelationshipsByType(_requiredResourceRel); foreach (PackageRelationship relationShip in requiredResources) { Uri targetUri = PackUriHelper.ResolvePartUri(partUri, relationShip.TargetUri); Uri absTargetUri = PackUriHelper.Create(packageUri, targetUri); PackagePart targetPart = package.GetPart(targetUri); if (schema.IsValidRequiredResourceMimeType(targetPart.ValidatedContentType())) { if (!validResources.ContainsKey(absTargetUri)) { validResources.Add(absTargetUri, true); } } else { if (!validResources.ContainsKey(absTargetUri)) { validResources.Add(absTargetUri, false); } } } } XpsSchemaValidator xpsSchemaValidator = new XpsSchemaValidator(this, schema, mimeType, stream, packageUri, partUri); _validResources.Push(validResources); if (rootElement != null) { xpsSchemaValidator.XmlReader.MoveToContent(); if (!rootElement.Equals(xpsSchemaValidator.XmlReader.Name)) { throw new FileFormatException(SR.Get(SRID.XpsValidatingLoaderUnsupportedMimeType)); } while (xpsSchemaValidator.XmlReader.Read()) { ; } } else { obj = XamlReader.Load(xpsSchemaValidator.XmlReader, pc, XamlParseMode.Synchronous); } _validResources.Pop(); } return(obj); }