using System; using System.Collections.Generic; using System.Configuration; using System.Web; using System.Web.Hosting; using System.Web.Configuration; using System.Xml; using umbraco.BusinessLogic; using umbraco.IO; namespace umbraco { /// /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information from web.config appsettings /// public class GlobalSettings { #region Private static fields // CURRENT UMBRACO VERSION ID private static string _currentVersion = "4.5.2"; private static string _reservedUrlsCache; private static string _reservedPathsCache; private static StartsWithContainer _reservedList = new StartsWithContainer(); #endregion /// /// Initializes a new instance of the class. /// public GlobalSettings() { } /// /// Gets the reserved urls from web.config. /// /// The reserved urls. public static string ReservedUrls { get { if (HttpContext.Current != null) return ConfigurationManager.AppSettings["umbracoReservedUrls"]; return String.Empty; } } /// /// Gets the reserved paths from web.config /// /// The reserved paths. public static string ReservedPaths { get { if (HttpContext.Current != null) return ConfigurationManager.AppSettings["umbracoReservedPaths"]; return String.Empty; } } /// /// Gets the name of the content XML file. /// /// The content XML. public static string ContentXML { get { try { return ConfigurationManager.AppSettings["umbracoContentXML"]; } catch { return String.Empty; } } } /// /// Gets the path to the storage directory (/data by default). /// /// The storage directory. public static string StorageDirectory { get { try { return ConfigurationManager.AppSettings["umbracoStorageDirectory"]; } catch { return String.Empty; } } } /// /// Gets the path to umbraco's root directory (/umbraco by default). /// /// The path. public static string Path { get { try { return IOHelper.ResolveUrl(ConfigurationManager.AppSettings["umbracoPath"]); } catch { return String.Empty; } } } /// /// Gets the path to umbraco's client directory (/umbraco_client by default). /// This is a relative path to the Umbraco Path as it always must exist beside the 'umbraco' /// folder since the CSS paths to images depend on it. /// /// The path. public static string ClientPath { get { return Path + "/../umbraco_client"; } } /// /// Gets the database connection string /// /// The database connection string. public static string DbDSN { get { try { return ConfigurationManager.AppSettings["umbracoDbDSN"]; } catch { return String.Empty; } } set { if (DbDSN != value) { SaveSetting("umbracoDbDSN", value); } } } /// /// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance. /// /// The configuration status. public static string ConfigurationStatus { get { try { return ConfigurationManager.AppSettings["umbracoConfigurationStatus"]; } catch { return String.Empty; } } set { SaveSetting("umbracoConfigurationStatus", value); } } private static AspNetHostingPermissionLevel? m_ApplicationTrustLevel = null; public static AspNetHostingPermissionLevel ApplicationTrustLevel { get { if (!m_ApplicationTrustLevel.HasValue) { //set minimum m_ApplicationTrustLevel = AspNetHostingPermissionLevel.None; //determine maximum foreach (AspNetHostingPermissionLevel trustLevel in new AspNetHostingPermissionLevel[] { AspNetHostingPermissionLevel.Unrestricted, AspNetHostingPermissionLevel.High, AspNetHostingPermissionLevel.Medium, AspNetHostingPermissionLevel.Low, AspNetHostingPermissionLevel.Minimal }) { try { new AspNetHostingPermission(trustLevel).Demand(); m_ApplicationTrustLevel = trustLevel; break; //we've set the highest permission we can } catch (System.Security.SecurityException) { continue; } } } return m_ApplicationTrustLevel.Value; } } /// /// Forces umbraco to be medium trust compatible /// /// If true, umbraco will be medium-trust compatible, no matter what Permission level the server is on. public static bool UseMediumTrust { get { try { if (ApplicationTrustLevel == AspNetHostingPermissionLevel.High || ApplicationTrustLevel == AspNetHostingPermissionLevel.Unrestricted) return false; else return bool.Parse(ConfigurationManager.AppSettings["umbracoUseMediumTrust"]); } catch { return false; } } } /// /// Saves a setting into the configuration file. /// /// Key of the setting to be saved. /// Value of the setting to be saved. protected static void SaveSetting(string key, string value) { WebConfigurationFileMap webConfig = new WebConfigurationFileMap(); var vDirs = webConfig.VirtualDirectories; var vDir = FullpathToRoot; foreach (VirtualDirectoryMapping v in webConfig.VirtualDirectories) { if (v.IsAppRoot) { vDir = v.PhysicalDirectory; } } XmlDocument doc = new XmlDocument(); doc.Load(String.Concat(vDir, "web.config")); XmlNode root = doc.DocumentElement; XmlNode setting = doc.SelectSingleNode(String.Concat("//appSettings/add[@key='", key, "']")); setting.Attributes["value"].InnerText = value; doc.Save(String.Concat(vDir, "web.config")); ConfigurationManager.RefreshSection("appSettings"); } /// /// Gets the full path to root. /// /// The fullpath to root. public static string FullpathToRoot { get { return HttpRuntime.AppDomainAppPath; } } /// /// Gets a value indicating whether umbraco is running in [debug mode]. /// /// true if [debug mode]; otherwise, false. public static bool DebugMode { get { try { return bool.Parse(ConfigurationManager.AppSettings["umbracoDebugMode"]); } catch { return false; } } } /// /// Gets a value indicating whether the current version of umbraco is configured. /// /// true if configured; otherwise, false. public static bool Configured { get { try { string configStatus = ConfigurationStatus; string currentVersion = CurrentVersion; if (currentVersion != configStatus) Log.Add(LogTypes.Debug, User.GetUser(0), -1, "CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'"); return (configStatus == currentVersion); } catch { return false; } } } /// /// Gets the time out in minutes. /// /// The time out in minutes. public static int TimeOutInMinutes { get { try { return int.Parse(ConfigurationManager.AppSettings["umbracoTimeOutInMinutes"]); } catch { return 20; } } } /// /// Gets a value indicating whether umbraco uses directory urls. /// /// true if umbraco uses directory urls; otherwise, false. public static bool UseDirectoryUrls { get { try { return bool.Parse(ConfigurationManager.AppSettings["umbracoUseDirectoryUrls"]); } catch { return false; } } } /// /// Returns a string value to determine if umbraco should skip version-checking. /// /// The version check period in days (0 = never). public static int VersionCheckPeriod { get { int versionCheckPeriod = 7; if (HttpContext.Current != null) { if (int.TryParse(ConfigurationManager.AppSettings["umbracoVersionCheckPeriod"], out versionCheckPeriod)) return versionCheckPeriod; } return versionCheckPeriod; } } /// /// Gets the URL forbitten characters. /// /// The URL forbitten characters. public static string UrlForbittenCharacters { get { if (HttpContext.Current != null) return ConfigurationManager.AppSettings["umbracoUrlForbittenCharacters"]; return ""; } } /// /// Gets the URL space character. /// /// The URL space character. public static string UrlSpaceCharacter { get { if (HttpContext.Current != null) return ConfigurationManager.AppSettings["umbracoUrlSpaceCharacter"]; return ""; } } /// /// Gets the SMTP server IP-address or hostname. /// /// The SMTP server. public static string SmtpServer { get { try { System.Net.Configuration.MailSettingsSectionGroup mailSettings = ConfigurationManager.GetSection("system.net/mailSettings") as System.Net.Configuration.MailSettingsSectionGroup; if (mailSettings != null) return mailSettings.Smtp.Network.Host; else return ConfigurationManager.AppSettings["umbracoSmtpServer"]; } catch { return ""; } } } /// /// Returns a string value to determine if umbraco should disbable xslt extensions /// /// "true" if version xslt extensions are disabled, otherwise, "false" public static string DisableXsltExtensions { get { if (HttpContext.Current != null) return ConfigurationManager.AppSettings["umbracoDisableXsltExtensions"]; return ""; } } /// /// Returns a string value to determine if umbraco should use Xhtml editing mode in the wysiwyg editor /// /// "true" if Xhtml mode is enable, otherwise, "false" public static string EditXhtmlMode { get { if (HttpContext.Current != null) return ConfigurationManager.AppSettings["umbracoEditXhtmlMode"]; return ""; } } /// /// Gets the default UI language. /// /// The default UI language. public static string DefaultUILanguage { get { if (HttpContext.Current != null) return ConfigurationManager.AppSettings["umbracoDefaultUILanguage"]; return ""; } } /// /// Gets the profile URL. /// /// The profile URL. public static string ProfileUrl { get { if (HttpContext.Current != null) return ConfigurationManager.AppSettings["umbracoProfileUrl"]; return ""; } } /// /// Gets a value indicating whether umbraco should hide top level nodes from generated urls. /// /// /// true if umbraco hides top level nodes from urls; otherwise, false. /// public static bool HideTopLevelNodeFromPath { get { if (HttpContext.Current != null) return bool.Parse(ConfigurationManager.AppSettings["umbracoHideTopLevelNodeFromPath"]); return false; } } /// /// Gets the current version. /// /// The current version. public static string CurrentVersion { get { // change this to be hardcoded in the binary return _currentVersion; } } /// /// Gets the major version number. /// /// The major version number. public static int VersionMajor { get { string[] version = CurrentVersion.Split(".".ToCharArray()); return int.Parse(version[0]); } } /// /// Gets the minor version number. /// /// The minor version number. public static int VersionMinor { get { string[] version = CurrentVersion.Split(".".ToCharArray()); return int.Parse(version[1]); } } /// /// Gets the patch version number. /// /// The patch version number. public static int VersionPatch { get { string[] version = CurrentVersion.Split(".".ToCharArray()); return int.Parse(version[2]); } } /// /// Gets the version comment (like beta or RC). /// /// The version comment. public static string VersionComment { get { string[] version = CurrentVersion.Split(".".ToCharArray()); if (version.Length > 3) return version[3]; else return ""; } } /// /// Requests the is in umbraco application directory structure. /// /// The context. /// public static bool RequestIsInUmbracoApplication(HttpContext context) { return context.Request.Path.ToLower().IndexOf(IOHelper.ResolveUrl(SystemDirectories.Umbraco).ToLower()) > -1; } public static bool RequestIsLiveEditRedirector(HttpContext context) { return context.Request.Path.ToLower().IndexOf(SystemDirectories.Umbraco.ToLower() + "/liveediting.aspx") > -1; } /// /// Gets a value indicating whether umbraco should force a secure (https) connection to the backoffice. /// /// true if [use SSL]; otherwise, false. public static bool UseSSL { get { try { return bool.Parse(ConfigurationManager.AppSettings["umbracoUseSSL"]); } catch { return false; } } } /// /// Gets the umbraco license. /// /// The license. public static string License { get { string license = "the open source license MIT. The umbraco UI is freeware licensed under the umbraco license."; if (HttpContext.Current != null) { XmlDocument versionDoc = new XmlDocument(); XmlTextReader versionReader = new XmlTextReader(IOHelper.MapPath(SystemDirectories.Umbraco + "/version.xml")); versionDoc.Load(versionReader); versionReader.Close(); // check for license try { string licenseUrl = versionDoc.SelectSingleNode("/version/licensing/licenseUrl").FirstChild.Value; string licenseValidation = versionDoc.SelectSingleNode("/version/licensing/licenseValidation").FirstChild.Value; string licensedTo = versionDoc.SelectSingleNode("/version/licensing/licensedTo").FirstChild.Value; if (licensedTo != "" && licenseUrl != "") { license = "umbraco Commercial License
Registered to:
" + licensedTo.Replace("\n", "
") + "
For use with domain:
" + licenseUrl; } } catch { } } return license; } } /// /// Developer method to test if configuration settings are loaded properly. /// /// true if succesfull; otherwise, false. public static bool test { get { try { HttpContext.Current.Response.Write("ContentXML :" + ContentXML + "\n"); HttpContext.Current.Response.Write("DbDSN :" + DbDSN + "\n"); HttpContext.Current.Response.Write("DebugMode :" + DebugMode + "\n"); HttpContext.Current.Response.Write("DefaultUILanguage :" + DefaultUILanguage + "\n"); HttpContext.Current.Response.Write("VersionCheckPeriod :" + VersionCheckPeriod + "\n"); HttpContext.Current.Response.Write("DisableXsltExtensions :" + DisableXsltExtensions + "\n"); HttpContext.Current.Response.Write("EditXhtmlMode :" + EditXhtmlMode + "\n"); HttpContext.Current.Response.Write("HideTopLevelNodeFromPath :" + HideTopLevelNodeFromPath + "\n"); HttpContext.Current.Response.Write("Path :" + Path + "\n"); HttpContext.Current.Response.Write("ProfileUrl :" + ProfileUrl + "\n"); HttpContext.Current.Response.Write("ReservedPaths :" + ReservedPaths + "\n"); HttpContext.Current.Response.Write("ReservedUrls :" + ReservedUrls + "\n"); HttpContext.Current.Response.Write("StorageDirectory :" + StorageDirectory + "\n"); HttpContext.Current.Response.Write("TimeOutInMinutes :" + TimeOutInMinutes + "\n"); HttpContext.Current.Response.Write("UrlForbittenCharacters :" + UrlForbittenCharacters + "\n"); HttpContext.Current.Response.Write("UrlSpaceCharacter :" + UrlSpaceCharacter + "\n"); HttpContext.Current.Response.Write("UseDirectoryUrls :" + UseDirectoryUrls + "\n"); return true; } catch { } return false; } } /// /// Determines whether the specified URL is reserved or is inside a reserved path. /// /// The URL to check. /// /// true if the specified URL is reserved; otherwise, false. /// public static bool IsReservedPathOrUrl(string url) { // check if GlobalSettings.ReservedPaths and GlobalSettings.ReservedUrls are unchanged if (!object.ReferenceEquals(_reservedPathsCache, GlobalSettings.ReservedPaths) || !object.ReferenceEquals(_reservedUrlsCache, GlobalSettings.ReservedUrls)) { // store references to strings to determine changes _reservedPathsCache = GlobalSettings.ReservedPaths; _reservedUrlsCache = GlobalSettings.ReservedUrls; string _root = SystemDirectories.Root.Trim().ToLower(); // add URLs and paths to a new list StartsWithContainer _newReservedList = new StartsWithContainer(); foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)) { //resolves the url to support tilde chars string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl).Trim().ToLower(); if (reservedUrlTrimmed.Length > 0) _newReservedList.Add(reservedUrlTrimmed); } foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)) { bool trimEnd = !reservedPath.EndsWith("/"); //resolves the url to support tilde chars string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath).Trim().ToLower(); if (reservedPathTrimmed.Length > 0) _newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/")); } // use the new list from now on _reservedList = _newReservedList; } string res = ""; foreach (string st in _reservedList._list.Keys) res += st + ","; HttpContext.Current.Trace.Write("umbracoGlobalsettings", "reserverd urls: '" + res + "'"); // return true if url starts with an element of the reserved list return _reservedList.StartsWith(url.ToLower()); } } /// /// Structure that checks in logarithmic time /// if a given string starts with one of the added keys. /// public class StartsWithContainer { /// Internal sorted list of keys. public SortedList _list = new SortedList(StartsWithComparator.Instance); /// /// Adds the specified new key. /// /// The new key. public void Add(string newKey) { // if the list already contains an element that begins with newKey, return if (String.IsNullOrEmpty(newKey) || StartsWith(newKey)) return; // create a new collection, so the old one can still be accessed SortedList newList = new SortedList(_list.Count + 1, StartsWithComparator.Instance); // add only keys that don't already start with newKey, others are unnecessary foreach (string key in _list.Keys) if (!key.StartsWith(newKey)) newList.Add(key, null); // add the new key newList.Add(newKey, null); // update the list (thread safe, _list was never in incomplete state) _list = newList; } /// /// Checks if the given string starts with any of the added keys. /// /// The target. /// true if a key is found that matches the start of target /// /// Runs in O(s*log(n)), with n the number of keys and s the length of target. /// public bool StartsWith(string target) { return _list.ContainsKey(target); } /// Comparator that tests if a string starts with another. /// Not a real comparator, since it is not reflexive. (x==y does not imply y==x) private sealed class StartsWithComparator : IComparer { /// Default string comparer. private readonly static Comparer _stringComparer = Comparer.Default; /// Gets an instance of the StartsWithComparator. public static readonly StartsWithComparator Instance = new StartsWithComparator(); /// /// Tests if whole begins with all characters of part. /// /// The part. /// The whole. /// /// Returns 0 if whole starts with part, otherwise performs standard string comparison. /// public int Compare(string part, string whole) { // let the default string comparer deal with null or when part is not smaller then whole if (part == null || whole == null || part.Length >= whole.Length) return _stringComparer.Compare(part, whole); // loop through all characters that part and whole have in common int pos = 0; bool match; do { match = (part[pos] == whole[pos]); } while (match && ++pos < part.Length); // return result of last comparison return match ? 0 : (part[pos] < whole[pos] ? -1 : 1); } } } }