2 // System.Security.SecurityElement.cs
5 // Miguel de Icaza (miguel@ximian.com)
6 // Lawrence Pit (loz@cable.a2000.nl)
7 // Sebastien Pouliot <spouliot@videotron.ca>
9 // (C) Ximian, Inc. http://www.ximian.com
11 using System.Globalization;
12 using System.Collections;
15 namespace System.Security
18 public sealed class SecurityElement
20 internal class SecurityAttribute {
23 private string _value;
25 public SecurityAttribute (string name, string value)
27 if (!IsValidAttributeName (name))
28 throw new ArgumentException (Locale.GetText ("Invalid XML attribute name") + ": " + name);
30 if (!IsValidAttributeValue (value))
31 throw new ArgumentException (Locale.GetText ("Invalid XML attribute value") + ": " + value);
42 get { return _value; }
51 // these values are determined by a simple test program against the MS.Net implementation:
52 // for (int i = 0; i < 256; i++) {
53 // if (!SecurityElement.IsValidTag ("" + ((char) i))) {
54 // System.Console.WriteLine ("TAG: " + i);
57 // note: this is actually an incorrect implementation of MS, as for example the &
58 // character is not a valid character in tag names.
59 private static char [] invalid_tag_chars = new char [] { ' ', '<', '>' };
60 private static char [] invalid_text_chars = new char [] { '<', '>' };
61 private static char [] invalid_attr_name_chars = new char [] { ' ', '<', '>' };
62 private static char [] invalid_attr_value_chars = new char [] { '"', '<', '>' };
63 private static char [] invalid_chars = new char [] { '<', '>', '"', '\'', '&' };
65 public SecurityElement (string tag) : this (tag, null)
69 public SecurityElement (string tag, string text)
75 public Hashtable Attributes {
77 if (attributes == null)
80 Hashtable result = new Hashtable (attributes.Count);
81 foreach (SecurityAttribute sa in attributes) {
82 result.Add (sa.Name, sa.Value);
88 if (value == null || value.Count == 0) {
93 if (attributes == null)
94 attributes = new ArrayList ();
97 IDictionaryEnumerator e = value.GetEnumerator ();
98 while (e.MoveNext ()) {
99 attributes.Add (new SecurityAttribute ((string) e.Key, (string) e.Value));
104 public ArrayList Children {
111 foreach (object o in value) {
113 throw new ArgumentNullException ();
114 // shouldn't we also throw an exception
115 // when o isn't an instance of SecurityElement?
128 throw new ArgumentNullException ();
129 if (!IsValidTag (value))
130 throw new ArgumentException (Locale.GetText ("Invalid XML string") + ": " + value);
131 int colon = value.IndexOf (':');
132 tag = colon < 0 ? value : value.Substring (colon + 1);
142 if (!IsValidText (value))
143 throw new ArgumentException (Locale.GetText ("Invalid XML string") + ": " + text);
148 public void AddAttribute (string name, string value)
151 throw new ArgumentNullException ("name");
153 throw new ArgumentNullException ("value");
154 if (GetAttribute (name) != null)
155 throw new ArgumentException (Locale.GetText ("Duplicate attribute : " + name));
157 if (attributes == null)
158 attributes = new ArrayList ();
159 attributes.Add (new SecurityAttribute (name, value));
162 public void AddChild (SecurityElement child)
165 throw new ArgumentNullException ("child");
167 if (children == null)
168 children = new ArrayList ();
170 children.Add (child);
173 public string Attribute (string name)
176 throw new ArgumentNullException ("name");
178 SecurityAttribute sa = GetAttribute (name);
179 return ((sa == null) ? null : sa.Value);
182 public bool Equal (SecurityElement other)
190 if (this.text != other.text)
193 if (this.tag != other.tag)
196 if (this.attributes == null && other.attributes != null && other.attributes.Count != 0)
199 if (other.attributes == null && this.attributes != null && this.attributes.Count != 0)
202 if (this.attributes != null && other.attributes != null) {
203 if (this.attributes.Count != other.attributes.Count)
205 foreach (SecurityAttribute sa1 in attributes) {
206 SecurityAttribute sa2 = other.GetAttribute (sa1.Name);
207 if ((sa2 == null) || (sa1.Value != sa2.Value))
212 if (this.children == null && other.children != null && other.children.Count != 0)
215 if (other.children == null && this.children != null && this.children.Count != 0)
218 if (this.children != null && other.children != null) {
219 if (this.children.Count != other.children.Count)
221 for (int i = 0; i < this.children.Count; i++)
222 if (!((SecurityElement) this.children [i]).Equal ((SecurityElement) other.children [i]))
229 public static string Escape (string str)
233 if (str.IndexOfAny (invalid_chars) == -1)
236 sb = new StringBuilder ();
237 int len = str.Length;
239 for (int i = 0; i < len; i++) {
243 case '<': sb.Append ("<"); break;
244 case '>': sb.Append (">"); break;
245 case '"': sb.Append ("""); break;
246 case '\'': sb.Append ("'"); break;
247 case '&': sb.Append ("&"); break;
248 default: sb.Append (c); break;
252 return sb.ToString ();
255 public static bool IsValidAttributeName (string name)
257 return name != null && name.IndexOfAny (invalid_attr_name_chars) == -1;
260 public static bool IsValidAttributeValue (string value)
262 return value != null && value.IndexOfAny (invalid_attr_value_chars) == -1;
265 public static bool IsValidTag (string value)
267 return value != null && value.IndexOfAny (invalid_tag_chars) == -1;
270 public static bool IsValidText (string value)
274 return value.IndexOfAny (invalid_text_chars) == -1;
277 public SecurityElement SearchForChildByTag (string tag)
280 throw new ArgumentNullException ("tag");
282 if (this.children == null)
285 for (int i = 0; i < children.Count; i++) {
286 SecurityElement elem = (SecurityElement) children [i];
293 public string SearchForTextOfTag (string tag)
296 throw new ArgumentNullException ("tag");
301 if (this.children == null)
304 for (int i = 0; i < children.Count; i++) {
305 string result = ((SecurityElement) children [i]).SearchForTextOfTag (tag);
313 public override string ToString ()
315 StringBuilder s = new StringBuilder ();
317 return s.ToString ();
320 private void ToXml (ref StringBuilder s, int level)
322 s.Append (' ', level * 3);
326 if (attributes != null) {
327 for (int i=0; i < attributes.Count; i++) {
328 SecurityAttribute sa = (SecurityAttribute) attributes [i];
330 // all other attributes must align with the first one
332 s.Append (' ', (level * 3) + tag.Length + 1);
337 if (i != attributes.Count - 1)
338 s.Append (Environment.NewLine);
342 if ((text == null || text == String.Empty) &&
343 (children == null || children.Count == 0))
344 s.Append ("/>").Append (Environment.NewLine);
346 s.Append (">").Append (text);
347 if (children != null) {
348 s.Append (Environment.NewLine);
349 foreach (SecurityElement child in children) {
350 child.ToXml (ref s, level + 1);
352 s.Append (' ', level * 3);
357 .Append (Environment.NewLine);
361 internal SecurityAttribute GetAttribute (string name)
363 if (attributes != null) {
364 foreach (SecurityAttribute sa in attributes) {