Files
Umbraco-CMS/src/Umbraco.Configuration/GlobalSettings.cs
2019-11-19 08:52:39 +01:00

418 lines
16 KiB
C#

using System;
using System.Configuration;
using System.Linq;
using System.Xml.Linq;
using Umbraco.Core.IO;
namespace Umbraco.Core.Configuration
{
// TODO: Replace checking for if the app settings exist and returning an empty string, instead return the defaults!
// TODO: need to massively cleanup these configuration classes
/// <summary>
/// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information from web.config appsettings
/// </summary>
public class GlobalSettings : IGlobalSettings
{
private readonly IIOHelper _ioHelper;
// TODO these should not be static
private static string _reservedPaths;
private static string _reservedUrls;
//ensure the built on (non-changeable) reserved paths are there at all times
internal const string StaticReservedPaths = "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; //must end with a comma!
internal const string StaticReservedUrls = "~/config/splashes/noNodes.aspx,~/.well-known,"; //must end with a comma!
public GlobalSettings(IIOHelper ioHelper)
{
_ioHelper = ioHelper;
}
/// <summary>
/// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
/// </summary>
private static void ResetInternal()
{
_reservedPaths = null;
_reservedUrls = null;
HasSmtpServer = null;
}
/// <summary>
/// Resets settings that were set programmatically, to their initial values.
/// </summary>
/// <remarks>To be used in unit tests.</remarks>
internal static void Reset()
{
ResetInternal();
}
public bool IsSmtpServerConfigured
{
get
{
var smtpSection = ConfigurationManager.GetSection("system.net/mailSettings/smtp") as ConfigurationSection;
if (smtpSection is null) return false;
var from = smtpSection.ElementInformation.Properties["from"];
if (@from != null
&& @from.Value is string fromPropValue
&& string.IsNullOrEmpty(fromPropValue) == false
&& !string.Equals("noreply@example.com", fromPropValue, StringComparison.OrdinalIgnoreCase))
{
return true;
}
var networkSection = ConfigurationManager.GetSection("system.net/mailSettings/smtp/network") as ConfigurationSection;
var host = networkSection?.ElementInformation.Properties["host"];
if (host != null
&& host.Value is string hostPropValue
&& string.IsNullOrEmpty(hostPropValue) == false)
{
return true;
}
var specifiedPickupDirectorySection = ConfigurationManager.GetSection("system.net/mailSettings/smtp/specifiedPickupDirectory") as ConfigurationSection;
var pickupDirectoryLocation = specifiedPickupDirectorySection?.ElementInformation.Properties["pickupDirectoryLocation"];
if (pickupDirectoryLocation != null
&& pickupDirectoryLocation.Value is string pickupDirectoryLocationPropValue
&& string.IsNullOrEmpty(pickupDirectoryLocationPropValue) == false)
{
return true;
}
return false;
}
}
/// <summary>
/// For testing only
/// </summary>
internal static bool? HasSmtpServer { get; set; }
/// <summary>
/// Gets the reserved urls from web.config.
/// </summary>
/// <value>The reserved urls.</value>
public string ReservedUrls
{
get
{
if (_reservedUrls != null) return _reservedUrls;
var urls = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ReservedUrls)
? ConfigurationManager.AppSettings[Constants.AppSettings.ReservedUrls]
: string.Empty;
//ensure the built on (non-changeable) reserved paths are there at all times
_reservedUrls = StaticReservedUrls + urls;
return _reservedUrls;
}
internal set => _reservedUrls = value;
}
/// <summary>
/// Gets the reserved paths from web.config
/// </summary>
/// <value>The reserved paths.</value>
public string ReservedPaths
{
get
{
if (_reservedPaths != null) return _reservedPaths;
var reservedPaths = StaticReservedPaths;
var umbPath = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path) && !ConfigurationManager.AppSettings[Constants.AppSettings.Path].IsNullOrWhiteSpace()
? ConfigurationManager.AppSettings[Constants.AppSettings.Path]
: "~/umbraco";
//always add the umbraco path to the list
reservedPaths += umbPath.EnsureEndsWith(',');
var allPaths = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ReservedPaths)
? ConfigurationManager.AppSettings[Constants.AppSettings.ReservedPaths]
: string.Empty;
_reservedPaths = reservedPaths + allPaths;
return _reservedPaths;
}
}
/// <summary>
/// Gets the name of the content XML file.
/// </summary>
/// <value>The content XML.</value>
/// <remarks>
/// Defaults to ~/App_Data/umbraco.config
/// </remarks>
public string ContentXmlFile
{
get
{
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ContentXML)
? ConfigurationManager.AppSettings[Constants.AppSettings.ContentXML]
: "~/App_Data/umbraco.config";
}
}
/// <summary>
/// Gets the path to umbraco's root directory (/umbraco by default).
/// </summary>
/// <value>The path.</value>
public string Path
{
get
{
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path)
? _ioHelper.ResolveUrl(ConfigurationManager.AppSettings[Constants.AppSettings.Path])
: string.Empty;
}
}
/// <summary>
/// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance.
/// </summary>
/// <value>The configuration status.</value>
public string ConfigurationStatus
{
get
{
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.ConfigurationStatus)
? ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus]
: string.Empty;
}
set
{
SaveSetting(Constants.AppSettings.ConfigurationStatus, value, _ioHelper);
}
}
/// <summary>
/// Saves a setting into the configuration file.
/// </summary>
/// <param name="key">Key of the setting to be saved.</param>
/// <param name="value">Value of the setting to be saved.</param>
internal static void SaveSetting(string key, string value, IIOHelper ioHelper)
{
var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root));
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
// Update appSetting if it exists, or else create a new appSetting for the given key and value
var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key);
if (setting == null)
appSettings.Add(new XElement("add", new XAttribute("key", key), new XAttribute("value", value)));
else
setting.Attribute("value").Value = value;
xml.Save(fileName, SaveOptions.DisableFormatting);
ConfigurationManager.RefreshSection("appSettings");
}
/// <summary>
/// Removes a setting from the configuration file.
/// </summary>
/// <param name="key">Key of the setting to be removed.</param>
public static void RemoveSetting(string key, IIOHelper ioHelper)
{
var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root));
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key);
if (setting != null)
{
setting.Remove();
xml.Save(fileName, SaveOptions.DisableFormatting);
ConfigurationManager.RefreshSection("appSettings");
}
}
/// <summary>
/// Gets a value indicating whether umbraco is running in [debug mode].
/// </summary>
/// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
public bool DebugMode
{
get
{
try
{
if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection compilation)
{
var debugElement = compilation.ElementInformation.Properties["debug"];
return debugElement != null && (debugElement.Value is bool debug && debug);
}
}
catch
{
// ignored
}
return false;
}
}
/// <summary>
/// Gets the time out in minutes.
/// </summary>
/// <value>The time out in minutes.</value>
public int TimeOutInMinutes
{
get
{
try
{
return int.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.TimeOutInMinutes]);
}
catch
{
return 20;
}
}
}
/// <summary>
/// Returns the number of days that should take place between version checks.
/// </summary>
/// <value>The version check period in days (0 = never).</value>
public int VersionCheckPeriod
{
get
{
try
{
return int.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.VersionCheckPeriod]);
}
catch
{
return 7;
}
}
}
/// <inheritdoc />
public LocalTempStorage LocalTempStorageLocation
{
get
{
var setting = ConfigurationManager.AppSettings[Constants.AppSettings.LocalTempStorage];
if (!string.IsNullOrWhiteSpace(setting))
return Enum<LocalTempStorage>.Parse(setting);
return LocalTempStorage.Default;
}
}
/// <summary>
/// Gets the default UI language.
/// </summary>
/// <value>The default UI language.</value>
// ReSharper disable once InconsistentNaming
public string DefaultUILanguage
{
get
{
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.DefaultUILanguage)
? ConfigurationManager.AppSettings[Constants.AppSettings.DefaultUILanguage]
: string.Empty;
}
}
/// <summary>
/// Gets a value indicating whether umbraco should hide top level nodes from generated urls.
/// </summary>
/// <value>
/// <c>true</c> if umbraco hides top level nodes from urls; otherwise, <c>false</c>.
/// </value>
public bool HideTopLevelNodeFromPath
{
get
{
try
{
return bool.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.HideTopLevelNodeFromPath]);
}
catch
{
return false;
}
}
}
/// <summary>
/// Gets a value indicating whether umbraco should force a secure (https) connection to the backoffice.
/// </summary>
public bool UseHttps
{
get
{
try
{
return bool.Parse(ConfigurationManager.AppSettings[Constants.AppSettings.UseHttps]);
}
catch
{
return false;
}
}
}
private string _umbracoMediaPath = null;
public string UmbracoMediaPath => GetterWithDefaultValue(Constants.AppSettings.UmbracoMediaPath, "~/media", ref _umbracoMediaPath);
private string _umbracoScriptsPath = null;
public string UmbracoScriptsPath => GetterWithDefaultValue(Constants.AppSettings.UmbracoScriptsPath, "~/scripts", ref _umbracoScriptsPath);
private string _umbracoCssPath = null;
public string UmbracoCssPath => GetterWithDefaultValue(Constants.AppSettings.UmbracoCssPath, "~/css", ref _umbracoCssPath);
private string _umbracoPath = null;
public string UmbracoPath => GetterWithDefaultValue(Constants.AppSettings.UmbracoPath, "~/umbraco", ref _umbracoPath);
private bool _installMissingDatabase;
public bool InstallMissingDatabase => GetterWithDefaultValue("Umbraco.Core.RuntimeState.InstallMissingDatabase", false, ref _installMissingDatabase);
private bool _installEmptyDatabase;
public bool InstallEmptyDatabase => GetterWithDefaultValue("Umbraco.Core.RuntimeState.InstallEmptyDatabase", false, ref _installEmptyDatabase);
private bool _disableElectionForSingleServer;
public bool DisableElectionForSingleServer => GetterWithDefaultValue(Constants.AppSettings.DisableElectionForSingleServer, false, ref _disableElectionForSingleServer);
private string _registerType;
public string RegisterType => GetterWithDefaultValue(Constants.AppSettings.RegisterType, string.Empty, ref _registerType);
private string _databaseFactoryServerVersion;
public string DatabaseFactoryServerVersion => GetterWithDefaultValue(Constants.AppSettings.Debug.DatabaseFactoryServerVersion, string.Empty, ref _databaseFactoryServerVersion);
private T GetterWithDefaultValue<T>(string appSettingKey, T defaultValue, ref T backingField)
{
if (backingField != null) return backingField;
if (ConfigurationManager.AppSettings.ContainsKey(appSettingKey))
{
try
{
var value = ConfigurationManager.AppSettings[appSettingKey];
backingField = (T)Convert.ChangeType(value, typeof(T));
}
catch
{
/* ignore and use default value */
backingField = defaultValue;
}
}
else
{
backingField = defaultValue;
}
return backingField;
}
}
}