Merge pull request #2024 from BogdanovKirill/webrequesttest
[mono.git] / mcs / class / System.Security / System.Security.Cryptography.Xml / DataObject.cs
index 609bd452a2344a6b3fdfa08d8c1146cbaaf7ad3b..bd7c529f137bc5e3138abfe4dea4d64b819e3783 100644 (file)
 // http://www.w3.org/2000/09/xmldsig#Object
 //
 // Author:
-//     Sebastien Pouliot (spouliot@motus.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
+//     Atsushi Enomoto (atsushi@ximian.com)
 //
-// (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System.Security.Cryptography;
-using System.Text;
 using System.Xml;
 
 namespace System.Security.Cryptography.Xml {
 
-// XmlElement part of the signature
-// Note: Looks like KeyInfoNode (but the later is XmlElement inside KeyInfo)
-// required for "enveloping signatures"
-public class DataObject {
+       // XmlElement part of the signature
+       // Note: Looks like KeyInfoNode (but the later is XmlElement inside KeyInfo)
+       // required for "enveloping signatures"
+       public class DataObject {
 
-       private string id;
-       private string mimeType;
-       private string encoding;
-       private string data;
-       private XmlDocument doc;
+               private XmlElement element;
+               private bool propertyModified;
 
-       static private string xmldsig = "http://www.w3.org/2000/09/xmldsig#";
+               public DataObject ()
+               {
+                       Build (null, null, null, null);
+               }
 
-       public DataObject (
-       {
-               Build (null, null, null, null);
-       }
+               public DataObject (string id, string mimeType, string encoding, XmlElement data
+               {
+                       if (data == null)
+                               throw new ArgumentNullException ("data");
 
-       public DataObject (string id, string mimeType, string encoding, XmlElement data) 
-       {
-               if (data == null)
-                       throw new ArgumentNullException ("data");
+                       Build (id, mimeType, encoding, data);
+               }
 
-               Build (id, mimeType, encoding, data);
-       }
+               // this one accept a null "data" parameter
+               private void Build (string id, string mimeType, string encoding, XmlElement data) 
+               {
+                       XmlDocument document = new XmlDocument ();
+                       XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Object, XmlSignature.NamespaceURI);
+                       if (id != null) {
+                               xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
+                       }
+                       if (mimeType != null) {
+                               xel.SetAttribute (XmlSignature.AttributeNames.MimeType, mimeType);
+                       }
+                       if (encoding != null) {
+                               xel.SetAttribute (XmlSignature.AttributeNames.Encoding, encoding);
+                       }
+                       if (data != null) {
+                               XmlNode newNode = document.ImportNode (data, true);
+                               xel.AppendChild (newNode);
+                       }
+                       element = xel;
+               }
+
+               // why is data a XmlNodeList instead of a XmlElement ?
+               public XmlNodeList Data {
+                       get { 
+                               return element.ChildNodes;
+                       }
+                       set {
+                               if (value == null)
+                                       throw new ArgumentNullException ("value");
+                               XmlDocument doc = new XmlDocument ();
+                               XmlElement el = (XmlElement) doc.ImportNode (element, true);
+                               while (el.LastChild != null)
+                                       el.RemoveChild (el.LastChild);
+                               foreach (XmlNode n in value)
+                                       el.AppendChild (doc.ImportNode (n, true));
+                               element = el;
+                               propertyModified = true;
+                       }
+               }
 
-       private void Build (string id, string mimeType, string encoding, XmlElement data) 
-       {
-               StringBuilder sb = new StringBuilder ();
-               sb.Append ("<Object ");
-               if (id != null) {
-                       this.id = id;
-                       sb.Append ("Id=\"");
-                       sb.Append (id);
-                       sb.Append ("\" ");
+               // default to null - no encoding
+               public string Encoding {
+                       get { return GetField (XmlSignature.AttributeNames.Encoding); }
+                       set { SetField (XmlSignature.AttributeNames.Encoding, value); }
                }
-               if (mimeType != null) {
-                       this.mimeType = mimeType;
-                       sb.Append ("MimeType=\"");
-                       sb.Append (mimeType);
-                       sb.Append ("\" ");
+
+               // default to null
+               public string Id {
+                       get { return GetField (XmlSignature.AttributeNames.Id); }
+                       set { SetField (XmlSignature.AttributeNames.Id, value); }
                }
-               if (encoding != null) {
-                       this.encoding = encoding;
-                       sb.Append ("Encoding=\"");
-                       sb.Append (encoding);
-                       sb.Append ("\" ");
+
+               // default to null
+               public string MimeType {
+                       get { return GetField (XmlSignature.AttributeNames.MimeType); }
+                       set { SetField (XmlSignature.AttributeNames.MimeType, value); }
                }
-               sb.Append ("xmlns=\"http://www.w3.org/2000/09/xmldsig#\" />");
                
-               doc = new XmlDocument ();
-               doc.LoadXml (sb.ToString ());
-               if (data != null) {
-                       XmlNodeList xnl = doc.GetElementsByTagName ("Object");
-                       XmlNode newNode = doc.ImportNode (data, true);
-                       xnl[0].AppendChild (newNode);
+               private string GetField (string attribute)
+               {
+                       XmlNode attr = element.Attributes [attribute];
+                       return attr != null ? attr.Value : null;
                }
-       }
 
-       // why is data a XmlNodeList instead of a XmlElement ?
-       public XmlNodeList Data {
-               get { 
-                       XmlNodeList xnl = doc.GetElementsByTagName ("Object");
-                       return xnl[0].ChildNodes;
-               }
-               set {
+               private void SetField (string attribute, string value)
+               {
+                       // MS-BUGS: it never cleans attribute value up.
                        if (value == null)
-                               throw new ArgumentNullException ("value");
-
-                       Build (id, mimeType, encoding, null);
-                       XmlNodeList xnl = doc.GetElementsByTagName ("Object");
-                       if ((xnl != null) && (xnl.Count > 0)) {
-                               foreach (XmlNode xn in value) {
-                                       XmlNode newNode = doc.ImportNode (xn, true);
-                                       xnl[0].AppendChild (newNode);
-                               }
+                               return;
+
+                       if (propertyModified)
+                               element.SetAttribute (attribute, value);
+                       else {
+                               XmlDocument document = new XmlDocument ();
+                               XmlElement el = document.ImportNode (element, true) as XmlElement;
+                               el.SetAttribute (attribute, value);
+                               element = el;
+                               propertyModified = true;
                        }
                }
-       }
-
-       // default to null - no encoding
-       public string Encoding {
-               get { return encoding; }
-               set { encoding = value; }
-       }
-
-       // default to null
-       public string Id {
-               get { return id; }
-               set { id = value; }
-       }
-
-       // default to null
-       public string MimeType {
-               get { return mimeType; }
-               set { mimeType = value; }
-       }
 
-       public XmlElement GetXml () 
-       {
-               if ((doc.DocumentElement.LocalName == "Object") && (doc.DocumentElement.NamespaceURI == "http://www.w3.org/2000/09/xmldsig#")) {
-                       // recreate all attributes in order
-                       XmlAttribute xa = null;
-                       doc.DocumentElement.Attributes.RemoveAll ();
-                       if (id != null) {
-                               xa = doc.CreateAttribute ("Id");
-                               xa.Value = id;
-                               doc.DocumentElement.Attributes.Append (xa);
-                       }
-                       if (mimeType != null) {
-                               xa = doc.CreateAttribute ("MimeType");
-                               xa.Value = mimeType;
-                               doc.DocumentElement.Attributes.Append (xa);
-                       }
-                       if (encoding != null) {
-                               xa = doc.CreateAttribute ("Encoding");
-                               xa.Value = encoding;
-                               doc.DocumentElement.Attributes.Append (xa);
+               public XmlElement GetXml () 
+               {
+                       if (propertyModified) {
+                               // It looks MS.NET returns element which comes from new XmlDocument every time
+                               XmlElement oldElement = element;
+                               XmlDocument doc = new XmlDocument ();
+                               element = doc.CreateElement (XmlSignature.ElementNames.Object, XmlSignature.NamespaceURI);
+                               foreach (XmlAttribute attribute in oldElement.Attributes) {
+                                       switch (attribute.Name) {
+                                       case XmlSignature.AttributeNames.Id:
+                                       case XmlSignature.AttributeNames.Encoding:
+                                       case XmlSignature.AttributeNames.MimeType:
+                                               element.SetAttribute (attribute.Name, attribute.Value);
+                                               break;
+                                       }
+                               }
+                               foreach (XmlNode n in oldElement.ChildNodes)
+                                       element.AppendChild (doc.ImportNode (n, true));
                        }
-                       xa = doc.CreateAttribute ("xmlns");
-                       xa.Value = xmldsig;
-                       doc.DocumentElement.Attributes.Append (xa);
+                       return element;
                }
-               return doc.DocumentElement;
-       }
 
-       public void LoadXml (XmlElement value) 
-       {
-               if (value == null)
-                       throw new ArgumentNullException ("value");
-
-               if ((value.LocalName == "Object") && (value.NamespaceURI == "http://www.w3.org/2000/09/xmldsig#")) {
-                       doc.LoadXml (value.OuterXml);
-                       XmlAttribute xa = value.Attributes ["Id"];
-                       id = ((xa != null) ? xa.InnerText : null);
-                       xa = value.Attributes ["MimeType"];
-                       mimeType = ((xa != null) ? xa.InnerText : null);
-                       xa = value.Attributes ["Encoding"];
-                       encoding = ((xa != null) ? xa.InnerText : null);
+               public void LoadXml (XmlElement value) 
+               {
+                       if (value == null)
+                               throw new ArgumentNullException ("value");
+                       element = value;
+                       propertyModified = false;
                }
-               else
-                       doc.LoadXml (value.OuterXml);
        }
 }
-
-}
\ No newline at end of file