932 lines
31 KiB
C#
932 lines
31 KiB
C#
// ==++==
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ==--==
|
|
// <OWNER>[....]</OWNER>
|
|
//
|
|
|
|
namespace System.Security
|
|
{
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Security.Util;
|
|
using System.Text;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Security.Permissions;
|
|
using System.Diagnostics.Contracts;
|
|
|
|
internal enum SecurityElementType
|
|
{
|
|
Regular = 0,
|
|
Format = 1,
|
|
Comment = 2
|
|
}
|
|
|
|
|
|
internal interface ISecurityElementFactory
|
|
{
|
|
SecurityElement CreateSecurityElement();
|
|
|
|
Object Copy();
|
|
|
|
String GetTag();
|
|
|
|
String Attribute( String attributeName );
|
|
}
|
|
|
|
[Serializable]
|
|
[System.Runtime.InteropServices.ComVisible(true)]
|
|
sealed public class SecurityElement : ISecurityElementFactory
|
|
{
|
|
internal String m_strTag;
|
|
internal String m_strText;
|
|
private ArrayList m_lChildren;
|
|
internal ArrayList m_lAttributes;
|
|
internal SecurityElementType m_type = SecurityElementType.Regular;
|
|
|
|
private static readonly char[] s_tagIllegalCharacters = new char[] { ' ', '<', '>' };
|
|
private static readonly char[] s_textIllegalCharacters = new char[] { '<', '>' };
|
|
private static readonly char[] s_valueIllegalCharacters = new char[] { '<', '>', '\"' };
|
|
private const String s_strIndent = " ";
|
|
|
|
private const int c_AttributesTypical = 4 * 2; // 4 attributes, times 2 strings per attribute
|
|
private const int c_ChildrenTypical = 1;
|
|
|
|
private static readonly String[] s_escapeStringPairs = new String[]
|
|
{
|
|
// these must be all once character escape sequences or a new escaping algorithm is needed
|
|
"<", "<",
|
|
">", ">",
|
|
"\"", """,
|
|
"\'", "'",
|
|
"&", "&"
|
|
};
|
|
|
|
private static readonly char[] s_escapeChars = new char[] { '<', '>', '\"', '\'', '&' };
|
|
|
|
//-------------------------- Constructors ---------------------------
|
|
|
|
internal SecurityElement()
|
|
{
|
|
}
|
|
|
|
////// ISecurityElementFactory implementation
|
|
|
|
SecurityElement ISecurityElementFactory.CreateSecurityElement()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
String ISecurityElementFactory.GetTag()
|
|
{
|
|
return ((SecurityElement)this).Tag;
|
|
}
|
|
|
|
Object ISecurityElementFactory.Copy()
|
|
{
|
|
return ((SecurityElement)this).Copy();
|
|
}
|
|
|
|
String ISecurityElementFactory.Attribute( String attributeName )
|
|
{
|
|
return ((SecurityElement)this).Attribute( attributeName );
|
|
}
|
|
|
|
//////////////
|
|
|
|
#if FEATURE_CAS_POLICY
|
|
public static SecurityElement FromString( String xml )
|
|
{
|
|
if (xml == null)
|
|
throw new ArgumentNullException( "xml" );
|
|
Contract.EndContractBlock();
|
|
|
|
return new Parser( xml ).GetTopElement();
|
|
}
|
|
#endif // FEATURE_CAS_POLICY
|
|
|
|
public SecurityElement( String tag )
|
|
{
|
|
if (tag == null)
|
|
throw new ArgumentNullException( "tag" );
|
|
|
|
if (!IsValidTag( tag ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), tag ) );
|
|
Contract.EndContractBlock();
|
|
|
|
m_strTag = tag;
|
|
m_strText = null;
|
|
}
|
|
|
|
public SecurityElement( String tag, String text )
|
|
{
|
|
if (tag == null)
|
|
throw new ArgumentNullException( "tag" );
|
|
|
|
if (!IsValidTag( tag ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), tag ) );
|
|
|
|
if (text != null && !IsValidText( text ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementText" ), text ) );
|
|
Contract.EndContractBlock();
|
|
|
|
m_strTag = tag;
|
|
m_strText = text;
|
|
}
|
|
|
|
//-------------------------- Properties -----------------------------
|
|
|
|
public String Tag
|
|
{
|
|
[Pure]
|
|
get
|
|
{
|
|
return m_strTag;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (value == null)
|
|
throw new ArgumentNullException( "Tag" );
|
|
|
|
if (!IsValidTag( value ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), value ) );
|
|
Contract.EndContractBlock();
|
|
|
|
m_strTag = value;
|
|
}
|
|
}
|
|
|
|
public Hashtable Attributes
|
|
{
|
|
get
|
|
{
|
|
if (m_lAttributes == null || m_lAttributes.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
Hashtable hashtable = new Hashtable( m_lAttributes.Count/2 );
|
|
|
|
int iMax = m_lAttributes.Count;
|
|
Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
|
|
|
|
for (int i = 0; i < iMax; i += 2)
|
|
{
|
|
hashtable.Add( m_lAttributes[i], m_lAttributes[i+1]);
|
|
}
|
|
|
|
return hashtable;
|
|
}
|
|
}
|
|
|
|
set
|
|
{
|
|
if (value == null || value.Count == 0)
|
|
{
|
|
m_lAttributes = null;
|
|
}
|
|
else
|
|
{
|
|
ArrayList list = new ArrayList(value.Count);
|
|
|
|
System.Collections.IDictionaryEnumerator enumerator = (System.Collections.IDictionaryEnumerator)value.GetEnumerator();
|
|
|
|
while (enumerator.MoveNext())
|
|
{
|
|
String attrName = (String)enumerator.Key;
|
|
String attrValue = (String)enumerator.Value;
|
|
|
|
if (!IsValidAttributeName( attrName ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementName" ), (String)enumerator.Current ) );
|
|
|
|
if (!IsValidAttributeValue( attrValue ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementValue" ), (String)enumerator.Value ) );
|
|
|
|
list.Add(attrName);
|
|
list.Add(attrValue);
|
|
}
|
|
|
|
m_lAttributes = list;
|
|
}
|
|
}
|
|
}
|
|
|
|
public String Text
|
|
{
|
|
get
|
|
{
|
|
return Unescape( m_strText );
|
|
}
|
|
|
|
set
|
|
{
|
|
if (value == null)
|
|
{
|
|
m_strText = null;
|
|
}
|
|
else
|
|
{
|
|
if (!IsValidText( value ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), value ) );
|
|
|
|
m_strText = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public ArrayList Children
|
|
{
|
|
get
|
|
{
|
|
ConvertSecurityElementFactories();
|
|
return m_lChildren;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (value != null)
|
|
{
|
|
IEnumerator enumerator = value.GetEnumerator();
|
|
|
|
while (enumerator.MoveNext())
|
|
{
|
|
if (enumerator.Current == null)
|
|
throw new ArgumentException( Environment.GetResourceString( "ArgumentNull_Child" ) );
|
|
}
|
|
}
|
|
|
|
m_lChildren = value;
|
|
}
|
|
}
|
|
|
|
internal void ConvertSecurityElementFactories()
|
|
{
|
|
if (m_lChildren == null)
|
|
return;
|
|
|
|
for (int i = 0; i < m_lChildren.Count; ++i)
|
|
{
|
|
ISecurityElementFactory iseFactory = m_lChildren[i] as ISecurityElementFactory;
|
|
if (iseFactory != null && !(m_lChildren[i] is SecurityElement))
|
|
m_lChildren[i] = iseFactory.CreateSecurityElement();
|
|
}
|
|
}
|
|
|
|
internal ArrayList InternalChildren
|
|
{
|
|
get
|
|
{
|
|
// Beware! This array list can contain SecurityElements and other ISecurityElementFactories.
|
|
// If you want to get a consistent SecurityElement view, call get_Children.
|
|
return m_lChildren;
|
|
}
|
|
}
|
|
|
|
//-------------------------- Public Methods -----------------------------
|
|
|
|
internal void AddAttributeSafe( String name, String value )
|
|
{
|
|
if (m_lAttributes == null)
|
|
{
|
|
m_lAttributes = new ArrayList( c_AttributesTypical );
|
|
}
|
|
else
|
|
{
|
|
int iMax = m_lAttributes.Count;
|
|
Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
|
|
|
|
for (int i = 0; i < iMax; i += 2)
|
|
{
|
|
String strAttrName = (String)m_lAttributes[i];
|
|
|
|
if (String.Equals(strAttrName, name))
|
|
throw new ArgumentException( Environment.GetResourceString( "Argument_AttributeNamesMustBeUnique" ) );
|
|
}
|
|
}
|
|
|
|
m_lAttributes.Add(name);
|
|
m_lAttributes.Add(value);
|
|
}
|
|
|
|
public void AddAttribute( String name, String value )
|
|
{
|
|
if (name == null)
|
|
throw new ArgumentNullException( "name" );
|
|
|
|
if (value == null)
|
|
throw new ArgumentNullException( "value" );
|
|
|
|
if (!IsValidAttributeName( name ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementName" ), name ) );
|
|
|
|
if (!IsValidAttributeValue( value ))
|
|
throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementValue" ), value ) );
|
|
Contract.EndContractBlock();
|
|
|
|
AddAttributeSafe( name, value );
|
|
}
|
|
|
|
public void AddChild( SecurityElement child )
|
|
{
|
|
if (child == null)
|
|
throw new ArgumentNullException( "child" );
|
|
Contract.EndContractBlock();
|
|
|
|
if (m_lChildren == null)
|
|
m_lChildren = new ArrayList( c_ChildrenTypical );
|
|
|
|
m_lChildren.Add( child );
|
|
}
|
|
|
|
internal void AddChild( ISecurityElementFactory child )
|
|
{
|
|
if (child == null)
|
|
throw new ArgumentNullException( "child" );
|
|
Contract.EndContractBlock();
|
|
|
|
if (m_lChildren == null)
|
|
m_lChildren = new ArrayList( c_ChildrenTypical );
|
|
|
|
m_lChildren.Add( child );
|
|
}
|
|
|
|
internal void AddChildNoDuplicates( ISecurityElementFactory child )
|
|
{
|
|
if (child == null)
|
|
throw new ArgumentNullException( "child" );
|
|
Contract.EndContractBlock();
|
|
|
|
if (m_lChildren == null)
|
|
{
|
|
m_lChildren = new ArrayList( c_ChildrenTypical );
|
|
m_lChildren.Add( child );
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < m_lChildren.Count; ++i)
|
|
{
|
|
if (m_lChildren[i] == child)
|
|
return;
|
|
}
|
|
m_lChildren.Add( child );
|
|
}
|
|
}
|
|
|
|
public bool Equal( SecurityElement other )
|
|
{
|
|
if (other == null)
|
|
return false;
|
|
|
|
// Check if the tags are the same
|
|
if (!String.Equals(m_strTag, other.m_strTag))
|
|
return false;
|
|
|
|
// Check if the text is the same
|
|
if (!String.Equals(m_strText, other.m_strText))
|
|
return false;
|
|
|
|
// Check if the attributes are the same and appear in the same
|
|
// order.
|
|
|
|
// Maybe we can get away by only checking the number of attributes
|
|
if (m_lAttributes == null || other.m_lAttributes == null)
|
|
{
|
|
if (m_lAttributes != other.m_lAttributes)
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
int iMax = m_lAttributes.Count;
|
|
Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
|
|
|
|
if (iMax != other.m_lAttributes.Count)
|
|
return false;
|
|
|
|
for (int i = 0; i < iMax; i++)
|
|
{
|
|
String lhs = (String)m_lAttributes[i];
|
|
String rhs = (String)other.m_lAttributes[i];
|
|
|
|
if (!String.Equals(lhs, rhs))
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Finally we must check the child and make sure they are
|
|
// equal and in the same order
|
|
|
|
// Maybe we can get away by only checking the number of children
|
|
if (m_lChildren == null || other.m_lChildren == null)
|
|
{
|
|
if (m_lChildren != other.m_lChildren)
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (m_lChildren.Count != other.m_lChildren.Count)
|
|
return false;
|
|
|
|
this.ConvertSecurityElementFactories();
|
|
other.ConvertSecurityElementFactories();
|
|
|
|
// Okay, we'll need to go through each one of them
|
|
IEnumerator lhs = m_lChildren.GetEnumerator();
|
|
IEnumerator rhs = other.m_lChildren.GetEnumerator();
|
|
|
|
SecurityElement e1, e2;
|
|
while (lhs.MoveNext())
|
|
{
|
|
rhs.MoveNext();
|
|
e1 = (SecurityElement)lhs.Current;
|
|
e2 = (SecurityElement)rhs.Current;
|
|
if (e1 == null || !e1.Equal(e2))
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
[System.Runtime.InteropServices.ComVisible(false)]
|
|
public SecurityElement Copy()
|
|
{
|
|
SecurityElement element = new SecurityElement( this.m_strTag, this.m_strText );
|
|
element.m_lChildren = this.m_lChildren == null ? null : new ArrayList( this.m_lChildren );
|
|
element.m_lAttributes = this.m_lAttributes == null ? null : new ArrayList(this.m_lAttributes);
|
|
|
|
return element;
|
|
}
|
|
|
|
[Pure]
|
|
public static bool IsValidTag( String tag )
|
|
{
|
|
if (tag == null)
|
|
return false;
|
|
|
|
return tag.IndexOfAny( s_tagIllegalCharacters ) == -1;
|
|
}
|
|
|
|
[Pure]
|
|
public static bool IsValidText( String text )
|
|
{
|
|
if (text == null)
|
|
return false;
|
|
|
|
return text.IndexOfAny( s_textIllegalCharacters ) == -1;
|
|
}
|
|
|
|
[Pure]
|
|
public static bool IsValidAttributeName( String name )
|
|
{
|
|
return IsValidTag( name );
|
|
}
|
|
|
|
[Pure]
|
|
public static bool IsValidAttributeValue( String value )
|
|
{
|
|
if (value == null)
|
|
return false;
|
|
|
|
return value.IndexOfAny( s_valueIllegalCharacters ) == -1;
|
|
}
|
|
|
|
private static String GetEscapeSequence( char c )
|
|
{
|
|
int iMax = s_escapeStringPairs.Length;
|
|
Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
|
|
|
|
for (int i = 0; i < iMax; i += 2)
|
|
{
|
|
String strEscSeq = s_escapeStringPairs[i];
|
|
String strEscValue = s_escapeStringPairs[i+1];
|
|
|
|
if (strEscSeq[0] == c)
|
|
return strEscValue;
|
|
}
|
|
|
|
Contract.Assert( false, "Unable to find escape sequence for this character" );
|
|
return c.ToString();
|
|
}
|
|
|
|
public static String Escape( String str )
|
|
{
|
|
if (str == null)
|
|
return null;
|
|
|
|
StringBuilder sb = null;
|
|
|
|
int strLen = str.Length;
|
|
int index; // Pointer into the string that indicates the location of the current '&' character
|
|
int newIndex = 0; // Pointer into the string that indicates the start index of the "remaining" string (that still needs to be processed).
|
|
|
|
|
|
do
|
|
{
|
|
index = str.IndexOfAny( s_escapeChars, newIndex );
|
|
|
|
if (index == -1)
|
|
{
|
|
if (sb == null)
|
|
return str;
|
|
else
|
|
{
|
|
sb.Append( str, newIndex, strLen - newIndex );
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sb == null)
|
|
sb = new StringBuilder();
|
|
|
|
sb.Append( str, newIndex, index - newIndex );
|
|
sb.Append( GetEscapeSequence( str[index] ) );
|
|
|
|
newIndex = ( index + 1 );
|
|
}
|
|
}
|
|
while (true);
|
|
|
|
// no normal exit is possible
|
|
}
|
|
|
|
private static String GetUnescapeSequence( String str, int index, out int newIndex )
|
|
{
|
|
int maxCompareLength = str.Length - index;
|
|
|
|
int iMax = s_escapeStringPairs.Length;
|
|
Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
|
|
|
|
for (int i = 0; i < iMax; i += 2)
|
|
{
|
|
String strEscSeq = s_escapeStringPairs[i];
|
|
String strEscValue = s_escapeStringPairs[i+1];
|
|
|
|
int length = strEscValue.Length;
|
|
|
|
if (length <= maxCompareLength && String.Compare( strEscValue, 0, str, index, length, StringComparison.Ordinal) == 0)
|
|
{
|
|
newIndex = index + strEscValue.Length;
|
|
return strEscSeq;
|
|
}
|
|
}
|
|
|
|
newIndex = index + 1;
|
|
return str[index].ToString();
|
|
}
|
|
|
|
|
|
private static String Unescape( String str )
|
|
{
|
|
if (str == null)
|
|
return null;
|
|
|
|
StringBuilder sb = null;
|
|
|
|
int strLen = str.Length;
|
|
int index; // Pointer into the string that indicates the location of the current '&' character
|
|
int newIndex = 0; // Pointer into the string that indicates the start index of the "remainging" string (that still needs to be processed).
|
|
|
|
do
|
|
{
|
|
index = str.IndexOf( '&', newIndex );
|
|
|
|
if (index == -1)
|
|
{
|
|
if (sb == null)
|
|
return str;
|
|
else
|
|
{
|
|
sb.Append( str, newIndex, strLen - newIndex );
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sb == null)
|
|
sb = new StringBuilder();
|
|
|
|
sb.Append(str, newIndex, index - newIndex);
|
|
sb.Append( GetUnescapeSequence( str, index, out newIndex ) ); // updates the newIndex too
|
|
|
|
}
|
|
}
|
|
while (true);
|
|
|
|
// C# reports a warning if I leave this in, but I still kinda want to just in case.
|
|
// Contract.Assert( false, "If you got here, the execution engine or compiler is really confused" );
|
|
// return str;
|
|
}
|
|
|
|
private delegate void ToStringHelperFunc( Object obj, String str );
|
|
|
|
private static void ToStringHelperStringBuilder( Object obj, String str )
|
|
{
|
|
((StringBuilder)obj).Append( str );
|
|
}
|
|
|
|
private static void ToStringHelperStreamWriter( Object obj, String str )
|
|
{
|
|
((StreamWriter)obj).Write( str );
|
|
}
|
|
|
|
public override String ToString ()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
ToString( "", sb, new ToStringHelperFunc( ToStringHelperStringBuilder ) );
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
internal void ToWriter( StreamWriter writer )
|
|
{
|
|
ToString( "", writer, new ToStringHelperFunc( ToStringHelperStreamWriter ) );
|
|
}
|
|
|
|
private void ToString( String indent, Object obj, ToStringHelperFunc func )
|
|
{
|
|
// First add the indent
|
|
|
|
// func( obj, indent );
|
|
|
|
// Add in the opening bracket and the tag.
|
|
|
|
func( obj, "<" );
|
|
|
|
switch (m_type)
|
|
{
|
|
case SecurityElementType.Format:
|
|
func( obj, "?" );
|
|
break;
|
|
|
|
case SecurityElementType.Comment:
|
|
func( obj, "!" );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
func( obj, m_strTag );
|
|
|
|
// If there are any attributes, plop those in.
|
|
|
|
if (m_lAttributes != null && m_lAttributes.Count > 0)
|
|
{
|
|
func( obj, " " );
|
|
|
|
int iMax = m_lAttributes.Count;
|
|
Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
|
|
|
|
for (int i = 0; i < iMax; i += 2)
|
|
{
|
|
String strAttrName = (String)m_lAttributes[i];
|
|
String strAttrValue = (String)m_lAttributes[i+1];
|
|
|
|
func( obj, strAttrName );
|
|
func( obj, "=\"" );
|
|
func( obj, strAttrValue );
|
|
func( obj, "\"" );
|
|
|
|
if (i != m_lAttributes.Count - 2)
|
|
{
|
|
if (m_type == SecurityElementType.Regular)
|
|
{
|
|
func( obj, Environment.NewLine );
|
|
}
|
|
else
|
|
{
|
|
func( obj, " " );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_strText == null && (m_lChildren == null || m_lChildren.Count == 0))
|
|
{
|
|
// If we are a single tag with no children, just add the end of tag text.
|
|
|
|
switch (m_type)
|
|
{
|
|
case SecurityElementType.Comment:
|
|
func( obj, ">" );
|
|
break;
|
|
|
|
case SecurityElementType.Format:
|
|
func( obj, " ?>" );
|
|
break;
|
|
|
|
default:
|
|
func( obj, "/>" );
|
|
break;
|
|
}
|
|
func( obj, Environment.NewLine );
|
|
}
|
|
else
|
|
{
|
|
// Close the current tag.
|
|
|
|
func( obj, ">" );
|
|
|
|
// Output the text
|
|
|
|
func( obj, m_strText );
|
|
|
|
// Output any children.
|
|
|
|
if (m_lChildren != null)
|
|
{
|
|
this.ConvertSecurityElementFactories();
|
|
|
|
func( obj, Environment.NewLine );
|
|
|
|
// String childIndent = indent + s_strIndent;
|
|
|
|
for (int i = 0; i < m_lChildren.Count; ++i)
|
|
{
|
|
((SecurityElement)m_lChildren[i]).ToString( "", obj, func );
|
|
}
|
|
|
|
// In the case where we have children, the close tag will not be on the same line as the
|
|
// opening tag, so we need to indent.
|
|
|
|
// func( obj, indent );
|
|
}
|
|
|
|
// Output the closing tag
|
|
|
|
func( obj, "</" );
|
|
func( obj, m_strTag );
|
|
func( obj, ">" );
|
|
func( obj, Environment.NewLine );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public String Attribute( String name )
|
|
{
|
|
if (name == null)
|
|
throw new ArgumentNullException( "name" );
|
|
Contract.EndContractBlock();
|
|
|
|
// Note: we don't check for validity here because an
|
|
// if an invalid name is passed we simply won't find it.
|
|
|
|
if (m_lAttributes == null)
|
|
return null;
|
|
|
|
// Go through all the attribute and see if we know about
|
|
// the one we are asked for
|
|
|
|
int iMax = m_lAttributes.Count;
|
|
Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
|
|
|
|
for (int i = 0; i < iMax; i += 2)
|
|
{
|
|
String strAttrName = (String)m_lAttributes[i];
|
|
|
|
if (String.Equals(strAttrName, name))
|
|
{
|
|
String strAttrValue = (String)m_lAttributes[i+1];
|
|
|
|
return Unescape(strAttrValue);
|
|
}
|
|
}
|
|
|
|
// In the case where we didn't find it, we are expected to
|
|
// return null
|
|
return null;
|
|
}
|
|
|
|
public SecurityElement SearchForChildByTag( String tag )
|
|
{
|
|
// Go through all the children and see if we can
|
|
// find the one are are asked for (matching tags)
|
|
|
|
if (tag == null)
|
|
throw new ArgumentNullException( "tag" );
|
|
Contract.EndContractBlock();
|
|
|
|
// Note: we don't check for a valid tag here because
|
|
// an invalid tag simply won't be found.
|
|
|
|
if (m_lChildren == null)
|
|
return null;
|
|
|
|
IEnumerator enumerator = m_lChildren.GetEnumerator();
|
|
|
|
while (enumerator.MoveNext())
|
|
{
|
|
SecurityElement current = (SecurityElement)enumerator.Current;
|
|
|
|
if (current != null && String.Equals(current.Tag, tag))
|
|
return current;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
#if FEATURE_CAS_POLICY
|
|
internal IPermission ToPermission(bool ignoreTypeLoadFailures)
|
|
{
|
|
IPermission ip = XMLUtil.CreatePermission( this, PermissionState.None, ignoreTypeLoadFailures );
|
|
if (ip == null)
|
|
return null;
|
|
ip.FromXml(this);
|
|
|
|
// Get the permission token here to ensure that the token
|
|
// type is updated appropriately now that we've loaded the type.
|
|
PermissionToken token = PermissionToken.GetToken( ip );
|
|
Contract.Assert((token.m_type & PermissionTokenType.DontKnow) == 0, "Token type not properly assigned");
|
|
|
|
return ip;
|
|
}
|
|
|
|
[System.Security.SecurityCritical] // auto-generated
|
|
internal Object ToSecurityObject()
|
|
{
|
|
switch (m_strTag)
|
|
{
|
|
case "PermissionSet":
|
|
PermissionSet pset = new PermissionSet(PermissionState.None);
|
|
pset.FromXml(this);
|
|
return pset;
|
|
|
|
default:
|
|
return ToPermission(false);
|
|
}
|
|
}
|
|
#endif // FEATURE_CAS_POLICY
|
|
|
|
internal String SearchForTextOfLocalName(String strLocalName)
|
|
{
|
|
// Search on each child in order and each
|
|
// child's child, depth-first
|
|
|
|
if (strLocalName == null)
|
|
throw new ArgumentNullException( "strLocalName" );
|
|
Contract.EndContractBlock();
|
|
|
|
// Note: we don't check for a valid tag here because
|
|
// an invalid tag simply won't be found.
|
|
|
|
// First we check this.
|
|
|
|
if (m_strTag == null) return null;
|
|
if (m_strTag.Equals( strLocalName ) || m_strTag.EndsWith( ":" + strLocalName, StringComparison.Ordinal ))
|
|
return Unescape( m_strText );
|
|
if (m_lChildren == null)
|
|
return null;
|
|
|
|
IEnumerator enumerator = m_lChildren.GetEnumerator();
|
|
|
|
while (enumerator.MoveNext())
|
|
{
|
|
String current = ((SecurityElement)enumerator.Current).SearchForTextOfLocalName( strLocalName );
|
|
|
|
if (current != null)
|
|
return current;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public String SearchForTextOfTag( String tag )
|
|
{
|
|
// Search on each child in order and each
|
|
// child's child, depth-first
|
|
|
|
if (tag == null)
|
|
throw new ArgumentNullException( "tag" );
|
|
Contract.EndContractBlock();
|
|
|
|
// Note: we don't check for a valid tag here because
|
|
// an invalid tag simply won't be found.
|
|
|
|
// First we check this.
|
|
|
|
if (String.Equals(m_strTag, tag))
|
|
return Unescape( m_strText );
|
|
if (m_lChildren == null)
|
|
return null;
|
|
|
|
IEnumerator enumerator = m_lChildren.GetEnumerator();
|
|
|
|
this.ConvertSecurityElementFactories();
|
|
|
|
while (enumerator.MoveNext())
|
|
{
|
|
String current = ((SecurityElement)enumerator.Current).SearchForTextOfTag( tag );
|
|
|
|
if (current != null)
|
|
return current;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|