2010-04-21 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web / SiteMapProvider.cs
index cceba6f018b3df832758e511230ec7950607c938..8d005f2aa494e772b318cbbd7e46b891f92ea788 100644 (file)
@@ -6,7 +6,7 @@
 //     Lluis Sanchez Gual (lluis@novell.com)
 //
 // (C) 2003 Ben Maurer
-// (C) 2005 Novell, Inc (http://www.novell.com)
+// (C) 2005-2009 Novell, Inc (http://www.novell.com)
 //
 
 //
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+using System.ComponentModel;
 using System.Collections;
 using System.Collections.Specialized;
 using System.Text;
 using System.Configuration.Provider;
 using System.Web.Util;
 using System.Globalization;
+using System.Web.Configuration;
 
-namespace System.Web {
-       public abstract class SiteMapProvider : ProviderBase {
+namespace System.Web
+{
+       public abstract class SiteMapProvider : ProviderBase
+       {
+               static readonly object siteMapResolveEvent = new object ();
+               
+               internal object this_lock = new object ();
                
                bool enableLocalization;
                SiteMapProvider parentProvider;
@@ -47,6 +53,13 @@ namespace System.Web {
                bool securityTrimming;
                object resolveLock = new Object();
                bool resolving;
+
+               EventHandlerList events = new EventHandlerList ();
+               
+               public event SiteMapResolveEventHandler SiteMapResolve {
+                       add { events.AddHandler (siteMapResolveEvent, value); }
+                       remove { events.RemoveHandler (siteMapResolveEvent, value); }
+               }
                
                protected virtual void AddNode (SiteMapNode node)
                {
@@ -62,10 +75,14 @@ namespace System.Web {
                {
                        if (context == null)
                                return null;
+
+                       HttpRequest req = context.Request;
+                       if (req == null)
+                               return null;
                        
-                       SiteMapNode ret = this.FindSiteMapNode (context.Request.RawUrl);
+                       SiteMapNode ret = this.FindSiteMapNode (req.RawUrl);
                        if (ret == null)
-                               ret = this.FindSiteMapNode (context.Request.Path);
+                               ret = this.FindSiteMapNode (req.Path);
                        return ret;
                }
 
@@ -157,8 +174,8 @@ namespace System.Web {
                public override void Initialize (string name, NameValueCollection attributes)
                {
                        base.Initialize (name, attributes);
-                       if (attributes["securityTrimmingEnabled"] != null)
-                               securityTrimming = (bool) Convert.ChangeType (attributes ["securityTrimmingEnabled"], typeof(bool));
+                       if (attributes ["securityTrimmingEnabled"] != null)
+                               securityTrimming = (bool) Convert.ChangeType (attributes ["securityTrimmingEnabled"], typeof (bool));
                }
                
                [MonoTODO ("need to implement cases 2 and 3")]
@@ -167,33 +184,47 @@ namespace System.Web {
                        if (context == null) throw new ArgumentNullException ("context");
                        if (node == null) throw new ArgumentNullException ("node");
 
-                       /* the node is accessible (according to msdn2)
-                        * if:
+                       if (!SecurityTrimmingEnabled)
+                               return true;
+
+                       /* The node is accessible (according to msdn2) if:
                         *
-                        * 1. the current user is in the node's Roles.
+                        * 1. The Roles exists on node and the current user is in at least one of the specified roles.
                         *
-                        * 2. the current thread's WindowsIdentity has
-                        * file access to the url. (and the url is
-                        * located within the current application).
+                        * 2. The current thread has an associated WindowsIdentity that has file access to the requested URL and
+                        * the URL is located within the directory structure for the application.
                         *
-                        * 3. the <authorization> configuration element
-                        * lists the current user as being authorized
-                        * for the node's url. (and the url is located
-                        * within the current application)
+                        * 3. The current user is authorized specifically for the requested URL in the authorization element for
+                        * the current application and the URL is located within the directory structure for the application. 
                        */
 
                        /* 1. */
-                       foreach (string rolename in node.Roles)
-                               if (context.User.IsInRole (rolename))
-                                       return true;
-
+                       IList roles = node.Roles;
+                       if (roles != null && roles.Count > 0) {
+                               foreach (string rolename in roles)
+                                       if (rolename == "*" || context.User.IsInRole (rolename))
+                                               return true;
+                       }
+                       
                        /* 2. */
                        /* XXX */
 
                        /* 3. */
-                       /* XXX */
+                       string url = node.Url;
+                       if(!String.IsNullOrEmpty(url)) {
+                               // TODO check url is located within the current application
+
+                               if (VirtualPathUtility.IsAppRelative (url) || !VirtualPathUtility.IsAbsolute (url))
+                                       url = VirtualPathUtility.Combine (VirtualPathUtility.AppendTrailingSlash (HttpRuntime.AppDomainAppVirtualPath), url);
 
-                       return true; // the default should be false.
+                               AuthorizationSection config = (AuthorizationSection) WebConfigurationManager.GetSection (
+                                       "system.web/authorization",
+                                       url);
+                               if (config != null)
+                                       return config.IsValidUser (context.User, context.Request.HttpMethod);
+                       }
+
+                       return false;
                }
                
                public virtual SiteMapNode CurrentNode {
@@ -214,7 +245,7 @@ namespace System.Web {
                
                public virtual SiteMapProvider RootProvider {
                        get {
-                               lock (this) {
+                               lock (this_lock) {
                                        if (rootProviderCache == null) {
                                                SiteMapProvider current = this;
                                                while (current.ParentProvider != null)
@@ -229,17 +260,19 @@ namespace System.Web {
                
                protected SiteMapNode ResolveSiteMapNode (HttpContext context)
                {
-                       SiteMapResolveEventArgs args = new SiteMapResolveEventArgs (context, this);
-                       if (SiteMapResolve != null) {
+                       SiteMapResolveEventHandler eh = events [siteMapResolveEvent] as SiteMapResolveEventHandler;
+
+                       if (eh != null) {
                                lock (resolveLock) {
-                                       if (resolving) return null;
+                                       if (resolving)
+                                               return null;
                                        resolving = true;
-                                       SiteMapNode r = SiteMapResolve (this, args);
+                                       SiteMapResolveEventArgs args = new SiteMapResolveEventArgs (context, this);
+                                       SiteMapNode r = eh (this, args);
                                        resolving = false;
                                        return r;
                                }
-                       }
-                       else
+                       } else
                                return null;
                }
                
@@ -265,8 +298,6 @@ namespace System.Web {
                        }
                }
 
-               public event SiteMapResolveEventHandler SiteMapResolve;
-
                internal static SiteMapNode ReturnNodeIfAccessible (SiteMapNode node)
                {
                        if (node.IsAccessibleToUser (HttpContext.Current))
@@ -279,5 +310,5 @@ namespace System.Web {
                }
        }
 }
-#endif
+