//------------------------------------------------------
        //
        //  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);
        }
Пример #2
0
        /// <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));
        }