The Labs \ Source Viewer \ SSCLI \ System.Net \ WebPermission

  1. //------------------------------------------------------------------------------
  2. // <copyright file="WebPermission.cs" company="Microsoft">
  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. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net
  16. {
  17.    
  18.     using System.Collections;
  19.     using System.Security;
  20.     using System.Security.Permissions;
  21.     using System.Text.RegularExpressions;
  22.     using System.Globalization;
  23.     using System.Runtime.Serialization;
  24.    
  25.     //NOTE: While WebPermissionAttribute resides in System.DLL,
  26.     // no classes from that DLL are able to make declarative usage of WebPermission.
  27.    
  28.    
  29.     // THE syntax of this attribute is as followed
  30.     // [WebPermission(SecurityAction.Assert, Connect="http://hostname/path/url", Accept="http://localhost/path/url")]
  31.     // [WebPermission(SecurityAction.Assert, ConnectPattern="http://hostname/www\.microsoft\.*/url/*", AcceptPattern="http://localhost/*")]
  32.    
  33.     // WHERE:
  34.     //=======
  35.     // - 'Connect' and 'Accept' keywords allow you to specify the final URI
  36.     // - 'ConnectPattern' and 'AcceptPattern' keywords allow you to specify a set of URI in escaped Regex form
  37.     // - They take '.*' as special "everything" indicators, which are fast-pathed.
  38.    
  39.     [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
  40.    
  41.     [Serializable()]
  42.     public sealed class WebPermissionAttribute : CodeAccessSecurityAttribute
  43.     {
  44.         private object m_accept = null;
  45.         private object m_connect = null;
  46.        
  47.         public WebPermissionAttribute(SecurityAction action) : base(action)
  48.         {
  49.         }
  50.        
  51.         public string Connect {
  52.             get { return m_connect as string; }
  53.             set {
  54.                 if (m_connect != null) {
  55.                     throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, "Connect", value), "value");
  56.                 }
  57.                 m_connect = value;
  58.             }
  59.         }
  60.        
  61.         public string Accept {
  62.             get { return m_accept as string; }
  63.             set {
  64.                 if (m_accept != null) {
  65.                     throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, "Accept", value), "value");
  66.                 }
  67.                 m_accept = value;
  68.             }
  69.         }
  70.        
  71.         public string ConnectPattern {
  72.             get { return m_connect is DelayedRegex ? m_connect.ToString() : m_connect is bool && (bool)m_connect ? WebPermission.MatchAll : null; }
  73.            
  74.             set {
  75.                 if (m_connect != null) {
  76.                     throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, "ConnectPatern", value), "value");
  77.                 }
  78.                 if (value == WebPermission.MatchAll) {
  79.                     m_connect = true;
  80.                 }
  81.                 else {
  82.                     m_connect = new DelayedRegex(value);
  83.                 }
  84.             }
  85.         }
  86.        
  87.         public string AcceptPattern {
  88.             get { return m_accept is DelayedRegex ? m_accept.ToString() : m_accept is bool && (bool)m_accept ? WebPermission.MatchAll : null; }
  89.            
  90.             set {
  91.                 if (m_accept != null) {
  92.                     throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, "AcceptPattern", value), "value");
  93.                 }
  94.                 if (value == WebPermission.MatchAll) {
  95.                     m_accept = true;
  96.                 }
  97.                 else {
  98.                     m_accept = new DelayedRegex(value);
  99.                 }
  100.             }
  101.         }
  102.        
  103. /*
  104.         public bool ConnectAll
  105.         {
  106.             get
  107.             {
  108.                 return m_connect is bool ? (bool) m_connect : false;
  109.             }
  110.             set
  111.             {
  112.                 if (m_connect != null)
  113.                 {
  114.                     throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, "ConnectAll", value), "value");
  115.                 }
  116.                 m_connect = value;
  117.             }
  118.         }
  119.         public bool AcceptAll
  120.         {
  121.             get
  122.             {
  123.                 return m_accept is bool ? (bool) m_accept : false;
  124.             }
  125.             set
  126.             {
  127.                 if (m_accept != null)
  128.                 {
  129.                     throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, "AcceptAll", value), "value");
  130.                 }
  131.                 m_accept = value;
  132.             }
  133.         }
  134. */       
  135.        
  136.         public override IPermission CreatePermission()
  137.         {
  138.             WebPermission perm = null;
  139.             if (Unrestricted) {
  140.                 perm = new WebPermission(PermissionState.Unrestricted);
  141.             }
  142.             else {
  143.                 NetworkAccess access = (NetworkAccess)0;
  144.                 if (m_connect is bool) {
  145.                     if ((bool)m_connect) {
  146.                         access |= NetworkAccess.Connect;
  147.                     }
  148.                     m_connect = null;
  149.                 }
  150.                 if (m_accept is bool) {
  151.                     if ((bool)m_accept) {
  152.                         access |= NetworkAccess.Accept;
  153.                     }
  154.                     m_accept = null;
  155.                 }
  156.                 perm = new WebPermission(access);
  157.                 if (m_accept != null) {
  158.                     if (m_accept is DelayedRegex) {
  159.                         perm.AddAsPattern(NetworkAccess.Accept, (DelayedRegex)m_accept);
  160.                     }
  161.                     else {
  162.                         perm.AddPermission(NetworkAccess.Accept, (string)m_accept);
  163.                     }
  164.                 }
  165.                 if (m_connect != null) {
  166.                     if (m_connect is DelayedRegex) {
  167.                         perm.AddAsPattern(NetworkAccess.Connect, (DelayedRegex)m_connect);
  168.                     }
  169.                     else {
  170.                         perm.AddPermission(NetworkAccess.Connect, (string)m_connect);
  171.                     }
  172.                 }
  173.             }
  174.             return perm;
  175.         }
  176.        
  177.     }
  178.    
  179.     [Serializable()]
  180.     internal class DelayedRegex
  181.     {
  182.         private Regex _AsRegex;
  183.         private string _AsString;
  184.        
  185.         internal DelayedRegex(string regexString)
  186.         {
  187.             if (regexString == null)
  188.                 throw new ArgumentNullException("regexString");
  189.            
  190.             _AsString = regexString;
  191.         }
  192.        
  193.         internal DelayedRegex(Regex regex)
  194.         {
  195.             if (regex == null)
  196.                 throw new ArgumentNullException("regex");
  197.            
  198.             _AsRegex = regex;
  199.         }
  200.        
  201.         internal Regex AsRegex {
  202.             get {
  203.                 if (_AsRegex == null) {
  204.                     _AsRegex = new Regex(_AsString + "[/]?", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant);
  205.                 }
  206.                 return _AsRegex;
  207.             }
  208.         }
  209.        
  210.         public override string ToString()
  211.         {
  212.             return _AsString != null ? _AsString : (_AsString = _AsRegex.ToString());
  213.         }
  214.     }
  215.    
  216.     /// <devdoc>
  217.     /// <para>
  218.     /// Controls rights to make or accept connections on a Web address.
  219.     /// </para>
  220.     /// </devdoc>
  221.     [Serializable()]
  222.     public sealed class WebPermission : CodeAccessPermission, IUnrestrictedPermission
  223.     {
  224.        
  225.         private bool m_noRestriction;
  226.         [OptionalField()]
  227.         private bool m_UnrestrictedConnect;
  228.         [OptionalField()]
  229.         private bool m_UnrestrictedAccept;
  230.         private ArrayList m_connectList = new ArrayList();
  231.         private ArrayList m_acceptList = new ArrayList();
  232.        
  233.         internal const string MatchAll = ".*";
  234.         private static Regex s_MatchAllRegex;
  235.         static internal Regex MatchAllRegex {
  236.             get {
  237.                 if (s_MatchAllRegex == null) {
  238.                     s_MatchAllRegex = new Regex(".*");
  239.                 }
  240.                 return s_MatchAllRegex;
  241.             }
  242.         }
  243.        
  244.         /// <devdoc>
  245.         /// <para>
  246.         /// Returns the enumeration of permissions to connect a remote URI.
  247.         /// </para>
  248.         /// </devdoc>
  249.         public IEnumerator ConnectList {
  250.             get {
  251.                 if (m_UnrestrictedConnect) {
  252.                     return (new Regex[] {MatchAllRegex}).GetEnumerator();
  253.                 }
  254.                
  255.                 ArrayList cloned = new ArrayList(m_connectList.Count);
  256.                
  257.                 for (int i = 0; i < m_connectList.Count; ++i)
  258.                     cloned.Add(m_connectList[i] is DelayedRegex ? (object)((DelayedRegex)m_connectList[i]).AsRegex : m_connectList[i] is Uri ? (object)((Uri)m_connectList[i]).GetComponents(UriComponents.HttpRequestUrl, UriFormat.UriEscaped) : m_connectList[i]);
  259.                
  260.                 return cloned.GetEnumerator();
  261.             }
  262.         }
  263.        
  264.         /// <devdoc>
  265.         /// <para>
  266.         /// Returns the enumeration of permissions to export a local URI.
  267.         /// </para>
  268.         /// </devdoc>
  269.         public IEnumerator AcceptList {
  270.             get {
  271.                 if (m_UnrestrictedAccept) {
  272.                     return (new Regex[] {MatchAllRegex}).GetEnumerator();
  273.                 }
  274.                
  275.                 ArrayList cloned = new ArrayList(m_acceptList.Count);
  276.                
  277.                 for (int i = 0; i < m_acceptList.Count; ++i)
  278.                     cloned.Add(m_acceptList[i] is DelayedRegex ? (object)((DelayedRegex)m_acceptList[i]).AsRegex : m_acceptList[i] is Uri ? (object)((Uri)m_acceptList[i]).GetComponents(UriComponents.HttpRequestUrl, UriFormat.UriEscaped) : m_acceptList[i]);
  279.                
  280.                 return cloned.GetEnumerator();
  281.             }
  282.         }
  283.        
  284.         /// <devdoc>
  285.         /// <para>
  286.         /// Creates a new instance of the <see cref='System.Net.WebPermission'/>
  287.         /// class that passes all demands or
  288.         /// that fails all demands.
  289.         /// </para>
  290.         /// </devdoc>
  291.         public WebPermission(PermissionState state)
  292.         {
  293.             m_noRestriction = (state == PermissionState.Unrestricted);
  294.         }
  295.        
  296.         internal WebPermission(bool unrestricted)
  297.         {
  298.             m_noRestriction = unrestricted;
  299.         }
  300.        
  301.         /// <devdoc>
  302.         /// <para>
  303.         /// Creates a new instance of the <see cref='System.Net.WebPermission'/> class.
  304.         /// </para>
  305.         /// </devdoc>
  306.         public WebPermission()
  307.         {
  308.         }
  309.        
  310.         internal WebPermission(NetworkAccess access)
  311.         {
  312.             m_UnrestrictedConnect = (access & NetworkAccess.Connect) != 0;
  313.             m_UnrestrictedAccept = (access & NetworkAccess.Accept) != 0;
  314.         }
  315.        
  316.         /// <devdoc>
  317.         /// <para>
  318.         /// Creates a new instance of the <see cref='System.Net.WebPermission'/>
  319.         /// class with the specified access rights for
  320.         /// the specified URI Pattern.
  321.         /// Suitable only for WebPermission policy object construction
  322.         /// </para>
  323.         /// </devdoc>
  324.         public WebPermission(NetworkAccess access, Regex uriRegex)
  325.         {
  326.             AddPermission(access, uriRegex);
  327.         }
  328.        
  329.         public WebPermission(NetworkAccess access, string uriString)
  330.         {
  331.             AddPermission(access, uriString);
  332.         }
  333.         internal WebPermission(NetworkAccess access, Uri uri)
  334.         {
  335.             AddPermission(access, uri);
  336.         }
  337.        
  338.         public void AddPermission(NetworkAccess access, string uriString)
  339.         {
  340.             if (uriString == null) {
  341.                 throw new ArgumentNullException("uriString");
  342.             }
  343.            
  344.             if (m_noRestriction) {
  345.                 return;
  346.             }
  347.            
  348.             Uri uri;
  349.             if (Uri.TryCreate(uriString, UriKind.Absolute, out uri))
  350.                 AddPermission(access, uri);
  351.             else {
  352.                 ArrayList lists = new ArrayList();
  353.                 if ((access & NetworkAccess.Connect) != 0 && !m_UnrestrictedConnect)
  354.                     lists.Add(m_connectList);
  355.                 if ((access & NetworkAccess.Accept) != 0 && !m_UnrestrictedAccept)
  356.                     lists.Add(m_acceptList);
  357.                
  358.                 foreach (ArrayList list in lists) {
  359.                     // avoid duplicated uris in the list
  360.                     bool found = false;
  361.                     foreach (object obj in list) {
  362.                         string str = obj as string;
  363.                         if (str != null && string.Compare(str, uriString, StringComparison.OrdinalIgnoreCase) == 0) {
  364.                             found = true;
  365.                             break;
  366.                         }
  367.                     }
  368.                    
  369.                     if (!found) {
  370.                         list.Add(uriString);
  371.                     }
  372.                 }
  373.             }
  374.         }
  375.        
  376.         internal void AddPermission(NetworkAccess access, Uri uri)
  377.         {
  378.             if (uri == null) {
  379.                 throw new ArgumentNullException("uri");
  380.             }
  381.            
  382.             if (m_noRestriction) {
  383.                 return;
  384.             }
  385.            
  386.             ArrayList lists = new ArrayList();
  387.             if ((access & NetworkAccess.Connect) != 0 && !m_UnrestrictedConnect)
  388.                 lists.Add(m_connectList);
  389.             if ((access & NetworkAccess.Accept) != 0 && !m_UnrestrictedAccept)
  390.                 lists.Add(m_acceptList);
  391.            
  392.             foreach (ArrayList list in lists) {
  393.                 // avoid duplicated uris in the list
  394.                 bool found = false;
  395.                 foreach (object permObj in list) {
  396.                     if ((permObj is Uri) && uri.Equals(permObj)) {
  397.                         found = true;
  398.                         break;
  399.                     }
  400.                 }
  401.                 if (!found) {
  402.                     list.Add(uri);
  403.                 }
  404.             }
  405.         }
  406.        
  407.         /// <devdoc>
  408.         /// <para>Adds a new instance of the <see cref='System.Net.WebPermission'/>
  409.         /// class with the specified access rights for the specified URI Pattern.
  410.         /// Should be used during a policy object creation and not for particular URI permission check</para>
  411.         /// </devdoc>
  412.         public void AddPermission(NetworkAccess access, Regex uriRegex)
  413.         {
  414.             if (uriRegex == null) {
  415.                 throw new ArgumentNullException("uriRegex");
  416.             }
  417.            
  418.             if (m_noRestriction) {
  419.                 return;
  420.             }
  421.            
  422.             if (uriRegex.ToString() == MatchAll) {
  423.                 if (!m_UnrestrictedConnect && (access & NetworkAccess.Connect) != 0) {
  424.                     m_UnrestrictedConnect = true;
  425.                     m_connectList.Clear();
  426.                 }
  427.                 if (!m_UnrestrictedAccept && (access & NetworkAccess.Accept) != 0) {
  428.                     m_UnrestrictedAccept = true;
  429.                     m_acceptList.Clear();
  430.                 }
  431.                 return;
  432.             }
  433.            
  434.             AddAsPattern(access, new DelayedRegex(uriRegex));
  435.         }
  436.        
  437.         // Overloaded form using string inputs
  438.         // Enforces case-insensitive matching
  439.         /// Adds a new instance of the System.Net.WebPermission
  440.         /// class with the specified access rights for the specified URI Pattern
  441.         internal void AddAsPattern(NetworkAccess access, DelayedRegex uriRegexPattern)
  442.         {
  443.             ArrayList lists = new ArrayList();
  444.             if ((access & NetworkAccess.Connect) != 0 && !m_UnrestrictedConnect)
  445.                 lists.Add(m_connectList);
  446.             if ((access & NetworkAccess.Accept) != 0 && !m_UnrestrictedAccept)
  447.                 lists.Add(m_acceptList);
  448.            
  449.             foreach (ArrayList list in lists) {
  450.                 // avoid duplicated regexes in the list
  451.                 bool found = false;
  452.                 foreach (object obj in list) {
  453.                     if ((obj is DelayedRegex) && (string.Compare(uriRegexPattern.ToString(), obj.ToString(), StringComparison.OrdinalIgnoreCase) == 0)) {
  454.                         found = true;
  455.                         break;
  456.                     }
  457.                 }
  458.                
  459.                 if (!found) {
  460.                     list.Add(uriRegexPattern);
  461.                 }
  462.             }
  463.         }
  464.        
  465.         // IUnrestrictedPermission interface methods
  466.         /// <devdoc>
  467.         /// <para>
  468.         /// Checks the overall permisison state of the object.
  469.         /// </para>
  470.         /// </devdoc>
  471.         public bool IsUnrestricted()
  472.         {
  473.             return m_noRestriction;
  474.         }
  475.        
  476.         // IPermission interface methods
  477.         /// <devdoc>
  478.         /// <para>
  479.         /// Creates a copy of a <see cref='System.Net.WebPermission'/> instance.
  480.         /// </para>
  481.         /// </devdoc>
  482.         public override IPermission Copy()
  483.         {
  484.             if (m_noRestriction) {
  485.                 return new WebPermission(true);
  486.             }
  487.            
  488.             WebPermission wp = new WebPermission((m_UnrestrictedConnect ? NetworkAccess.Connect : (NetworkAccess)0) | (m_UnrestrictedAccept ? NetworkAccess.Accept : (NetworkAccess)0));
  489.             wp.m_acceptList = (ArrayList)m_acceptList.Clone();
  490.             wp.m_connectList = (ArrayList)m_connectList.Clone();
  491.             return wp;
  492.         }
  493.        
  494.         /// <devdoc>
  495.         /// <para>Compares two <see cref='System.Net.WebPermission'/> instances.</para>
  496.         /// </devdoc>
  497.         public override bool IsSubsetOf(IPermission target)
  498.         {
  499.             // Pattern suggested by security engine
  500.             if (target == null) {
  501.                 return !m_noRestriction && !m_UnrestrictedConnect && !m_UnrestrictedAccept && m_connectList.Count == 0 && m_acceptList.Count == 0;
  502.             }
  503.            
  504.             WebPermission other = target as WebPermission;
  505.             if (other == null) {
  506.                 throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
  507.             }
  508.            
  509.             if (other.m_noRestriction) {
  510.                 return true;
  511.             }
  512.             else if (m_noRestriction) {
  513.                 return false;
  514.             }
  515.            
  516.             //
  517.             // Besides SPECIAL case, this method is restricted to only final URIs (strings) on
  518.             // the current object.
  519.             // The restriction comes from the problem of finding a Regex to be a subset of another Regex
  520.             //
  521.             DelayedRegex regex = null;
  522.            
  523.             if (!other.m_UnrestrictedAccept) {
  524.                 if (m_UnrestrictedAccept) {
  525.                     return false;
  526.                 }
  527.                 else if (m_acceptList.Count != 0) {
  528.                     if (other.m_acceptList.Count == 0) {
  529.                         return false;
  530.                     }
  531.                     foreach (object obj in this.m_acceptList) {
  532.                         regex = obj as DelayedRegex;
  533.                         if (regex != null) {
  534.                             if (isSpecialSubsetCase(obj.ToString(), other.m_acceptList))
  535.                                 continue;
  536.                             throw new NotSupportedException(SR.GetString(SR.net_perm_both_regex));
  537.                         }
  538.                         if (!isMatchedURI(obj, other.m_acceptList))
  539.                             return false;
  540.                     }
  541.                 }
  542.             }
  543.            
  544.             if (!other.m_UnrestrictedConnect) {
  545.                 if (m_UnrestrictedConnect) {
  546.                     return false;
  547.                 }
  548.                 else if (m_connectList.Count != 0) {
  549.                     if (other.m_connectList.Count == 0) {
  550.                         return false;
  551.                     }
  552.                     foreach (object obj in this.m_connectList) {
  553.                         regex = obj as DelayedRegex;
  554.                         if (regex != null) {
  555.                             if (isSpecialSubsetCase(obj.ToString(), other.m_connectList))
  556.                                 continue;
  557.                             throw new NotSupportedException(SR.GetString(SR.net_perm_both_regex));
  558.                         }
  559.                         if (!isMatchedURI(obj, other.m_connectList))
  560.                             return false;
  561.                     }
  562.                 }
  563.             }
  564.            
  565.             return true;
  566.         }
  567.        
  568.         //Checks special case when testing Regex to be a subset of other Regex
  569.         //Support only the case when both Regexes are identical as strings.
  570.         private static bool isSpecialSubsetCase(string regexToCheck, ArrayList permList)
  571.         {
  572.            
  573.             Uri uri;
  574.             foreach (object uriPattern in permList) {
  575.                 DelayedRegex regex = uriPattern as DelayedRegex;
  576.                 if (regex != null) {
  577.                     //regex parameter against regex permission
  578.                     if (String.Compare(regexToCheck, regex.ToString(), StringComparison.OrdinalIgnoreCase) == 0)
  579.                         return true;
  580.                 }
  581.                 else if ((uri = uriPattern as Uri) != null) {
  582.                     //regex parameter against Uri permission
  583.                     if (String.Compare(regexToCheck, Regex.Escape(uri.GetComponents(UriComponents.HttpRequestUrl, UriFormat.UriEscaped)), StringComparison.OrdinalIgnoreCase) == 0)
  584.                         return true;
  585.                 }
  586.                 else if (String.Compare(regexToCheck, Regex.Escape(uriPattern.ToString()), StringComparison.OrdinalIgnoreCase) == 0) {
  587.                     //regex parameter against string permission
  588.                     return true;
  589.                 }
  590.                
  591.             }
  592.            
  593.             return false;
  594.         }
  595.        
  596.         // The union of two web permissions is formed by concatenating
  597.         // the list of allowed regular expressions. There is no check
  598.         // for duplicates/overlaps
  599.         /// <devdoc>
  600.         /// <para>Returns the logical union between two <see cref='System.Net.WebPermission'/> instances.</para>
  601.         /// </devdoc>
  602.         public override IPermission Union(IPermission target)
  603.         {
  604.             // Pattern suggested by Security engine
  605.             if (target == null) {
  606.                 return this.Copy();
  607.             }
  608.             WebPermission other = target as WebPermission;
  609.             if (other == null) {
  610.                 throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
  611.             }
  612.            
  613.             if (m_noRestriction || other.m_noRestriction) {
  614.                 return new WebPermission(true);
  615.             }
  616.            
  617.             WebPermission result = new WebPermission();
  618.            
  619.             if (m_UnrestrictedConnect || other.m_UnrestrictedConnect) {
  620.                 result.m_UnrestrictedConnect = true;
  621.             }
  622.             else {
  623.                 result.m_connectList = (ArrayList)other.m_connectList.Clone();
  624.                
  625.                 for (int i = 0; i < m_connectList.Count; i++) {
  626.                     DelayedRegex uriPattern = m_connectList[i] as DelayedRegex;
  627.                     if (uriPattern == null)
  628.                         if (m_connectList[i] is string)
  629.                             result.AddPermission(NetworkAccess.Connect, (string)m_connectList[i]);
  630.                         else
  631.                             result.AddPermission(NetworkAccess.Connect, (Uri)m_connectList[i]);
  632.                     else
  633.                         result.AddAsPattern(NetworkAccess.Connect, uriPattern);
  634.                 }
  635.             }
  636.            
  637.             if (m_UnrestrictedAccept || other.m_UnrestrictedAccept) {
  638.                 result.m_UnrestrictedAccept = true;
  639.             }
  640.             else {
  641.                 result.m_acceptList = (ArrayList)other.m_acceptList.Clone();
  642.                
  643.                 for (int i = 0; i < m_acceptList.Count; i++) {
  644.                     DelayedRegex uriPattern = m_acceptList[i] as DelayedRegex;
  645.                     if (uriPattern == null)
  646.                         if (m_acceptList[i] is string)
  647.                             result.AddPermission(NetworkAccess.Accept, (string)m_acceptList[i]);
  648.                         else
  649.                             result.AddPermission(NetworkAccess.Accept, (Uri)m_acceptList[i]);
  650.                     else
  651.                         result.AddAsPattern(NetworkAccess.Accept, uriPattern);
  652.                 }
  653.             }
  654.            
  655.             return result;
  656.         }
  657.        
  658.         /// <devdoc>
  659.         /// <para>Returns the logical intersection between two <see cref='System.Net.WebPermission'/> instances.</para>
  660.         /// </devdoc>
  661.         public override IPermission Intersect(IPermission target)
  662.         {
  663.             // Pattern suggested by Security engine
  664.             if (target == null) {
  665.                 return null;
  666.             }
  667.            
  668.             WebPermission other = target as WebPermission;
  669.             if (other == null) {
  670.                 throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
  671.             }
  672.            
  673.             if (m_noRestriction) {
  674.                 return other.Copy();
  675.             }
  676.             if (other.m_noRestriction) {
  677.                 return Copy();
  678.             }
  679.            
  680.             WebPermission result = new WebPermission();
  681.            
  682.             if (m_UnrestrictedConnect && other.m_UnrestrictedConnect) {
  683.                 result.m_UnrestrictedConnect = true;
  684.             }
  685.             else if (m_UnrestrictedConnect || other.m_UnrestrictedConnect) {
  686.                 result.m_connectList = (ArrayList)(m_UnrestrictedConnect ? other : this).m_connectList.Clone();
  687.             }
  688.             else {
  689.                 intersectList(m_connectList, other.m_connectList, result.m_connectList);
  690.             }
  691.            
  692.             if (m_UnrestrictedAccept && other.m_UnrestrictedAccept) {
  693.                 result.m_UnrestrictedAccept = true;
  694.             }
  695.             else if (m_UnrestrictedAccept || other.m_UnrestrictedAccept) {
  696.                 result.m_acceptList = (ArrayList)(m_UnrestrictedAccept ? other : this).m_acceptList.Clone();
  697.             }
  698.             else {
  699.                 intersectList(m_acceptList, other.m_acceptList, result.m_acceptList);
  700.             }
  701.            
  702.             // return null if resulting permission is restricted and empty
  703.             if (!result.m_UnrestrictedConnect && !result.m_UnrestrictedAccept && result.m_connectList.Count == 0 && result.m_acceptList.Count == 0) {
  704.                 return null;
  705.             }
  706.             return result;
  707.         }
  708.        
  709.         /// <devdoc>
  710.         /// </devdoc>
  711.         public override void FromXml(SecurityElement securityElement)
  712.         {
  713.             if (securityElement == null) {
  714.                
  715.                 //
  716.                 // null SecurityElement
  717.                 //
  718.                
  719.                 throw new ArgumentNullException("securityElement");
  720.             }
  721.             if (!securityElement.Tag.Equals("IPermission")) {
  722.                
  723.                 //
  724.                 // SecurityElement must be a permission element
  725.                 //
  726.                
  727.                 throw new ArgumentException(SR.GetString(SR.net_not_ipermission), "securityElement");
  728.             }
  729.            
  730.             string className = securityElement.Attribute("class");
  731.            
  732.             if (className == null) {
  733.                
  734.                 //
  735.                 // SecurityElement must be a permission element for this type
  736.                 //
  737.                
  738.                 throw new ArgumentException(SR.GetString(SR.net_no_classname), "securityElement");
  739.             }
  740.             if (className.IndexOf(this.GetType().FullName) < 0) {
  741.                
  742.                 //
  743.                 // SecurityElement must be a permission element for this type
  744.                 //
  745.                
  746.                 throw new ArgumentException(SR.GetString(SR.net_no_typename), "securityElement");
  747.             }
  748.            
  749.             string str = securityElement.Attribute("Unrestricted");
  750.            
  751.             m_connectList = new ArrayList();
  752.             m_acceptList = new ArrayList();
  753.             m_UnrestrictedAccept = m_UnrestrictedConnect = false;
  754.            
  755.             if (str != null && string.Compare(str, "true", StringComparison.OrdinalIgnoreCase) == 0) {
  756.                 m_noRestriction = true;
  757.                 return;
  758.             }
  759.            
  760.             m_noRestriction = false;
  761.            
  762.             SecurityElement et = securityElement.SearchForChildByTag("ConnectAccess");
  763.             string uriPattern;
  764.            
  765.             if (et != null) {
  766.                
  767.                 foreach (SecurityElement uriElem in et.Children) {
  768.                     //NOTE: Any stuff coming from XML is treated as URI PATTERN!
  769.                     if (uriElem.Tag.Equals("URI")) {
  770.                         try {
  771.                             uriPattern = uriElem.Attribute("uri");
  772.                         }
  773.                         catch {
  774.                             uriPattern = null;
  775.                         }
  776.                         if (uriPattern == null) {
  777.                             throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val_in_element), "ConnectAccess");
  778.                         }
  779.                         if (uriPattern == MatchAll) {
  780.                             m_UnrestrictedConnect = true;
  781.                             m_connectList = new ArrayList();
  782.                             break;
  783.                         }
  784.                         else {
  785.                             AddAsPattern(NetworkAccess.Connect, new DelayedRegex(uriPattern));
  786.                         }
  787.                     }
  788.                     else {
  789.                         // improper tag found, just ignore
  790.                     }
  791.                 }
  792.             }
  793.            
  794.             et = securityElement.SearchForChildByTag("AcceptAccess");
  795.             if (et != null) {
  796.                
  797.                 foreach (SecurityElement uriElem in et.Children) {
  798.                     //NOTE: Any stuff coming from XML is treated as URI PATTERN!
  799.                     if (uriElem.Tag.Equals("URI")) {
  800.                         try {
  801.                             uriPattern = uriElem.Attribute("uri");
  802.                         }
  803.                         catch {
  804.                             uriPattern = null;
  805.                         }
  806.                         if (uriPattern == null) {
  807.                             throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val_in_element), "AcceptAccess");
  808.                         }
  809.                         if (uriPattern == MatchAll) {
  810.                             m_UnrestrictedAccept = true;
  811.                             m_acceptList = new ArrayList();
  812.                             break;
  813.                         }
  814.                         else {
  815.                             AddAsPattern(NetworkAccess.Accept, new DelayedRegex(uriPattern));
  816.                         }
  817.                     }
  818.                     else {
  819.                         // improper tag found, just ignore
  820.                     }
  821.                 }
  822.             }
  823.         }
  824.        
  825.         /// <devdoc>
  826.         /// <para>[To be supplied.]</para>
  827.         /// </devdoc>
  828.         public override SecurityElement ToXml()
  829.         {
  830.            
  831.             SecurityElement securityElement = new SecurityElement("IPermission");
  832.            
  833.             securityElement.AddAttribute("class", this.GetType().FullName + ", " + this.GetType().Module.Assembly.FullName.Replace('"', '\''));
  834.             securityElement.AddAttribute("version", "1");
  835.            
  836.             if (!IsUnrestricted()) {
  837.                 string tempStr = null;
  838.                
  839.                 if (m_UnrestrictedConnect || m_connectList.Count > 0) {
  840.                     SecurityElement connectElement = new SecurityElement("ConnectAccess");
  841.                    
  842.                     if (m_UnrestrictedConnect) {
  843.                         SecurityElement uripattern = new SecurityElement("URI");
  844.                         uripattern.AddAttribute("uri", SecurityElement.Escape(MatchAll));
  845.                         connectElement.AddChild(uripattern);
  846.                     }
  847.                     else {
  848.                         //NOTE All strings going to XML will become URI PATTERNS i.e. escaped to Regex
  849.                         foreach (object obj in m_connectList) {
  850.                             Uri uri = obj as Uri;
  851.                             if (uri != null)
  852.                                 tempStr = Regex.Escape(uri.GetComponents(UriComponents.HttpRequestUrl, UriFormat.UriEscaped));
  853.                             else
  854.                                 tempStr = obj.ToString();
  855.                            
  856.                             if (obj is string)
  857.                                 tempStr = Regex.Escape(tempStr);
  858.                            
  859.                             SecurityElement uripattern = new SecurityElement("URI");
  860.                             uripattern.AddAttribute("uri", SecurityElement.Escape(tempStr));
  861.                             connectElement.AddChild(uripattern);
  862.                         }
  863.                     }
  864.                    
  865.                     securityElement.AddChild(connectElement);
  866.                 }
  867.                
  868.                 if (m_UnrestrictedAccept || m_acceptList.Count > 0) {
  869.                     SecurityElement acceptElement = new SecurityElement("AcceptAccess");
  870.                    
  871.                     if (m_UnrestrictedAccept) {
  872.                         SecurityElement uripattern = new SecurityElement("URI");
  873.                         uripattern.AddAttribute("uri", SecurityElement.Escape(MatchAll));
  874.                         acceptElement.AddChild(uripattern);
  875.                     }
  876.                     else {
  877.                         //NOTE All strings going to XML will become URI PATTERNS i.e. escaped to Regex
  878.                         foreach (object obj in m_acceptList) {
  879.                             Uri uri = obj as Uri;
  880.                             if (uri != null)
  881.                                 tempStr = Regex.Escape(uri.GetComponents(UriComponents.HttpRequestUrl, UriFormat.UriEscaped));
  882.                             else
  883.                                 tempStr = obj.ToString();
  884.                            
  885.                             if (obj is string)
  886.                                 tempStr = Regex.Escape(tempStr);
  887.                            
  888.                             SecurityElement uripattern = new SecurityElement("URI");
  889.                             uripattern.AddAttribute("uri", SecurityElement.Escape(tempStr));
  890.                             acceptElement.AddChild(uripattern);
  891.                         }
  892.                     }
  893.                    
  894.                     securityElement.AddChild(acceptElement);
  895.                 }
  896.             }
  897.             else {
  898.                 securityElement.AddAttribute("Unrestricted", "true");
  899.             }
  900.             return securityElement;
  901.         }
  902.        
  903.         // Verifies a single Uri against a set of regular expressions
  904.         private static bool isMatchedURI(object uriToCheck, ArrayList uriPatternList)
  905.         {
  906.            
  907.             string stringUri = uriToCheck as string;
  908.            
  909.             foreach (object uriPattern in uriPatternList) {
  910.                 DelayedRegex R = uriPattern as DelayedRegex;
  911.                
  912.                 //perform case insensitive comparison of final URIs or strings, a Uri is never equal compares a string (strings are invalid Uris)
  913.                 if (R == null) {
  914.                     if (uriToCheck.GetType() == uriPattern.GetType()) {
  915.                         if (stringUri != null && string.Compare(stringUri, (string)uriPattern, StringComparison.OrdinalIgnoreCase) == 0) {
  916.                             return true;
  917.                         }
  918.                         else if (stringUri == null && uriToCheck.Equals(uriPattern)) {
  919.                             return true;
  920.                         }
  921.                     }
  922.                     continue;
  923.                 }
  924.                
  925.                 //Otherwise trying match final URI against given Regex pattern
  926.                 string s = stringUri != null ? stringUri : ((Uri)uriToCheck).GetComponents(UriComponents.HttpRequestUrl, UriFormat.UriEscaped);
  927.                 Match M = R.AsRegex.Match(s);
  928.                 // Found match for the regular expression?
  929.                 // ... which starts at the begining
  930.                 if ((M != null) && (M.Index == 0) && (M.Length == s.Length)) {
  931.                     // ... and the whole string matched
  932.                     return true;
  933.                 }
  934.                
  935.                 if (stringUri != null)
  936.                     continue;
  937.                 //
  938.                 // check if the URI was presented in non-canonical form
  939.                 //
  940.                 s = ((Uri)uriToCheck).GetComponents(UriComponents.HttpRequestUrl, UriFormat.SafeUnescaped);
  941.                 M = R.AsRegex.Match(s);
  942.                 // Found match for the regular expression?
  943.                 // ... which starts at the begining
  944.                 if ((M != null) && (M.Index == 0) && (M.Length == s.Length)) {
  945.                     // ... and the whole string matched
  946.                     return true;
  947.                 }
  948.             }
  949.             return false;
  950.         }
  951.        
  952.         // We should keep the result as compact as possible since otherwise even
  953.         // simple scenarios in Policy Wizard won;t work due to repeated Union/Intersect calls
  954.         // The issue comes from the "hard" Regex.IsSubsetOf(Regex) problem.
  955.         private static void intersectList(ArrayList A, ArrayList B, ArrayList result)
  956.         {
  957.             bool[] aDone = new bool[A.Count];
  958.             bool[] bDone = new bool[B.Count];
  959.             int ia = 0;
  960.             int ib;
  961.            
  962.             // The optimization is done according to the following truth
  963.             // (A|B|C) intersect (B|C|E|D)) == B|C|(A inter E)|(A inter D)
  964.             //
  965.             // We also check on any duplicates in the result
  966.            
  967.             // Round 1st
  968.             // Getting rid of same permissons in the input arrays (assuming X /\ X = X)
  969.             foreach (object a in A) {
  970.                 ib = 0;
  971.                 foreach (object b in B) {
  972.                    
  973.                     // check to see if b is in the result already
  974.                     if (!bDone[ib]) {
  975.                        
  976.                         //if both are regexes or both are Uris or both are strings
  977.                         if (a.GetType() == b.GetType()) {
  978.                             if (a is Uri) {
  979.                                 // both are uris
  980.                                 if (a.Equals(b)) {
  981.                                     result.Add(a);
  982.                                     aDone[ia] = bDone[ib] = true;
  983.                                     //since permissions are ORed we can break and go to the next A
  984.                                     break;
  985.                                 }
  986.                             }
  987.                             else {
  988.                                 // regexes and strings uses ToString() output
  989.                                 if (string.Compare(a.ToString(), b.ToString(), StringComparison.OrdinalIgnoreCase) == 0) {
  990.                                     result.Add(a);
  991.                                     aDone[ia] = bDone[ib] = true;
  992.                                     //since permissions are ORed we can break and go to the next A
  993.                                     break;
  994.                                 }
  995.                             }
  996.                         }
  997.                     }
  998.                     ++ib;
  999.                 }
  1000.                 //foreach b in B
  1001.                 ++ia;
  1002.             }
  1003.             //foreach a in A
  1004.             ia = 0;
  1005.             // Round second
  1006.             // Grab only intersections of objects not found in both A and B
  1007.             foreach (object a in A) {
  1008.                
  1009.                 if (!aDone[ia]) {
  1010.                     ib = 0;
  1011.                     foreach (object b in B) {
  1012.                        
  1013.                         if (!bDone[ib]) {
  1014.                             bool resultUri;
  1015.                             object intesection = intersectPair(a, b, out resultUri);
  1016.                            
  1017.                             if (intesection != null) {
  1018.                                 bool found = false;
  1019.                                 // check to see if we already have the same result
  1020.                                 foreach (object obj in result) {
  1021.                                     if (resultUri == (obj is Uri)) {
  1022.                                         if (resultUri ? intesection.Equals(obj) : string.Compare(obj.ToString(), intesection.ToString(), StringComparison.OrdinalIgnoreCase) == 0) {
  1023.                                             found = true;
  1024.                                             break;
  1025.                                         }
  1026.                                     }
  1027.                                 }
  1028.                                
  1029.                                 if (!found) {
  1030.                                     result.Add(intesection);
  1031.                                 }
  1032.                             }
  1033.                         }
  1034.                         ++ib;
  1035.                     }
  1036.                 }
  1037.                 ++ia;
  1038.             }
  1039.         }
  1040.        
  1041.         private static object intersectPair(object L, object R, out bool isUri)
  1042.         {
  1043.            
  1044.             //VERY OLD OPTION: return new Regex("(?=(" + ((Regex)X[i]).ToString()+ "))(" + ((Regex)Y[j]).ToString() + ")","i");
  1045.             //STILL OLD OPTION: return new Regex("(?=.*?(" + L.ToString() + "))" + "(?=.*?(" + R.ToString() + "))");
  1046.             // check RegexSpec.doc
  1047.             //CURRENT OPTION: return new Regex("(?=(" + L.ToString() + "))(" + R.ToString() + ")", RegexOptions.IgnoreCase );
  1048.             isUri = false;
  1049.             DelayedRegex L_Pattern = L as DelayedRegex;
  1050.             DelayedRegex R_Pattern = R as DelayedRegex;
  1051.            
  1052.             if (L_Pattern != null && R_Pattern != null) {
  1053.                 //both are Regex
  1054.                 return new DelayedRegex("(?=(" + L_Pattern.ToString() + "))(" + R_Pattern.ToString() + ")");
  1055.             }
  1056.             else if (L_Pattern != null && R_Pattern == null) {
  1057.                 //only L is a Regex
  1058.                 isUri = R is Uri;
  1059.                 string uriString = isUri ? ((Uri)R).GetComponents(UriComponents.HttpRequestUrl, UriFormat.UriEscaped) : R.ToString();
  1060.                
  1061.                 Match M = L_Pattern.AsRegex.Match(uriString);
  1062.                 // Found match for the regular expression?
  1063.                 // ... which starts at the begining
  1064.                 if ((M != null) && (M.Index == 0) && (M.Length == uriString.Length)) {
  1065.                     // ... and the whole string matched
  1066.                     return R;
  1067.                 }
  1068.                 return null;
  1069.             }
  1070.             else if (L_Pattern == null && R_Pattern != null) {
  1071.                 //only R is a Regex
  1072.                 isUri = L is Uri;
  1073.                 string uriString = isUri ? ((Uri)L).GetComponents(UriComponents.HttpRequestUrl, UriFormat.UriEscaped) : L.ToString();
  1074.                 Match M = R_Pattern.AsRegex.Match(uriString);
  1075.                 // Found match for the regular expression?
  1076.                 // ... which starts at the begining
  1077.                 if ((M != null) && (M.Index == 0) && (M.Length == uriString.Length)) {
  1078.                     // ... and the whole string matched
  1079.                     return L;
  1080.                 }
  1081.                 return null;
  1082.             }
  1083.             //both are Uris or strings
  1084.             isUri = L is Uri;
  1085.             if (isUri)
  1086.                 return L.Equals(R) ? L : null;
  1087.             else
  1088.                 return string.Compare(L.ToString(), R.ToString(), StringComparison.OrdinalIgnoreCase) == 0 ? L : null;
  1089.         }
  1090.     }
  1091.     // class WebPermission
  1092. }
  1093. // namespace System.Net

Developer Fusion