2004-05-13 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Security / System.Security.Cryptography.Xml / DataObject.cs
1 //
2 // DataObject.cs - DataObject implementation for XML Signature
3 // http://www.w3.org/2000/09/xmldsig#Object
4 //
5 // Author:
6 //      Sebastien Pouliot (spouliot@motus.com)
7 //      Atsushi Enomoto (atsushi@ximian.com)
8 //
9 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
10 // (C) 2004 Novell Inc.
11 //
12
13 using System.Xml;
14
15 namespace System.Security.Cryptography.Xml {
16
17         // XmlElement part of the signature
18         // Note: Looks like KeyInfoNode (but the later is XmlElement inside KeyInfo)
19         // required for "enveloping signatures"
20         public class DataObject {
21
22                 private string id;
23                 private string mimeType;
24                 private string encoding;
25                 private XmlElement element;
26                 private bool propertyModified;
27
28                 public DataObject ()
29                 {
30                         Build (null, null, null, null);
31                 }
32
33                 public DataObject (string id, string mimeType, string encoding, XmlElement data) 
34                 {
35                         if (data == null)
36                                 throw new ArgumentNullException ("data");
37
38                         Build (id, mimeType, encoding, data);
39                 }
40
41                 // this one accept a null "data" parameter
42                 private void Build (string id, string mimeType, string encoding, XmlElement data) 
43                 {
44                         XmlDocument document = new XmlDocument ();
45                         XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Object, XmlSignature.NamespaceURI);
46                         if (id != null) {
47                                 this.id = id;
48                                 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
49                         }
50                         if (mimeType != null) {
51                                 this.mimeType = mimeType;
52                                 xel.SetAttribute (XmlSignature.AttributeNames.MimeType, mimeType);
53                         }
54                         if (encoding != null) {
55                                 this.encoding = encoding;
56                                 xel.SetAttribute (XmlSignature.AttributeNames.Encoding, encoding);
57                         }
58                         if (data != null) {
59                                 XmlNode newNode = document.ImportNode (data, true);
60                                 xel.AppendChild (newNode);
61                         }
62                         document.AppendChild (xel); // FIXME: it should not be appended
63                         
64                         element = document.DocumentElement;
65                 }
66
67                 // why is data a XmlNodeList instead of a XmlElement ?
68                 public XmlNodeList Data {
69                         get { 
70                                 return element.ChildNodes;
71                         }
72                         set {
73                                 if (value == null)
74                                         throw new ArgumentNullException ("value");
75                                 XmlDocument doc = new XmlDocument ();
76                                 XmlElement el = (XmlElement) doc.ImportNode (element, true);
77                                 doc.AppendChild (el); // FIXME: it should not be appended
78                                 el.RemoveAll ();
79                                 foreach (XmlNode n in value)
80                                         el.AppendChild (doc.ImportNode (n, true));
81                                 element = el;
82                                 propertyModified = true;
83                         }
84                 }
85
86                 // default to null - no encoding
87                 public string Encoding {
88                         get { return GetField (XmlSignature.AttributeNames.Encoding); }
89                         set { SetField (XmlSignature.AttributeNames.Encoding, value); }
90                 }
91
92                 // default to null
93                 public string Id {
94                         get { return GetField (XmlSignature.AttributeNames.Id); }
95                         set { SetField (XmlSignature.AttributeNames.Id, value); }
96                 }
97
98                 // default to null
99                 public string MimeType {
100                         get { return GetField (XmlSignature.AttributeNames.MimeType); }
101                         set { SetField (XmlSignature.AttributeNames.MimeType, value); }
102                 }
103                 
104                 private string GetField (string attribute)
105                 {
106                         XmlNode attr = element.Attributes [attribute];
107                         return attr != null ? attr.Value : null;
108                 }
109
110                 private void SetField (string attribute, string value)
111                 {
112                         // MS-BUGS: it never cleans attribute value up.
113                         if (value == null)
114                                 return;
115
116                         if (propertyModified)
117                                 element.SetAttribute (attribute, value);
118                         else {
119                                 XmlDocument document = new XmlDocument ();
120                                 XmlElement el = document.ImportNode (element, true) as XmlElement;
121                                 el.Attributes.RemoveAll ();
122                                 document.AppendChild (el); // FIXME: it should not be appended
123                                 el.SetAttribute (attribute, value);
124                                 element = el;
125                                 propertyModified = true;
126                         }
127                 }
128
129                 public XmlElement GetXml () 
130                 {
131                         if (propertyModified) {
132                                 // It looks MS.NET returns element which comes from new XmlDocument every time
133                                 XmlElement oldElement = element;
134                                 XmlDocument doc = new XmlDocument ();
135                                 element = doc.CreateElement (XmlSignature.ElementNames.Object, XmlSignature.NamespaceURI);
136                                 doc.AppendChild (element); // FIXME: it should not be appended
137                                 foreach (XmlAttribute attribute in oldElement.Attributes) {
138                                         switch (attribute.Name) {
139                                         case XmlSignature.AttributeNames.Id:
140                                         case XmlSignature.AttributeNames.Encoding:
141                                         case XmlSignature.AttributeNames.MimeType:
142                                                 element.SetAttribute (attribute.Name, attribute.Value);
143                                                 break;
144                                         }
145                                 }
146                                 foreach (XmlNode n in oldElement.ChildNodes)
147                                         element.AppendChild (doc.ImportNode (n, true));
148                         }
149                         return element;
150                 }
151
152                 public void LoadXml (XmlElement value) 
153                 {
154                         if (value == null)
155                                 throw new ArgumentNullException ("value");
156                         element = value;
157                         propertyModified = false;
158                 }
159         }
160 }