Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / xsp / System / Web / XmlSiteMapProvider.cs / 1 / XmlSiteMapProvider.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* * XmlSiteMapProvider class definition * * Copyright (c) 2002 Microsoft Corporation */ namespace System.Web { using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Design; using System.Configuration; using System.Configuration.Provider; using System.Globalization; using System.IO; using System.Resources; using System.Security; using System.Security.Permissions; using System.Web.Compilation; using System.Web.Configuration; using System.Web.Hosting; using System.Web.UI; using System.Web.Util; using System.Xml; // XmlMapProvider that generates sitemap tree from xml files [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class XmlSiteMapProvider : StaticSiteMapProvider, IDisposable { private string _filename; private VirtualPath _virtualPath; private VirtualPath _normalizedVirtualPath; private SiteMapNode _siteMapNode; private XmlDocument _document; private bool _initialized; private FileChangeEventHandler _handler; private StringCollection _parentSiteMapFileCollection; private const string _providerAttribute = "provider"; private const string _siteMapFileAttribute = "siteMapFile"; private const string _siteMapNodeName = "siteMapNode"; private const string _xmlSiteMapFileExtension = ".sitemap"; private const string _resourcePrefix = "$resources:"; private const int _resourcePrefixLength = 10; private const char _resourceKeySeparator = ','; private static readonly char[] _seperators = new char[] { ';', ',' }; private ArrayList _childProviderList; // table containing mappings from child providers to their root nodes. private Hashtable _childProviderTable; public XmlSiteMapProvider() { } private ArrayList ChildProviderList { get { if (_childProviderList == null) { lock (_lock) { if (_childProviderList == null) { _childProviderList = ArrayList.ReadOnly(new ArrayList(ChildProviderTable.Keys)); } } } return _childProviderList; } } private Hashtable ChildProviderTable { get { if (_childProviderTable == null) { lock (_lock) { if (_childProviderTable == null) { _childProviderTable = new Hashtable(); } } } return _childProviderTable; } } public override SiteMapNode RootNode { get { BuildSiteMap(); return ReturnNodeIfAccessible(_siteMapNode); } } protected internal override void AddNode(SiteMapNode node, SiteMapNode parentNode) { if (node == null) { throw new ArgumentNullException("node"); } if (parentNode == null) { throw new ArgumentNullException("parentNode"); } SiteMapProvider ownerProvider = node.Provider; SiteMapProvider parentOwnerProvider = parentNode.Provider; if (ownerProvider != this) { throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, node.ToString()), "node"); } if (parentOwnerProvider != this) { throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, parentNode.ToString()), "parentNode"); } lock (_lock) { // First remove it from its current location. RemoveNode(node); AddNodeInternal(node, parentNode, null); } } private void AddNodeInternal(SiteMapNode node, SiteMapNode parentNode, XmlNode xmlNode) { lock (_lock) { String url = node.Url; String key = node.Key; bool isValidUrl = false; // Only add the node to the url table if it's a static node. if (!String.IsNullOrEmpty(url)) { if (UrlTable[url] != null) { if (xmlNode != null) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Url, url), xmlNode); } else { throw new InvalidOperationException(SR.GetString( SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Url, url)); } } isValidUrl = true; } if (KeyTable.Contains(key)) { if (xmlNode != null) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Key, key), xmlNode); } else { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Key, key)); } } if (isValidUrl) { UrlTable[url] = node; } KeyTable[key] = node; // Add the new node into parentNode collection if (parentNode != null) { ParentNodeTable[node] = parentNode; if (ChildNodeCollectionTable[parentNode] == null) { ChildNodeCollectionTable[parentNode] = new SiteMapNodeCollection(); } ((SiteMapNodeCollection)ChildNodeCollectionTable[parentNode]).Add(node); } } } protected virtual void AddProvider(string providerName, SiteMapNode parentNode) { if (parentNode == null) { throw new ArgumentNullException("parentNode"); } if (parentNode.Provider != this) { throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, parentNode.ToString()), "parentNode"); } SiteMapNode node = GetNodeFromProvider(providerName); AddNodeInternal(node, parentNode, null); } public override SiteMapNode BuildSiteMap() { SiteMapNode tempNode = _siteMapNode; // If siteMap is already constructed, simply returns it. // Child providers will only be updated when the parent providers need to access them. if (tempNode != null) { return tempNode; } XmlDocument document = GetConfigDocument(); lock (_lock) { if (_siteMapNode != null) { return _siteMapNode; } Clear(); // Need to check if the sitemap file exists before opening it. CheckSiteMapFileExists(); try { using (Stream stream = _normalizedVirtualPath.OpenFile()) { XmlReader reader = new XmlTextReader(stream); document.Load(reader); } } catch (XmlException e) { string sourceFile = _virtualPath.VirtualPathString; string physicalDir = _normalizedVirtualPath.MapPathInternal(); if (physicalDir != null && HttpRuntime.HasPathDiscoveryPermission(physicalDir)) { sourceFile = physicalDir; } throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Error_loading_Config_file, _virtualPath, e.Message), e, sourceFile, e.LineNumber); } catch (Exception e) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Error_loading_Config_file, _virtualPath, e.Message), e); } XmlNode node = null; foreach (XmlNode siteMapMode in document.ChildNodes) { if (String.Equals(siteMapMode.Name, "siteMap", StringComparison.Ordinal)) { node = siteMapMode; break; } } if (node == null) throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Top_Element_Must_Be_SiteMap), document); bool enableLocalization = false; HandlerBase.GetAndRemoveBooleanAttribute(node, "enableLocalization", ref enableLocalization); EnableLocalization = enableLocalization; XmlNode topElement = null; foreach (XmlNode subNode in node.ChildNodes) { if (subNode.NodeType == XmlNodeType.Element) { if (!_siteMapNodeName.Equals(subNode.Name)) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Only_SiteMapNode_Allowed), subNode); } if (topElement != null) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Only_One_SiteMapNode_Required_At_Top), subNode); } topElement = subNode; } } if (topElement == null) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Only_One_SiteMapNode_Required_At_Top), node); } Queue queue = new Queue(50); // The parentnode of the top node does not exist, // simply add a null to satisfy the ConvertFromXmlNode condition. queue.Enqueue(null); queue.Enqueue(topElement); _siteMapNode = ConvertFromXmlNode(queue); return _siteMapNode; } } private void CheckSiteMapFileExists() { if (!System.Web.UI.Util.VirtualFileExistsWithAssert(_normalizedVirtualPath)) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_FileName_does_not_exist, _virtualPath)); } } protected override void Clear() { lock (_lock) { ChildProviderTable.Clear(); _siteMapNode = null; _childProviderList = null; base.Clear(); } } // helper method to convert an XmlNode to a SiteMapNode private SiteMapNode ConvertFromXmlNode(Queue queue) { SiteMapNode rootNode = null; while (true) { if (queue.Count == 0) { return rootNode; } SiteMapNode parentNode = (SiteMapNode)queue.Dequeue(); XmlNode xmlNode = (XmlNode)queue.Dequeue(); SiteMapNode node = null; if (!_siteMapNodeName.Equals(xmlNode.Name)) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Only_SiteMapNode_Allowed), xmlNode); } string providerName = null; HandlerBase.GetAndRemoveNonEmptyStringAttribute(xmlNode, _providerAttribute, ref providerName); // If the siteMapNode references another provider if (providerName != null) { node = GetNodeFromProvider(providerName); // No other attributes or child nodes are allowed on a provider node. HandlerBase.CheckForUnrecognizedAttributes(xmlNode); HandlerBase.CheckForNonCommentChildNodes(xmlNode); } else { string siteMapFile = null; HandlerBase.GetAndRemoveNonEmptyStringAttribute(xmlNode, _siteMapFileAttribute, ref siteMapFile); if (siteMapFile != null) { node = GetNodeFromSiteMapFile(xmlNode, VirtualPath.Create(siteMapFile)); } else { node = GetNodeFromXmlNode(xmlNode, queue); } } AddNodeInternal(node, parentNode, xmlNode); if (rootNode == null) { rootNode = node; } } } protected virtual void Dispose(bool disposing) { if (_handler != null) { Debug.Assert(_filename != null); HttpRuntime.FileChangesMonitor.StopMonitoringFile(_filename, _handler); } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void EnsureChildSiteMapProviderUpToDate(SiteMapProvider childProvider) { SiteMapNode oldNode = (SiteMapNode)ChildProviderTable[childProvider]; SiteMapNode newNode = childProvider.GetRootNodeCore(); if (newNode == null) { throw new ProviderException(SR.GetString(SR.XmlSiteMapProvider_invalid_sitemapnode_returned, childProvider.Name)); } // child providers have been updated. if (!oldNode.Equals(newNode)) { // If the child provider table has been updated, simply return null. // This will happen when the current provider's sitemap file is changed or Clear() is called; if (oldNode == null) { return; } lock (_lock) { oldNode = (SiteMapNode)ChildProviderTable[childProvider]; // If the child provider table has been updated, simply return null. See above. if (oldNode == null) { return; } newNode = childProvider.GetRootNodeCore(); if (newNode == null) { throw new ProviderException(SR.GetString(SR.XmlSiteMapProvider_invalid_sitemapnode_returned, childProvider.Name)); } if (!oldNode.Equals(newNode)) { // If the current provider does not contain any nodes but one child provider // ie. _siteMapNode == oldNode // the oldNode needs to be removed from Url table and the new node will be added. if (_siteMapNode.Equals(oldNode)) { UrlTable.Remove(oldNode.Url); KeyTable.Remove(oldNode.Key); UrlTable.Add(newNode.Url, newNode); KeyTable.Add(newNode.Key, newNode); _siteMapNode = newNode; } // First find the parent node SiteMapNode parent = (SiteMapNode)ParentNodeTable[oldNode]; // parent is null when the provider does not contain any static nodes, ie. // it only contains definition to include one child provider. if (parent != null) { // Update the child nodes table SiteMapNodeCollection list = (SiteMapNodeCollection)ChildNodeCollectionTable[parent]; // Add the newNode to where the oldNode is within parent node's collection. int index = list.IndexOf(oldNode); if (index != -1) { list.Remove(oldNode); list.Insert(index, newNode); } else { list.Add(newNode); } // Update the parent table ParentNodeTable[newNode] = parent; ParentNodeTable.Remove(oldNode); // Update the Url table UrlTable.Remove(oldNode.Url); KeyTable.Remove(oldNode.Key); UrlTable.Add(newNode.Url, newNode); KeyTable.Add(newNode.Key, newNode); } else { // Notify the parent provider to update its child provider collection. XmlSiteMapProvider provider = ParentProvider as XmlSiteMapProvider; if (provider != null) { provider.EnsureChildSiteMapProviderUpToDate(this); } } // Update provider nodes; ChildProviderTable[childProvider] = newNode; _childProviderList = null; } } } } // Returns sitemap node; Search recursively in child providers if not found. public override SiteMapNode FindSiteMapNode(string rawUrl) { SiteMapNode node = base.FindSiteMapNode(rawUrl); if (node == null) { foreach(SiteMapProvider provider in ChildProviderList) { // First make sure the child provider is up-to-date. EnsureChildSiteMapProviderUpToDate(provider); node = provider.FindSiteMapNode(rawUrl); if (node != null) { return node; } } } return node; } // Returns sitemap node; Search recursively in child providers if not found. public override SiteMapNode FindSiteMapNodeFromKey(string key) { SiteMapNode node = base.FindSiteMapNodeFromKey(key); if (node == null) { foreach (SiteMapProvider provider in ChildProviderList) { // First make sure the child provider is up-to-date. EnsureChildSiteMapProviderUpToDate(provider); node = provider.FindSiteMapNodeFromKey(key); if (node != null) { return node; } } } return node; } private XmlDocument GetConfigDocument() { if (_document != null) return _document; if (!_initialized) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_Not_Initialized)); } // Do the error checking here if (_virtualPath == null) { throw new ArgumentException( SR.GetString(SR.XmlSiteMapProvider_missing_siteMapFile, _siteMapFileAttribute)); } if (!_virtualPath.Extension.Equals(_xmlSiteMapFileExtension, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_Invalid_Extension, _virtualPath)); } _normalizedVirtualPath = _virtualPath.CombineWithAppRoot(); _normalizedVirtualPath.FailIfNotWithinAppRoot(); // Make sure the file exists CheckSiteMapFileExists(); _parentSiteMapFileCollection = new StringCollection(); XmlSiteMapProvider xmlParentProvider = ParentProvider as XmlSiteMapProvider; if (xmlParentProvider != null && xmlParentProvider._parentSiteMapFileCollection != null) { if (xmlParentProvider._parentSiteMapFileCollection.Contains(_normalizedVirtualPath.VirtualPathString)) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_FileName_already_in_use, _virtualPath)); } // Copy the sitemapfiles in used from parent provider to current provider. foreach (string filename in xmlParentProvider._parentSiteMapFileCollection) { _parentSiteMapFileCollection.Add(filename); } } // Add current sitemap file to the collection _parentSiteMapFileCollection.Add(_normalizedVirtualPath.VirtualPathString); _filename = HostingEnvironment.MapPathInternal(_normalizedVirtualPath); if (!String.IsNullOrEmpty(_filename)) { _handler = new FileChangeEventHandler(this.OnConfigFileChange); HttpRuntime.FileChangesMonitor.StartMonitoringFile(_filename, _handler); ResourceKey = (new FileInfo(_filename)).Name; } _document = new ConfigXmlDocument(); return _document; } private SiteMapNode GetNodeFromProvider(string providerName) { SiteMapProvider provider = GetProviderFromName(providerName); SiteMapNode node = null; // Check infinite recursive sitemap files if (provider is XmlSiteMapProvider) { XmlSiteMapProvider xmlProvider = (XmlSiteMapProvider)provider; StringCollection parentSiteMapFileCollection = new StringCollection(); if (_parentSiteMapFileCollection != null) { foreach (string filename in _parentSiteMapFileCollection) { parentSiteMapFileCollection.Add(filename); } } // Make sure the provider is initialized before adding to the collection. xmlProvider.BuildSiteMap(); parentSiteMapFileCollection.Add(_normalizedVirtualPath.VirtualPathString); if (parentSiteMapFileCollection.Contains(VirtualPath.GetVirtualPathString(xmlProvider._normalizedVirtualPath))) { throw new InvalidOperationException(SR.GetString(SR.XmlSiteMapProvider_FileName_already_in_use, xmlProvider._virtualPath)); } xmlProvider._parentSiteMapFileCollection = parentSiteMapFileCollection; } node = provider.GetRootNodeCore(); if (node == null) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_invalid_GetRootNodeCore, ((ProviderBase)provider).Name)); } ChildProviderTable.Add(provider, node); _childProviderList = null; provider.ParentProvider = this; return node; } private SiteMapNode GetNodeFromSiteMapFile(XmlNode xmlNode, VirtualPath siteMapFile) { SiteMapNode node = null; // For external sitemap files, its secuity setting is inherited from parent provider bool secuityTrimmingEnabled = SecurityTrimmingEnabled; HandlerBase.GetAndRemoveBooleanAttribute(xmlNode, _securityTrimmingEnabledAttrName, ref secuityTrimmingEnabled); // No other attributes or non-comment nodes are allowed on a siteMapFile node HandlerBase.CheckForUnrecognizedAttributes(xmlNode); HandlerBase.CheckForNonCommentChildNodes(xmlNode); XmlSiteMapProvider childProvider = new XmlSiteMapProvider(); // siteMapFile was relative to the sitemap file where this xmlnode is defined, make it an application path. siteMapFile = _normalizedVirtualPath.Parent.Combine(siteMapFile); childProvider.ParentProvider = this; childProvider.Initialize(siteMapFile, secuityTrimmingEnabled); childProvider.BuildSiteMap(); node = childProvider._siteMapNode; ChildProviderTable.Add(childProvider, node); _childProviderList = null; return node; } private void HandleResourceAttribute(XmlNode xmlNode, ref NameValueCollection collection, string attrName, ref string text, bool allowImplicitResource) { if (String.IsNullOrEmpty(text)) { return; } string resourceKey = null; string temp = text.TrimStart(new char[] { ' ' }); if (temp != null && temp.Length > _resourcePrefixLength) { if (temp.ToLower(CultureInfo.InvariantCulture).StartsWith(_resourcePrefix, StringComparison.Ordinal)) { if (!allowImplicitResource) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_multiple_resource_definition, attrName), xmlNode); } resourceKey = temp.Substring(_resourcePrefixLength + 1); if (resourceKey.Length == 0) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_resourceKey_cannot_be_empty), xmlNode); } // Retrieve className from attribute string className = null; string key = null; int index = resourceKey.IndexOf(_resourceKeySeparator); if (index == -1) { throw new ConfigurationErrorsException( SR.GetString( SR.XmlSiteMapProvider_invalid_resource_key, resourceKey), xmlNode); } className = resourceKey.Substring(0, index); key = resourceKey.Substring(index + 1); // Retrieve resource key and default value from attribute int defaultIndex = key.IndexOf(_resourceKeySeparator); if (defaultIndex != -1) { text = key.Substring(defaultIndex + 1); key = key.Substring(0, defaultIndex); } else { text = null; } if (collection == null) { collection = new NameValueCollection(); } collection.Add(attrName, className.Trim()); collection.Add(attrName, key.Trim()); } } } private SiteMapNode GetNodeFromXmlNode(XmlNode xmlNode, Queue queue) { SiteMapNode node = null; // static nodes string title = null, url = null, description = null, roles = null, resourceKey = null; // Url attribute is NOT required for a xml node. HandlerBase.GetAndRemoveStringAttribute(xmlNode, "url", ref url); HandlerBase.GetAndRemoveStringAttribute(xmlNode, "title", ref title); HandlerBase.GetAndRemoveStringAttribute(xmlNode, "description", ref description); HandlerBase.GetAndRemoveStringAttribute(xmlNode, "roles", ref roles); HandlerBase.GetAndRemoveStringAttribute(xmlNode, "resourceKey", ref resourceKey); // Do not add the resourceKey if the resource is not valid. if (!String.IsNullOrEmpty(resourceKey) && !ValidateResource(ResourceKey, resourceKey + ".title")) { resourceKey = null; } HandlerBase.CheckForbiddenAttribute(xmlNode, _securityTrimmingEnabledAttrName); NameValueCollection resourceKeyCollection = null; bool allowImplicitResourceAttribute = String.IsNullOrEmpty(resourceKey); HandleResourceAttribute(xmlNode, ref resourceKeyCollection, "title", ref title, allowImplicitResourceAttribute); HandleResourceAttribute(xmlNode, ref resourceKeyCollection, "description", ref description, allowImplicitResourceAttribute); ArrayList roleList = new ArrayList(); if (roles != null) { int foundIndex = roles.IndexOf('?'); if (foundIndex != -1) { throw new ConfigurationErrorsException( SR.GetString(SR.Auth_rule_names_cant_contain_char, roles[foundIndex].ToString(CultureInfo.InvariantCulture)), xmlNode); } foreach (string role in roles.Split(_seperators)) { string trimmedRole = role.Trim(); if (trimmedRole.Length > 0) { roleList.Add(trimmedRole); } } } roleList = ArrayList.ReadOnly(roleList); String key = null; // Make urls absolute. if (!String.IsNullOrEmpty(url)) { // URL needs to be trimmed. VSWhidbey 411041 url = url.Trim(); if (!UrlPath.IsAbsolutePhysicalPath(url)) { if (UrlPath.IsRelativeUrl(url)) { url = UrlPath.Combine(HttpRuntime.AppDomainAppVirtualPathString, url); } } // VSWhidbey 418056, Reject any suspicious or mal-formed Urls. string decodedUrl = HttpUtility.UrlDecode(url); if (!String.Equals(url, decodedUrl, StringComparison.Ordinal)) { throw new ConfigurationErrorsException( SR.GetString(SR.Property_Had_Malformed_Url, "url", url), xmlNode); } key = url.ToLowerInvariant(); } else { key = Guid.NewGuid().ToString(); } // attribute collection does not contain pre-defined properties like title, url, etc. ReadOnlyNameValueCollection attributeCollection = new ReadOnlyNameValueCollection(); attributeCollection.SetReadOnly(false); foreach (XmlAttribute attribute in xmlNode.Attributes) { string value = attribute.Value; HandleResourceAttribute(xmlNode, ref resourceKeyCollection, attribute.Name, ref value, allowImplicitResourceAttribute); attributeCollection[attribute.Name] = value; } attributeCollection.SetReadOnly(true); node = new SiteMapNode(this, key, url, title, description, roleList, attributeCollection, resourceKeyCollection, resourceKey); node.ReadOnly = true; foreach (XmlNode subNode in xmlNode.ChildNodes) { if (subNode.NodeType != XmlNodeType.Element) continue; queue.Enqueue(node); queue.Enqueue(subNode); } return node; } private SiteMapProvider GetProviderFromName(string providerName) { Debug.Assert(providerName != null); SiteMapProvider provider = SiteMap.Providers[providerName]; if (provider == null) { throw new ProviderException(SR.GetString(SR.Provider_Not_Found, providerName)); } return provider; } protected internal override SiteMapNode GetRootNodeCore() { BuildSiteMap(); return _siteMapNode; } public override void Initialize(string name, NameValueCollection attributes) { if (_initialized) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_Cannot_Be_Inited_Twice)); } if (attributes != null) { if (string.IsNullOrEmpty(attributes["description"])) { attributes.Remove("description"); attributes.Add("description", SR.GetString(SR.XmlSiteMapProvider_Description)); } string siteMapFile = null; ProviderUtil.GetAndRemoveStringAttribute(attributes, _siteMapFileAttribute, name, ref siteMapFile); _virtualPath = VirtualPath.CreateAllowNull(siteMapFile); } base.Initialize(name, attributes); if (attributes != null) { ProviderUtil.CheckUnrecognizedAttributes(attributes, name); } _initialized = true; } private void Initialize(VirtualPath virtualPath, bool secuityTrimmingEnabled) { NameValueCollection coll = new NameValueCollection(); coll.Add(_siteMapFileAttribute, virtualPath.VirtualPathString); coll.Add(_securityTrimmingEnabledAttrName, System.Web.UI.Util.GetStringFromBool(secuityTrimmingEnabled)); // Use the siteMapFile virtual path as the provider name Initialize(virtualPath.VirtualPathString, coll); } private void OnConfigFileChange(Object sender, FileChangeEvent e) { // Notifiy the parent for the change. XmlSiteMapProvider parentProvider = ParentProvider as XmlSiteMapProvider; if (parentProvider != null) { parentProvider.OnConfigFileChange(sender, e); } Clear(); } protected internal override void RemoveNode(SiteMapNode node) { if (node == null) { throw new ArgumentNullException("node"); } SiteMapProvider ownerProvider = node.Provider; if (ownerProvider != this) { // Only nodes defined in this provider tree can be removed. SiteMapProvider parentProvider = ownerProvider.ParentProvider; while (parentProvider != this) { if (parentProvider == null) { // Cannot remove nodes defined in other providers throw new InvalidOperationException(SR.GetString( SR.XmlSiteMapProvider_cannot_remove_node, node.ToString(), this.Name, ownerProvider.Name)); } parentProvider = parentProvider.ParentProvider; } } if (node.Equals(ownerProvider.GetRootNodeCore())) { throw new InvalidOperationException(SR.GetString(SR.SiteMapProvider_cannot_remove_root_node)); } if (ownerProvider != this) { // Remove node from the owner provider. ownerProvider.RemoveNode(node); } base.RemoveNode(node); } protected virtual void RemoveProvider(string providerName) { if (providerName == null) { throw new ArgumentNullException("providerName"); } lock (_lock) { SiteMapProvider provider = GetProviderFromName(providerName); SiteMapNode rootNode = (SiteMapNode)ChildProviderTable[provider]; if (rootNode == null) { throw new InvalidOperationException(SR.GetString(SR.XmlSiteMapProvider_cannot_find_provider, provider.Name, this.Name)); } provider.ParentProvider = null; ChildProviderTable.Remove(provider); _childProviderList = null; base.RemoveNode(rootNode); } } // VSWhidbey: 493981 Helper method to check if the valid resource type exists. // Note that this only returns false if the classKey cannot be found, regardless of resourceKey. private bool ValidateResource(string classKey, string resourceKey) { try { HttpContext.GetGlobalResourceObject(classKey, resourceKey); } catch (MissingManifestResourceException) { return false; } return true; } private class ReadOnlyNameValueCollection : NameValueCollection { public ReadOnlyNameValueCollection() { IsReadOnly = true; } internal void SetReadOnly(bool isReadonly) { IsReadOnly = isReadonly; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* * XmlSiteMapProvider class definition * * Copyright (c) 2002 Microsoft Corporation */ namespace System.Web { using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Design; using System.Configuration; using System.Configuration.Provider; using System.Globalization; using System.IO; using System.Resources; using System.Security; using System.Security.Permissions; using System.Web.Compilation; using System.Web.Configuration; using System.Web.Hosting; using System.Web.UI; using System.Web.Util; using System.Xml; // XmlMapProvider that generates sitemap tree from xml files [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class XmlSiteMapProvider : StaticSiteMapProvider, IDisposable { private string _filename; private VirtualPath _virtualPath; private VirtualPath _normalizedVirtualPath; private SiteMapNode _siteMapNode; private XmlDocument _document; private bool _initialized; private FileChangeEventHandler _handler; private StringCollection _parentSiteMapFileCollection; private const string _providerAttribute = "provider"; private const string _siteMapFileAttribute = "siteMapFile"; private const string _siteMapNodeName = "siteMapNode"; private const string _xmlSiteMapFileExtension = ".sitemap"; private const string _resourcePrefix = "$resources:"; private const int _resourcePrefixLength = 10; private const char _resourceKeySeparator = ','; private static readonly char[] _seperators = new char[] { ';', ',' }; private ArrayList _childProviderList; // table containing mappings from child providers to their root nodes. private Hashtable _childProviderTable; public XmlSiteMapProvider() { } private ArrayList ChildProviderList { get { if (_childProviderList == null) { lock (_lock) { if (_childProviderList == null) { _childProviderList = ArrayList.ReadOnly(new ArrayList(ChildProviderTable.Keys)); } } } return _childProviderList; } } private Hashtable ChildProviderTable { get { if (_childProviderTable == null) { lock (_lock) { if (_childProviderTable == null) { _childProviderTable = new Hashtable(); } } } return _childProviderTable; } } public override SiteMapNode RootNode { get { BuildSiteMap(); return ReturnNodeIfAccessible(_siteMapNode); } } protected internal override void AddNode(SiteMapNode node, SiteMapNode parentNode) { if (node == null) { throw new ArgumentNullException("node"); } if (parentNode == null) { throw new ArgumentNullException("parentNode"); } SiteMapProvider ownerProvider = node.Provider; SiteMapProvider parentOwnerProvider = parentNode.Provider; if (ownerProvider != this) { throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, node.ToString()), "node"); } if (parentOwnerProvider != this) { throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, parentNode.ToString()), "parentNode"); } lock (_lock) { // First remove it from its current location. RemoveNode(node); AddNodeInternal(node, parentNode, null); } } private void AddNodeInternal(SiteMapNode node, SiteMapNode parentNode, XmlNode xmlNode) { lock (_lock) { String url = node.Url; String key = node.Key; bool isValidUrl = false; // Only add the node to the url table if it's a static node. if (!String.IsNullOrEmpty(url)) { if (UrlTable[url] != null) { if (xmlNode != null) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Url, url), xmlNode); } else { throw new InvalidOperationException(SR.GetString( SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Url, url)); } } isValidUrl = true; } if (KeyTable.Contains(key)) { if (xmlNode != null) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Key, key), xmlNode); } else { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Key, key)); } } if (isValidUrl) { UrlTable[url] = node; } KeyTable[key] = node; // Add the new node into parentNode collection if (parentNode != null) { ParentNodeTable[node] = parentNode; if (ChildNodeCollectionTable[parentNode] == null) { ChildNodeCollectionTable[parentNode] = new SiteMapNodeCollection(); } ((SiteMapNodeCollection)ChildNodeCollectionTable[parentNode]).Add(node); } } } protected virtual void AddProvider(string providerName, SiteMapNode parentNode) { if (parentNode == null) { throw new ArgumentNullException("parentNode"); } if (parentNode.Provider != this) { throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, parentNode.ToString()), "parentNode"); } SiteMapNode node = GetNodeFromProvider(providerName); AddNodeInternal(node, parentNode, null); } public override SiteMapNode BuildSiteMap() { SiteMapNode tempNode = _siteMapNode; // If siteMap is already constructed, simply returns it. // Child providers will only be updated when the parent providers need to access them. if (tempNode != null) { return tempNode; } XmlDocument document = GetConfigDocument(); lock (_lock) { if (_siteMapNode != null) { return _siteMapNode; } Clear(); // Need to check if the sitemap file exists before opening it. CheckSiteMapFileExists(); try { using (Stream stream = _normalizedVirtualPath.OpenFile()) { XmlReader reader = new XmlTextReader(stream); document.Load(reader); } } catch (XmlException e) { string sourceFile = _virtualPath.VirtualPathString; string physicalDir = _normalizedVirtualPath.MapPathInternal(); if (physicalDir != null && HttpRuntime.HasPathDiscoveryPermission(physicalDir)) { sourceFile = physicalDir; } throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Error_loading_Config_file, _virtualPath, e.Message), e, sourceFile, e.LineNumber); } catch (Exception e) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Error_loading_Config_file, _virtualPath, e.Message), e); } XmlNode node = null; foreach (XmlNode siteMapMode in document.ChildNodes) { if (String.Equals(siteMapMode.Name, "siteMap", StringComparison.Ordinal)) { node = siteMapMode; break; } } if (node == null) throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Top_Element_Must_Be_SiteMap), document); bool enableLocalization = false; HandlerBase.GetAndRemoveBooleanAttribute(node, "enableLocalization", ref enableLocalization); EnableLocalization = enableLocalization; XmlNode topElement = null; foreach (XmlNode subNode in node.ChildNodes) { if (subNode.NodeType == XmlNodeType.Element) { if (!_siteMapNodeName.Equals(subNode.Name)) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Only_SiteMapNode_Allowed), subNode); } if (topElement != null) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Only_One_SiteMapNode_Required_At_Top), subNode); } topElement = subNode; } } if (topElement == null) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Only_One_SiteMapNode_Required_At_Top), node); } Queue queue = new Queue(50); // The parentnode of the top node does not exist, // simply add a null to satisfy the ConvertFromXmlNode condition. queue.Enqueue(null); queue.Enqueue(topElement); _siteMapNode = ConvertFromXmlNode(queue); return _siteMapNode; } } private void CheckSiteMapFileExists() { if (!System.Web.UI.Util.VirtualFileExistsWithAssert(_normalizedVirtualPath)) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_FileName_does_not_exist, _virtualPath)); } } protected override void Clear() { lock (_lock) { ChildProviderTable.Clear(); _siteMapNode = null; _childProviderList = null; base.Clear(); } } // helper method to convert an XmlNode to a SiteMapNode private SiteMapNode ConvertFromXmlNode(Queue queue) { SiteMapNode rootNode = null; while (true) { if (queue.Count == 0) { return rootNode; } SiteMapNode parentNode = (SiteMapNode)queue.Dequeue(); XmlNode xmlNode = (XmlNode)queue.Dequeue(); SiteMapNode node = null; if (!_siteMapNodeName.Equals(xmlNode.Name)) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_Only_SiteMapNode_Allowed), xmlNode); } string providerName = null; HandlerBase.GetAndRemoveNonEmptyStringAttribute(xmlNode, _providerAttribute, ref providerName); // If the siteMapNode references another provider if (providerName != null) { node = GetNodeFromProvider(providerName); // No other attributes or child nodes are allowed on a provider node. HandlerBase.CheckForUnrecognizedAttributes(xmlNode); HandlerBase.CheckForNonCommentChildNodes(xmlNode); } else { string siteMapFile = null; HandlerBase.GetAndRemoveNonEmptyStringAttribute(xmlNode, _siteMapFileAttribute, ref siteMapFile); if (siteMapFile != null) { node = GetNodeFromSiteMapFile(xmlNode, VirtualPath.Create(siteMapFile)); } else { node = GetNodeFromXmlNode(xmlNode, queue); } } AddNodeInternal(node, parentNode, xmlNode); if (rootNode == null) { rootNode = node; } } } protected virtual void Dispose(bool disposing) { if (_handler != null) { Debug.Assert(_filename != null); HttpRuntime.FileChangesMonitor.StopMonitoringFile(_filename, _handler); } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void EnsureChildSiteMapProviderUpToDate(SiteMapProvider childProvider) { SiteMapNode oldNode = (SiteMapNode)ChildProviderTable[childProvider]; SiteMapNode newNode = childProvider.GetRootNodeCore(); if (newNode == null) { throw new ProviderException(SR.GetString(SR.XmlSiteMapProvider_invalid_sitemapnode_returned, childProvider.Name)); } // child providers have been updated. if (!oldNode.Equals(newNode)) { // If the child provider table has been updated, simply return null. // This will happen when the current provider's sitemap file is changed or Clear() is called; if (oldNode == null) { return; } lock (_lock) { oldNode = (SiteMapNode)ChildProviderTable[childProvider]; // If the child provider table has been updated, simply return null. See above. if (oldNode == null) { return; } newNode = childProvider.GetRootNodeCore(); if (newNode == null) { throw new ProviderException(SR.GetString(SR.XmlSiteMapProvider_invalid_sitemapnode_returned, childProvider.Name)); } if (!oldNode.Equals(newNode)) { // If the current provider does not contain any nodes but one child provider // ie. _siteMapNode == oldNode // the oldNode needs to be removed from Url table and the new node will be added. if (_siteMapNode.Equals(oldNode)) { UrlTable.Remove(oldNode.Url); KeyTable.Remove(oldNode.Key); UrlTable.Add(newNode.Url, newNode); KeyTable.Add(newNode.Key, newNode); _siteMapNode = newNode; } // First find the parent node SiteMapNode parent = (SiteMapNode)ParentNodeTable[oldNode]; // parent is null when the provider does not contain any static nodes, ie. // it only contains definition to include one child provider. if (parent != null) { // Update the child nodes table SiteMapNodeCollection list = (SiteMapNodeCollection)ChildNodeCollectionTable[parent]; // Add the newNode to where the oldNode is within parent node's collection. int index = list.IndexOf(oldNode); if (index != -1) { list.Remove(oldNode); list.Insert(index, newNode); } else { list.Add(newNode); } // Update the parent table ParentNodeTable[newNode] = parent; ParentNodeTable.Remove(oldNode); // Update the Url table UrlTable.Remove(oldNode.Url); KeyTable.Remove(oldNode.Key); UrlTable.Add(newNode.Url, newNode); KeyTable.Add(newNode.Key, newNode); } else { // Notify the parent provider to update its child provider collection. XmlSiteMapProvider provider = ParentProvider as XmlSiteMapProvider; if (provider != null) { provider.EnsureChildSiteMapProviderUpToDate(this); } } // Update provider nodes; ChildProviderTable[childProvider] = newNode; _childProviderList = null; } } } } // Returns sitemap node; Search recursively in child providers if not found. public override SiteMapNode FindSiteMapNode(string rawUrl) { SiteMapNode node = base.FindSiteMapNode(rawUrl); if (node == null) { foreach(SiteMapProvider provider in ChildProviderList) { // First make sure the child provider is up-to-date. EnsureChildSiteMapProviderUpToDate(provider); node = provider.FindSiteMapNode(rawUrl); if (node != null) { return node; } } } return node; } // Returns sitemap node; Search recursively in child providers if not found. public override SiteMapNode FindSiteMapNodeFromKey(string key) { SiteMapNode node = base.FindSiteMapNodeFromKey(key); if (node == null) { foreach (SiteMapProvider provider in ChildProviderList) { // First make sure the child provider is up-to-date. EnsureChildSiteMapProviderUpToDate(provider); node = provider.FindSiteMapNodeFromKey(key); if (node != null) { return node; } } } return node; } private XmlDocument GetConfigDocument() { if (_document != null) return _document; if (!_initialized) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_Not_Initialized)); } // Do the error checking here if (_virtualPath == null) { throw new ArgumentException( SR.GetString(SR.XmlSiteMapProvider_missing_siteMapFile, _siteMapFileAttribute)); } if (!_virtualPath.Extension.Equals(_xmlSiteMapFileExtension, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_Invalid_Extension, _virtualPath)); } _normalizedVirtualPath = _virtualPath.CombineWithAppRoot(); _normalizedVirtualPath.FailIfNotWithinAppRoot(); // Make sure the file exists CheckSiteMapFileExists(); _parentSiteMapFileCollection = new StringCollection(); XmlSiteMapProvider xmlParentProvider = ParentProvider as XmlSiteMapProvider; if (xmlParentProvider != null && xmlParentProvider._parentSiteMapFileCollection != null) { if (xmlParentProvider._parentSiteMapFileCollection.Contains(_normalizedVirtualPath.VirtualPathString)) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_FileName_already_in_use, _virtualPath)); } // Copy the sitemapfiles in used from parent provider to current provider. foreach (string filename in xmlParentProvider._parentSiteMapFileCollection) { _parentSiteMapFileCollection.Add(filename); } } // Add current sitemap file to the collection _parentSiteMapFileCollection.Add(_normalizedVirtualPath.VirtualPathString); _filename = HostingEnvironment.MapPathInternal(_normalizedVirtualPath); if (!String.IsNullOrEmpty(_filename)) { _handler = new FileChangeEventHandler(this.OnConfigFileChange); HttpRuntime.FileChangesMonitor.StartMonitoringFile(_filename, _handler); ResourceKey = (new FileInfo(_filename)).Name; } _document = new ConfigXmlDocument(); return _document; } private SiteMapNode GetNodeFromProvider(string providerName) { SiteMapProvider provider = GetProviderFromName(providerName); SiteMapNode node = null; // Check infinite recursive sitemap files if (provider is XmlSiteMapProvider) { XmlSiteMapProvider xmlProvider = (XmlSiteMapProvider)provider; StringCollection parentSiteMapFileCollection = new StringCollection(); if (_parentSiteMapFileCollection != null) { foreach (string filename in _parentSiteMapFileCollection) { parentSiteMapFileCollection.Add(filename); } } // Make sure the provider is initialized before adding to the collection. xmlProvider.BuildSiteMap(); parentSiteMapFileCollection.Add(_normalizedVirtualPath.VirtualPathString); if (parentSiteMapFileCollection.Contains(VirtualPath.GetVirtualPathString(xmlProvider._normalizedVirtualPath))) { throw new InvalidOperationException(SR.GetString(SR.XmlSiteMapProvider_FileName_already_in_use, xmlProvider._virtualPath)); } xmlProvider._parentSiteMapFileCollection = parentSiteMapFileCollection; } node = provider.GetRootNodeCore(); if (node == null) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_invalid_GetRootNodeCore, ((ProviderBase)provider).Name)); } ChildProviderTable.Add(provider, node); _childProviderList = null; provider.ParentProvider = this; return node; } private SiteMapNode GetNodeFromSiteMapFile(XmlNode xmlNode, VirtualPath siteMapFile) { SiteMapNode node = null; // For external sitemap files, its secuity setting is inherited from parent provider bool secuityTrimmingEnabled = SecurityTrimmingEnabled; HandlerBase.GetAndRemoveBooleanAttribute(xmlNode, _securityTrimmingEnabledAttrName, ref secuityTrimmingEnabled); // No other attributes or non-comment nodes are allowed on a siteMapFile node HandlerBase.CheckForUnrecognizedAttributes(xmlNode); HandlerBase.CheckForNonCommentChildNodes(xmlNode); XmlSiteMapProvider childProvider = new XmlSiteMapProvider(); // siteMapFile was relative to the sitemap file where this xmlnode is defined, make it an application path. siteMapFile = _normalizedVirtualPath.Parent.Combine(siteMapFile); childProvider.ParentProvider = this; childProvider.Initialize(siteMapFile, secuityTrimmingEnabled); childProvider.BuildSiteMap(); node = childProvider._siteMapNode; ChildProviderTable.Add(childProvider, node); _childProviderList = null; return node; } private void HandleResourceAttribute(XmlNode xmlNode, ref NameValueCollection collection, string attrName, ref string text, bool allowImplicitResource) { if (String.IsNullOrEmpty(text)) { return; } string resourceKey = null; string temp = text.TrimStart(new char[] { ' ' }); if (temp != null && temp.Length > _resourcePrefixLength) { if (temp.ToLower(CultureInfo.InvariantCulture).StartsWith(_resourcePrefix, StringComparison.Ordinal)) { if (!allowImplicitResource) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_multiple_resource_definition, attrName), xmlNode); } resourceKey = temp.Substring(_resourcePrefixLength + 1); if (resourceKey.Length == 0) { throw new ConfigurationErrorsException( SR.GetString(SR.XmlSiteMapProvider_resourceKey_cannot_be_empty), xmlNode); } // Retrieve className from attribute string className = null; string key = null; int index = resourceKey.IndexOf(_resourceKeySeparator); if (index == -1) { throw new ConfigurationErrorsException( SR.GetString( SR.XmlSiteMapProvider_invalid_resource_key, resourceKey), xmlNode); } className = resourceKey.Substring(0, index); key = resourceKey.Substring(index + 1); // Retrieve resource key and default value from attribute int defaultIndex = key.IndexOf(_resourceKeySeparator); if (defaultIndex != -1) { text = key.Substring(defaultIndex + 1); key = key.Substring(0, defaultIndex); } else { text = null; } if (collection == null) { collection = new NameValueCollection(); } collection.Add(attrName, className.Trim()); collection.Add(attrName, key.Trim()); } } } private SiteMapNode GetNodeFromXmlNode(XmlNode xmlNode, Queue queue) { SiteMapNode node = null; // static nodes string title = null, url = null, description = null, roles = null, resourceKey = null; // Url attribute is NOT required for a xml node. HandlerBase.GetAndRemoveStringAttribute(xmlNode, "url", ref url); HandlerBase.GetAndRemoveStringAttribute(xmlNode, "title", ref title); HandlerBase.GetAndRemoveStringAttribute(xmlNode, "description", ref description); HandlerBase.GetAndRemoveStringAttribute(xmlNode, "roles", ref roles); HandlerBase.GetAndRemoveStringAttribute(xmlNode, "resourceKey", ref resourceKey); // Do not add the resourceKey if the resource is not valid. if (!String.IsNullOrEmpty(resourceKey) && !ValidateResource(ResourceKey, resourceKey + ".title")) { resourceKey = null; } HandlerBase.CheckForbiddenAttribute(xmlNode, _securityTrimmingEnabledAttrName); NameValueCollection resourceKeyCollection = null; bool allowImplicitResourceAttribute = String.IsNullOrEmpty(resourceKey); HandleResourceAttribute(xmlNode, ref resourceKeyCollection, "title", ref title, allowImplicitResourceAttribute); HandleResourceAttribute(xmlNode, ref resourceKeyCollection, "description", ref description, allowImplicitResourceAttribute); ArrayList roleList = new ArrayList(); if (roles != null) { int foundIndex = roles.IndexOf('?'); if (foundIndex != -1) { throw new ConfigurationErrorsException( SR.GetString(SR.Auth_rule_names_cant_contain_char, roles[foundIndex].ToString(CultureInfo.InvariantCulture)), xmlNode); } foreach (string role in roles.Split(_seperators)) { string trimmedRole = role.Trim(); if (trimmedRole.Length > 0) { roleList.Add(trimmedRole); } } } roleList = ArrayList.ReadOnly(roleList); String key = null; // Make urls absolute. if (!String.IsNullOrEmpty(url)) { // URL needs to be trimmed. VSWhidbey 411041 url = url.Trim(); if (!UrlPath.IsAbsolutePhysicalPath(url)) { if (UrlPath.IsRelativeUrl(url)) { url = UrlPath.Combine(HttpRuntime.AppDomainAppVirtualPathString, url); } } // VSWhidbey 418056, Reject any suspicious or mal-formed Urls. string decodedUrl = HttpUtility.UrlDecode(url); if (!String.Equals(url, decodedUrl, StringComparison.Ordinal)) { throw new ConfigurationErrorsException( SR.GetString(SR.Property_Had_Malformed_Url, "url", url), xmlNode); } key = url.ToLowerInvariant(); } else { key = Guid.NewGuid().ToString(); } // attribute collection does not contain pre-defined properties like title, url, etc. ReadOnlyNameValueCollection attributeCollection = new ReadOnlyNameValueCollection(); attributeCollection.SetReadOnly(false); foreach (XmlAttribute attribute in xmlNode.Attributes) { string value = attribute.Value; HandleResourceAttribute(xmlNode, ref resourceKeyCollection, attribute.Name, ref value, allowImplicitResourceAttribute); attributeCollection[attribute.Name] = value; } attributeCollection.SetReadOnly(true); node = new SiteMapNode(this, key, url, title, description, roleList, attributeCollection, resourceKeyCollection, resourceKey); node.ReadOnly = true; foreach (XmlNode subNode in xmlNode.ChildNodes) { if (subNode.NodeType != XmlNodeType.Element) continue; queue.Enqueue(node); queue.Enqueue(subNode); } return node; } private SiteMapProvider GetProviderFromName(string providerName) { Debug.Assert(providerName != null); SiteMapProvider provider = SiteMap.Providers[providerName]; if (provider == null) { throw new ProviderException(SR.GetString(SR.Provider_Not_Found, providerName)); } return provider; } protected internal override SiteMapNode GetRootNodeCore() { BuildSiteMap(); return _siteMapNode; } public override void Initialize(string name, NameValueCollection attributes) { if (_initialized) { throw new InvalidOperationException( SR.GetString(SR.XmlSiteMapProvider_Cannot_Be_Inited_Twice)); } if (attributes != null) { if (string.IsNullOrEmpty(attributes["description"])) { attributes.Remove("description"); attributes.Add("description", SR.GetString(SR.XmlSiteMapProvider_Description)); } string siteMapFile = null; ProviderUtil.GetAndRemoveStringAttribute(attributes, _siteMapFileAttribute, name, ref siteMapFile); _virtualPath = VirtualPath.CreateAllowNull(siteMapFile); } base.Initialize(name, attributes); if (attributes != null) { ProviderUtil.CheckUnrecognizedAttributes(attributes, name); } _initialized = true; } private void Initialize(VirtualPath virtualPath, bool secuityTrimmingEnabled) { NameValueCollection coll = new NameValueCollection(); coll.Add(_siteMapFileAttribute, virtualPath.VirtualPathString); coll.Add(_securityTrimmingEnabledAttrName, System.Web.UI.Util.GetStringFromBool(secuityTrimmingEnabled)); // Use the siteMapFile virtual path as the provider name Initialize(virtualPath.VirtualPathString, coll); } private void OnConfigFileChange(Object sender, FileChangeEvent e) { // Notifiy the parent for the change. XmlSiteMapProvider parentProvider = ParentProvider as XmlSiteMapProvider; if (parentProvider != null) { parentProvider.OnConfigFileChange(sender, e); } Clear(); } protected internal override void RemoveNode(SiteMapNode node) { if (node == null) { throw new ArgumentNullException("node"); } SiteMapProvider ownerProvider = node.Provider; if (ownerProvider != this) { // Only nodes defined in this provider tree can be removed. SiteMapProvider parentProvider = ownerProvider.ParentProvider; while (parentProvider != this) { if (parentProvider == null) { // Cannot remove nodes defined in other providers throw new InvalidOperationException(SR.GetString( SR.XmlSiteMapProvider_cannot_remove_node, node.ToString(), this.Name, ownerProvider.Name)); } parentProvider = parentProvider.ParentProvider; } } if (node.Equals(ownerProvider.GetRootNodeCore())) { throw new InvalidOperationException(SR.GetString(SR.SiteMapProvider_cannot_remove_root_node)); } if (ownerProvider != this) { // Remove node from the owner provider. ownerProvider.RemoveNode(node); } base.RemoveNode(node); } protected virtual void RemoveProvider(string providerName) { if (providerName == null) { throw new ArgumentNullException("providerName"); } lock (_lock) { SiteMapProvider provider = GetProviderFromName(providerName); SiteMapNode rootNode = (SiteMapNode)ChildProviderTable[provider]; if (rootNode == null) { throw new InvalidOperationException(SR.GetString(SR.XmlSiteMapProvider_cannot_find_provider, provider.Name, this.Name)); } provider.ParentProvider = null; ChildProviderTable.Remove(provider); _childProviderList = null; base.RemoveNode(rootNode); } } // VSWhidbey: 493981 Helper method to check if the valid resource type exists. // Note that this only returns false if the classKey cannot be found, regardless of resourceKey. private bool ValidateResource(string classKey, string resourceKey) { try { HttpContext.GetGlobalResourceObject(classKey, resourceKey); } catch (MissingManifestResourceException) { return false; } return true; } private class ReadOnlyNameValueCollection : NameValueCollection { public ReadOnlyNameValueCollection() { IsReadOnly = true; } internal void SetReadOnly(bool isReadonly) { IsReadOnly = isReadonly; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ObjectDataSourceDisposingEventArgs.cs
- ColorConverter.cs
- IChannel.cs
- StrongBox.cs
- StylusCaptureWithinProperty.cs
- DynamicMethod.cs
- SimpleType.cs
- NavigationPropertyEmitter.cs
- MeasurementDCInfo.cs
- SystemMulticastIPAddressInformation.cs
- DateTimeEditor.cs
- KeyPullup.cs
- _TransmitFileOverlappedAsyncResult.cs
- GridViewRowPresenter.cs
- ImageMap.cs
- FileRecordSequence.cs
- ClusterSafeNativeMethods.cs
- DropDownHolder.cs
- IsolatedStorageFileStream.cs
- TrackingProfileManager.cs
- ReflectionHelper.cs
- EventDescriptorCollection.cs
- MissingManifestResourceException.cs
- QilExpression.cs
- SiteMap.cs
- PropertyValue.cs
- BindingExpressionBase.cs
- DynamicVirtualDiscoSearcher.cs
- SurrogateEncoder.cs
- TrailingSpaceComparer.cs
- SQLByte.cs
- _HTTPDateParse.cs
- InputBinding.cs
- IntSecurity.cs
- KnownTypes.cs
- Visual3D.cs
- File.cs
- CodeDirectoryCompiler.cs
- BuildProviderAppliesToAttribute.cs
- CompilerLocalReference.cs
- ItemsControl.cs
- Baml2006Reader.cs
- RTLAwareMessageBox.cs
- HeaderCollection.cs
- XslVisitor.cs
- EventRecord.cs
- SafeHandles.cs
- XamlBrushSerializer.cs
- SchemaTypeEmitter.cs
- DataKey.cs
- WebPartDisplayMode.cs
- ISessionStateStore.cs
- JsonObjectDataContract.cs
- BamlRecords.cs
- PnrpPeerResolverBindingElement.cs
- HttpChannelHelper.cs
- AssertFilter.cs
- LabelLiteral.cs
- DbDeleteCommandTree.cs
- configsystem.cs
- HttpTransportSecurityElement.cs
- DbConnectionStringCommon.cs
- ColumnTypeConverter.cs
- TargetConverter.cs
- FileUpload.cs
- HttpFileCollection.cs
- BulletChrome.cs
- OleDbCommandBuilder.cs
- VariantWrapper.cs
- SimpleExpression.cs
- GradientBrush.cs
- InputReport.cs
- ReadOnlyCollectionBase.cs
- DataRow.cs
- ItemCheckEvent.cs
- DataGridViewColumnDesigner.cs
- SourceLineInfo.cs
- EdmFunctionAttribute.cs
- ProjectionCamera.cs
- Point3DCollectionValueSerializer.cs
- SqlDataSourceFilteringEventArgs.cs
- MapPathBasedVirtualPathProvider.cs
- PolyQuadraticBezierSegment.cs
- BrowserCapabilitiesCodeGenerator.cs
- RecordConverter.cs
- DispatcherOperation.cs
- CompositeCollection.cs
- ServicePointManager.cs
- TaiwanCalendar.cs
- GatewayDefinition.cs
- ComponentResourceKey.cs
- PermissionAttributes.cs
- DateTimeFormatInfo.cs
- BoundColumn.cs
- CellNormalizer.cs
- Fonts.cs
- FormClosedEvent.cs
- StrokeFIndices.cs
- RedBlackList.cs
- SEHException.cs