diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings.cs b/src/Umbraco.Core/Configuration/LegacyUmbracoSettings.cs
similarity index 95%
rename from src/Umbraco.Core/Configuration/UmbracoSettings.cs
rename to src/Umbraco.Core/Configuration/LegacyUmbracoSettings.cs
index 9292fd21e9..e32d1d4b51 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings.cs
+++ b/src/Umbraco.Core/Configuration/LegacyUmbracoSettings.cs
@@ -1,1613 +1,1613 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Web;
-using System.Web.Caching;
-using System.Web.Security;
-using System.Xml;
-using System.Configuration;
-
-using System.Collections.Generic;
-using Umbraco.Core.Logging;
-using Umbraco.Core.CodeAnnotations;
-
-
-namespace Umbraco.Core.Configuration
-{
- //NOTE: Do not expose this class ever until we cleanup all configuration including removal of static classes, etc...
- // we have this two tasks logged:
- // http://issues.umbraco.org/issue/U4-58
- // http://issues.umbraco.org/issue/U4-115
-
- //TODO: Re-enable logging !!!!
-
- //TODO: We need to convert this to a real section, it's currently using HttpRuntime.Cache to detect cahnges, this is real poor, especially in a console app
-
- ///
- /// The UmbracoSettings Class contains general settings information for the entire Umbraco instance based on information from the /config/umbracoSettings.config file
- ///
- internal class UmbracoSettings
- {
- private static bool GetKeyValue(string key, bool defaultValue)
- {
- bool value;
- string stringValue = GetKey(key);
-
- if (string.IsNullOrWhiteSpace(stringValue))
- return defaultValue;
- if (bool.TryParse(stringValue, out value))
- return value;
- return defaultValue;
- }
-
- private static int GetKeyValue(string key, int defaultValue)
- {
- int value;
- string stringValue = GetKey(key);
-
- if (string.IsNullOrWhiteSpace(stringValue))
- return defaultValue;
- if (int.TryParse(stringValue, out value))
- return value;
- return defaultValue;
- }
-
- ///
- /// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
- ///
- private static void ResetInternal()
- {
- _addTrailingSlash = null;
- _forceSafeAliases = null;
- _useLegacySchema = null;
- _useDomainPrefixes = null;
- _umbracoLibraryCacheDuration = null;
- SettingsFilePath = null;
- }
-
- internal const string TempFriendlyXmlChildContainerNodename = ""; // "children";
-
- ///
- /// Gets the umbraco settings document.
- ///
- /// The _umbraco settings.
- internal static XmlDocument UmbracoSettingsXmlDoc
- {
- get
- {
- var us = (XmlDocument)HttpRuntime.Cache["umbracoSettingsFile"] ?? EnsureSettingsDocument();
- return us;
- }
- }
-
- private static string _path;
-
- ///
- /// Gets/sets the settings file path, the setter can be used in unit tests
- ///
- internal static string SettingsFilePath
- {
- get { return _path ?? (_path = GlobalSettings.FullpathToRoot + Path.DirectorySeparatorChar + "config" + Path.DirectorySeparatorChar); }
- set { _path = value; }
- }
-
- internal const string Filename = "umbracoSettings.config";
-
- internal static XmlDocument EnsureSettingsDocument()
- {
- var settingsFile = HttpRuntime.Cache["umbracoSettingsFile"];
-
- // Check for language file in cache
- if (settingsFile == null)
- {
- var temp = new XmlDocument();
- var settingsReader = new XmlTextReader(SettingsFilePath + Filename);
- try
- {
- temp.Load(settingsReader);
- HttpRuntime.Cache.Insert("umbracoSettingsFile", temp,
- new CacheDependency(SettingsFilePath + Filename));
- }
- catch (XmlException e)
- {
- throw new XmlException("Your umbracoSettings.config file fails to pass as valid XML. Refer to the InnerException for more information", e);
- }
- catch (Exception e)
- {
- LogHelper.Error("Error reading umbracoSettings file: " + e.ToString(), e);
- }
- settingsReader.Close();
- return temp;
- }
- else
- return (XmlDocument)settingsFile;
- }
-
- internal static void Save()
- {
- UmbracoSettingsXmlDoc.Save(SettingsFilePath + Filename);
- }
-
-
- ///
- /// Selects a xml node in the umbraco settings config file.
- ///
- /// The xpath query to the specific node.
- /// If found, it returns the specific configuration xml node.
- internal static XmlNode GetKeyAsNode(string key)
- {
- if (key == null)
- throw new ArgumentException("Key cannot be null");
- EnsureSettingsDocument();
- if (UmbracoSettingsXmlDoc == null || UmbracoSettingsXmlDoc.DocumentElement == null)
- return null;
- return UmbracoSettingsXmlDoc.DocumentElement.SelectSingleNode(key);
- }
-
- ///
- /// Gets the value of configuration xml node with the specified key.
- ///
- /// The key.
- ///
- internal static string GetKey(string key)
- {
- EnsureSettingsDocument();
-
- string attrName = null;
- var pos = key.IndexOf('@');
- if (pos > 0)
- {
- attrName = key.Substring(pos + 1);
- key = key.Substring(0, pos - 1);
- }
-
- var node = UmbracoSettingsXmlDoc.DocumentElement.SelectSingleNode(key);
- if (node == null)
- return string.Empty;
-
- if (pos < 0)
- {
- if (node.FirstChild == null || node.FirstChild.Value == null)
- return string.Empty;
- return node.FirstChild.Value;
- }
- else
- {
- var attr = node.Attributes[attrName];
- if (attr == null)
- return string.Empty;
- return attr.Value;
- }
- }
-
- ///
- /// Gets a value indicating whether the media library will create new directories in the /media directory.
- ///
- ///
- /// true if new directories are allowed otherwise, false.
- ///
- internal static bool UploadAllowDirectories
- {
- get { return bool.Parse(GetKey("/settings/content/UploadAllowDirectories")); }
- }
-
- ///
- /// THIS IS TEMPORARY until we fix up settings all together, this setting is actually not 'settable' but is
- /// here for future purposes since we check for thsi settings in the module.
- ///
- internal static bool EnableBaseRestHandler
- {
- get { return true; }
- }
-
- ///
- /// THIS IS TEMPORARY until we fix up settings all together, this setting is actually not 'settable' but is
- /// here for future purposes since we check for thsi settings in the module.
- ///
- internal static string BootSplashPage
- {
- get { return "~/config/splashes/booting.aspx"; }
- }
-
- ///
- /// Gets a value indicating whether logging is enabled in umbracoSettings.config (/settings/logging/enableLogging).
- ///
- /// true if logging is enabled; otherwise, false.
- internal static bool EnableLogging
- {
- get
- {
- // We return true if no enable logging element is present in
- // umbracoSettings (to enable default behaviour when upgrading)
- var enableLogging = GetKey("/settings/logging/enableLogging");
- return String.IsNullOrEmpty(enableLogging) || bool.Parse(enableLogging);
- }
- }
-
- ///
- /// Gets a value indicating whether logging happens async.
- ///
- /// true if async logging is enabled; otherwise, false.
- internal static bool EnableAsyncLogging
- {
- get
- {
- string value = GetKey("/settings/logging/enableAsyncLogging");
- bool result;
- if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
- return result;
- return false;
- }
- }
-
- ///
- /// Gets the assembly of an external logger that can be used to store log items in 3rd party systems
- ///
- internal static string ExternalLoggerAssembly
- {
- get
- {
- var value = GetKeyAsNode("/settings/logging/externalLogger");
- return value != null ? value.Attributes["assembly"].Value : "";
- }
- }
-
- ///
- /// Gets the type of an external logger that can be used to store log items in 3rd party systems
- ///
- internal static string ExternalLoggerType
- {
- get
- {
- var value = GetKeyAsNode("/settings/logging/externalLogger");
- return value != null ? value.Attributes["type"].Value : "";
- }
- }
-
- ///
- /// Long Audit Trail to external log too
- ///
- internal static bool ExternalLoggerLogAuditTrail
- {
- get
- {
- var value = GetKeyAsNode("/settings/logging/externalLogger");
- if (value != null)
- {
- var logAuditTrail = value.Attributes["logAuditTrail"].Value;
- bool result;
- if (!string.IsNullOrEmpty(logAuditTrail) && bool.TryParse(logAuditTrail, out result))
- return result;
- }
- return false;
- }
- }
-
- ///
- /// Keep user alive as long as they have their browser open? Default is true
- ///
- internal static bool KeepUserLoggedIn
- {
- get
- {
- var value = GetKey("/settings/security/keepUserLoggedIn");
- bool result;
- if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
- return result;
- return true;
- }
- }
-
- internal static string AuthCookieName
- {
- get
- {
- var value = GetKey("/settings/security/authCookieName");
- if (string.IsNullOrEmpty(value) == false)
- {
- return value;
- }
- return "UMB_UCONTEXT";
- }
- }
-
- internal static string AuthCookieDomain
- {
- get
- {
- var value = GetKey("/settings/security/authCookieDomain");
- if (string.IsNullOrEmpty(value) == false)
- {
- return value;
- }
- return FormsAuthentication.CookieDomain;
- }
- }
-
- ///
- /// Enables the experimental canvas (live) editing on the frontend of the website
- ///
- internal static bool EnableCanvasEditing
- {
- get
- {
- var value = GetKey("/settings/content/EnableCanvasEditing");
- bool result;
- if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
- return result;
- return true;
- }
- }
-
- ///
- /// Show disabled users in the tree in the Users section in the backoffice
- ///
- internal static bool HideDisabledUsersInBackoffice
- {
- get
- {
- string value = GetKey("/settings/security/hideDisabledUsersInBackoffice");
- bool result;
- if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
- return result;
- return false;
- }
- }
-
- ///
- /// Gets a value indicating whether the logs will be auto cleaned
- ///
- /// true if logs are to be automatically cleaned; otherwise, false
- internal static bool AutoCleanLogs
- {
- get
- {
- string value = GetKey("/settings/logging/autoCleanLogs");
- bool result;
- if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
- return result;
- return false;
- }
- }
-
- ///
- /// Gets the value indicating the log cleaning frequency (in miliseconds)
- ///
- internal static int CleaningMiliseconds
- {
- get
- {
- string value = GetKey("/settings/logging/cleaningMiliseconds");
- int result;
- if (!string.IsNullOrEmpty(value) && int.TryParse(value, out result))
- return result;
- return -1;
- }
- }
-
- internal static int MaxLogAge
- {
- get
- {
- string value = GetKey("/settings/logging/maxLogAge");
- int result;
- if (!string.IsNullOrEmpty(value) && int.TryParse(value, out result))
- return result;
- return -1;
- }
- }
-
- ///
- /// Gets the disabled log types.
- ///
- /// The disabled log types.
- internal static XmlNode DisabledLogTypes
- {
- get { return GetKeyAsNode("/settings/logging/disabledLogTypes"); }
- }
-
- ///
- /// Gets the package server url.
- ///
- /// The package server url.
- internal static string PackageServer
- {
- get { return "packages.umbraco.org"; }
- }
-
- static bool? _useDomainPrefixes = null;
-
- ///
- /// Gets a value indicating whether umbraco will use domain prefixes.
- ///
- /// true if umbraco will use domain prefixes; otherwise, false.
- internal static bool UseDomainPrefixes
- {
- get
- {
- // default: false
- return _useDomainPrefixes ?? GetKeyValue("/settings/requestHandler/useDomainPrefixes", false);
- }
- /*internal*/ set
- {
- // for unit tests only
- _useDomainPrefixes = value;
- }
- }
-
- static bool? _addTrailingSlash = null;
-
- ///
- /// This will add a trailing slash (/) to urls when in directory url mode
- /// NOTICE: This will always return false if Directory Urls in not active
- ///
- internal static bool AddTrailingSlash
- {
- get
- {
- // default: false
- return GlobalSettings.UseDirectoryUrls
- && (_addTrailingSlash ?? GetKeyValue("/settings/requestHandler/addTrailingSlash", false));
- }
- /*internal*/ set
- {
- // for unit tests only
- _addTrailingSlash = value;
- }
- }
-
- ///
- /// Gets a value indicating whether umbraco will use ASP.NET MasterPages for rendering instead of its propriatary templating system.
- ///
- /// true if umbraco will use ASP.NET MasterPages; otherwise, false.
- internal static bool UseAspNetMasterPages
- {
- get
- {
- try
- {
- bool result;
- if (bool.TryParse(GetKey("/settings/templates/useAspNetMasterPages"), out result))
- return result;
- return false;
- }
- catch
- {
- return false;
- }
- }
- }
-
- ///
- /// Gets a value indicating whether umbraco will attempt to load any skins to override default template files
- ///
- /// true if umbraco will override templates with skins if present and configured false.
- internal static bool EnableTemplateFolders
- {
- get
- {
- try
- {
- bool result;
- if (bool.TryParse(GetKey("/settings/templates/enableTemplateFolders"), out result))
- return result;
- return false;
- }
- catch
- {
- return false;
- }
- }
- }
-
- //TODO: I"m not sure why we need this, need to ask Gareth what the deal is, pretty sure we can remove it or change it, seems like
- // massive overkill.
-
- ///
- /// razor DynamicNode typecasting detects XML and returns DynamicXml - Root elements that won't convert to DynamicXml
- ///
- internal static IEnumerable NotDynamicXmlDocumentElements
- {
- get
- {
- try
- {
- List items = new List();
- XmlNode root = GetKeyAsNode("/settings/scripting/razor/notDynamicXmlDocumentElements");
- foreach (XmlNode element in root.SelectNodes(".//element"))
- {
- items.Add(element.InnerText);
- }
- return items;
- }
- catch
- {
- return new List() { "p", "div" };
- }
- }
- }
-
- private static IEnumerable _razorDataTypeModelStaticMapping;
- private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
-
- internal static IEnumerable RazorDataTypeModelStaticMapping
- {
- get
- {
- /*
-
- DigibizAdvancedMediaPicker.RazorModel.ModelBinder
- DigibizAdvancedMediaPicker.RazorModel.ModelBinder
-
- */
-
- using (var l = new UpgradeableReadLock(Lock))
- {
- if (_razorDataTypeModelStaticMapping == null)
- {
- l.UpgradeToWriteLock();
-
- List items = new List();
- XmlNode root = GetKeyAsNode("/settings/scripting/razor/dataTypeModelStaticMappings");
- if (root != null)
- {
- foreach (XmlNode element in root.SelectNodes(".//mapping"))
- {
- string propertyTypeAlias = null, nodeTypeAlias = null;
- Guid? dataTypeGuid = null;
- if (!string.IsNullOrEmpty(element.InnerText))
- {
- if (element.Attributes["dataTypeGuid"] != null)
- {
- dataTypeGuid = (Guid?)new Guid(element.Attributes["dataTypeGuid"].Value);
- }
- if (element.Attributes["propertyTypeAlias"] != null && !string.IsNullOrEmpty(element.Attributes["propertyTypeAlias"].Value))
- {
- propertyTypeAlias = element.Attributes["propertyTypeAlias"].Value;
- }
- if (element.Attributes["nodeTypeAlias"] != null && !string.IsNullOrEmpty(element.Attributes["nodeTypeAlias"].Value))
- {
- nodeTypeAlias = element.Attributes["nodeTypeAlias"].Value;
- }
- items.Add(new RazorDataTypeModelStaticMappingItem()
- {
- DataTypeGuid = dataTypeGuid,
- PropertyTypeAlias = propertyTypeAlias,
- NodeTypeAlias = nodeTypeAlias,
- TypeName = element.InnerText,
- Raw = element.OuterXml
- });
- }
- }
- }
-
- _razorDataTypeModelStaticMapping = items;
- }
-
- return _razorDataTypeModelStaticMapping;
- }
- }
- }
-
- ///
- /// Gets a value indicating whether umbraco will clone XML cache on publish.
- ///
- ///
- /// true if umbraco will clone XML cache on publish; otherwise, false.
- ///
- internal static bool CloneXmlCacheOnPublish
- {
- get
- {
- try
- {
- bool result;
- if (bool.TryParse(GetKey("/settings/content/cloneXmlContent"), out result))
- return result;
- return false;
- }
- catch
- {
- return false;
- }
- }
- }
-
- ///
- /// Gets a value indicating whether rich text editor content should be parsed by tidy.
- ///
- /// true if content is parsed; otherwise, false.
- internal static bool TidyEditorContent
- {
- get { return bool.Parse(GetKey("/settings/content/TidyEditorContent")); }
- }
-
- ///
- /// Gets the encoding type for the tidyied content.
- ///
- /// The encoding type as string.
- internal static string TidyCharEncoding
- {
- get
- {
- string encoding = GetKey("/settings/content/TidyCharEncoding");
- if (String.IsNullOrEmpty(encoding))
- {
- encoding = "UTF8";
- }
- return encoding;
- }
- }
-
- ///
- /// Gets the property context help option, this can either be 'text', 'icon' or 'none'
- ///
- /// The property context help option.
- internal static string PropertyContextHelpOption
- {
- get { return GetKey("/settings/content/PropertyContextHelpOption").ToLower(); }
- }
-
- internal static string DefaultBackofficeProvider
- {
- get
- {
- string defaultProvider = GetKey("/settings/providers/users/DefaultBackofficeProvider");
- if (String.IsNullOrEmpty(defaultProvider))
- defaultProvider = "UsersMembershipProvider";
-
- return defaultProvider;
- }
- }
-
- private static bool? _forceSafeAliases;
-
- ///
- /// Whether to force safe aliases (no spaces, no special characters) at businesslogic level on contenttypes and propertytypes
- ///
- internal static bool ForceSafeAliases
- {
- get
- {
- // default: true
- return _forceSafeAliases ?? GetKeyValue("/settings/content/ForceSafeAliases", true);
- }
- /*internal*/ set
- {
- // used for unit testing
- _forceSafeAliases = value;
- }
- }
-
- ///
- /// Gets a value indicating whether to try to skip IIS custom errors.
- ///
- [UmbracoWillObsolete("Use UmbracoSettings.For.TrySkipIisCustomErrors instead.")]
- internal static bool TrySkipIisCustomErrors
- {
- get { return GetKeyValue("/settings/web.routing/@trySkipIisCustomErrors", false); }
- }
-
- ///
- /// Gets a value indicating whether internal redirect preserves the template.
- ///
- [UmbracoWillObsolete("Use UmbracoSettings.For.InternalRedirectPerservesTemplate instead.")]
- internal static bool InternalRedirectPreservesTemplate
- {
- get { return GetKeyValue("/settings/web.routing/@internalRedirectPreservesTemplate", false); }
- }
-
- ///
- /// File types that will not be allowed to be uploaded via the content/media upload control
- ///
- public static IEnumerable DisallowedUploadFiles
- {
- get
- {
- var val = GetKey("/settings/content/disallowedUploadFiles");
- return val.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
- }
- }
-
- ///
- /// Gets the allowed image file types.
- ///
- /// The allowed image file types.
- internal static string ImageFileTypes
- {
- get { return GetKey("/settings/content/imaging/imageFileTypes").ToLowerInvariant(); }
- }
-
- ///
- /// Gets the allowed script file types.
- ///
- /// The allowed script file types.
- internal static string ScriptFileTypes
- {
- get { return GetKey("/settings/content/scripteditor/scriptFileTypes"); }
- }
-
- private static int? _umbracoLibraryCacheDuration;
-
- ///
- /// Gets the duration in seconds to cache queries to umbraco library member and media methods
- /// Default is 1800 seconds (30 minutes)
- ///
- internal static int UmbracoLibraryCacheDuration
- {
- get
- {
- // default: 1800
- return _umbracoLibraryCacheDuration ?? GetKeyValue("/settings/content/UmbracoLibraryCacheDuration", 1800);
- }
- /*internal*/ set
- {
- // for unit tests only
- _umbracoLibraryCacheDuration = value;
- }
- }
-
- ///
- /// Gets the path to the scripts folder used by the script editor.
- ///
- /// The script folder path.
- internal static string ScriptFolderPath
- {
- get { return GetKey("/settings/content/scripteditor/scriptFolderPath"); }
- }
-
- ///
- /// Enabled or disable the script/code editor
- ///
- internal static bool ScriptDisableEditor
- {
- get
- {
- string _tempValue = GetKey("/settings/content/scripteditor/scriptDisableEditor");
- if (_tempValue != String.Empty)
- return bool.Parse(_tempValue);
- else
- return false;
- }
- }
-
- ///
- /// Gets a value indicating whether umbraco will ensure unique node naming.
- /// This will ensure that nodes cannot have the same url, but will add extra characters to a url.
- /// ex: existingnodename.aspx would become existingnodename(1).aspx if a node with the same name is found
- ///
- /// true if umbraco ensures unique node naming; otherwise, false.
- internal static bool EnsureUniqueNaming
- {
- get
- {
- try
- {
- return bool.Parse(GetKey("/settings/content/ensureUniqueNaming"));
- }
- catch
- {
- return false;
- }
- }
- }
-
- ///
- /// Gets the notification email sender.
- ///
- /// The notification email sender.
- internal static string NotificationEmailSender
- {
- get { return GetKey("/settings/content/notifications/email"); }
- }
-
- ///
- /// Gets a value indicating whether notification-emails are HTML.
- ///
- ///
- /// true if html notification-emails are disabled; otherwise, false.
- ///
- internal static bool NotificationDisableHtmlEmail
- {
- get
- {
- var tempValue = GetKey("/settings/content/notifications/disableHtmlEmail");
- return tempValue != String.Empty && bool.Parse(tempValue);
- }
- }
-
- ///
- /// Gets the allowed attributes on images.
- ///
- /// The allowed attributes on images.
- internal static string ImageAllowedAttributes
- {
- get { return GetKey("/settings/content/imaging/allowedAttributes"); }
- }
-
- internal static XmlNode ImageAutoFillImageProperties
- {
- get { return GetKeyAsNode("/settings/content/imaging/autoFillImageProperties"); }
- }
-
- ///
- /// Gets the scheduled tasks as XML
- ///
- /// The scheduled tasks.
- internal static XmlNode ScheduledTasks
- {
- get { return GetKeyAsNode("/settings/scheduledTasks"); }
- }
-
- ///
- /// Gets a list of characters that will be replaced when generating urls
- ///
- /// The URL replacement characters.
- internal static XmlNode UrlReplaceCharacters
- {
- get { return GetKeyAsNode("/settings/requestHandler/urlReplacing"); }
- }
-
- ///
- /// Whether to replace double dashes from url (ie my--story----from--dash.aspx caused by multiple url replacement chars
- ///
- internal static bool RemoveDoubleDashesFromUrlReplacing
- {
- get
- {
- try
- {
- return bool.Parse(UrlReplaceCharacters.Attributes.GetNamedItem("removeDoubleDashes").Value);
- }
- catch
- {
- return false;
- }
- }
- }
-
- ///
- /// Gets a value indicating whether umbraco will use distributed calls.
- /// This enables umbraco to share cache and content across multiple servers.
- /// Used for load-balancing high-traffic sites.
- ///
- /// true if umbraco uses distributed calls; otherwise, false.
- internal static bool UseDistributedCalls
- {
- get
- {
- try
- {
- return bool.Parse(GetKeyAsNode("/settings/distributedCall").Attributes.GetNamedItem("enable").Value);
- }
- catch
- {
- return false;
- }
- }
- }
-
-
- ///
- /// Gets the ID of the user with access rights to perform the distributed calls.
- ///
- /// The distributed call user.
- internal static int DistributedCallUser
- {
- get
- {
- try
- {
- return int.Parse(GetKey("/settings/distributedCall/user"));
- }
- catch
- {
- return -1;
- }
- }
- }
-
- ///
- /// Gets the html injected into a (x)html page if Umbraco is running in preview mode
- ///
- internal static string PreviewBadge
- {
- get
- {
- try
- {
- return GetKey("/settings/content/PreviewBadge");
- }
- catch
- {
- return "In Preview Mode - click to end";
- }
- }
- }
-
- ///
- /// Gets IP or hostnames of the distribution servers.
- /// These servers will receive a call everytime content is created/deleted/removed
- /// and update their content cache accordingly, ensuring a consistent cache on all servers
- ///
- /// The distribution servers.
- internal static XmlNode DistributionServers
- {
- get
- {
- try
- {
- return GetKeyAsNode("/settings/distributedCall/servers");
- }
- catch
- {
- return null;
- }
- }
- }
-
- ///
- /// Gets HelpPage configurations.
- /// A help page configuration specify language, user type, application, application url and
- /// the target help page url.
- ///
- internal static XmlNode HelpPages
- {
- get
- {
- try
- {
- return GetKeyAsNode("/settings/help");
- }
- catch
- {
- return null;
- }
- }
- }
-
- ///
- /// Gets all repositories registered, and returns them as XmlNodes, containing name, alias and webservice url.
- /// These repositories are used by the build-in package installer and uninstaller to install new packages and check for updates.
- /// All repositories should have a unique alias.
- /// All packages installed from a repository gets the repository alias included in the install information
- ///
- /// The repository servers.
- internal static XmlNode Repositories
- {
- get
- {
- try
- {
- return GetKeyAsNode("/settings/repositories");
- }
- catch
- {
- return null;
- }
- }
- }
-
- ///
- /// Gets a value indicating whether umbraco will use the viewstate mover module.
- /// The viewstate mover will move all asp.net viewstate information to the bottom of the aspx page
- /// to ensure that search engines will index text instead of javascript viewstate information.
- ///
- ///
- /// true if umbraco will use the viewstate mover module; otherwise, false.
- ///
- internal static bool UseViewstateMoverModule
- {
- get
- {
- try
- {
- return
- bool.Parse(
- GetKeyAsNode("/settings/viewstateMoverModule").Attributes.GetNamedItem("enable").Value);
- }
- catch
- {
- return false;
- }
- }
- }
-
-
- ///
- /// Tells us whether the Xml Content cache is disabled or not
- /// Default is enabled
- ///
- internal static bool IsXmlContentCacheDisabled
- {
- get
- {
- try
- {
- bool xmlCacheEnabled;
- string value = GetKey("/settings/content/XmlCacheEnabled");
- if (bool.TryParse(value, out xmlCacheEnabled))
- return !xmlCacheEnabled;
- // Return default
- return false;
- }
- catch
- {
- return false;
- }
- }
- }
-
- ///
- /// Check if there's changes to the umbraco.config xml file cache on disk on each request
- /// Makes it possible to updates environments by syncing the umbraco.config file across instances
- /// Relates to http://umbraco.codeplex.com/workitem/30722
- ///
- internal static bool XmlContentCheckForDiskChanges
- {
- get
- {
- try
- {
- bool checkForDiskChanges;
- string value = GetKey("/settings/content/XmlContentCheckForDiskChanges");
- if (bool.TryParse(value, out checkForDiskChanges))
- return checkForDiskChanges;
- // Return default
- return false;
- }
- catch
- {
- return false;
- }
- }
- }
-
- ///
- /// If this is enabled, all Umbraco objects will generate data in the preview table (cmsPreviewXml).
- /// If disabled, only documents will generate data.
- /// This feature is useful if anyone would like to see how data looked at a given time
- ///
- internal static bool EnableGlobalPreviewStorage
- {
- get
- {
- try
- {
- bool globalPreviewEnabled = false;
- string value = GetKey("/settings/content/GlobalPreviewStorageEnabled");
- if (bool.TryParse(value, out globalPreviewEnabled))
- return !globalPreviewEnabled;
- // Return default
- return false;
- }
- catch
- {
- return false;
- }
- }
- }
-
- private static bool? _useLegacySchema;
-
- ///
- /// Whether to use the new 4.1 schema or the old legacy schema
- ///
- ///
- /// true if yes, use the old node/data model; otherwise, false.
- ///
- internal static bool UseLegacyXmlSchema
- {
- get
- {
- // default: true
- return _useLegacySchema ?? GetKeyValue("/settings/content/UseLegacyXmlSchema", false);
- }
- /*internal*/ set
- {
- // used for unit testing
- _useLegacySchema = value;
- }
- }
-
- [Obsolete("This setting is not used anymore, the only file extensions that are supported are .cs and .vb files")]
- internal static IEnumerable AppCodeFileExtensionsList
- {
- get
- {
- return (from XmlNode x in AppCodeFileExtensions
- where !String.IsNullOrEmpty(x.InnerText)
- select x.InnerText).ToList();
- }
- }
-
- [Obsolete("This setting is not used anymore, the only file extensions that are supported are .cs and .vb files")]
- internal static XmlNode AppCodeFileExtensions
- {
- get
- {
- XmlNode value = GetKeyAsNode("/settings/developer/appCodeFileExtensions");
- if (value != null)
- {
- return value;
- }
-
- // default is .cs and .vb
- value = UmbracoSettingsXmlDoc.CreateElement("appCodeFileExtensions");
- value.AppendChild(XmlHelper.AddTextNode(UmbracoSettingsXmlDoc, "ext", "cs"));
- value.AppendChild(XmlHelper.AddTextNode(UmbracoSettingsXmlDoc, "ext", "vb"));
- return value;
- }
- }
-
- ///
- /// Tells us whether the Xml to always update disk cache, when changes are made to content
- /// Default is enabled
- ///
- internal static bool ContinouslyUpdateXmlDiskCache
- {
- get
- {
- try
- {
- bool updateDiskCache;
- string value = GetKey("/settings/content/ContinouslyUpdateXmlDiskCache");
- if (bool.TryParse(value, out updateDiskCache))
- return updateDiskCache;
- // Return default
- return false;
- }
- catch
- {
- return true;
- }
- }
- }
-
- ///
- /// Tells us whether to use a splash page while umbraco is initializing content.
- /// If not, requests are queued while umbraco loads content. For very large sites (+10k nodes) it might be usefull to
- /// have a splash page
- /// Default is disabled
- ///
- internal static bool EnableSplashWhileLoading
- {
- get
- {
- try
- {
- bool updateDiskCache;
- string value = GetKey("/settings/content/EnableSplashWhileLoading");
- if (bool.TryParse(value, out updateDiskCache))
- return updateDiskCache;
- // Return default
- return false;
- }
- catch
- {
- return false;
- }
- }
- }
-
- private static bool? _resolveUrlsFromTextString;
- internal static bool ResolveUrlsFromTextString
- {
- get
- {
- if (_resolveUrlsFromTextString == null)
- {
- try
- {
- bool enableDictionaryFallBack;
- var value = GetKey("/settings/content/ResolveUrlsFromTextString");
- if (value != null)
- if (bool.TryParse(value, out enableDictionaryFallBack))
- _resolveUrlsFromTextString = enableDictionaryFallBack;
- }
- catch (Exception ex)
- {
- Trace.WriteLine("Could not load /settings/content/ResolveUrlsFromTextString from umbracosettings.config:\r\n {0}",
- ex.Message);
-
- // set url resolving to true (default (legacy) behavior) to ensure we don't keep writing to trace
- _resolveUrlsFromTextString = true;
- }
- }
- return _resolveUrlsFromTextString == true;
- }
- }
-
-
- private static RenderingEngine? _defaultRenderingEngine;
-
- ///
- /// Enables MVC, and at the same time disable webform masterpage templates.
- /// This ensure views are automaticly created instead of masterpages.
- /// Views are display in the tree instead of masterpages and a MVC template editor
- /// is used instead of the masterpages editor
- ///
- /// true if umbraco defaults to using MVC views for templating, otherwise false.
- internal static RenderingEngine DefaultRenderingEngine
- {
- get
- {
- if (_defaultRenderingEngine == null)
- {
- try
- {
- var engine = RenderingEngine.WebForms;
- var value = GetKey("/settings/templates/defaultRenderingEngine");
- if (value != null)
- {
- Enum.TryParse(value, true, out engine);
- }
- _defaultRenderingEngine = engine;
- }
- catch (Exception ex)
- {
- LogHelper.Error("Could not load /settings/templates/defaultRenderingEngine from umbracosettings.config", ex);
- _defaultRenderingEngine = RenderingEngine.WebForms;
- }
- }
- return _defaultRenderingEngine.Value;
- }
- //internal set
- //{
- // _defaultRenderingEngine = value;
- // var node = UmbracoSettingsXmlDoc.DocumentElement.SelectSingleNode("/settings/templates/defaultRenderingEngine");
- // node.InnerText = value.ToString();
- //}
- }
-
- private static MacroErrorBehaviour? _macroErrorBehaviour;
-
- ///
- /// This configuration setting defines how to handle macro errors:
- /// - Inline - Show error within macro as text (default and current Umbraco 'normal' behavior)
- /// - Silent - Suppress error and hide macro
- /// - Throw - Throw an exception and invoke the global error handler (if one is defined, if not you'll get a YSOD)
- ///
- /// MacroErrorBehaviour enum defining how to handle macro errors.
- internal static MacroErrorBehaviour MacroErrorBehaviour
- {
- get
- {
- if (_macroErrorBehaviour == null)
- {
- try
- {
- var behaviour = MacroErrorBehaviour.Inline;
- var value = GetKey("/settings/content/MacroErrors");
- if (value != null)
- {
- Enum.TryParse(value, true, out behaviour);
- }
- _macroErrorBehaviour = behaviour;
- }
- catch (Exception ex)
- {
- LogHelper.Error("Could not load /settings/content/MacroErrors from umbracosettings.config", ex);
- _macroErrorBehaviour = MacroErrorBehaviour.Inline;
- }
- }
- return _macroErrorBehaviour.Value;
- }
- }
-
- private static IconPickerBehaviour? _iconPickerBehaviour;
-
- ///
- /// This configuration setting defines how to show icons in the document type editor.
- /// - ShowDuplicates - Show duplicates in files and sprites. (default and current Umbraco 'normal' behaviour)
- /// - HideSpriteDuplicates - Show files on disk and hide duplicates from the sprite
- /// - HideFileDuplicates - Show files in the sprite and hide duplicates on disk
- ///
- /// MacroErrorBehaviour enum defining how to show icons in the document type editor.
- internal static IconPickerBehaviour IconPickerBehaviour
- {
- get
- {
- if (_iconPickerBehaviour == null)
- {
- try
- {
- var behaviour = IconPickerBehaviour.ShowDuplicates;
- var value = GetKey("/settings/content/DocumentTypeIconList");
- if (value != null)
- {
- Enum.TryParse(value, true, out behaviour);
- }
- _iconPickerBehaviour = behaviour;
- }
- catch (Exception ex)
- {
- LogHelper.Error("Could not load /settings/content/DocumentTypeIconList from umbracosettings.config", ex);
- _iconPickerBehaviour = IconPickerBehaviour.ShowDuplicates;
- }
- }
- return _iconPickerBehaviour.Value;
- }
- }
-
- ///
- /// Gets the default document type property used when adding new properties through the back-office
- ///
- /// Configured text for the default document type property
- /// If undefined, 'Textstring' is the default
- public static string DefaultDocumentTypeProperty
- {
- get
- {
- var defaultDocumentTypeProperty = GetKey("/settings/content/defaultDocumentTypeProperty");
- if (string.IsNullOrEmpty(defaultDocumentTypeProperty))
- {
- defaultDocumentTypeProperty = "Textstring";
- }
-
- return defaultDocumentTypeProperty;
- }
- }
-
- ///
- /// Configuration regarding webservices
- ///
- /// Put in seperate class for more logik/seperation
- internal class WebServices
- {
- ///
- /// Gets a value indicating whether this is enabled.
- ///
- /// true if enabled; otherwise, false.
- public static bool Enabled
- {
- get
- {
- try
- {
- return
- bool.Parse(GetKeyAsNode("/settings/webservices").Attributes.GetNamedItem("enabled").Value);
- }
- catch
- {
- return false;
- }
- }
- }
-
- #region "Webservice configuration"
-
- ///
- /// Gets the document service users who have access to use the document web service
- ///
- /// The document service users.
- public static string[] DocumentServiceUsers
- {
- get
- {
- try
- {
- return GetKey("/settings/webservices/documentServiceUsers").Split(',');
- }
- catch
- {
- return new string[0];
- }
- }
- }
-
- ///
- /// Gets the file service users who have access to use the file web service
- ///
- /// The file service users.
- public static string[] FileServiceUsers
- {
- get
- {
- try
- {
- return GetKey("/settings/webservices/fileServiceUsers").Split(',');
- }
- catch
- {
- return new string[0];
- }
- }
- }
-
-
- ///
- /// Gets the folders used by the file web service
- ///
- /// The file service folders.
- public static string[] FileServiceFolders
- {
- get
- {
- try
- {
- return GetKey("/settings/webservices/fileServiceFolders").Split(',');
- }
- catch
- {
- return new string[0];
- }
- }
- }
-
- ///
- /// Gets the member service users who have access to use the member web service
- ///
- /// The member service users.
- public static string[] MemberServiceUsers
- {
- get
- {
- try
- {
- return GetKey("/settings/webservices/memberServiceUsers").Split(',');
- }
- catch
- {
- return new string[0];
- }
- }
- }
-
- ///
- /// Gets the stylesheet service users who have access to use the stylesheet web service
- ///
- /// The stylesheet service users.
- public static string[] StylesheetServiceUsers
- {
- get
- {
- try
- {
- return GetKey("/settings/webservices/stylesheetServiceUsers").Split(',');
- }
- catch
- {
- return new string[0];
- }
- }
- }
-
- ///
- /// Gets the template service users who have access to use the template web service
- ///
- /// The template service users.
- public static string[] TemplateServiceUsers
- {
- get
- {
- try
- {
- return GetKey("/settings/webservices/templateServiceUsers").Split(',');
- }
- catch
- {
- return new string[0];
- }
- }
- }
-
- ///
- /// Gets the media service users who have access to use the media web service
- ///
- /// The media service users.
- public static string[] MediaServiceUsers
- {
- get
- {
- try
- {
- return GetKey("/settings/webservices/mediaServiceUsers").Split(',');
- }
- catch
- {
- return new string[0];
- }
- }
- }
-
-
- ///
- /// Gets the maintenance service users who have access to use the maintance web service
- ///
- /// The maintenance service users.
- public static string[] MaintenanceServiceUsers
- {
- get
- {
- try
- {
- return GetKey("/settings/webservices/maintenanceServiceUsers").Split(',');
- }
- catch
- {
- return new string[0];
- }
- }
- }
-
- #endregion
- }
-
- #region Extensible settings
-
- ///
- /// Resets settings that were set programmatically, to their initial values.
- ///
- /// To be used in unit tests.
- internal static void Reset()
- {
- ResetInternal();
-
- using (new WriteLock(SectionsLock))
- {
- foreach (var section in Sections.Values)
- section.ResetSection();
- }
- }
-
- private static readonly ReaderWriterLockSlim SectionsLock = new ReaderWriterLockSlim();
- private static readonly Dictionary Sections = new Dictionary();
-
- ///
- /// Gets the specified UmbracoConfigurationSection.
- ///
- /// The type of the UmbracoConfigurationSectiont.
- /// The UmbracoConfigurationSection of the specified type.
- public static T For()
- where T : UmbracoConfigurationSection, new()
- {
- var sectionType = typeof (T);
- using (new WriteLock(SectionsLock))
- {
- if (Sections.ContainsKey(sectionType)) return Sections[sectionType] as T;
-
- var attr = sectionType.GetCustomAttribute(false);
- if (attr == null)
- throw new InvalidOperationException(string.Format("Type \"{0}\" is missing attribute ConfigurationKeyAttribute.", sectionType.FullName));
-
- var sectionKey = attr.ConfigurationKey;
- if (string.IsNullOrWhiteSpace(sectionKey))
- throw new InvalidOperationException(string.Format("Type \"{0}\" ConfigurationKeyAttribute value is null or empty.", sectionType.FullName));
-
- var section = GetSection(sectionType, sectionKey);
-
- Sections[sectionType] = section;
- return section as T;
- }
- }
-
- private static UmbracoConfigurationSection GetSection(Type sectionType, string key)
- {
- if (!sectionType.Inherits())
- throw new ArgumentException(string.Format(
- "Type \"{0}\" does not inherit from UmbracoConfigurationSection.", sectionType.FullName), "sectionType");
-
- var section = ConfigurationManager.GetSection(key);
-
- if (section != null && section.GetType() != sectionType)
- throw new InvalidCastException(string.Format("Section at key \"{0}\" is of type \"{1}\" and not \"{2}\".",
- key, section.GetType().FullName, sectionType.FullName));
-
- if (section != null) return section as UmbracoConfigurationSection;
-
- section = Activator.CreateInstance(sectionType) as UmbracoConfigurationSection;
-
- if (section == null)
- throw new NullReferenceException(string.Format(
- "Activator failed to create an instance of type \"{0}\" for key\"{1}\" and returned null.",
- sectionType.FullName, key));
-
- return section as UmbracoConfigurationSection;
- }
-
- #endregion
- }
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Web;
+using System.Web.Caching;
+using System.Web.Security;
+using System.Xml;
+using System.Configuration;
+
+using System.Collections.Generic;
+using Umbraco.Core.Logging;
+using Umbraco.Core.CodeAnnotations;
+
+
+namespace Umbraco.Core.Configuration
+{
+ //NOTE: Do not expose this class ever until we cleanup all configuration including removal of static classes, etc...
+ // we have this two tasks logged:
+ // http://issues.umbraco.org/issue/U4-58
+ // http://issues.umbraco.org/issue/U4-115
+
+ //TODO: Re-enable logging !!!!
+
+ //TODO: We need to convert this to a real section, it's currently using HttpRuntime.Cache to detect cahnges, this is real poor, especially in a console app
+
+ ///
+ /// The UmbracoSettings Class contains general settings information for the entire Umbraco instance based on information from the /config/umbracoSettings.config file
+ ///
+ internal class LegacyUmbracoSettings
+ {
+ private static bool GetKeyValue(string key, bool defaultValue)
+ {
+ bool value;
+ string stringValue = GetKey(key);
+
+ if (string.IsNullOrWhiteSpace(stringValue))
+ return defaultValue;
+ if (bool.TryParse(stringValue, out value))
+ return value;
+ return defaultValue;
+ }
+
+ private static int GetKeyValue(string key, int defaultValue)
+ {
+ int value;
+ string stringValue = GetKey(key);
+
+ if (string.IsNullOrWhiteSpace(stringValue))
+ return defaultValue;
+ if (int.TryParse(stringValue, out value))
+ return value;
+ return defaultValue;
+ }
+
+ ///
+ /// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
+ ///
+ private static void ResetInternal()
+ {
+ _addTrailingSlash = null;
+ _forceSafeAliases = null;
+ _useLegacySchema = null;
+ _useDomainPrefixes = null;
+ _umbracoLibraryCacheDuration = null;
+ SettingsFilePath = null;
+ }
+
+ internal const string TempFriendlyXmlChildContainerNodename = ""; // "children";
+
+ ///
+ /// Gets the umbraco settings document.
+ ///
+ /// The _umbraco settings.
+ internal static XmlDocument UmbracoSettingsXmlDoc
+ {
+ get
+ {
+ var us = (XmlDocument)HttpRuntime.Cache["umbracoSettingsFile"] ?? EnsureSettingsDocument();
+ return us;
+ }
+ }
+
+ private static string _path;
+
+ ///
+ /// Gets/sets the settings file path, the setter can be used in unit tests
+ ///
+ internal static string SettingsFilePath
+ {
+ get { return _path ?? (_path = GlobalSettings.FullpathToRoot + Path.DirectorySeparatorChar + "config" + Path.DirectorySeparatorChar); }
+ set { _path = value; }
+ }
+
+ internal const string Filename = "umbracoSettings.config";
+
+ internal static XmlDocument EnsureSettingsDocument()
+ {
+ var settingsFile = HttpRuntime.Cache["umbracoSettingsFile"];
+
+ // Check for language file in cache
+ if (settingsFile == null)
+ {
+ var temp = new XmlDocument();
+ var settingsReader = new XmlTextReader(SettingsFilePath + Filename);
+ try
+ {
+ temp.Load(settingsReader);
+ HttpRuntime.Cache.Insert("umbracoSettingsFile", temp,
+ new CacheDependency(SettingsFilePath + Filename));
+ }
+ catch (XmlException e)
+ {
+ throw new XmlException("Your umbracoSettings.config file fails to pass as valid XML. Refer to the InnerException for more information", e);
+ }
+ catch (Exception e)
+ {
+ LogHelper.Error("Error reading umbracoSettings file: " + e.ToString(), e);
+ }
+ settingsReader.Close();
+ return temp;
+ }
+ else
+ return (XmlDocument)settingsFile;
+ }
+
+ internal static void Save()
+ {
+ UmbracoSettingsXmlDoc.Save(SettingsFilePath + Filename);
+ }
+
+
+ ///
+ /// Selects a xml node in the umbraco settings config file.
+ ///
+ /// The xpath query to the specific node.
+ /// If found, it returns the specific configuration xml node.
+ internal static XmlNode GetKeyAsNode(string key)
+ {
+ if (key == null)
+ throw new ArgumentException("Key cannot be null");
+ EnsureSettingsDocument();
+ if (UmbracoSettingsXmlDoc == null || UmbracoSettingsXmlDoc.DocumentElement == null)
+ return null;
+ return UmbracoSettingsXmlDoc.DocumentElement.SelectSingleNode(key);
+ }
+
+ ///
+ /// Gets the value of configuration xml node with the specified key.
+ ///
+ /// The key.
+ ///
+ internal static string GetKey(string key)
+ {
+ EnsureSettingsDocument();
+
+ string attrName = null;
+ var pos = key.IndexOf('@');
+ if (pos > 0)
+ {
+ attrName = key.Substring(pos + 1);
+ key = key.Substring(0, pos - 1);
+ }
+
+ var node = UmbracoSettingsXmlDoc.DocumentElement.SelectSingleNode(key);
+ if (node == null)
+ return string.Empty;
+
+ if (pos < 0)
+ {
+ if (node.FirstChild == null || node.FirstChild.Value == null)
+ return string.Empty;
+ return node.FirstChild.Value;
+ }
+ else
+ {
+ var attr = node.Attributes[attrName];
+ if (attr == null)
+ return string.Empty;
+ return attr.Value;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the media library will create new directories in the /media directory.
+ ///
+ ///
+ /// true if new directories are allowed otherwise, false.
+ ///
+ internal static bool UploadAllowDirectories
+ {
+ get { return bool.Parse(GetKey("/settings/content/UploadAllowDirectories")); }
+ }
+
+ ///
+ /// THIS IS TEMPORARY until we fix up settings all together, this setting is actually not 'settable' but is
+ /// here for future purposes since we check for thsi settings in the module.
+ ///
+ internal static bool EnableBaseRestHandler
+ {
+ get { return true; }
+ }
+
+ ///
+ /// THIS IS TEMPORARY until we fix up settings all together, this setting is actually not 'settable' but is
+ /// here for future purposes since we check for thsi settings in the module.
+ ///
+ internal static string BootSplashPage
+ {
+ get { return "~/config/splashes/booting.aspx"; }
+ }
+
+ ///
+ /// Gets a value indicating whether logging is enabled in umbracoSettings.config (/settings/logging/enableLogging).
+ ///
+ /// true if logging is enabled; otherwise, false.
+ internal static bool EnableLogging
+ {
+ get
+ {
+ // We return true if no enable logging element is present in
+ // umbracoSettings (to enable default behaviour when upgrading)
+ var enableLogging = GetKey("/settings/logging/enableLogging");
+ return String.IsNullOrEmpty(enableLogging) || bool.Parse(enableLogging);
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether logging happens async.
+ ///
+ /// true if async logging is enabled; otherwise, false.
+ internal static bool EnableAsyncLogging
+ {
+ get
+ {
+ string value = GetKey("/settings/logging/enableAsyncLogging");
+ bool result;
+ if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
+ return result;
+ return false;
+ }
+ }
+
+ ///
+ /// Gets the assembly of an external logger that can be used to store log items in 3rd party systems
+ ///
+ internal static string ExternalLoggerAssembly
+ {
+ get
+ {
+ var value = GetKeyAsNode("/settings/logging/externalLogger");
+ return value != null ? value.Attributes["assembly"].Value : "";
+ }
+ }
+
+ ///
+ /// Gets the type of an external logger that can be used to store log items in 3rd party systems
+ ///
+ internal static string ExternalLoggerType
+ {
+ get
+ {
+ var value = GetKeyAsNode("/settings/logging/externalLogger");
+ return value != null ? value.Attributes["type"].Value : "";
+ }
+ }
+
+ ///
+ /// Long Audit Trail to external log too
+ ///
+ internal static bool ExternalLoggerLogAuditTrail
+ {
+ get
+ {
+ var value = GetKeyAsNode("/settings/logging/externalLogger");
+ if (value != null)
+ {
+ var logAuditTrail = value.Attributes["logAuditTrail"].Value;
+ bool result;
+ if (!string.IsNullOrEmpty(logAuditTrail) && bool.TryParse(logAuditTrail, out result))
+ return result;
+ }
+ return false;
+ }
+ }
+
+ ///
+ /// Keep user alive as long as they have their browser open? Default is true
+ ///
+ internal static bool KeepUserLoggedIn
+ {
+ get
+ {
+ var value = GetKey("/settings/security/keepUserLoggedIn");
+ bool result;
+ if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
+ return result;
+ return true;
+ }
+ }
+
+ internal static string AuthCookieName
+ {
+ get
+ {
+ var value = GetKey("/settings/security/authCookieName");
+ if (string.IsNullOrEmpty(value) == false)
+ {
+ return value;
+ }
+ return "UMB_UCONTEXT";
+ }
+ }
+
+ internal static string AuthCookieDomain
+ {
+ get
+ {
+ var value = GetKey("/settings/security/authCookieDomain");
+ if (string.IsNullOrEmpty(value) == false)
+ {
+ return value;
+ }
+ return FormsAuthentication.CookieDomain;
+ }
+ }
+
+ ///
+ /// Enables the experimental canvas (live) editing on the frontend of the website
+ ///
+ internal static bool EnableCanvasEditing
+ {
+ get
+ {
+ var value = GetKey("/settings/content/EnableCanvasEditing");
+ bool result;
+ if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
+ return result;
+ return true;
+ }
+ }
+
+ ///
+ /// Show disabled users in the tree in the Users section in the backoffice
+ ///
+ internal static bool HideDisabledUsersInBackoffice
+ {
+ get
+ {
+ string value = GetKey("/settings/security/hideDisabledUsersInBackoffice");
+ bool result;
+ if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
+ return result;
+ return false;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the logs will be auto cleaned
+ ///
+ /// true if logs are to be automatically cleaned; otherwise, false
+ internal static bool AutoCleanLogs
+ {
+ get
+ {
+ string value = GetKey("/settings/logging/autoCleanLogs");
+ bool result;
+ if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
+ return result;
+ return false;
+ }
+ }
+
+ ///
+ /// Gets the value indicating the log cleaning frequency (in miliseconds)
+ ///
+ internal static int CleaningMiliseconds
+ {
+ get
+ {
+ string value = GetKey("/settings/logging/cleaningMiliseconds");
+ int result;
+ if (!string.IsNullOrEmpty(value) && int.TryParse(value, out result))
+ return result;
+ return -1;
+ }
+ }
+
+ internal static int MaxLogAge
+ {
+ get
+ {
+ string value = GetKey("/settings/logging/maxLogAge");
+ int result;
+ if (!string.IsNullOrEmpty(value) && int.TryParse(value, out result))
+ return result;
+ return -1;
+ }
+ }
+
+ ///
+ /// Gets the disabled log types.
+ ///
+ /// The disabled log types.
+ internal static XmlNode DisabledLogTypes
+ {
+ get { return GetKeyAsNode("/settings/logging/disabledLogTypes"); }
+ }
+
+ ///
+ /// Gets the package server url.
+ ///
+ /// The package server url.
+ internal static string PackageServer
+ {
+ get { return "packages.umbraco.org"; }
+ }
+
+ static bool? _useDomainPrefixes = null;
+
+ ///
+ /// Gets a value indicating whether umbraco will use domain prefixes.
+ ///
+ /// true if umbraco will use domain prefixes; otherwise, false.
+ internal static bool UseDomainPrefixes
+ {
+ get
+ {
+ // default: false
+ return _useDomainPrefixes ?? GetKeyValue("/settings/requestHandler/useDomainPrefixes", false);
+ }
+ /*internal*/ set
+ {
+ // for unit tests only
+ _useDomainPrefixes = value;
+ }
+ }
+
+ static bool? _addTrailingSlash = null;
+
+ ///
+ /// This will add a trailing slash (/) to urls when in directory url mode
+ /// NOTICE: This will always return false if Directory Urls in not active
+ ///
+ internal static bool AddTrailingSlash
+ {
+ get
+ {
+ // default: false
+ return GlobalSettings.UseDirectoryUrls
+ && (_addTrailingSlash ?? GetKeyValue("/settings/requestHandler/addTrailingSlash", false));
+ }
+ /*internal*/ set
+ {
+ // for unit tests only
+ _addTrailingSlash = value;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether umbraco will use ASP.NET MasterPages for rendering instead of its propriatary templating system.
+ ///
+ /// true if umbraco will use ASP.NET MasterPages; otherwise, false.
+ internal static bool UseAspNetMasterPages
+ {
+ get
+ {
+ try
+ {
+ bool result;
+ if (bool.TryParse(GetKey("/settings/templates/useAspNetMasterPages"), out result))
+ return result;
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether umbraco will attempt to load any skins to override default template files
+ ///
+ /// true if umbraco will override templates with skins if present and configured false.
+ internal static bool EnableTemplateFolders
+ {
+ get
+ {
+ try
+ {
+ bool result;
+ if (bool.TryParse(GetKey("/settings/templates/enableTemplateFolders"), out result))
+ return result;
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ //TODO: I"m not sure why we need this, need to ask Gareth what the deal is, pretty sure we can remove it or change it, seems like
+ // massive overkill.
+
+ ///
+ /// razor DynamicNode typecasting detects XML and returns DynamicXml - Root elements that won't convert to DynamicXml
+ ///
+ internal static IEnumerable NotDynamicXmlDocumentElements
+ {
+ get
+ {
+ try
+ {
+ List items = new List();
+ XmlNode root = GetKeyAsNode("/settings/scripting/razor/notDynamicXmlDocumentElements");
+ foreach (XmlNode element in root.SelectNodes(".//element"))
+ {
+ items.Add(element.InnerText);
+ }
+ return items;
+ }
+ catch
+ {
+ return new List() { "p", "div" };
+ }
+ }
+ }
+
+ private static IEnumerable _razorDataTypeModelStaticMapping;
+ private static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
+
+ internal static IEnumerable RazorDataTypeModelStaticMapping
+ {
+ get
+ {
+ /*
+
+ DigibizAdvancedMediaPicker.RazorModel.ModelBinder
+ DigibizAdvancedMediaPicker.RazorModel.ModelBinder
+
+ */
+
+ using (var l = new UpgradeableReadLock(Lock))
+ {
+ if (_razorDataTypeModelStaticMapping == null)
+ {
+ l.UpgradeToWriteLock();
+
+ List items = new List();
+ XmlNode root = GetKeyAsNode("/settings/scripting/razor/dataTypeModelStaticMappings");
+ if (root != null)
+ {
+ foreach (XmlNode element in root.SelectNodes(".//mapping"))
+ {
+ string propertyTypeAlias = null, nodeTypeAlias = null;
+ Guid? dataTypeGuid = null;
+ if (!string.IsNullOrEmpty(element.InnerText))
+ {
+ if (element.Attributes["dataTypeGuid"] != null)
+ {
+ dataTypeGuid = (Guid?)new Guid(element.Attributes["dataTypeGuid"].Value);
+ }
+ if (element.Attributes["propertyTypeAlias"] != null && !string.IsNullOrEmpty(element.Attributes["propertyTypeAlias"].Value))
+ {
+ propertyTypeAlias = element.Attributes["propertyTypeAlias"].Value;
+ }
+ if (element.Attributes["nodeTypeAlias"] != null && !string.IsNullOrEmpty(element.Attributes["nodeTypeAlias"].Value))
+ {
+ nodeTypeAlias = element.Attributes["nodeTypeAlias"].Value;
+ }
+ items.Add(new RazorDataTypeModelStaticMappingItem()
+ {
+ DataTypeGuid = dataTypeGuid,
+ PropertyTypeAlias = propertyTypeAlias,
+ NodeTypeAlias = nodeTypeAlias,
+ TypeName = element.InnerText,
+ Raw = element.OuterXml
+ });
+ }
+ }
+ }
+
+ _razorDataTypeModelStaticMapping = items;
+ }
+
+ return _razorDataTypeModelStaticMapping;
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether umbraco will clone XML cache on publish.
+ ///
+ ///
+ /// true if umbraco will clone XML cache on publish; otherwise, false.
+ ///
+ internal static bool CloneXmlCacheOnPublish
+ {
+ get
+ {
+ try
+ {
+ bool result;
+ if (bool.TryParse(GetKey("/settings/content/cloneXmlContent"), out result))
+ return result;
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether rich text editor content should be parsed by tidy.
+ ///
+ /// true if content is parsed; otherwise, false.
+ internal static bool TidyEditorContent
+ {
+ get { return bool.Parse(GetKey("/settings/content/TidyEditorContent")); }
+ }
+
+ ///
+ /// Gets the encoding type for the tidyied content.
+ ///
+ /// The encoding type as string.
+ internal static string TidyCharEncoding
+ {
+ get
+ {
+ string encoding = GetKey("/settings/content/TidyCharEncoding");
+ if (String.IsNullOrEmpty(encoding))
+ {
+ encoding = "UTF8";
+ }
+ return encoding;
+ }
+ }
+
+ ///
+ /// Gets the property context help option, this can either be 'text', 'icon' or 'none'
+ ///
+ /// The property context help option.
+ internal static string PropertyContextHelpOption
+ {
+ get { return GetKey("/settings/content/PropertyContextHelpOption").ToLower(); }
+ }
+
+ internal static string DefaultBackofficeProvider
+ {
+ get
+ {
+ string defaultProvider = GetKey("/settings/providers/users/DefaultBackofficeProvider");
+ if (String.IsNullOrEmpty(defaultProvider))
+ defaultProvider = "UsersMembershipProvider";
+
+ return defaultProvider;
+ }
+ }
+
+ private static bool? _forceSafeAliases;
+
+ ///
+ /// Whether to force safe aliases (no spaces, no special characters) at businesslogic level on contenttypes and propertytypes
+ ///
+ internal static bool ForceSafeAliases
+ {
+ get
+ {
+ // default: true
+ return _forceSafeAliases ?? GetKeyValue("/settings/content/ForceSafeAliases", true);
+ }
+ /*internal*/ set
+ {
+ // used for unit testing
+ _forceSafeAliases = value;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether to try to skip IIS custom errors.
+ ///
+ [UmbracoWillObsolete("Use UmbracoSettings.For.TrySkipIisCustomErrors instead.")]
+ internal static bool TrySkipIisCustomErrors
+ {
+ get { return GetKeyValue("/settings/web.routing/@trySkipIisCustomErrors", false); }
+ }
+
+ ///
+ /// Gets a value indicating whether internal redirect preserves the template.
+ ///
+ [UmbracoWillObsolete("Use UmbracoSettings.For.InternalRedirectPerservesTemplate instead.")]
+ internal static bool InternalRedirectPreservesTemplate
+ {
+ get { return GetKeyValue("/settings/web.routing/@internalRedirectPreservesTemplate", false); }
+ }
+
+ ///
+ /// File types that will not be allowed to be uploaded via the content/media upload control
+ ///
+ public static IEnumerable DisallowedUploadFiles
+ {
+ get
+ {
+ var val = GetKey("/settings/content/disallowedUploadFiles");
+ return val.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
+ }
+ }
+
+ ///
+ /// Gets the allowed image file types.
+ ///
+ /// The allowed image file types.
+ internal static string ImageFileTypes
+ {
+ get { return GetKey("/settings/content/imaging/imageFileTypes").ToLowerInvariant(); }
+ }
+
+ ///
+ /// Gets the allowed script file types.
+ ///
+ /// The allowed script file types.
+ internal static string ScriptFileTypes
+ {
+ get { return GetKey("/settings/content/scripteditor/scriptFileTypes"); }
+ }
+
+ private static int? _umbracoLibraryCacheDuration;
+
+ ///
+ /// Gets the duration in seconds to cache queries to umbraco library member and media methods
+ /// Default is 1800 seconds (30 minutes)
+ ///
+ internal static int UmbracoLibraryCacheDuration
+ {
+ get
+ {
+ // default: 1800
+ return _umbracoLibraryCacheDuration ?? GetKeyValue("/settings/content/UmbracoLibraryCacheDuration", 1800);
+ }
+ /*internal*/ set
+ {
+ // for unit tests only
+ _umbracoLibraryCacheDuration = value;
+ }
+ }
+
+ ///
+ /// Gets the path to the scripts folder used by the script editor.
+ ///
+ /// The script folder path.
+ internal static string ScriptFolderPath
+ {
+ get { return GetKey("/settings/content/scripteditor/scriptFolderPath"); }
+ }
+
+ ///
+ /// Enabled or disable the script/code editor
+ ///
+ internal static bool ScriptDisableEditor
+ {
+ get
+ {
+ string _tempValue = GetKey("/settings/content/scripteditor/scriptDisableEditor");
+ if (_tempValue != String.Empty)
+ return bool.Parse(_tempValue);
+ else
+ return false;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether umbraco will ensure unique node naming.
+ /// This will ensure that nodes cannot have the same url, but will add extra characters to a url.
+ /// ex: existingnodename.aspx would become existingnodename(1).aspx if a node with the same name is found
+ ///
+ /// true if umbraco ensures unique node naming; otherwise, false.
+ internal static bool EnsureUniqueNaming
+ {
+ get
+ {
+ try
+ {
+ return bool.Parse(GetKey("/settings/content/ensureUniqueNaming"));
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Gets the notification email sender.
+ ///
+ /// The notification email sender.
+ internal static string NotificationEmailSender
+ {
+ get { return GetKey("/settings/content/notifications/email"); }
+ }
+
+ ///
+ /// Gets a value indicating whether notification-emails are HTML.
+ ///
+ ///
+ /// true if html notification-emails are disabled; otherwise, false.
+ ///
+ internal static bool NotificationDisableHtmlEmail
+ {
+ get
+ {
+ var tempValue = GetKey("/settings/content/notifications/disableHtmlEmail");
+ return tempValue != String.Empty && bool.Parse(tempValue);
+ }
+ }
+
+ ///
+ /// Gets the allowed attributes on images.
+ ///
+ /// The allowed attributes on images.
+ internal static string ImageAllowedAttributes
+ {
+ get { return GetKey("/settings/content/imaging/allowedAttributes"); }
+ }
+
+ internal static XmlNode ImageAutoFillImageProperties
+ {
+ get { return GetKeyAsNode("/settings/content/imaging/autoFillImageProperties"); }
+ }
+
+ ///
+ /// Gets the scheduled tasks as XML
+ ///
+ /// The scheduled tasks.
+ internal static XmlNode ScheduledTasks
+ {
+ get { return GetKeyAsNode("/settings/scheduledTasks"); }
+ }
+
+ ///
+ /// Gets a list of characters that will be replaced when generating urls
+ ///
+ /// The URL replacement characters.
+ internal static XmlNode UrlReplaceCharacters
+ {
+ get { return GetKeyAsNode("/settings/requestHandler/urlReplacing"); }
+ }
+
+ ///
+ /// Whether to replace double dashes from url (ie my--story----from--dash.aspx caused by multiple url replacement chars
+ ///
+ internal static bool RemoveDoubleDashesFromUrlReplacing
+ {
+ get
+ {
+ try
+ {
+ return bool.Parse(UrlReplaceCharacters.Attributes.GetNamedItem("removeDoubleDashes").Value);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether umbraco will use distributed calls.
+ /// This enables umbraco to share cache and content across multiple servers.
+ /// Used for load-balancing high-traffic sites.
+ ///
+ /// true if umbraco uses distributed calls; otherwise, false.
+ internal static bool UseDistributedCalls
+ {
+ get
+ {
+ try
+ {
+ return bool.Parse(GetKeyAsNode("/settings/distributedCall").Attributes.GetNamedItem("enable").Value);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+
+ ///
+ /// Gets the ID of the user with access rights to perform the distributed calls.
+ ///
+ /// The distributed call user.
+ internal static int DistributedCallUser
+ {
+ get
+ {
+ try
+ {
+ return int.Parse(GetKey("/settings/distributedCall/user"));
+ }
+ catch
+ {
+ return -1;
+ }
+ }
+ }
+
+ ///
+ /// Gets the html injected into a (x)html page if Umbraco is running in preview mode
+ ///
+ internal static string PreviewBadge
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/content/PreviewBadge");
+ }
+ catch
+ {
+ return "In Preview Mode - click to end";
+ }
+ }
+ }
+
+ ///
+ /// Gets IP or hostnames of the distribution servers.
+ /// These servers will receive a call everytime content is created/deleted/removed
+ /// and update their content cache accordingly, ensuring a consistent cache on all servers
+ ///
+ /// The distribution servers.
+ internal static XmlNode DistributionServers
+ {
+ get
+ {
+ try
+ {
+ return GetKeyAsNode("/settings/distributedCall/servers");
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ }
+
+ ///
+ /// Gets HelpPage configurations.
+ /// A help page configuration specify language, user type, application, application url and
+ /// the target help page url.
+ ///
+ internal static XmlNode HelpPages
+ {
+ get
+ {
+ try
+ {
+ return GetKeyAsNode("/settings/help");
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ }
+
+ ///
+ /// Gets all repositories registered, and returns them as XmlNodes, containing name, alias and webservice url.
+ /// These repositories are used by the build-in package installer and uninstaller to install new packages and check for updates.
+ /// All repositories should have a unique alias.
+ /// All packages installed from a repository gets the repository alias included in the install information
+ ///
+ /// The repository servers.
+ internal static XmlNode Repositories
+ {
+ get
+ {
+ try
+ {
+ return GetKeyAsNode("/settings/repositories");
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether umbraco will use the viewstate mover module.
+ /// The viewstate mover will move all asp.net viewstate information to the bottom of the aspx page
+ /// to ensure that search engines will index text instead of javascript viewstate information.
+ ///
+ ///
+ /// true if umbraco will use the viewstate mover module; otherwise, false.
+ ///
+ internal static bool UseViewstateMoverModule
+ {
+ get
+ {
+ try
+ {
+ return
+ bool.Parse(
+ GetKeyAsNode("/settings/viewstateMoverModule").Attributes.GetNamedItem("enable").Value);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+
+ ///
+ /// Tells us whether the Xml Content cache is disabled or not
+ /// Default is enabled
+ ///
+ internal static bool IsXmlContentCacheDisabled
+ {
+ get
+ {
+ try
+ {
+ bool xmlCacheEnabled;
+ string value = GetKey("/settings/content/XmlCacheEnabled");
+ if (bool.TryParse(value, out xmlCacheEnabled))
+ return !xmlCacheEnabled;
+ // Return default
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Check if there's changes to the umbraco.config xml file cache on disk on each request
+ /// Makes it possible to updates environments by syncing the umbraco.config file across instances
+ /// Relates to http://umbraco.codeplex.com/workitem/30722
+ ///
+ internal static bool XmlContentCheckForDiskChanges
+ {
+ get
+ {
+ try
+ {
+ bool checkForDiskChanges;
+ string value = GetKey("/settings/content/XmlContentCheckForDiskChanges");
+ if (bool.TryParse(value, out checkForDiskChanges))
+ return checkForDiskChanges;
+ // Return default
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// If this is enabled, all Umbraco objects will generate data in the preview table (cmsPreviewXml).
+ /// If disabled, only documents will generate data.
+ /// This feature is useful if anyone would like to see how data looked at a given time
+ ///
+ internal static bool EnableGlobalPreviewStorage
+ {
+ get
+ {
+ try
+ {
+ bool globalPreviewEnabled = false;
+ string value = GetKey("/settings/content/GlobalPreviewStorageEnabled");
+ if (bool.TryParse(value, out globalPreviewEnabled))
+ return !globalPreviewEnabled;
+ // Return default
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ private static bool? _useLegacySchema;
+
+ ///
+ /// Whether to use the new 4.1 schema or the old legacy schema
+ ///
+ ///
+ /// true if yes, use the old node/data model; otherwise, false.
+ ///
+ internal static bool UseLegacyXmlSchema
+ {
+ get
+ {
+ // default: true
+ return _useLegacySchema ?? GetKeyValue("/settings/content/UseLegacyXmlSchema", false);
+ }
+ /*internal*/ set
+ {
+ // used for unit testing
+ _useLegacySchema = value;
+ }
+ }
+
+ [Obsolete("This setting is not used anymore, the only file extensions that are supported are .cs and .vb files")]
+ internal static IEnumerable AppCodeFileExtensionsList
+ {
+ get
+ {
+ return (from XmlNode x in AppCodeFileExtensions
+ where !String.IsNullOrEmpty(x.InnerText)
+ select x.InnerText).ToList();
+ }
+ }
+
+ [Obsolete("This setting is not used anymore, the only file extensions that are supported are .cs and .vb files")]
+ internal static XmlNode AppCodeFileExtensions
+ {
+ get
+ {
+ XmlNode value = GetKeyAsNode("/settings/developer/appCodeFileExtensions");
+ if (value != null)
+ {
+ return value;
+ }
+
+ // default is .cs and .vb
+ value = UmbracoSettingsXmlDoc.CreateElement("appCodeFileExtensions");
+ value.AppendChild(XmlHelper.AddTextNode(UmbracoSettingsXmlDoc, "ext", "cs"));
+ value.AppendChild(XmlHelper.AddTextNode(UmbracoSettingsXmlDoc, "ext", "vb"));
+ return value;
+ }
+ }
+
+ ///
+ /// Tells us whether the Xml to always update disk cache, when changes are made to content
+ /// Default is enabled
+ ///
+ internal static bool ContinouslyUpdateXmlDiskCache
+ {
+ get
+ {
+ try
+ {
+ bool updateDiskCache;
+ string value = GetKey("/settings/content/ContinouslyUpdateXmlDiskCache");
+ if (bool.TryParse(value, out updateDiskCache))
+ return updateDiskCache;
+ // Return default
+ return false;
+ }
+ catch
+ {
+ return true;
+ }
+ }
+ }
+
+ ///
+ /// Tells us whether to use a splash page while umbraco is initializing content.
+ /// If not, requests are queued while umbraco loads content. For very large sites (+10k nodes) it might be usefull to
+ /// have a splash page
+ /// Default is disabled
+ ///
+ internal static bool EnableSplashWhileLoading
+ {
+ get
+ {
+ try
+ {
+ bool updateDiskCache;
+ string value = GetKey("/settings/content/EnableSplashWhileLoading");
+ if (bool.TryParse(value, out updateDiskCache))
+ return updateDiskCache;
+ // Return default
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ private static bool? _resolveUrlsFromTextString;
+ internal static bool ResolveUrlsFromTextString
+ {
+ get
+ {
+ if (_resolveUrlsFromTextString == null)
+ {
+ try
+ {
+ bool enableDictionaryFallBack;
+ var value = GetKey("/settings/content/ResolveUrlsFromTextString");
+ if (value != null)
+ if (bool.TryParse(value, out enableDictionaryFallBack))
+ _resolveUrlsFromTextString = enableDictionaryFallBack;
+ }
+ catch (Exception ex)
+ {
+ Trace.WriteLine("Could not load /settings/content/ResolveUrlsFromTextString from umbracosettings.config:\r\n {0}",
+ ex.Message);
+
+ // set url resolving to true (default (legacy) behavior) to ensure we don't keep writing to trace
+ _resolveUrlsFromTextString = true;
+ }
+ }
+ return _resolveUrlsFromTextString == true;
+ }
+ }
+
+
+ private static RenderingEngine? _defaultRenderingEngine;
+
+ ///
+ /// Enables MVC, and at the same time disable webform masterpage templates.
+ /// This ensure views are automaticly created instead of masterpages.
+ /// Views are display in the tree instead of masterpages and a MVC template editor
+ /// is used instead of the masterpages editor
+ ///
+ /// true if umbraco defaults to using MVC views for templating, otherwise false.
+ internal static RenderingEngine DefaultRenderingEngine
+ {
+ get
+ {
+ if (_defaultRenderingEngine == null)
+ {
+ try
+ {
+ var engine = RenderingEngine.WebForms;
+ var value = GetKey("/settings/templates/defaultRenderingEngine");
+ if (value != null)
+ {
+ Enum.TryParse(value, true, out engine);
+ }
+ _defaultRenderingEngine = engine;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.Error("Could not load /settings/templates/defaultRenderingEngine from umbracosettings.config", ex);
+ _defaultRenderingEngine = RenderingEngine.WebForms;
+ }
+ }
+ return _defaultRenderingEngine.Value;
+ }
+ //internal set
+ //{
+ // _defaultRenderingEngine = value;
+ // var node = UmbracoSettingsXmlDoc.DocumentElement.SelectSingleNode("/settings/templates/defaultRenderingEngine");
+ // node.InnerText = value.ToString();
+ //}
+ }
+
+ private static MacroErrorBehaviour? _macroErrorBehaviour;
+
+ ///
+ /// This configuration setting defines how to handle macro errors:
+ /// - Inline - Show error within macro as text (default and current Umbraco 'normal' behavior)
+ /// - Silent - Suppress error and hide macro
+ /// - Throw - Throw an exception and invoke the global error handler (if one is defined, if not you'll get a YSOD)
+ ///
+ /// MacroErrorBehaviour enum defining how to handle macro errors.
+ internal static MacroErrorBehaviour MacroErrorBehaviour
+ {
+ get
+ {
+ if (_macroErrorBehaviour == null)
+ {
+ try
+ {
+ var behaviour = MacroErrorBehaviour.Inline;
+ var value = GetKey("/settings/content/MacroErrors");
+ if (value != null)
+ {
+ Enum.TryParse(value, true, out behaviour);
+ }
+ _macroErrorBehaviour = behaviour;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.Error("Could not load /settings/content/MacroErrors from umbracosettings.config", ex);
+ _macroErrorBehaviour = MacroErrorBehaviour.Inline;
+ }
+ }
+ return _macroErrorBehaviour.Value;
+ }
+ }
+
+ private static IconPickerBehaviour? _iconPickerBehaviour;
+
+ ///
+ /// This configuration setting defines how to show icons in the document type editor.
+ /// - ShowDuplicates - Show duplicates in files and sprites. (default and current Umbraco 'normal' behaviour)
+ /// - HideSpriteDuplicates - Show files on disk and hide duplicates from the sprite
+ /// - HideFileDuplicates - Show files in the sprite and hide duplicates on disk
+ ///
+ /// MacroErrorBehaviour enum defining how to show icons in the document type editor.
+ internal static IconPickerBehaviour IconPickerBehaviour
+ {
+ get
+ {
+ if (_iconPickerBehaviour == null)
+ {
+ try
+ {
+ var behaviour = IconPickerBehaviour.ShowDuplicates;
+ var value = GetKey("/settings/content/DocumentTypeIconList");
+ if (value != null)
+ {
+ Enum.TryParse(value, true, out behaviour);
+ }
+ _iconPickerBehaviour = behaviour;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.Error("Could not load /settings/content/DocumentTypeIconList from umbracosettings.config", ex);
+ _iconPickerBehaviour = IconPickerBehaviour.ShowDuplicates;
+ }
+ }
+ return _iconPickerBehaviour.Value;
+ }
+ }
+
+ ///
+ /// Gets the default document type property used when adding new properties through the back-office
+ ///
+ /// Configured text for the default document type property
+ /// If undefined, 'Textstring' is the default
+ public static string DefaultDocumentTypeProperty
+ {
+ get
+ {
+ var defaultDocumentTypeProperty = GetKey("/settings/content/defaultDocumentTypeProperty");
+ if (string.IsNullOrEmpty(defaultDocumentTypeProperty))
+ {
+ defaultDocumentTypeProperty = "Textstring";
+ }
+
+ return defaultDocumentTypeProperty;
+ }
+ }
+
+ ///
+ /// Configuration regarding webservices
+ ///
+ /// Put in seperate class for more logik/seperation
+ internal class WebServices
+ {
+ ///
+ /// Gets a value indicating whether this is enabled.
+ ///
+ /// true if enabled; otherwise, false.
+ public static bool Enabled
+ {
+ get
+ {
+ try
+ {
+ return
+ bool.Parse(GetKeyAsNode("/settings/webservices").Attributes.GetNamedItem("enabled").Value);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ #region "Webservice configuration"
+
+ ///
+ /// Gets the document service users who have access to use the document web service
+ ///
+ /// The document service users.
+ public static string[] DocumentServiceUsers
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/webservices/documentServiceUsers").Split(',');
+ }
+ catch
+ {
+ return new string[0];
+ }
+ }
+ }
+
+ ///
+ /// Gets the file service users who have access to use the file web service
+ ///
+ /// The file service users.
+ public static string[] FileServiceUsers
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/webservices/fileServiceUsers").Split(',');
+ }
+ catch
+ {
+ return new string[0];
+ }
+ }
+ }
+
+
+ ///
+ /// Gets the folders used by the file web service
+ ///
+ /// The file service folders.
+ public static string[] FileServiceFolders
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/webservices/fileServiceFolders").Split(',');
+ }
+ catch
+ {
+ return new string[0];
+ }
+ }
+ }
+
+ ///
+ /// Gets the member service users who have access to use the member web service
+ ///
+ /// The member service users.
+ public static string[] MemberServiceUsers
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/webservices/memberServiceUsers").Split(',');
+ }
+ catch
+ {
+ return new string[0];
+ }
+ }
+ }
+
+ ///
+ /// Gets the stylesheet service users who have access to use the stylesheet web service
+ ///
+ /// The stylesheet service users.
+ public static string[] StylesheetServiceUsers
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/webservices/stylesheetServiceUsers").Split(',');
+ }
+ catch
+ {
+ return new string[0];
+ }
+ }
+ }
+
+ ///
+ /// Gets the template service users who have access to use the template web service
+ ///
+ /// The template service users.
+ public static string[] TemplateServiceUsers
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/webservices/templateServiceUsers").Split(',');
+ }
+ catch
+ {
+ return new string[0];
+ }
+ }
+ }
+
+ ///
+ /// Gets the media service users who have access to use the media web service
+ ///
+ /// The media service users.
+ public static string[] MediaServiceUsers
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/webservices/mediaServiceUsers").Split(',');
+ }
+ catch
+ {
+ return new string[0];
+ }
+ }
+ }
+
+
+ ///
+ /// Gets the maintenance service users who have access to use the maintance web service
+ ///
+ /// The maintenance service users.
+ public static string[] MaintenanceServiceUsers
+ {
+ get
+ {
+ try
+ {
+ return GetKey("/settings/webservices/maintenanceServiceUsers").Split(',');
+ }
+ catch
+ {
+ return new string[0];
+ }
+ }
+ }
+
+ #endregion
+ }
+
+ #region Extensible settings
+
+ ///
+ /// Resets settings that were set programmatically, to their initial values.
+ ///
+ /// To be used in unit tests.
+ internal static void Reset()
+ {
+ ResetInternal();
+
+ using (new WriteLock(SectionsLock))
+ {
+ foreach (var section in Sections.Values)
+ section.ResetSection();
+ }
+ }
+
+ private static readonly ReaderWriterLockSlim SectionsLock = new ReaderWriterLockSlim();
+ private static readonly Dictionary Sections = new Dictionary();
+
+ ///
+ /// Gets the specified UmbracoConfigurationSection.
+ ///
+ /// The type of the UmbracoConfigurationSectiont.
+ /// The UmbracoConfigurationSection of the specified type.
+ public static T For()
+ where T : UmbracoConfigurationSection, new()
+ {
+ var sectionType = typeof (T);
+ using (new WriteLock(SectionsLock))
+ {
+ if (Sections.ContainsKey(sectionType)) return Sections[sectionType] as T;
+
+ var attr = sectionType.GetCustomAttribute(false);
+ if (attr == null)
+ throw new InvalidOperationException(string.Format("Type \"{0}\" is missing attribute ConfigurationKeyAttribute.", sectionType.FullName));
+
+ var sectionKey = attr.ConfigurationKey;
+ if (string.IsNullOrWhiteSpace(sectionKey))
+ throw new InvalidOperationException(string.Format("Type \"{0}\" ConfigurationKeyAttribute value is null or empty.", sectionType.FullName));
+
+ var section = GetSection(sectionType, sectionKey);
+
+ Sections[sectionType] = section;
+ return section as T;
+ }
+ }
+
+ private static UmbracoConfigurationSection GetSection(Type sectionType, string key)
+ {
+ if (!sectionType.Inherits())
+ throw new ArgumentException(string.Format(
+ "Type \"{0}\" does not inherit from UmbracoConfigurationSection.", sectionType.FullName), "sectionType");
+
+ var section = ConfigurationManager.GetSection(key);
+
+ if (section != null && section.GetType() != sectionType)
+ throw new InvalidCastException(string.Format("Section at key \"{0}\" is of type \"{1}\" and not \"{2}\".",
+ key, section.GetType().FullName, sectionType.FullName));
+
+ if (section != null) return section as UmbracoConfigurationSection;
+
+ section = Activator.CreateInstance(sectionType) as UmbracoConfigurationSection;
+
+ if (section == null)
+ throw new NullReferenceException(string.Format(
+ "Activator failed to create an instance of type \"{0}\" for key\"{1}\" and returned null.",
+ sectionType.FullName, key));
+
+ return section as UmbracoConfigurationSection;
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/AppCodeFileExtensionsCollection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/AppCodeFileExtensionsCollection.cs
new file mode 100644
index 0000000000..ab4e51a946
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/AppCodeFileExtensionsCollection.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class AppCodeFileExtensionsCollection : ConfigurationElementCollection, IEnumerable
+ {
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new FileExtensionElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((FileExtensionElement)element).Value;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ for (var i = 0; i < Count; i++)
+ {
+ yield return BaseGet(i) as FileExtensionElement;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/AppCodeFileExtensionsElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/AppCodeFileExtensionsElement.cs
new file mode 100644
index 0000000000..707b83d638
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/AppCodeFileExtensionsElement.cs
@@ -0,0 +1,14 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class AppCodeFileExtensionsElement : ConfigurationElement
+ {
+ [ConfigurationCollection(typeof(AppCodeFileExtensionsCollection), AddItemName = "ext")]
+ [ConfigurationProperty("", IsDefaultCollection = true)]
+ public AppCodeFileExtensionsCollection AppCodeFileExtensionsCollection
+ {
+ get { return (AppCodeFileExtensionsCollection)base[""]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/CharCollection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/CharCollection.cs
new file mode 100644
index 0000000000..bdc69754c3
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/CharCollection.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class CharCollection : ConfigurationElementCollection, IEnumerable
+ {
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new CharElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((CharElement)element).Char;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ for (var i = 0; i < Count; i++)
+ {
+ yield return BaseGet(i) as CharElement;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/CharElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/CharElement.cs
new file mode 100644
index 0000000000..e94f015974
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/CharElement.cs
@@ -0,0 +1,10 @@
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class CharElement : InnerTextConfigurationElement
+ {
+ internal string Char
+ {
+ get { return RawXml.Attribute("org").Value; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/CommaDelimitedConfigurationElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/CommaDelimitedConfigurationElement.cs
new file mode 100644
index 0000000000..514a0ab37a
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/CommaDelimitedConfigurationElement.cs
@@ -0,0 +1,70 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ ///
+ /// Defines a configuration section that contains inner text that is comma delimited
+ ///
+ internal class CommaDelimitedConfigurationElement : InnerTextConfigurationElement, IEnumerable
+ {
+ public override CommaDelimitedStringCollection Value
+ {
+ get
+ {
+ var converter = new CommaDelimitedStringCollectionConverter();
+ return (CommaDelimitedStringCollection) converter.ConvertFrom(RawValue);
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return new InnerEnumerator(Value.GetEnumerator());
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return new InnerEnumerator(Value.GetEnumerator());
+ }
+
+ ///
+ /// A wrapper for StringEnumerator since it doesn't explicitly implement IEnumerable
+ ///
+ private class InnerEnumerator : IEnumerator
+ {
+ private readonly StringEnumerator _stringEnumerator;
+
+ public InnerEnumerator(StringEnumerator stringEnumerator)
+ {
+ _stringEnumerator = stringEnumerator;
+ }
+
+ public bool MoveNext()
+ {
+ return _stringEnumerator.MoveNext();
+ }
+
+ public void Reset()
+ {
+ _stringEnumerator.Reset();
+ }
+
+ string IEnumerator.Current
+ {
+ get { return _stringEnumerator.Current; }
+ }
+
+ public object Current
+ {
+ get { return _stringEnumerator.Current; }
+ }
+
+ public void Dispose()
+ {
+ _stringEnumerator.DisposeIfDisposable();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs
new file mode 100644
index 0000000000..aa36f3e670
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs
@@ -0,0 +1,193 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ContentElement : ConfigurationElement
+ {
+ [ConfigurationProperty("imaging")]
+ internal ContentImagingElement Imaging
+ {
+ get { return (ContentImagingElement)this["imaging"]; }
+ }
+
+ [ConfigurationProperty("scripteditor")]
+ internal ContentScriptEditorElement ScriptEditor
+ {
+ get { return (ContentScriptEditorElement)this["scripteditor"]; }
+ }
+
+ [ConfigurationProperty("EnableCanvasEditing")]
+ internal InnerTextConfigurationElement EnableCanvasEditing
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["EnableCanvasEditing"],
+ //set the default
+ false);
+ }
+ }
+
+ [ConfigurationProperty("ResolveUrlsFromTextString")]
+ internal InnerTextConfigurationElement ResolveUrlsFromTextString
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["ResolveUrlsFromTextString"],
+ //set the default
+ true);
+ }
+ }
+
+ [ConfigurationProperty("UploadAllowDirectories")]
+ internal InnerTextConfigurationElement UploadAllowDirectories
+ {
+ get { return (InnerTextConfigurationElement)this["UploadAllowDirectories"]; }
+ }
+
+ [ConfigurationProperty("errors")]
+ public ContentErrorsElement Errors
+ {
+ get { return (ContentErrorsElement)base["errors"]; }
+ }
+
+ [ConfigurationProperty("notifications")]
+ public NotificationsElement Notifications
+ {
+ get { return (NotificationsElement)base["notifications"]; }
+ }
+
+ [ConfigurationProperty("ensureUniqueNaming")]
+ public InnerTextConfigurationElement EnsureUniqueNaming
+ {
+ get { return (InnerTextConfigurationElement)base["ensureUniqueNaming"]; }
+ }
+
+ [ConfigurationProperty("TidyEditorContent")]
+ public InnerTextConfigurationElement TidyEditorContent
+ {
+ get { return (InnerTextConfigurationElement)base["TidyEditorContent"]; }
+ }
+
+ [ConfigurationProperty("TidyCharEncoding")]
+ public InnerTextConfigurationElement TidyCharEncoding
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["TidyCharEncoding"],
+ //set the default
+ "Raw");
+ }
+ }
+
+ [ConfigurationProperty("XmlCacheEnabled")]
+ public InnerTextConfigurationElement XmlCacheEnabled
+ {
+ get { return (InnerTextConfigurationElement)base["XmlCacheEnabled"]; }
+ }
+
+ [ConfigurationProperty("ContinouslyUpdateXmlDiskCache")]
+ public InnerTextConfigurationElement ContinouslyUpdateXmlDiskCache
+ {
+ get { return (InnerTextConfigurationElement)base["ContinouslyUpdateXmlDiskCache"]; }
+ }
+
+ [ConfigurationProperty("XmlContentCheckForDiskChanges")]
+ public InnerTextConfigurationElement XmlContentCheckForDiskChanges
+ {
+ get { return (InnerTextConfigurationElement)base["XmlContentCheckForDiskChanges"]; }
+ }
+
+ [ConfigurationProperty("EnableSplashWhileLoading")]
+ public InnerTextConfigurationElement EnableSplashWhileLoading
+ {
+ get { return (InnerTextConfigurationElement)base["EnableSplashWhileLoading"]; }
+ }
+
+ [ConfigurationProperty("PropertyContextHelpOption")]
+ public InnerTextConfigurationElement PropertyContextHelpOption
+ {
+ get { return (InnerTextConfigurationElement)base["PropertyContextHelpOption"]; }
+ }
+
+ [ConfigurationProperty("UseLegacyXmlSchema")]
+ public InnerTextConfigurationElement UseLegacyXmlSchema
+ {
+ get { return (InnerTextConfigurationElement)base["UseLegacyXmlSchema"]; }
+ }
+
+ [ConfigurationProperty("ForceSafeAliases")]
+ public InnerTextConfigurationElement ForceSafeAliases
+ {
+ get { return (InnerTextConfigurationElement)base["ForceSafeAliases"]; }
+ }
+
+ [ConfigurationProperty("PreviewBadge")]
+ public InnerTextConfigurationElement PreviewBadge
+ {
+ get { return (InnerTextConfigurationElement)base["PreviewBadge"]; }
+ }
+
+ [ConfigurationProperty("UmbracoLibraryCacheDuration")]
+ public InnerTextConfigurationElement UmbracoLibraryCacheDuration
+ {
+ get { return (InnerTextConfigurationElement)base["UmbracoLibraryCacheDuration"]; }
+ }
+
+ [ConfigurationProperty("MacroErrors")]
+ public InnerTextConfigurationElement MacroErrors
+ {
+ get { return (InnerTextConfigurationElement)base["MacroErrors"]; }
+ }
+
+ [ConfigurationProperty("DocumentTypeIconList")]
+ public InnerTextConfigurationElement DocumentTypeIconList
+ {
+ get { return (InnerTextConfigurationElement)base["DocumentTypeIconList"]; }
+ }
+
+ [ConfigurationProperty("disallowedUploadFiles")]
+ public CommaDelimitedConfigurationElement DisallowedUploadFiles
+ {
+ get { return (CommaDelimitedConfigurationElement)base["disallowedUploadFiles"]; }
+ }
+
+ [ConfigurationProperty("cloneXmlContent")]
+ internal InnerTextConfigurationElement CloneXmlContent
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["cloneXmlContent"],
+ //set the default
+ true);
+ }
+ }
+
+ [ConfigurationProperty("GlobalPreviewStorageEnabled")]
+ internal InnerTextConfigurationElement GlobalPreviewStorageEnabled
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["GlobalPreviewStorageEnabled"],
+ //set the default
+ false);
+ }
+ }
+
+ [ConfigurationProperty("defaultDocumentTypeProperty")]
+ internal InnerTextConfigurationElement DefaultDocumentTypeProperty
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["defaultDocumentTypeProperty"],
+ //set the default
+ "Textstring");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentError404Collection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentError404Collection.cs
new file mode 100644
index 0000000000..5d9591997f
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentError404Collection.cs
@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ContentError404Collection : ConfigurationElementCollection, IEnumerable
+ {
+ internal void Add(ContentErrorPageElement element)
+ {
+ BaseAdd(element);
+ }
+
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new ContentErrorPageElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((ContentErrorPageElement)element).Culture
+ + ((ContentErrorPageElement)element).Value;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ for (var i = 0; i < Count; i++)
+ {
+ yield return BaseGet(i) as ContentErrorPageElement;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorPageElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorPageElement.cs
new file mode 100644
index 0000000000..7054c90194
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorPageElement.cs
@@ -0,0 +1,23 @@
+using System.Xml.Linq;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ContentErrorPageElement : InnerTextConfigurationElement
+ {
+ public ContentErrorPageElement(XElement rawXml)
+ : base(rawXml)
+ {
+ }
+
+ public ContentErrorPageElement()
+ {
+
+ }
+
+ internal string Culture
+ {
+ get { return (string) RawXml.Attribute("culture"); }
+ set { RawXml.Attribute("culture").Value = value; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorsElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorsElement.cs
new file mode 100644
index 0000000000..5b45df1608
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentErrorsElement.cs
@@ -0,0 +1,43 @@
+using System.Linq;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ContentErrorsElement : RawXmlConfigurationElement
+ {
+
+ public ContentError404Collection Error404Collection
+ {
+ get
+ {
+ var result = new ContentError404Collection();
+ if (RawXml != null)
+ {
+ var e404 = RawXml.Elements("error404").First();
+ var ePages = e404.Elements("errorPage").ToArray();
+ if (ePages.Any())
+ {
+ //there are multiple
+ foreach (var e in ePages)
+ {
+ result.Add(new ContentErrorPageElement(e)
+ {
+ Culture = (string)e.Attribute("culture"),
+ RawValue = e.Value
+ });
+ }
+ }
+ else
+ {
+ //there's only one defined
+ result.Add(new ContentErrorPageElement(e404)
+ {
+ RawValue = e404.Value
+ });
+ }
+ }
+ return result;
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingAutoFillPropertiesCollection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingAutoFillPropertiesCollection.cs
new file mode 100644
index 0000000000..b77d85e585
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingAutoFillPropertiesCollection.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ContentImagingAutoFillPropertiesCollection : ConfigurationElementCollection, IEnumerable
+ {
+
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new ContentImagingAutoFillUploadFieldElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((ContentImagingAutoFillUploadFieldElement)element).Alias;
+ }
+
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ for (var i = 0; i < Count; i++)
+ {
+ yield return BaseGet(i) as ContentImagingAutoFillUploadFieldElement;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingAutoFillUploadFieldElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingAutoFillUploadFieldElement.cs
new file mode 100644
index 0000000000..9ec8ff21c1
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingAutoFillUploadFieldElement.cs
@@ -0,0 +1,37 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ContentImagingAutoFillUploadFieldElement : ConfigurationElement
+ {
+ [ConfigurationProperty("alias", IsKey = true)]
+ internal string Alias
+ {
+ get { return (string)this["alias"]; }
+ }
+
+ [ConfigurationProperty("widthFieldAlias")]
+ internal InnerTextConfigurationElement WidthFieldAlias
+ {
+ get { return (InnerTextConfigurationElement)this["widthFieldAlias"]; }
+ }
+
+ [ConfigurationProperty("heightFieldAlias")]
+ internal InnerTextConfigurationElement HeightFieldAlias
+ {
+ get { return (InnerTextConfigurationElement)this["heightFieldAlias"]; }
+ }
+
+ [ConfigurationProperty("lengthFieldAlias")]
+ internal InnerTextConfigurationElement LengthFieldAlias
+ {
+ get { return (InnerTextConfigurationElement)this["lengthFieldAlias"]; }
+ }
+
+ [ConfigurationProperty("extensionFieldAlias")]
+ internal InnerTextConfigurationElement ExtensionFieldAlias
+ {
+ get { return (InnerTextConfigurationElement)this["extensionFieldAlias"]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingElement.cs
new file mode 100644
index 0000000000..6b639f81b6
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingElement.cs
@@ -0,0 +1,27 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ContentImagingElement : ConfigurationElement
+ {
+ [ConfigurationProperty("imageFileTypes")]
+ internal CommaDelimitedConfigurationElement ImageFileTypes
+ {
+ get { return (CommaDelimitedConfigurationElement)this["imageFileTypes"]; }
+ }
+
+ [ConfigurationProperty("allowedAttributes")]
+ internal CommaDelimitedConfigurationElement AllowedAttributes
+ {
+ get { return (CommaDelimitedConfigurationElement)this["allowedAttributes"]; }
+ }
+
+ [ConfigurationCollection(typeof(ContentImagingAutoFillPropertiesCollection), AddItemName = "uploadField")]
+ [ConfigurationProperty("autoFillImageProperties", IsDefaultCollection = true)]
+ public ContentImagingAutoFillPropertiesCollection ImageAutoFillProperties
+ {
+ get { return (ContentImagingAutoFillPropertiesCollection)base["autoFillImageProperties"]; }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentScriptEditorElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentScriptEditorElement.cs
new file mode 100644
index 0000000000..0ef94906b2
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentScriptEditorElement.cs
@@ -0,0 +1,25 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ContentScriptEditorElement : ConfigurationElement
+ {
+ [ConfigurationProperty("scriptFolderPath")]
+ internal InnerTextConfigurationElement ScriptFolderPath
+ {
+ get { return (InnerTextConfigurationElement)this["scriptFolderPath"]; }
+ }
+
+ [ConfigurationProperty("scriptFileTypes")]
+ internal CommaDelimitedConfigurationElement ScriptFileTypes
+ {
+ get { return (CommaDelimitedConfigurationElement)this["scriptFileTypes"]; }
+ }
+
+ [ConfigurationProperty("scriptDisableEditor")]
+ internal InnerTextConfigurationElement DisableScriptEditor
+ {
+ get { return (InnerTextConfigurationElement)this["scriptDisableEditor"]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/CustomBooleanTypeConverter.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/CustomBooleanTypeConverter.cs
new file mode 100644
index 0000000000..b066b4a876
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/CustomBooleanTypeConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.ComponentModel;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ ///
+ /// Allows for converting string representations of 0 and 1 to boolean
+ ///
+ internal class CustomBooleanTypeConverter : BooleanConverter
+ {
+ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+ {
+ if (sourceType == typeof(string))
+ {
+ return true;
+ }
+ return base.CanConvertFrom(context, sourceType);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
+ {
+ if (value is string)
+ {
+ var str = (string)value;
+ if (str == "1") return true;
+ if (str == "0" || str == "") return false;
+ }
+
+ return base.ConvertFrom(context, culture, value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/DeveloperElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/DeveloperElement.cs
new file mode 100644
index 0000000000..b18375cbd7
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/DeveloperElement.cs
@@ -0,0 +1,13 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class DeveloperElement : ConfigurationElement
+ {
+ [ConfigurationProperty("appCodeFileExtensions")]
+ internal AppCodeFileExtensionsElement AppCodeFileExtensions
+ {
+ get { return (AppCodeFileExtensionsElement)this["appCodeFileExtensions"]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/DisabledLogTypesCollection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/DisabledLogTypesCollection.cs
new file mode 100644
index 0000000000..545ee70622
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/DisabledLogTypesCollection.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class DisabledLogTypesCollection : ConfigurationElementCollection, IEnumerable
+ {
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new LogTypeElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((LogTypeElement)element).Value;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ for (var i = 0; i < Count; i++)
+ {
+ yield return BaseGet(i) as LogTypeElement;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/DistributedCallElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/DistributedCallElement.cs
new file mode 100644
index 0000000000..2295ffdc94
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/DistributedCallElement.cs
@@ -0,0 +1,26 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class DistributedCallElement : ConfigurationElement
+ {
+ [ConfigurationProperty("enable")]
+ public bool Enabled
+ {
+ get { return (bool)base["enable"]; }
+ }
+
+ [ConfigurationProperty("user")]
+ internal InnerTextConfigurationElement UserId
+ {
+ get { return (InnerTextConfigurationElement)this["user"]; }
+ }
+
+ [ConfigurationCollection(typeof(ServerCollection), AddItemName = "server")]
+ [ConfigurationProperty("servers", IsDefaultCollection = true)]
+ public ServerCollection Servers
+ {
+ get { return (ServerCollection)base["servers"]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ExternalLoggerElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ExternalLoggerElement.cs
new file mode 100644
index 0000000000..231941b49f
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ExternalLoggerElement.cs
@@ -0,0 +1,25 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class ExternalLoggerElement : ConfigurationElement
+ {
+ [ConfigurationProperty("assembly")]
+ internal string Assembly
+ {
+ get { return (string)base["assembly"]; }
+ }
+
+ [ConfigurationProperty("type")]
+ internal string Type
+ {
+ get { return (string)base["type"]; }
+ }
+
+ [ConfigurationProperty("logAuditTrail")]
+ internal bool LogAuditTrail
+ {
+ get { return (bool)base["logAuditTrail"]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/FileExtensionElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/FileExtensionElement.cs
new file mode 100644
index 0000000000..85249c3718
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/FileExtensionElement.cs
@@ -0,0 +1,7 @@
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class FileExtensionElement : InnerTextConfigurationElement
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/HelpElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/HelpElement.cs
new file mode 100644
index 0000000000..d6b448555a
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/HelpElement.cs
@@ -0,0 +1,20 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class HelpElement : ConfigurationElement
+ {
+ [ConfigurationProperty("defaultUrl")]
+ public string DefaultUrl
+ {
+ get { return (string) base["defaultUrl"]; }
+ }
+
+ [ConfigurationCollection(typeof (LinksCollection), AddItemName = "link")]
+ [ConfigurationProperty("", IsDefaultCollection = true)]
+ public LinksCollection Links
+ {
+ get { return (LinksCollection) base[""]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/InnerTextConfigurationElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/InnerTextConfigurationElement.cs
new file mode 100644
index 0000000000..e074d181cb
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/InnerTextConfigurationElement.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Xml;
+using System.Xml.Linq;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ ///
+ /// A full config section is required for any full element and we have some elements that are defined like this:
+ /// {element}MyValue{/element} instead of as attribute values.
+ ///
+ ///
+ internal class InnerTextConfigurationElement : RawXmlConfigurationElement
+ {
+ public InnerTextConfigurationElement()
+ {
+ }
+
+ public InnerTextConfigurationElement(XElement rawXml) : base(rawXml)
+ {
+ }
+
+ protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
+ {
+ base.DeserializeElement(reader, serializeCollectionKey);
+ //now validate and set the raw value
+ if (RawXml.HasElements)
+ throw new InvalidOperationException("An InnerTextConfigurationElement cannot contain any child elements, only attributes and a value");
+ RawValue = RawXml.Value;
+
+ //RawValue = reader.ReadElementContentAsString();
+ }
+
+ public virtual T Value
+ {
+ get
+ {
+ var converted = RawValue.TryConvertTo();
+ if (converted.Success == false)
+ throw new InvalidCastException("Could not convert value " + RawValue + " to type " + typeof(T));
+ return converted.Result;
+ }
+ }
+
+ ///
+ /// Exposes the raw string value
+ ///
+ internal string RawValue { get; set; }
+
+ ///
+ /// Implicit operator so we don't need to use the 'Value' property explicitly
+ ///
+ ///
+ ///
+ public static implicit operator T(InnerTextConfigurationElement m)
+ {
+ return m.Value;
+ }
+
+ ///
+ /// Return the string value of Value
+ ///
+ ///
+ public override string ToString()
+ {
+ return string.Format("{0}", Value);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/LinkElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/LinkElement.cs
new file mode 100644
index 0000000000..f0c1e40451
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/LinkElement.cs
@@ -0,0 +1,37 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class LinkElement : ConfigurationElement
+ {
+ [ConfigurationProperty("application")]
+ internal string Application
+ {
+ get { return (string)base["application"]; }
+ }
+
+ [ConfigurationProperty("applicationUrl")]
+ internal string ApplicationUrl
+ {
+ get { return (string)base["applicationUrl"]; }
+ }
+
+ [ConfigurationProperty("language")]
+ internal string Language
+ {
+ get { return (string)base["language"]; }
+ }
+
+ [ConfigurationProperty("userType")]
+ internal string UserType
+ {
+ get { return (string)base["userType"]; }
+ }
+
+ [ConfigurationProperty("helpUrl")]
+ internal string HelpUrl
+ {
+ get { return (string)base["helpUrl"]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/LinksCollection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/LinksCollection.cs
new file mode 100644
index 0000000000..94d399b97e
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/LinksCollection.cs
@@ -0,0 +1,34 @@
+using System.Collections.Generic;
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class LinksCollection : ConfigurationElementCollection, IEnumerable
+ {
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new LinkElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((LinkElement)element).Application
+ + ((LinkElement)element).ApplicationUrl
+ + ((LinkElement)element).Language
+ + ((LinkElement)element).UserType;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ for (var i = 0; i < Count; i++)
+ {
+ yield return BaseGet(i) as LinkElement;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/LogTypeElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/LogTypeElement.cs
new file mode 100644
index 0000000000..9dbee14e07
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/LogTypeElement.cs
@@ -0,0 +1,7 @@
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class LogTypeElement : InnerTextConfigurationElement
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/LoggingElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/LoggingElement.cs
new file mode 100644
index 0000000000..61ad7a3d33
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/LoggingElement.cs
@@ -0,0 +1,68 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class LoggingElement : ConfigurationElement
+ {
+ [ConfigurationProperty("autoCleanLogs")]
+ internal InnerTextConfigurationElement AutoCleanLogs
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["autoCleanLogs"],
+ //set the default
+ false);
+ }
+ }
+
+ [ConfigurationProperty("enableLogging")]
+ internal InnerTextConfigurationElement EnableLogging
+ {
+ get { return (InnerTextConfigurationElement)this["enableLogging"]; }
+ }
+
+ [ConfigurationProperty("enableAsyncLogging")]
+ internal InnerTextConfigurationElement EnableAsyncLogging
+ {
+ get { return (InnerTextConfigurationElement)this["enableAsyncLogging"]; }
+ }
+
+ [ConfigurationProperty("cleaningMiliseconds")]
+ internal InnerTextConfigurationElement CleaningMiliseconds
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["cleaningMiliseconds"],
+ //set the default
+ -1);
+ }
+ }
+
+ [ConfigurationProperty("maxLogAge")]
+ internal InnerTextConfigurationElement MaxLogAge
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement)this["maxLogAge"],
+ //set the default
+ -1);
+ }
+ }
+
+ [ConfigurationCollection(typeof(DisabledLogTypesCollection), AddItemName = "logTypeAlias")]
+ [ConfigurationProperty("disabledLogTypes", IsDefaultCollection = true)]
+ public DisabledLogTypesCollection DisabledLogTypes
+ {
+ get { return (DisabledLogTypesCollection)base["disabledLogTypes"]; }
+ }
+
+ [ConfigurationProperty("externalLogger")]
+ internal ExternalLoggerElement ExternalLogger
+ {
+ get { return (ExternalLoggerElement)this["externalLogger"]; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/NotDynamicXmlDocumentElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/NotDynamicXmlDocumentElement.cs
new file mode 100644
index 0000000000..200cc50aef
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/NotDynamicXmlDocumentElement.cs
@@ -0,0 +1,7 @@
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class NotDynamicXmlDocumentElement : InnerTextConfigurationElement
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/NotDynamicXmlDocumentElementCollection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/NotDynamicXmlDocumentElementCollection.cs
new file mode 100644
index 0000000000..075db3f074
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/NotDynamicXmlDocumentElementCollection.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class NotDynamicXmlDocumentElementCollection : ConfigurationElementCollection, IEnumerable
+ {
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new NotDynamicXmlDocumentElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((NotDynamicXmlDocumentElement) element).Value;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ for (var i = 0; i < Count; i++)
+ {
+ yield return BaseGet(i) as NotDynamicXmlDocumentElement;
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/NotificationsElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/NotificationsElement.cs
new file mode 100644
index 0000000000..51178cc21e
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/NotificationsElement.cs
@@ -0,0 +1,25 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+ internal class NotificationsElement : ConfigurationElement
+ {
+ [ConfigurationProperty("email")]
+ internal InnerTextConfigurationElement EmailAddress
+ {
+ get { return (InnerTextConfigurationElement)this["email"]; }
+ }
+
+ [ConfigurationProperty("disableHtmlEmail")]
+ internal InnerTextConfigurationElement DisableHtmlEmail
+ {
+ get
+ {
+ return new OptionalInnerTextConfigurationElement(
+ (InnerTextConfigurationElement) this["disableHtmlEmail"],
+ //set the default
+ false);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ObjectExtensions.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ObjectExtensions.cs
new file mode 100644
index 0000000000..46fbc3b17a
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ObjectExtensions.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Umbraco.Core.Configuration.UmbracoSettings
+{
+
+ internal static class ObjectExtensions
+ {
+
+ //private static readonly ConcurrentDictionary> ObjectFactoryCache = new ConcurrentDictionary>();
+
+ public static IEnumerable AsEnumerableOfOne(this T input)
+ {
+ return Enumerable.Repeat(input, 1);
+ }
+
+ public static void DisposeIfDisposable(this object input)
+ {
+ var disposable = input as IDisposable;
+ if (disposable != null) disposable.Dispose();
+ }
+
+ ///
+ /// Provides a shortcut way of safely casting an input when you cannot guarantee the is an instance type (i.e., when the C# AS keyword is not applicable)
+ ///
+ ///
+ /// The input.
+ ///
+ public static T SafeCast(this object input)
+ {
+ if (ReferenceEquals(null, input) || ReferenceEquals(default(T), input)) return default(T);
+ if (input is T) return (T)input;
+ return default(T);
+ }
+
+ ///
+ /// Tries to convert the input object to the output type using TypeConverters
+ ///
+ ///
+ ///
+ ///
+ public static Attempt TryConvertTo(this object input)
+ {
+ var result = TryConvertTo(input, typeof(T));
+ if (!result.Success)
+ {
+ //just try a straight up conversion
+ try
+ {
+ var converted = (T)input;
+ return new Attempt(true, converted);
+ }
+ catch (Exception e)
+ {
+ return new Attempt(e);
+ }
+ }
+ return !result.Success ? Attempt.False : new Attempt(true, (T)result.Result);
+ }
+
+ ///
+ /// Tries to convert the input object to the output type using TypeConverters. If the destination type is a superclass of the input type,
+ /// if will use .
+ ///
+ /// The input.
+ /// Type of the destination.
+ ///
+ public static Attempt