XmlSignatureProperties.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Base / MS / Internal / IO / Packaging / XmlSignatureProperties.cs / 1 / XmlSignatureProperties.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  Helper for XmlDigitalSignatureProcessor. 
//  Generates and consumes Metro-compliant SignatureProperties element within an
//  XmlDSig signature. 
//
// History:
//  01/25/2004: BruceMac: First iteration
//  12/02/2005: BruceMac: Security Mitigations and support short form for UTC dates "Z" 
//
//----------------------------------------------------------------------------- 
 
using System;
using System.Collections; 
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Cryptography; 
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates; 
using System.Security.Permissions; 
using System.Xml;
using System.IO; 
using System.Windows;
using System.IO.Packaging;
using System.Diagnostics;
 
namespace MS.Internal.IO.Packaging
{ 
    ///  
    /// Signature Handler implementation that follows the Feb 12, 2002 W3C DigSig Recommendation
    ///  
    /// See: http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/ for details
    static internal class XmlSignatureProperties
    {
        //----------------------------------------------------------------------------- 
        //
        // Internal Properties 
        // 
        //-----------------------------------------------------------------------------
        ///  
        /// Signature Time Format - default to most descriptive form - in Xml syntax
        /// 
        internal static String DefaultDateTimeFormat
        { 
            get
            { 
                return _dateTimePatternMap[0].Format; 
            }
        } 

        //------------------------------------------------------------------------------
        //
        // Internal Methods 
        //
        //----------------------------------------------------------------------------- 
        ///  
        /// Verify the given string is a legal Xml format
        ///  
        /// xml format to verify
        /// true if legal
        internal static bool LegalFormat(String candidateFormat)
        { 
            if (candidateFormat == null)
                throw new ArgumentNullException("candidateFormat"); 
 
            return (GetIndex(candidateFormat) != -1);
        } 

        /// 
        /// Obtain a W3C formatted SigningTime (equivalent to TimeStamp)
        ///  
        /// xml document we are building
        /// time to persist 
        /// id of new signature 
        /// format to use - must be Xml date format legal syntax
        /// given writer with SignatureProperties xml added to it 
        /// format matches that described in http://www.w3.org/TR/NOTE-datetime 
        /// 
        /// 
        ///      
        ///         
        ///              
        ///                 YYYY-MM-DDThh:mm:ssTZD 
        ///                 1997-07-16T19:20:30.45+01:00
        ///              
        ///         
        ///     
        /// 
        ///  
        internal static XmlElement AssembleSignatureProperties(
            XmlDocument xDoc, 
            DateTime dateTime, 
            String xmlDateTimeFormat,
            String signatureId) 
        {
            Invariant.Assert(xDoc != null);
            Invariant.Assert(signatureId != null);
 
            // check for null format - use default if null
            if (xmlDateTimeFormat == null) 
            { 
                xmlDateTimeFormat = DefaultDateTimeFormat;
            } 

            string[] dateTimeFormats = ConvertXmlFormatStringToDateTimeFormatString(xmlDateTimeFormat);

            //  
            XmlElement signatureProperties = xDoc.CreateElement(XTable.Get(XTable.ID.SignaturePropertiesTagName),
                SignedXml.XmlDsigNamespaceUrl); 
 
            // 
            XmlElement signatureProperty = xDoc.CreateElement(XTable.Get(XTable.ID.SignaturePropertyTagName), 
                SignedXml.XmlDsigNamespaceUrl);
            signatureProperties.AppendChild(signatureProperty);
            XmlAttribute idAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SignaturePropertyIdAttrName));
            idAttr.Value = XTable.Get(XTable.ID.SignaturePropertyIdAttrValue); 
            signatureProperty.Attributes.Append(idAttr);
            XmlAttribute targetAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.TargetAttrName)); 
            targetAttr.Value = "#" + signatureId; 
            signatureProperty.Attributes.Append(targetAttr);
 
            // 
            XmlElement signatureTime = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeTagName),
                XTable.Get(XTable.ID.OpcSignatureNamespace));
            XmlElement signatureTimeFormat = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeFormatTagName), 
                XTable.Get(XTable.ID.OpcSignatureNamespace));
            XmlElement signatureTimeValue = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeValueTagName), 
                XTable.Get(XTable.ID.OpcSignatureNamespace)); 

            signatureTimeFormat.AppendChild(xDoc.CreateTextNode(xmlDateTimeFormat)); 
            signatureTimeValue.AppendChild(xDoc.CreateTextNode(DateTimeToXmlFormattedTime(dateTime, dateTimeFormats[0])));

            signatureTime.AppendChild(signatureTimeFormat);
            signatureTime.AppendChild(signatureTimeValue); 

            signatureProperty.AppendChild(signatureTime); 
 
            return signatureProperties;
        } 

        /// 
        /// Parse the xml and determine the signing time
        ///  
        /// NodeReader positioned at the SignatureProperties tag
        /// value of the Id attribute on the Signature tag 
        /// format found 
        /// illegal format
        /// signing time 
        internal static DateTime ParseSigningTime(XmlReader reader, string signatureId, out String timeFormat)
        {
            if (reader == null)
                throw new ArgumentNullException("reader"); 

            bool signatureTimePropertyFound = false; 
            bool signatureTimeIdFound = false; 
            string w3cSignatureNameSpace = SignedXml.XmlDsigNamespaceUrl;
 
            //  tag
            string signaturePropertyTag = XTable.Get(XTable.ID.SignaturePropertyTagName);
            string signaturePropertiesTag = XTable.Get(XTable.ID.SignaturePropertiesTagName);
 
            //initializing to a dummy value
            DateTime signingTime = DateTime.Now; 
            timeFormat = null; 

            while (reader.Read()) 
            {
                //Looking for  tag
                if (reader.MoveToContent() == XmlNodeType.Element
                    && (String.CompareOrdinal(reader.NamespaceURI, w3cSignatureNameSpace) == 0) 
                    && (String.CompareOrdinal(reader.LocalName, signaturePropertyTag) == 0)
                    && reader.Depth == 2) 
                { 
                    //Verify Attributes
                    //Look for well-defined Id attribute and if it is present 
                    if (VerifyIdAttribute(reader))
                    {
                        //If we encounter more than one  tag with the expected
                        //id, then its an error. 
                        if (signatureTimeIdFound)
                            throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); 
                        else 
                            signatureTimeIdFound = true;
 
                        //VerifyTargetAttribute will return false, if the Target attribute is missing
                        //or contains an incorrect value.
                        if(VerifyTargetAttribute(reader, signatureId))
                        { 
                            signingTime = ParseSignatureTimeTag(reader, out timeFormat);
                            signatureTimePropertyFound = true; 
                        } 
                    }
                } 
                else
                    //Expected  tag not found.
                    //Look for end tag corresponding to  or
                    //if these are other custom defined properties, then anything with 
                    //depth greater than 2 should be ignored as these can be nested elements.
                    if (((String.CompareOrdinal(signaturePropertyTag, reader.LocalName) == 0 
                        && (reader.NodeType == XmlNodeType.EndElement))) 
                        || reader.Depth > 2)
                        continue; 
                    else
                        //If we find the end tag for  then we can stop parsing
                        if ((String.CompareOrdinal(signaturePropertiesTag, reader.LocalName) == 0
                        && (reader.NodeType == XmlNodeType.EndElement))) 
                            break;
                        else 
                            throw new XmlException(SR.Get(SRID.RequiredTagNotFound, signaturePropertyTag)); 
            }
 
            //We did find one or more  tags but there were none that
            //defined the id attribute and target attribute and  element tag correctly.
            if(!signatureTimePropertyFound)
                throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); 

            return signingTime; 
        } 

 
        //------------------------------------------------------------------------------
        //
        // Private Methods
        // 
        //------------------------------------------------------------------------------
 
        ///  
        /// Parse the SignatureTime tag
        ///  
        /// NodeReader positioned at the SignatureProperty tag
        /// format found
        /// illegal format
        /// signing time 
        private static DateTime ParseSignatureTimeTag(XmlReader reader, out String timeFormat)
        { 
            //There are no attributes on all the three tags that we parse in this method 
            //, , 
            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); 
 
            //  must be one of  or 
                                // 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.Get(SRID.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 -  
                                // 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.Get(SRID.PackageSignatureCorruption));
                        } 
                        else
                            //If we encounter any tag other than  or  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.Get(SRID.PackageSignatureCorruption));
                        } 
                        else 
                            // if we do not find the nested elements as expected
                            throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); 
                }
            }
            else
                throw new XmlException(SR.Get(SRID.RequiredTagNotFound, signatureTimeTag)); 

 
            // generate an equivalent DateTime object 
            if (timeValue != null && timeFormat != null)
                return XmlFormattedTimeToDateTime(timeValue, timeFormat); 
            else
                throw new XmlException(SR.Get(SRID.PackageSignatureCorruption));
        }
 
        /// 
        /// DateTime to XML Format 
        ///  
        /// date time to convert
        /// format to use - specified in DateTime syntax 
        /// opc-legal string suitable for embedding in XML digital signatures
        private static String DateTimeToXmlFormattedTime(DateTime dt, string format)
        {
            DateTimeFormatInfo formatter = new DateTimeFormatInfo(); 
            formatter.FullDateTimePattern = format;
            return dt.ToString(format, formatter); 
        } 

        ///  
        /// XML Format time string to DateTime
        /// 
        /// string to parse
        /// format to use - specified in Xml Signature date syntax 
        /// Format does not match the given string
        /// DateTime 
        private static DateTime XmlFormattedTimeToDateTime(String s, String format) 
        {
            // convert Xml syntax to equivalent DateTime syntax 
            string[] legalFormats = ConvertXmlFormatStringToDateTimeFormatString(format);

            // the default formatter is culture-invariant (which is what we want)
            DateTimeFormatInfo formatter = new DateTimeFormatInfo(); 
            formatter.FullDateTimePattern = format;
            return DateTime.ParseExact(s, legalFormats, formatter, 
                DateTimeStyles.NoCurrentDateDefault 
                | DateTimeStyles.AllowLeadingWhite
                | DateTimeStyles.AllowTrailingWhite); 
        }

        /// 
        /// Get index of the row that matches the given format 
        /// 
        /// format to lookup 
        /// -1 if not found 
        private static int GetIndex(String format)
        { 
            for (int i = 0; i < _dateTimePatternMap.GetLength(0); i++)
            {
                if (String.CompareOrdinal(_dateTimePatternMap[i].Format, format) == 0)
                { 
                    return i;
                } 
            } 
            return -1;
        } 

        /// 
        /// Convert Xml format syntax to DateTime format syntax
        ///  
        /// 
        ///  
        private static string[] ConvertXmlFormatStringToDateTimeFormatString(String format) 
        {
            return _dateTimePatternMap[GetIndex(format)].Patterns; 
        }

        /// 
        /// Verify if the SignatureProperty tag has a valid Id attribute 
        /// 
        /// NodeReader positioned at the SignatureProperty tag 
        /// true, if Id attribute is present and has the correct value, else false 
        private static bool VerifyIdAttribute(XmlReader reader)
        { 
            string idAttrValue = reader.GetAttribute(XTable.Get(XTable.ID.SignaturePropertyIdAttrName));

            if(idAttrValue!=null
                && (String.CompareOrdinal(idAttrValue,XTable.Get(XTable.ID.SignaturePropertyIdAttrValue)) == 0)) 
                return true;
            else 
                return false; 
        }
 
        /// 
        /// Verify if the mandatory Target attribute exists on the SignatureProperty tag
        /// 
        /// NodeReader positioned at the SignatureProperty tag 
        /// value of the Id attribute on the Signature tag
        /// true, if Target attribute is present and has the correct value, else false 
        private static bool VerifyTargetAttribute(XmlReader reader, string signatureId) 
        {
            string idTargetValue = reader.GetAttribute(XTable.Get(XTable.ID.TargetAttrName)); 

            if (idTargetValue != null)
            {
                //whether there is an Id attribute on the  tag or no, 
                //an empty Target attribute on  tag, is allowed.
                //Empty string means current document 
                if (String.CompareOrdinal(idTargetValue, String.Empty) == 0) 
                    return true;
                else 
                {
                    //If the Target attribute has a non-empty string then
                    //it must match the  tag Id attribute value
                    if (signatureId != null && String.CompareOrdinal(idTargetValue, "#" + signatureId) == 0) 
                        return true;
                    else 
                        return false; 
                }
            } 
            else
                return false;
        }
 
        //-----------------------------------------------------------------------------
        // 
        // Private Fields 
        //
        //------------------------------------------------------------------------------ 

        // This is a mapping between time formats allowed by Opc spec (taken from
        // http://www.w3.org/TR/NOTE-datetime) and the equivalent formatting string
        // expected by the DateTimeFormatInfo class. 
        private struct TimeFormatMapEntry
        { 
            public TimeFormatMapEntry(string xmlFormatString, string[] dateTimePatterns) 
            {
                _xmlFormatString = xmlFormatString; 
                _dateTimePatterns = dateTimePatterns;
            }

            public string   Format { get { return _xmlFormatString; }} 
            public string[] Patterns { get { return _dateTimePatterns; }}
 
            private string      _xmlFormatString; 
            private string[]    _dateTimePatterns;
        }; 

        private static readonly TimeFormatMapEntry[] _dateTimePatternMap =
        {
            // Opc Spec value                                   Equivalent DateTimePattern(s) 
            new TimeFormatMapEntry("YYYY-MM-DDThh:mm:ss.sTZD",  new string[] {"yyyy-MM-ddTHH:mm:ss.fzzz",   "yyyy-MM-ddTHH:mm:ss.fZ"}),
            new TimeFormatMapEntry("YYYY-MM-DDThh:mm:ssTZD",    new string[] {"yyyy-MM-ddTHH:mm:sszzz",     "yyyy-MM-ddTHH:mm:ssZ"}), 
            new TimeFormatMapEntry("YYYY-MM-DDThh:mmTZD",       new string[] {"yyyy-MM-ddTHH:mmzzz",        "yyyy-MM-ddTHH:mmZ"}), 
            new TimeFormatMapEntry("YYYY-MM-DD",                new string[] {"yyyy-MM-dd"}),
            new TimeFormatMapEntry("YYYY-MM",                   new string[] {"yyyy-MM"}), 
            new TimeFormatMapEntry("YYYY",                      new string[] {"yyyy"}),
        };
    }
  } 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  Helper for XmlDigitalSignatureProcessor. 
//  Generates and consumes Metro-compliant SignatureProperties element within an
//  XmlDSig signature. 
//
// History:
//  01/25/2004: BruceMac: First iteration
//  12/02/2005: BruceMac: Security Mitigations and support short form for UTC dates "Z" 
//
//----------------------------------------------------------------------------- 
 
using System;
using System.Collections; 
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Cryptography; 
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates; 
using System.Security.Permissions; 
using System.Xml;
using System.IO; 
using System.Windows;
using System.IO.Packaging;
using System.Diagnostics;
 
namespace MS.Internal.IO.Packaging
{ 
    ///  
    /// Signature Handler implementation that follows the Feb 12, 2002 W3C DigSig Recommendation
    ///  
    /// See: http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/ for details
    static internal class XmlSignatureProperties
    {
        //----------------------------------------------------------------------------- 
        //
        // Internal Properties 
        // 
        //-----------------------------------------------------------------------------
        ///  
        /// Signature Time Format - default to most descriptive form - in Xml syntax
        /// 
        internal static String DefaultDateTimeFormat
        { 
            get
            { 
                return _dateTimePatternMap[0].Format; 
            }
        } 

        //------------------------------------------------------------------------------
        //
        // Internal Methods 
        //
        //----------------------------------------------------------------------------- 
        ///  
        /// Verify the given string is a legal Xml format
        ///  
        /// xml format to verify
        /// true if legal
        internal static bool LegalFormat(String candidateFormat)
        { 
            if (candidateFormat == null)
                throw new ArgumentNullException("candidateFormat"); 
 
            return (GetIndex(candidateFormat) != -1);
        } 

        /// 
        /// Obtain a W3C formatted SigningTime (equivalent to TimeStamp)
        ///  
        /// xml document we are building
        /// time to persist 
        /// id of new signature 
        /// format to use - must be Xml date format legal syntax
        /// given writer with SignatureProperties xml added to it 
        /// format matches that described in http://www.w3.org/TR/NOTE-datetime 
        /// 
        /// 
        ///      
        ///         
        ///              
        ///                 YYYY-MM-DDThh:mm:ssTZD 
        ///                 1997-07-16T19:20:30.45+01:00
        ///              
        ///         
        ///     
        /// 
        ///  
        internal static XmlElement AssembleSignatureProperties(
            XmlDocument xDoc, 
            DateTime dateTime, 
            String xmlDateTimeFormat,
            String signatureId) 
        {
            Invariant.Assert(xDoc != null);
            Invariant.Assert(signatureId != null);
 
            // check for null format - use default if null
            if (xmlDateTimeFormat == null) 
            { 
                xmlDateTimeFormat = DefaultDateTimeFormat;
            } 

            string[] dateTimeFormats = ConvertXmlFormatStringToDateTimeFormatString(xmlDateTimeFormat);

            //  
            XmlElement signatureProperties = xDoc.CreateElement(XTable.Get(XTable.ID.SignaturePropertiesTagName),
                SignedXml.XmlDsigNamespaceUrl); 
 
            // 
            XmlElement signatureProperty = xDoc.CreateElement(XTable.Get(XTable.ID.SignaturePropertyTagName), 
                SignedXml.XmlDsigNamespaceUrl);
            signatureProperties.AppendChild(signatureProperty);
            XmlAttribute idAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SignaturePropertyIdAttrName));
            idAttr.Value = XTable.Get(XTable.ID.SignaturePropertyIdAttrValue); 
            signatureProperty.Attributes.Append(idAttr);
            XmlAttribute targetAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.TargetAttrName)); 
            targetAttr.Value = "#" + signatureId; 
            signatureProperty.Attributes.Append(targetAttr);
 
            // 
            XmlElement signatureTime = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeTagName),
                XTable.Get(XTable.ID.OpcSignatureNamespace));
            XmlElement signatureTimeFormat = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeFormatTagName), 
                XTable.Get(XTable.ID.OpcSignatureNamespace));
            XmlElement signatureTimeValue = xDoc.CreateElement(XTable.Get(XTable.ID.SignatureTimeValueTagName), 
                XTable.Get(XTable.ID.OpcSignatureNamespace)); 

            signatureTimeFormat.AppendChild(xDoc.CreateTextNode(xmlDateTimeFormat)); 
            signatureTimeValue.AppendChild(xDoc.CreateTextNode(DateTimeToXmlFormattedTime(dateTime, dateTimeFormats[0])));

            signatureTime.AppendChild(signatureTimeFormat);
            signatureTime.AppendChild(signatureTimeValue); 

            signatureProperty.AppendChild(signatureTime); 
 
            return signatureProperties;
        } 

        /// 
        /// Parse the xml and determine the signing time
        ///  
        /// NodeReader positioned at the SignatureProperties tag
        /// value of the Id attribute on the Signature tag 
        /// format found 
        /// illegal format
        /// signing time 
        internal static DateTime ParseSigningTime(XmlReader reader, string signatureId, out String timeFormat)
        {
            if (reader == null)
                throw new ArgumentNullException("reader"); 

            bool signatureTimePropertyFound = false; 
            bool signatureTimeIdFound = false; 
            string w3cSignatureNameSpace = SignedXml.XmlDsigNamespaceUrl;
 
            //  tag
            string signaturePropertyTag = XTable.Get(XTable.ID.SignaturePropertyTagName);
            string signaturePropertiesTag = XTable.Get(XTable.ID.SignaturePropertiesTagName);
 
            //initializing to a dummy value
            DateTime signingTime = DateTime.Now; 
            timeFormat = null; 

            while (reader.Read()) 
            {
                //Looking for  tag
                if (reader.MoveToContent() == XmlNodeType.Element
                    && (String.CompareOrdinal(reader.NamespaceURI, w3cSignatureNameSpace) == 0) 
                    && (String.CompareOrdinal(reader.LocalName, signaturePropertyTag) == 0)
                    && reader.Depth == 2) 
                { 
                    //Verify Attributes
                    //Look for well-defined Id attribute and if it is present 
                    if (VerifyIdAttribute(reader))
                    {
                        //If we encounter more than one  tag with the expected
                        //id, then its an error. 
                        if (signatureTimeIdFound)
                            throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); 
                        else 
                            signatureTimeIdFound = true;
 
                        //VerifyTargetAttribute will return false, if the Target attribute is missing
                        //or contains an incorrect value.
                        if(VerifyTargetAttribute(reader, signatureId))
                        { 
                            signingTime = ParseSignatureTimeTag(reader, out timeFormat);
                            signatureTimePropertyFound = true; 
                        } 
                    }
                } 
                else
                    //Expected  tag not found.
                    //Look for end tag corresponding to  or
                    //if these are other custom defined properties, then anything with 
                    //depth greater than 2 should be ignored as these can be nested elements.
                    if (((String.CompareOrdinal(signaturePropertyTag, reader.LocalName) == 0 
                        && (reader.NodeType == XmlNodeType.EndElement))) 
                        || reader.Depth > 2)
                        continue; 
                    else
                        //If we find the end tag for  then we can stop parsing
                        if ((String.CompareOrdinal(signaturePropertiesTag, reader.LocalName) == 0
                        && (reader.NodeType == XmlNodeType.EndElement))) 
                            break;
                        else 
                            throw new XmlException(SR.Get(SRID.RequiredTagNotFound, signaturePropertyTag)); 
            }
 
            //We did find one or more  tags but there were none that
            //defined the id attribute and target attribute and  element tag correctly.
            if(!signatureTimePropertyFound)
                throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); 

            return signingTime; 
        } 

 
        //------------------------------------------------------------------------------
        //
        // Private Methods
        // 
        //------------------------------------------------------------------------------
 
        ///  
        /// Parse the SignatureTime tag
        ///  
        /// NodeReader positioned at the SignatureProperty tag
        /// format found
        /// illegal format
        /// signing time 
        private static DateTime ParseSignatureTimeTag(XmlReader reader, out String timeFormat)
        { 
            //There are no attributes on all the three tags that we parse in this method 
            //, , 
            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); 
 
            //  must be one of  or 
                                // 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.Get(SRID.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 -  
                                // 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.Get(SRID.PackageSignatureCorruption));
                        } 
                        else
                            //If we encounter any tag other than  or  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.Get(SRID.PackageSignatureCorruption));
                        } 
                        else 
                            // if we do not find the nested elements as expected
                            throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); 
                }
            }
            else
                throw new XmlException(SR.Get(SRID.RequiredTagNotFound, signatureTimeTag)); 

 
            // generate an equivalent DateTime object 
            if (timeValue != null && timeFormat != null)
                return XmlFormattedTimeToDateTime(timeValue, timeFormat); 
            else
                throw new XmlException(SR.Get(SRID.PackageSignatureCorruption));
        }
 
        /// 
        /// DateTime to XML Format 
        ///  
        /// date time to convert
        /// format to use - specified in DateTime syntax 
        /// opc-legal string suitable for embedding in XML digital signatures
        private static String DateTimeToXmlFormattedTime(DateTime dt, string format)
        {
            DateTimeFormatInfo formatter = new DateTimeFormatInfo(); 
            formatter.FullDateTimePattern = format;
            return dt.ToString(format, formatter); 
        } 

        ///  
        /// XML Format time string to DateTime
        /// 
        /// string to parse
        /// format to use - specified in Xml Signature date syntax 
        /// Format does not match the given string
        /// DateTime 
        private static DateTime XmlFormattedTimeToDateTime(String s, String format) 
        {
            // convert Xml syntax to equivalent DateTime syntax 
            string[] legalFormats = ConvertXmlFormatStringToDateTimeFormatString(format);

            // the default formatter is culture-invariant (which is what we want)
            DateTimeFormatInfo formatter = new DateTimeFormatInfo(); 
            formatter.FullDateTimePattern = format;
            return DateTime.ParseExact(s, legalFormats, formatter, 
                DateTimeStyles.NoCurrentDateDefault 
                | DateTimeStyles.AllowLeadingWhite
                | DateTimeStyles.AllowTrailingWhite); 
        }

        /// 
        /// Get index of the row that matches the given format 
        /// 
        /// format to lookup 
        /// -1 if not found 
        private static int GetIndex(String format)
        { 
            for (int i = 0; i < _dateTimePatternMap.GetLength(0); i++)
            {
                if (String.CompareOrdinal(_dateTimePatternMap[i].Format, format) == 0)
                { 
                    return i;
                } 
            } 
            return -1;
        } 

        /// 
        /// Convert Xml format syntax to DateTime format syntax
        ///  
        /// 
        ///  
        private static string[] ConvertXmlFormatStringToDateTimeFormatString(String format) 
        {
            return _dateTimePatternMap[GetIndex(format)].Patterns; 
        }

        /// 
        /// Verify if the SignatureProperty tag has a valid Id attribute 
        /// 
        /// NodeReader positioned at the SignatureProperty tag 
        /// true, if Id attribute is present and has the correct value, else false 
        private static bool VerifyIdAttribute(XmlReader reader)
        { 
            string idAttrValue = reader.GetAttribute(XTable.Get(XTable.ID.SignaturePropertyIdAttrName));

            if(idAttrValue!=null
                && (String.CompareOrdinal(idAttrValue,XTable.Get(XTable.ID.SignaturePropertyIdAttrValue)) == 0)) 
                return true;
            else 
                return false; 
        }
 
        /// 
        /// Verify if the mandatory Target attribute exists on the SignatureProperty tag
        /// 
        /// NodeReader positioned at the SignatureProperty tag 
        /// value of the Id attribute on the Signature tag
        /// true, if Target attribute is present and has the correct value, else false 
        private static bool VerifyTargetAttribute(XmlReader reader, string signatureId) 
        {
            string idTargetValue = reader.GetAttribute(XTable.Get(XTable.ID.TargetAttrName)); 

            if (idTargetValue != null)
            {
                //whether there is an Id attribute on the  tag or no, 
                //an empty Target attribute on  tag, is allowed.
                //Empty string means current document 
                if (String.CompareOrdinal(idTargetValue, String.Empty) == 0) 
                    return true;
                else 
                {
                    //If the Target attribute has a non-empty string then
                    //it must match the  tag Id attribute value
                    if (signatureId != null && String.CompareOrdinal(idTargetValue, "#" + signatureId) == 0) 
                        return true;
                    else 
                        return false; 
                }
            } 
            else
                return false;
        }
 
        //-----------------------------------------------------------------------------
        // 
        // Private Fields 
        //
        //------------------------------------------------------------------------------ 

        // This is a mapping between time formats allowed by Opc spec (taken from
        // http://www.w3.org/TR/NOTE-datetime) and the equivalent formatting string
        // expected by the DateTimeFormatInfo class. 
        private struct TimeFormatMapEntry
        { 
            public TimeFormatMapEntry(string xmlFormatString, string[] dateTimePatterns) 
            {
                _xmlFormatString = xmlFormatString; 
                _dateTimePatterns = dateTimePatterns;
            }

            public string   Format { get { return _xmlFormatString; }} 
            public string[] Patterns { get { return _dateTimePatterns; }}
 
            private string      _xmlFormatString; 
            private string[]    _dateTimePatterns;
        }; 

        private static readonly TimeFormatMapEntry[] _dateTimePatternMap =
        {
            // Opc Spec value                                   Equivalent DateTimePattern(s) 
            new TimeFormatMapEntry("YYYY-MM-DDThh:mm:ss.sTZD",  new string[] {"yyyy-MM-ddTHH:mm:ss.fzzz",   "yyyy-MM-ddTHH:mm:ss.fZ"}),
            new TimeFormatMapEntry("YYYY-MM-DDThh:mm:ssTZD",    new string[] {"yyyy-MM-ddTHH:mm:sszzz",     "yyyy-MM-ddTHH:mm:ssZ"}), 
            new TimeFormatMapEntry("YYYY-MM-DDThh:mmTZD",       new string[] {"yyyy-MM-ddTHH:mmzzz",        "yyyy-MM-ddTHH:mmZ"}), 
            new TimeFormatMapEntry("YYYY-MM-DD",                new string[] {"yyyy-MM-dd"}),
            new TimeFormatMapEntry("YYYY-MM",                   new string[] {"yyyy-MM"}), 
            new TimeFormatMapEntry("YYYY",                      new string[] {"yyyy"}),
        };
    }
  } 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK