2 // System.Security.SecurityElement.cs
5 // Miguel de Icaza (miguel@ximian.com)
6 // Lawrence Pit (loz@cable.a2000.nl)
8 // (C) Ximian, Inc. http://www.ximian.com
10 using System.Globalization;
11 using System.Collections;
14 namespace System.Security
17 public sealed class SecurityElement
24 // these values are determined by a simple test program against the MS.Net implementation:
25 // for (int i = 0; i < 256; i++) {
26 // if (!SecurityElement.IsValidTag ("" + ((char) i))) {
27 // System.Console.WriteLine ("TAG: " + i);
30 // note: this is actually an incorrect implementation of MS, as for example the &
31 // character is not a valid character in tag names.
32 private static char [] invalid_tag_chars = new char [] { ' ', '<', '>' };
33 private static char [] invalid_text_chars = new char [] { '<', '>' };
34 private static char [] invalid_attr_name_chars = new char [] { ' ', '<', '>' };
35 private static char [] invalid_attr_value_chars = new char [] { '"', '<', '>' };
36 private static char [] invalid_chars = new char [] { '<', '>', '"', '\'', '&' };
38 public SecurityElement (string tag) : this (tag, null)
42 public SecurityElement (string tag, string text)
45 this.Text = (text == null) ? String.Empty : text;
48 public Hashtable Attributes {
50 if (attributes == null)
53 Hashtable result = new Hashtable ();
54 IDictionaryEnumerator e = attributes.GetEnumerator ();
56 result.Add (e.Key, e.Value);
61 if (value == null || value.Count == 0) {
66 Hashtable result = new Hashtable ();
67 IDictionaryEnumerator e = value.GetEnumerator ();
68 while (e.MoveNext ()) {
69 string key = (string) e.Key;
70 string val = (string) e.Value;
71 if (!IsValidAttributeName (key))
72 throw new ArgumentException (Locale.GetText ("Invalid XML string") + ": " + key);
74 if (!IsValidAttributeValue (val))
75 throw new ArgumentException (Locale.GetText ("Invalid XML string") + ": " + key);
77 result.Add (key, val);
83 public ArrayList Children {
90 foreach (object o in value) {
92 throw new ArgumentNullException ();
93 // shouldn't we also throw an exception
94 // when o isn't an instance of SecurityElement?
107 throw new ArgumentNullException ();
108 if (!IsValidTag (value))
109 throw new ArgumentException (Locale.GetText ("Invalid XML string") + ": " + value);
120 if (!IsValidText (value))
121 throw new ArgumentException (Locale.GetText ("Invalid XML string") + ": " + text);
126 public void AddAttribute (string name, string value)
128 if (name == null || value == null)
129 throw new ArgumentNullException ();
131 if (attributes == null)
132 attributes = new Hashtable ();
135 // The hashtable will throw ArgumentException if name is already there
138 if (!IsValidAttributeName (name))
139 throw new ArgumentException (Locale.GetText ("Invalid XML string") + ": " + name);
141 if (!IsValidAttributeValue (value))
142 throw new ArgumentException (Locale.GetText ("Invalid XML string") + ": " + value);
144 attributes.Add (name, value);
147 public void AddChild (SecurityElement child)
150 throw new ArgumentNullException ();
152 if (children == null)
153 children = new ArrayList ();
155 children.Add (child);
158 public string Attribute (string name)
161 throw new ArgumentNullException ();
163 if (attributes != null)
164 return (string) attributes [name];
169 public bool Equal (SecurityElement other)
177 if (this.text != other.text)
180 if (this.tag != other.tag)
183 if (this.attributes == null && other.attributes != null && other.attributes.Count != 0)
186 if (other.attributes == null && this.attributes != null && this.attributes.Count != 0)
189 if (this.attributes != null && other.attributes != null) {
190 if (this.attributes.Count != other.attributes.Count)
192 IDictionaryEnumerator e = attributes.GetEnumerator ();
193 while (e.MoveNext ())
194 if (other.attributes [e.Key] != e.Value)
198 if (this.children == null && other.children != null && other.children.Count != 0)
201 if (other.children == null && this.children != null && this.children.Count != 0)
204 if (this.children != null && other.children != null) {
205 if (this.children.Count != other.children.Count)
207 for (int i = 0; i < this.children.Count; i++)
208 if (!((SecurityElement) this.children [i]).Equal ((SecurityElement) other.children [i]))
215 public static string Escape (string str)
219 if (str.IndexOfAny (invalid_chars) == -1)
222 sb = new StringBuilder ();
223 int len = str.Length;
225 for (int i = 0; i < len; i++) {
229 case '<': sb.Append ("<"); break;
230 case '>': sb.Append (">"); break;
231 case '"': sb.Append ("""); break;
232 case '\'': sb.Append ("'"); break;
233 case '&': sb.Append ("&"); break;
234 default: sb.Append (c); break;
238 return sb.ToString ();
241 public static bool IsValidAttributeName (string name)
243 return name != null && name.IndexOfAny (invalid_attr_name_chars) == -1;
246 public static bool IsValidAttributeValue (string value)
248 return value != null && value.IndexOfAny (invalid_attr_value_chars) == -1;
251 public static bool IsValidTag (string value)
253 return value != null && value.IndexOfAny (invalid_tag_chars) == -1;
256 public static bool IsValidText (string value)
258 return value != null && value.IndexOfAny (invalid_text_chars) == -1;
261 public SecurityElement SearchForChildByTag (string tag)
264 throw new ArgumentNullException ("tag");
266 if (this.children == null)
269 for (int i = 0; i < children.Count; i++) {
270 SecurityElement elem = (SecurityElement) children [i];
277 public string SearchForTextOfTag (string tag)
280 throw new ArgumentNullException ("tag");
285 if (this.children == null)
288 for (int i = 0; i < children.Count; i++) {
289 string result = ((SecurityElement) children [i]).SearchForTextOfTag (tag);
297 public override string ToString ()
299 StringBuilder s = new StringBuilder ();
301 return s.ToString ();
304 private void ToXml(ref StringBuilder s, int level)
306 s.Append (' ', level << 2);
310 if (attributes != null) {
311 IDictionaryEnumerator e = attributes.GetEnumerator ();
312 while (e.MoveNext ()) {
321 if ((text == null || text == String.Empty) &&
322 (children == null || children.Count == 0))
325 s.Append (">").Append (text);
326 if (children != null) {
327 foreach (SecurityElement child in children) {
328 s.Append (Environment.NewLine);
329 child.ToXml (ref s, level + 1);
332 s.Append (Environment.NewLine)
333 .Append (' ', level << 2)