1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
|
//------------------------------------------------------------------------------
// <copyright file="SiteMapProvider.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* Copyright (c) 2002 Microsoft Corporation
*/
namespace System.Web {
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Web.Security;
using System.Web.UI;
using System.Web.Util;
using System.Security.Permissions;
public abstract class SiteMapProvider : ProviderBase {
private bool _securityTrimmingEnabled;
private bool _enableLocalization;
private String _resourceKey;
internal const String _securityTrimmingEnabledAttrName = "securityTrimmingEnabled";
private const string _allRoles = "*";
private SiteMapProvider _rootProvider;
private SiteMapProvider _parentProvider;
private object _resolutionTicket = new object();
internal readonly object _lock = new Object();
public virtual SiteMapNode CurrentNode {
get {
HttpContext context = HttpContext.Current;
SiteMapNode result = null;
// First check the SiteMap resolve events.
result = ResolveSiteMapNode(context);
if (result == null) {
result = FindSiteMapNode(context);
}
return ReturnNodeIfAccessible(result);
}
}
public bool EnableLocalization {
get {
return _enableLocalization;
}
set {
_enableLocalization = value;
}
}
// Parent provider
public virtual SiteMapProvider ParentProvider {
get {
return _parentProvider;
}
set {
_parentProvider = value;
}
}
public string ResourceKey {
get {
return _resourceKey;
}
set {
_resourceKey = value;
}
}
public virtual SiteMapProvider RootProvider {
get {
if (_rootProvider == null) {
lock (_lock) {
if (_rootProvider == null) {
Hashtable providers = new Hashtable();
SiteMapProvider candidate = this;
providers.Add(candidate, null);
while (candidate.ParentProvider != null) {
if (providers.Contains(candidate.ParentProvider))
throw new ProviderException(SR.GetString(SR.SiteMapProvider_Circular_Provider));
candidate = candidate.ParentProvider;
providers.Add(candidate, null);
}
_rootProvider = candidate;
}
}
}
return _rootProvider;
}
}
public virtual SiteMapNode RootNode {
get {
SiteMapNode node = GetRootNodeCore();
return ReturnNodeIfAccessible(node);
}
}
public bool SecurityTrimmingEnabled {
get {
return _securityTrimmingEnabled;
}
}
public event SiteMapResolveEventHandler SiteMapResolve;
/// <devdoc>
/// <para>Add single node to provider.</para>
/// </devdoc>
protected virtual void AddNode(SiteMapNode node) {
AddNode(node, null);
}
protected internal virtual void AddNode(SiteMapNode node, SiteMapNode parentNode) {
throw new NotImplementedException();
}
public virtual SiteMapNode FindSiteMapNode(HttpContext context) {
if (context == null) {
return null;
}
string rawUrl = context.Request.RawUrl;
SiteMapNode result = null;
// First check the RawUrl
result = FindSiteMapNode(rawUrl);
if (result == null) {
int queryStringIndex = rawUrl.IndexOf("?", StringComparison.Ordinal);
if (queryStringIndex != -1) {
// check the RawUrl without querystring
result = FindSiteMapNode(rawUrl.Substring(0, queryStringIndex));
}
if (result == null) {
Page page = context.CurrentHandler as Page;
if (page != null) {
// Try without server side query strings
string qs = page.ClientQueryString;
if (qs.Length > 0) {
result = FindSiteMapNode(context.Request.Path + "?" + qs);
}
}
if (result == null) {
// Check the request path
result = FindSiteMapNode(context.Request.Path);
}
}
}
return result;
}
public virtual SiteMapNode FindSiteMapNodeFromKey(string key) {
return FindSiteMapNode(key);
}
public abstract SiteMapNode FindSiteMapNode(string rawUrl);
public abstract SiteMapNodeCollection GetChildNodes(SiteMapNode node);
public virtual SiteMapNode GetCurrentNodeAndHintAncestorNodes(int upLevel) {
if (upLevel < -1) {
throw new ArgumentOutOfRangeException("upLevel");
}
return CurrentNode;
}
public virtual SiteMapNode GetCurrentNodeAndHintNeighborhoodNodes(int upLevel, int downLevel) {
if (upLevel < -1) {
throw new ArgumentOutOfRangeException("upLevel");
}
if (downLevel < -1) {
throw new ArgumentOutOfRangeException("downLevel");
}
return CurrentNode;
}
public abstract SiteMapNode GetParentNode(SiteMapNode node);
public virtual SiteMapNode GetParentNodeRelativeToCurrentNodeAndHintDownFromParent (
int walkupLevels, int relativeDepthFromWalkup) {
if (walkupLevels < 0) {
throw new ArgumentOutOfRangeException("walkupLevels");
}
if (relativeDepthFromWalkup < 0) {
throw new ArgumentOutOfRangeException("relativeDepthFromWalkup");
}
// First get current nodes and hints about its ancestors.
SiteMapNode currentNode = GetCurrentNodeAndHintAncestorNodes(walkupLevels);
// Simply return if the currentNode is null.
if (currentNode == null) {
return null;
}
// Find the target node by walk up the parent tree.
SiteMapNode targetNode = GetParentNodesInternal(currentNode, walkupLevels);
if (targetNode == null) {
return null;
}
// Get hints about its lower neighborhood nodes.
HintNeighborhoodNodes(targetNode, 0, relativeDepthFromWalkup);
return targetNode;
}
public virtual SiteMapNode GetParentNodeRelativeToNodeAndHintDownFromParent(
SiteMapNode node, int walkupLevels, int relativeDepthFromWalkup) {
if (walkupLevels < 0) {
throw new ArgumentOutOfRangeException("walkupLevels");
}
if (relativeDepthFromWalkup < 0) {
throw new ArgumentOutOfRangeException("relativeDepthFromWalkup");
}
if (node == null) {
throw new ArgumentNullException("node");
}
// First get hints about ancestor nodes;
HintAncestorNodes(node, walkupLevels);
// walk up the parent node until the target node is found.
SiteMapNode ancestorNode = GetParentNodesInternal(node, walkupLevels);
if (ancestorNode == null) {
return null;
}
// Get hints about its neighthood nodes
HintNeighborhoodNodes(ancestorNode, 0, relativeDepthFromWalkup);
return ancestorNode;
}
private SiteMapNode GetParentNodesInternal(SiteMapNode node, int walkupLevels) {
Debug.Assert(node != null);
if (walkupLevels <= 0) {
return node;
}
do {
node = node.ParentNode;
walkupLevels--;
} while (node != null && walkupLevels != 0);
return node;
}
/*
* A reference node that must be returned by all sitemap providers, this is
* required for the parent provider to keep track of the relations between
* two providers.
* For example, the parent provider uses this method to keep track of the parent
* node of child provider's root node.
*/
protected internal abstract SiteMapNode GetRootNodeCore();
protected static SiteMapNode GetRootNodeCoreFromProvider(SiteMapProvider provider) {
return provider.GetRootNodeCore();
}
public virtual void HintAncestorNodes(SiteMapNode node, int upLevel) {
if (node == null) {
throw new ArgumentNullException("node");
}
if (upLevel < -1) {
throw new ArgumentOutOfRangeException("upLevel");
}
}
public virtual void HintNeighborhoodNodes(SiteMapNode node, int upLevel, int downLevel) {
if (node == null) {
throw new ArgumentNullException("node");
}
if (upLevel < -1) {
throw new ArgumentOutOfRangeException("upLevel");
}
if (downLevel < -1) {
throw new ArgumentOutOfRangeException("downLevel");
}
}
public override void Initialize(string name, NameValueCollection attributes) {
if (attributes != null) {
if (string.IsNullOrEmpty(attributes["description"])) {
attributes.Remove("description");
attributes.Add("description", this.GetType().Name);
}
ProviderUtil.GetAndRemoveBooleanAttribute(attributes, _securityTrimmingEnabledAttrName, Name, ref _securityTrimmingEnabled);
}
base.Initialize(name, attributes);
}
public virtual bool IsAccessibleToUser(HttpContext context, SiteMapNode node) {
if (node == null) {
throw new ArgumentNullException("node");
}
if (context == null) {
throw new ArgumentNullException("context");
}
if (!SecurityTrimmingEnabled) {
return true;
}
if (node.Roles != null) {
foreach (string role in node.Roles) {
// Grant access if one of the roles is a "*".
if (role == _allRoles ||
context.User != null && context.User.IsInRole(role)) {
return true;
}
}
}
VirtualPath virtualPath = node.VirtualPath;
if (virtualPath == null ||
!virtualPath.IsWithinAppRoot) {
return false;
}
return System.Web.UI.Util.IsUserAllowedToPath(context, virtualPath);
}
protected internal virtual void RemoveNode(SiteMapNode node) {
throw new NotImplementedException();
}
protected SiteMapNode ResolveSiteMapNode(HttpContext context) {
SiteMapResolveEventHandler eventHandler = SiteMapResolve;
if (eventHandler == null)
return null;
if (!context.Items.Contains(_resolutionTicket)) {
context.Items.Add(_resolutionTicket, true);
try {
Delegate[] ds = eventHandler.GetInvocationList();
int len = ds.Length;
for (int i = 0; i < len; i++) {
SiteMapNode ret = ((SiteMapResolveEventHandler)ds[i])(this, new SiteMapResolveEventArgs(context, this));
if (ret != null) {
return ret;
}
}
} finally {
context.Items.Remove(_resolutionTicket);
}
}
return null;
}
internal SiteMapNode ReturnNodeIfAccessible(SiteMapNode node) {
if (node != null && node.IsAccessibleToUser(HttpContext.Current)) {
return node;
}
return null;
}
}
}
|