//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ /// <summary> /// GenerateRelationshipSigningReferences /// </summary> /// <param name="manager"></param> /// <param name="xDoc"></param> /// <param name="hashAlgorithm"></param> /// <param name="relationshipSelectors"></param> /// <param name="manifest"></param> /// <returns>number of references to be signed</returns> private static int GenerateRelationshipSigningReferences( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, IEnumerable <PackageRelationshipSelector> relationshipSelectors, XmlNode manifest) { // PartUri - and its list of PackageRelationshipSelectors Dictionary <Uri, List <PackageRelationshipSelector> > partAndSelectorDictionary = new Dictionary <Uri, List <PackageRelationshipSelector> >(); foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectors) { //update the partAndSelectorDictionary for each relationshipSelector Uri relationshipPartUri = PackUriHelper.GetRelationshipPartUri(relationshipSelector.SourceUri); List <PackageRelationshipSelector> selectors; if (partAndSelectorDictionary.ContainsKey(relationshipPartUri)) { selectors = partAndSelectorDictionary[relationshipPartUri]; } else { selectors = new List <PackageRelationshipSelector>(); partAndSelectorDictionary.Add(relationshipPartUri, selectors); } selectors.Add(relationshipSelector); } // now that we have them grouped by Part name, emit the XML // Here is an optimization for saving space by declaring the OPC namespace and prefix // in the <Manifest> tag. It will become: // <Manifest xmlns:opc="http://schemas.openxmlformats.org/package/2006/digital-signature"> // Later when we generate the RelationshipSigningReference we can use the namespace prefix "opc" // instead of the long namespace itself, thus saving some space if the manifest has more than one // RelationshipSigningReference. // XmlElement xmlE = (XmlElement)manifest; xmlE.SetAttribute(XTable.Get(XTable.ID.OpcSignatureNamespaceAttribute), XTable.Get(XTable.ID.OpcSignatureNamespace)); int count = 0; foreach (Uri partName in partAndSelectorDictionary.Keys) { // emit xml and append manifest.AppendChild( GenerateRelationshipSigningReference(manager, xDoc, hashAlgorithm, partName, /* we are guaranteed that this is a valid part Uri, so we do not use PackUriHelper.CreatePartUri */ partAndSelectorDictionary[partName])); count++; } return(count); }
/// <summary> /// Returns the associated RelationshipPart for this part /// </summary> /// <param name="part">may be null</param> /// <returns>name of relationship part for the given part</returns> private static Uri GetRelationshipPartUri(PackagePart part) { Uri sourceUri; if (part == null) { sourceUri = PackUriHelper.PackageRootUri; } else { sourceUri = part.Uri; } return(PackUriHelper.GetRelationshipPartUri(sourceUri)); }