XmlSignatureProperties.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Packaging / XmlSignatureProperties.cs / 1305600 / 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;
using MS.Internal.WindowsBase; 

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;
using MS.Internal.WindowsBase; 

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