The Labs \ Source Viewer \ SSCLI \ System.Security \ SecurityElement

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Security
  16. {
  17.     using System;
  18.     using System.Collections;
  19.     using System.Security.Util;
  20.     using System.Text;
  21.     using System.Globalization;
  22.     using System.IO;
  23.     using System.Security.Permissions;
  24.    
  25.     internal enum SecurityElementType
  26.     {
  27.         Regular = 0,
  28.         Format = 1,
  29.         Comment = 2
  30.     }
  31.    
  32.    
  33.     internal interface ISecurityElementFactory
  34.     {
  35.         SecurityElement CreateSecurityElement();
  36.        
  37.         object Copy();
  38.        
  39.         string GetTag();
  40.        
  41.         string Attribute(string attributeName);
  42.     }
  43.    
  44.     [Serializable()]
  45.     [System.Runtime.InteropServices.ComVisible(true)]
  46.     public sealed class SecurityElement : ISecurityElementFactory
  47.     {
  48.         internal string m_strTag;
  49.         internal string m_strText;
  50.         private ArrayList m_lChildren;
  51.         internal ArrayList m_lAttributes;
  52.         internal SecurityElementType m_type = SecurityElementType.Regular;
  53.        
  54.         private static readonly char[] s_tagIllegalCharacters = new char[] {' ', '<', '>'};
  55.         private static readonly char[] s_textIllegalCharacters = new char[] {'<', '>'};
  56.         private static readonly char[] s_valueIllegalCharacters = new char[] {'<', '>', '"'};
  57.         private const string s_strIndent = " ";
  58.        
  59.         private const int c_AttributesTypical = 4 * 2;
  60.         // 4 attributes, times 2 strings per attribute
  61.         private const int c_ChildrenTypical = 1;
  62.        
  63.         private static readonly string[] s_escapeStringPairs = new string[] {"<", "&lt;", ">", "&gt;", "\"", "&quot;", "'", "&apos;", "&", "&amp;"
  64.             // these must be all once character escape sequences or a new escaping algorithm is needed
  65.         };
  66.        
  67.         private static readonly char[] s_escapeChars = new char[] {'<', '>', '"', '\'', '&'};
  68.        
  69.         //-------------------------- Constructors ---------------------------
  70.        
  71.         internal SecurityElement()
  72.         {
  73.         }
  74.        
  75.         ////// ISecurityElementFactory implementation
  76.        
  77.         SecurityElement ISecurityElementFactory.CreateSecurityElement()
  78.         {
  79.             return this;
  80.         }
  81.        
  82.         string ISecurityElementFactory.GetTag()
  83.         {
  84.             return ((SecurityElement)this).Tag;
  85.         }
  86.        
  87.         object ISecurityElementFactory.Copy()
  88.         {
  89.             return ((SecurityElement)this).Copy();
  90.         }
  91.        
  92.         string ISecurityElementFactory.Attribute(string attributeName)
  93.         {
  94.             return ((SecurityElement)this).Attribute(attributeName);
  95.         }
  96.        
  97.         //////////////
  98.        
  99.         public static SecurityElement FromString(string xml)
  100.         {
  101.             if (xml == null)
  102.                 throw new ArgumentNullException("xml");
  103.            
  104.             return new Parser(xml).GetTopElement();
  105.         }
  106.        
  107.         public SecurityElement(string tag)
  108.         {
  109.             if (tag == null)
  110.                 throw new ArgumentNullException("tag");
  111.            
  112.             if (!IsValidTag(tag))
  113.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementTag"), tag));
  114.            
  115.             m_strTag = tag;
  116.             m_strText = null;
  117.         }
  118.        
  119.         public SecurityElement(string tag, string text)
  120.         {
  121.             if (tag == null)
  122.                 throw new ArgumentNullException("tag");
  123.            
  124.             if (!IsValidTag(tag))
  125.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementTag"), tag));
  126.            
  127.             if (text != null && !IsValidText(text))
  128.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementText"), text));
  129.            
  130.             m_strTag = tag;
  131.             m_strText = text;
  132.         }
  133.        
  134.         //-------------------------- Properties -----------------------------
  135.        
  136.         public string Tag {
  137.             get { return m_strTag; }
  138.            
  139.             set {
  140.                 if (value == null)
  141.                     throw new ArgumentNullException("Tag");
  142.                
  143.                 if (!IsValidTag(value))
  144.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementTag"), value));
  145.                
  146.                 m_strTag = value;
  147.             }
  148.         }
  149.        
  150.         public System.Collections.Hashtable Attributes {
  151.             get {
  152.                 if (m_lAttributes == null || m_lAttributes.Count == 0) {
  153.                     return null;
  154.                 }
  155.                 else {
  156.                     System.Collections.Hashtable hashtable = new System.Collections.Hashtable(m_lAttributes.Count);
  157.                    
  158.                     int iMax = m_lAttributes.Count;
  159.                     BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  160.                    
  161.                     for (int i = 0; i < iMax; i += 2) {
  162.                         hashtable.Add(m_lAttributes[i], m_lAttributes[i + 1]);
  163.                     }
  164.                    
  165.                     return hashtable;
  166.                 }
  167.             }
  168.            
  169.             set {
  170.                 if (value == null || value.Count == 0) {
  171.                     m_lAttributes = null;
  172.                 }
  173.                 else {
  174.                     ArrayList list = new ArrayList(value.Count);
  175.                    
  176.                     System.Collections.IDictionaryEnumerator enumerator = (System.Collections.IDictionaryEnumerator)value.GetEnumerator();
  177.                    
  178.                     while (enumerator.MoveNext()) {
  179.                         string attrName = (string)enumerator.Key;
  180.                         string attrValue = (string)enumerator.Value;
  181.                        
  182.                         if (!IsValidAttributeName(attrName))
  183.                             throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementName"), (string)enumerator.Current));
  184.                        
  185.                         if (!IsValidAttributeValue(attrValue))
  186.                             throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementValue"), (string)enumerator.Value));
  187.                        
  188.                         list.Add(attrName);
  189.                         list.Add(attrValue);
  190.                     }
  191.                    
  192.                     m_lAttributes = list;
  193.                 }
  194.             }
  195.         }
  196.        
  197.         public string Text {
  198.             get { return Unescape(m_strText); }
  199.            
  200.             set {
  201.                 if (value == null) {
  202.                     m_strText = null;
  203.                 }
  204.                 else {
  205.                     if (!IsValidText(value))
  206.                         throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementTag"), value));
  207.                    
  208.                     m_strText = value;
  209.                 }
  210.             }
  211.         }
  212.        
  213.         public ArrayList Children {
  214.             get {
  215.                 ConvertSecurityElementFactories();
  216.                 return m_lChildren;
  217.             }
  218.            
  219.             set {
  220.                 if (value != null) {
  221.                     IEnumerator enumerator = value.GetEnumerator();
  222.                    
  223.                     while (enumerator.MoveNext()) {
  224.                         if (enumerator.Current == null)
  225.                             throw new ArgumentException(Environment.GetResourceString("ArgumentNull_Child"));
  226.                     }
  227.                 }
  228.                
  229.                 m_lChildren = value;
  230.             }
  231.         }
  232.        
  233.         internal void ConvertSecurityElementFactories()
  234.         {
  235.             if (m_lChildren == null)
  236.                 return;
  237.            
  238.             for (int i = 0; i < m_lChildren.Count; ++i) {
  239.                 ISecurityElementFactory iseFactory = m_lChildren[i] as ISecurityElementFactory;
  240.                 if (iseFactory != null && !(m_lChildren[i] is SecurityElement))
  241.                     m_lChildren[i] = iseFactory.CreateSecurityElement();
  242.             }
  243.         }
  244.        
  245.         internal ArrayList InternalChildren {
  246. // Beware! This array list can contain SecurityElements and other ISecurityElementFactories.
  247. // If you want to get a consistent SecurityElement view, call get_Children.
  248.             get { return m_lChildren; }
  249.         }
  250.        
  251.         //-------------------------- Public Methods -----------------------------
  252.        
  253.         internal void AddAttributeSafe(string name, string value)
  254.         {
  255.             if (m_lAttributes == null) {
  256.                 m_lAttributes = new ArrayList(c_AttributesTypical);
  257.             }
  258.             else {
  259.                 int iMax = m_lAttributes.Count;
  260.                 BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  261.                
  262.                 for (int i = 0; i < iMax; i += 2) {
  263.                     string strAttrName = (string)m_lAttributes[i];
  264.                    
  265.                     if (String.Equals(strAttrName, name))
  266.                         throw new ArgumentException(Environment.GetResourceString("Argument_AttributeNamesMustBeUnique"));
  267.                 }
  268.             }
  269.            
  270.             m_lAttributes.Add(name);
  271.             m_lAttributes.Add(value);
  272.         }
  273.        
  274.         public void AddAttribute(string name, string value)
  275.         {
  276.             if (name == null)
  277.                 throw new ArgumentNullException("name");
  278.            
  279.             if (value == null)
  280.                 throw new ArgumentNullException("value");
  281.            
  282.             if (!IsValidAttributeName(name))
  283.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementName"), name));
  284.            
  285.             if (!IsValidAttributeValue(value))
  286.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidElementValue"), value));
  287.            
  288.             AddAttributeSafe(name, value);
  289.         }
  290.        
  291.         public void AddChild(SecurityElement child)
  292.         {
  293.             if (child == null)
  294.                 throw new ArgumentNullException("child");
  295.            
  296.             if (m_lChildren == null)
  297.                 m_lChildren = new ArrayList(c_ChildrenTypical);
  298.            
  299.             m_lChildren.Add(child);
  300.         }
  301.        
  302.         internal void AddChild(ISecurityElementFactory child)
  303.         {
  304.             if (child == null)
  305.                 throw new ArgumentNullException("child");
  306.            
  307.             if (m_lChildren == null)
  308.                 m_lChildren = new ArrayList(c_ChildrenTypical);
  309.            
  310.             m_lChildren.Add(child);
  311.         }
  312.        
  313.         internal void AddChildNoDuplicates(ISecurityElementFactory child)
  314.         {
  315.             if (child == null)
  316.                 throw new ArgumentNullException("child");
  317.            
  318.             if (m_lChildren == null) {
  319.                 m_lChildren = new ArrayList(c_ChildrenTypical);
  320.                 m_lChildren.Add(child);
  321.             }
  322.             else {
  323.                 for (int i = 0; i < m_lChildren.Count; ++i) {
  324.                     if (m_lChildren[i] == child)
  325.                         return;
  326.                 }
  327.                 m_lChildren.Add(child);
  328.             }
  329.         }
  330.        
  331.         public bool Equal(SecurityElement other)
  332.         {
  333.             if (other == null)
  334.                 return false;
  335.            
  336.             // Check if the tags are the same
  337.             if (!String.Equals(m_strTag, other.m_strTag))
  338.                 return false;
  339.            
  340.             // Check if the text is the same
  341.             if (!String.Equals(m_strText, other.m_strText))
  342.                 return false;
  343.            
  344.             // Check if the attributes are the same and appear in the same
  345.             // order.
  346.            
  347.             // Maybe we can get away by only checking the number of attributes
  348.             if (m_lAttributes == null || other.m_lAttributes == null) {
  349.                 if (m_lAttributes != other.m_lAttributes)
  350.                     return false;
  351.             }
  352.             else {
  353.                 int iMax = m_lAttributes.Count;
  354.                 BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  355.                
  356.                 if (iMax != other.m_lAttributes.Count)
  357.                     return false;
  358.                
  359.                 for (int i = 0; i < iMax; i++) {
  360.                     string lhs = (string)m_lAttributes[i];
  361.                     string rhs = (string)other.m_lAttributes[i];
  362.                    
  363.                     if (!String.Equals(lhs, rhs))
  364.                         return false;
  365.                 }
  366.             }
  367.            
  368.             // Finally we must check the child and make sure they are
  369.             // equal and in the same order
  370.            
  371.             // Maybe we can get away by only checking the number of children
  372.             if (m_lChildren == null || other.m_lChildren == null) {
  373.                 if (m_lChildren != other.m_lChildren)
  374.                     return false;
  375.             }
  376.             else {
  377.                 if (m_lChildren.Count != other.m_lChildren.Count)
  378.                     return false;
  379.                
  380.                 this.ConvertSecurityElementFactories();
  381.                 other.ConvertSecurityElementFactories();
  382.                
  383.                 // Okay, we'll need to go through each one of them
  384.                 IEnumerator lhs = m_lChildren.GetEnumerator();
  385.                 IEnumerator rhs = other.m_lChildren.GetEnumerator();
  386.                
  387.                 SecurityElement e1;
  388.                 SecurityElement e2;
  389.                 while (lhs.MoveNext()) {
  390.                     rhs.MoveNext();
  391.                     e1 = (SecurityElement)lhs.Current;
  392.                     e2 = (SecurityElement)rhs.Current;
  393.                     if (e1 == null || !e1.Equal(e2))
  394.                         return false;
  395.                 }
  396.             }
  397.            
  398.             return true;
  399.         }
  400.        
  401.         [System.Runtime.InteropServices.ComVisible(false)]
  402.         public SecurityElement Copy()
  403.         {
  404.             SecurityElement element = new SecurityElement(this.m_strTag, this.m_strText);
  405.            
  406.             element.m_lChildren = this.m_lChildren == null ? null : new ArrayList(this.m_lChildren);
  407.             element.m_lAttributes = this.m_lAttributes == null ? null : new ArrayList(this.m_lAttributes);
  408.            
  409.             return element;
  410.         }
  411.        
  412.         public static bool IsValidTag(string tag)
  413.         {
  414.             if (tag == null)
  415.                 return false;
  416.            
  417.             return tag.IndexOfAny(s_tagIllegalCharacters) == -1;
  418.         }
  419.        
  420.         public static bool IsValidText(string text)
  421.         {
  422.             if (text == null)
  423.                 return false;
  424.            
  425.             return text.IndexOfAny(s_textIllegalCharacters) == -1;
  426.         }
  427.        
  428.         public static bool IsValidAttributeName(string name)
  429.         {
  430.             return IsValidTag(name);
  431.         }
  432.        
  433.         public static bool IsValidAttributeValue(string value)
  434.         {
  435.             if (value == null)
  436.                 return false;
  437.            
  438.             return value.IndexOfAny(s_valueIllegalCharacters) == -1;
  439.         }
  440.        
  441.         private static string GetEscapeSequence(char c)
  442.         {
  443.             int iMax = s_escapeStringPairs.Length;
  444.             BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  445.            
  446.             for (int i = 0; i < iMax; i += 2) {
  447.                 string strEscSeq = s_escapeStringPairs[i];
  448.                 string strEscValue = s_escapeStringPairs[i + 1];
  449.                
  450.                 if (strEscSeq[0] == c)
  451.                     return strEscValue;
  452.             }
  453.            
  454.             BCLDebug.Assert(false, "Unable to find escape sequence for this character");
  455.             return c.ToString();
  456.         }
  457.        
  458.         public static string Escape(string str)
  459.         {
  460.             if (str == null)
  461.                 return null;
  462.            
  463.             StringBuilder sb = null;
  464.            
  465.             string temp = str;
  466.             int index;
  467.            
  468.             do {
  469.                 index = temp.IndexOfAny(s_escapeChars);
  470.                
  471.                 if (index == -1) {
  472.                     if (sb == null)
  473.                         return str;
  474.                     else {
  475.                         sb.Append(temp);
  476.                         return sb.ToString();
  477.                     }
  478.                 }
  479.                 else {
  480.                     if (sb == null)
  481.                         sb = new StringBuilder();
  482.                    
  483.                     sb.Append(temp.Substring(0, index));
  484.                     sb.Append(GetEscapeSequence(temp[index]));
  485.                    
  486.                     temp = temp.Substring(index + 1);
  487.                 }
  488.             }
  489.             while (true);
  490.            
  491.             // no normal exit is possible
  492.         }
  493.        
  494.         private static string GetUnescapeSequence(string str, int index, out int newIndex)
  495.         {
  496.             int maxCompareLength = str.Length - index;
  497.            
  498.             int iMax = s_escapeStringPairs.Length;
  499.             BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  500.            
  501.             for (int i = 0; i < iMax; i += 2) {
  502.                 string strEscSeq = s_escapeStringPairs[i];
  503.                 string strEscValue = s_escapeStringPairs[i + 1];
  504.                
  505.                 int length = strEscValue.Length;
  506.                
  507.                 if (length <= maxCompareLength && String.Compare(strEscValue, 0, str, index, length, StringComparison.Ordinal) == 0) {
  508.                     newIndex = index + strEscValue.Length;
  509.                     return strEscSeq;
  510.                 }
  511.             }
  512.            
  513.             newIndex = index + 1;
  514.             return str[index].ToString();
  515.         }
  516.        
  517.        
  518.         private static string Unescape(string str)
  519.         {
  520.             if (str == null)
  521.                 return null;
  522.            
  523.             StringBuilder sb = null;
  524.            
  525.             string temp = str;
  526.             int index;
  527.             int newIndex;
  528.            
  529.             do {
  530.                 index = temp.IndexOf('&');
  531.                
  532.                 if (index == -1) {
  533.                     if (sb == null)
  534.                         return str;
  535.                     else {
  536.                         sb.Append(temp);
  537.                         return sb.ToString();
  538.                     }
  539.                 }
  540.                 else {
  541.                     if (sb == null)
  542.                         sb = new StringBuilder();
  543.                    
  544.                     sb.Append(temp.Substring(0, index));
  545.                     sb.Append(GetUnescapeSequence(temp, index, out newIndex));
  546.                    
  547.                     temp = temp.Substring(newIndex);
  548.                 }
  549.             }
  550.             while (true);
  551.            
  552.             // C# reports a warning if I leave this in, but I still kinda want to just in case.
  553.             // BCLDebug.Assert( false, "If you got here, the execution engine or compiler is really confused" );
  554.             // return str;
  555.         }
  556.        
  557.         private delegate void ToStringHelperFunc(object obj, string str);
  558.        
  559.         private static void ToStringHelperStringBuilder(object obj, string str)
  560.         {
  561.             ((StringBuilder)obj).Append(str);
  562.         }
  563.        
  564.         private static void ToStringHelperStreamWriter(object obj, string str)
  565.         {
  566.             ((StreamWriter)obj).Write(str);
  567.         }
  568.        
  569.         public override string ToString()
  570.         {
  571.             StringBuilder sb = new StringBuilder();
  572.            
  573.             ToString("", sb, new ToStringHelperFunc(ToStringHelperStringBuilder));
  574.            
  575.             return sb.ToString();
  576.         }
  577.        
  578.         internal void ToWriter(StreamWriter writer)
  579.         {
  580.             ToString("", writer, new ToStringHelperFunc(ToStringHelperStreamWriter));
  581.         }
  582.        
  583.         private void ToString(string indent, object obj, ToStringHelperFunc func)
  584.         {
  585.             // First add the indent
  586.            
  587.             // func( obj, indent );
  588.            
  589.             // Add in the opening bracket and the tag.
  590.            
  591.             func(obj, "<");
  592.            
  593.             switch (m_type) {
  594.                 case SecurityElementType.Format:
  595.                     func(obj, "?");
  596.                     break;
  597.                 case SecurityElementType.Comment:
  598.                    
  599.                     func(obj, "!");
  600.                     break;
  601.                 default:
  602.                    
  603.                     break;
  604.             }
  605.            
  606.             func(obj, m_strTag);
  607.            
  608.             // If there are any attributes, plop those in.
  609.            
  610.             if (m_lAttributes != null && m_lAttributes.Count > 0) {
  611.                 func(obj, " ");
  612.                
  613.                 int iMax = m_lAttributes.Count;
  614.                 BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  615.                
  616.                 for (int i = 0; i < iMax; i += 2) {
  617.                     string strAttrName = (string)m_lAttributes[i];
  618.                     string strAttrValue = (string)m_lAttributes[i + 1];
  619.                    
  620.                     func(obj, strAttrName);
  621.                     func(obj, "=\"");
  622.                     func(obj, strAttrValue);
  623.                     func(obj, "\"");
  624.                    
  625.                     if (i != m_lAttributes.Count - 2) {
  626.                         if (m_type == SecurityElementType.Regular) {
  627.                             func(obj, Environment.NewLine);
  628.                         }
  629.                         else {
  630.                             func(obj, " ");
  631.                         }
  632.                     }
  633.                 }
  634.             }
  635.            
  636.             if (m_strText == null && (m_lChildren == null || m_lChildren.Count == 0)) {
  637.                 // If we are a single tag with no children, just add the end of tag text.
  638.                
  639.                 switch (m_type) {
  640.                     case SecurityElementType.Comment:
  641.                         func(obj, ">");
  642.                         break;
  643.                     case SecurityElementType.Format:
  644.                        
  645.                         func(obj, " ?>");
  646.                         break;
  647.                     default:
  648.                        
  649.                         func(obj, "/>");
  650.                         break;
  651.                 }
  652.                 func(obj, Environment.NewLine);
  653.             }
  654.             else {
  655.                 // Close the current tag.
  656.                
  657.                 func(obj, ">");
  658.                
  659.                 // Output the text
  660.                
  661.                 func(obj, m_strText);
  662.                
  663.                 // Output any children.
  664.                
  665.                 if (m_lChildren != null) {
  666.                     this.ConvertSecurityElementFactories();
  667.                    
  668.                     func(obj, Environment.NewLine);
  669.                    
  670.                     // String childIndent = indent + s_strIndent;
  671.                    
  672.                     for (int i = 0; i < m_lChildren.Count; ++i) {
  673.                         ((SecurityElement)m_lChildren[i]).ToString("", obj, func);
  674.                     }
  675.                    
  676.                     // In the case where we have children, the close tag will not be on the same line as the
  677.                     // opening tag, so we need to indent.
  678.                    
  679.                     // func( obj, indent );
  680.                 }
  681.                
  682.                 // Output the closing tag
  683.                
  684.                 func(obj, "</");
  685.                 func(obj, m_strTag);
  686.                 func(obj, ">");
  687.                 func(obj, Environment.NewLine);
  688.             }
  689.         }
  690.        
  691.        
  692.        
  693.         public string Attribute(string name)
  694.         {
  695.             if (name == null)
  696.                 throw new ArgumentNullException("name");
  697.            
  698.             // Note: we don't check for validity here because an
  699.             // if an invalid name is passed we simply won't find it.
  700.            
  701.             if (m_lAttributes == null)
  702.                 return null;
  703.            
  704.             // Go through all the attribute and see if we know about
  705.             // the one we are asked for
  706.            
  707.             int iMax = m_lAttributes.Count;
  708.             BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  709.            
  710.             for (int i = 0; i < iMax; i += 2) {
  711.                 string strAttrName = (string)m_lAttributes[i];
  712.                
  713.                 if (String.Equals(strAttrName, name)) {
  714.                     string strAttrValue = (string)m_lAttributes[i + 1];
  715.                    
  716.                     return Unescape(strAttrValue);
  717.                 }
  718.             }
  719.            
  720.             // In the case where we didn't find it, we are expected to
  721.             // return null
  722.             return null;
  723.         }
  724.        
  725.         public SecurityElement SearchForChildByTag(string tag)
  726.         {
  727.             // Go through all the children and see if we can
  728.             // find the one are are asked for (matching tags)
  729.            
  730.             if (tag == null)
  731.                 throw new ArgumentNullException("tag");
  732.            
  733.             // Note: we don't check for a valid tag here because
  734.             // an invalid tag simply won't be found.
  735.            
  736.             if (m_lChildren == null)
  737.                 return null;
  738.            
  739.             IEnumerator enumerator = m_lChildren.GetEnumerator();
  740.            
  741.             while (enumerator.MoveNext()) {
  742.                 SecurityElement current = (SecurityElement)enumerator.Current;
  743.                
  744.                 if (current != null && String.Equals(current.Tag, tag))
  745.                     return current;
  746.             }
  747.            
  748.             return null;
  749.         }
  750.        
  751.         internal IPermission ToPermission(bool ignoreTypeLoadFailures)
  752.         {
  753.             IPermission ip = XMLUtil.CreatePermission(this, PermissionState.None, ignoreTypeLoadFailures);
  754.             if (ip == null)
  755.                 return null;
  756.             ip.FromXml(this);
  757.            
  758.             // Get the permission token here to ensure that the token
  759.             // type is updated appropriately now that we've loaded the type.
  760.             PermissionToken token = PermissionToken.GetToken(ip);
  761.             BCLDebug.Assert((token.m_type & PermissionTokenType.DontKnow) == 0, "Token type not properly assigned");
  762.            
  763.             return ip;
  764.         }
  765.        
  766.         internal object ToSecurityObject()
  767.         {
  768.             switch (m_strTag) {
  769.                 case "PermissionSet":
  770.                     PermissionSet pset = new PermissionSet(PermissionState.None);
  771.                     pset.FromXml(this);
  772.                     return pset;
  773.                 default:
  774.                    
  775.                     return ToPermission(false);
  776.             }
  777.         }
  778.        
  779.         internal string SearchForTextOfLocalName(string strLocalName)
  780.         {
  781.             // Search on each child in order and each
  782.             // child's child, depth-first
  783.            
  784.             if (strLocalName == null)
  785.                 throw new ArgumentNullException("strLocalName");
  786.            
  787.             // Note: we don't check for a valid tag here because
  788.             // an invalid tag simply won't be found.
  789.            
  790.             // First we check this.
  791.            
  792.             if (m_strTag == null)
  793.                 return null;
  794.             if (m_strTag.Equals(strLocalName) || m_strTag.EndsWith(":" + strLocalName, StringComparison.Ordinal))
  795.                 return Unescape(m_strText);
  796.            
  797.             if (m_lChildren == null)
  798.                 return null;
  799.            
  800.             IEnumerator enumerator = m_lChildren.GetEnumerator();
  801.            
  802.             while (enumerator.MoveNext()) {
  803.                 string current = ((SecurityElement)enumerator.Current).SearchForTextOfLocalName(strLocalName);
  804.                
  805.                 if (current != null)
  806.                     return current;
  807.             }
  808.            
  809.             return null;
  810.         }
  811.        
  812.         public string SearchForTextOfTag(string tag)
  813.         {
  814.             // Search on each child in order and each
  815.             // child's child, depth-first
  816.            
  817.             if (tag == null)
  818.                 throw new ArgumentNullException("tag");
  819.            
  820.             // Note: we don't check for a valid tag here because
  821.             // an invalid tag simply won't be found.
  822.            
  823.             // First we check this.
  824.            
  825.             if (String.Equals(m_strTag, tag))
  826.                 return Unescape(m_strText);
  827.            
  828.             if (m_lChildren == null)
  829.                 return null;
  830.            
  831.             IEnumerator enumerator = m_lChildren.GetEnumerator();
  832.            
  833.             this.ConvertSecurityElementFactories();
  834.            
  835.             while (enumerator.MoveNext()) {
  836.                 string current = ((SecurityElement)enumerator.Current).SearchForTextOfTag(tag);
  837.                
  838.                 if (current != null)
  839.                     return current;
  840.             }
  841.            
  842.             return null;
  843.         }
  844.     }
  845. }

Developer Fusion