Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0
This commit is contained in:
@@ -27,7 +27,7 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ICacheRefresher"/> implementations.
|
||||
/// </summary>
|
||||
public IEnumerable<ICacheRefresher> CacheResolvers
|
||||
public IEnumerable<ICacheRefresher> CacheRefreshers
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -54,7 +54,8 @@ namespace Umbraco.Core.Models
|
||||
Trashed = trashed;
|
||||
}
|
||||
|
||||
public UmbracoEntity(int trashed)
|
||||
// for MySql
|
||||
public UmbracoEntity(UInt64 trashed)
|
||||
{
|
||||
AdditionalData = new Dictionary<string, object>();
|
||||
Trashed = trashed == 1;
|
||||
|
||||
@@ -115,6 +115,11 @@ namespace Umbraco.Core.Strings
|
||||
return InvalidFileNameChars.Contains(c) == false;
|
||||
}
|
||||
|
||||
public static string CutMaxLength(string text, int length)
|
||||
{
|
||||
return text.Length <= length ? text : text.Substring(0, length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Configuration
|
||||
@@ -168,6 +173,7 @@ namespace Umbraco.Core.Strings
|
||||
return WithConfig(CleanStringType.UrlSegment, new Config
|
||||
{
|
||||
PreFilter = ApplyUrlReplaceCharacters,
|
||||
PostFilter = x => CutMaxLength(x, 240),
|
||||
IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', // letter, digit or underscore
|
||||
StringType = (UrlReplacingToAscii ? CleanStringType.Ascii : CleanStringType.Utf8) | CleanStringType.LowerCase,
|
||||
BreakTermsOnUpper = false,
|
||||
@@ -202,6 +208,7 @@ namespace Umbraco.Core.Strings
|
||||
{
|
||||
StringType = CleanStringType.Utf8 | CleanStringType.Unchanged;
|
||||
PreFilter = null;
|
||||
PostFilter = null;
|
||||
IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c);
|
||||
BreakTermsOnUpper = false;
|
||||
CutAcronymOnNonUpper = false;
|
||||
@@ -214,6 +221,7 @@ namespace Umbraco.Core.Strings
|
||||
return new Config
|
||||
{
|
||||
PreFilter = PreFilter,
|
||||
PostFilter = PostFilter,
|
||||
IsTerm = IsTerm,
|
||||
StringType = StringType,
|
||||
BreakTermsOnUpper = BreakTermsOnUpper,
|
||||
@@ -224,6 +232,7 @@ namespace Umbraco.Core.Strings
|
||||
}
|
||||
|
||||
public Func<string, string> PreFilter { get; set; }
|
||||
public Func<string, string> PostFilter { get; set; }
|
||||
public Func<char, bool, bool> IsTerm { get; set; }
|
||||
|
||||
public CleanStringType StringType { get; set; }
|
||||
@@ -554,6 +563,10 @@ function validateSafeAlias(id, value, immediate, callback) {{
|
||||
// clean
|
||||
text = CleanCodeString(text, stringType, separator.Value, culture, config);
|
||||
|
||||
// apply post-filter
|
||||
if (config.PostFilter != null)
|
||||
text = config.PostFilter(text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,12 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
return _content.Count > 0;
|
||||
}
|
||||
|
||||
public IPublishedContent CreateFragment(string contentTypeAlias, IDictionary<string, object> dataValues,
|
||||
bool isPreviewing, bool managed)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
class SolidPublishedContent : IPublishedContent
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%@ Page Language="c#" MasterPageFile="../../masterpages/umbracoPage.Master" Title="Edit data type"
|
||||
ValidateRequest="false"
|
||||
CodeBehind="editDatatype.aspx.cs" AutoEventWireup="True" Inherits="umbraco.cms.presentation.developer.editDatatype" %>
|
||||
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
|
||||
@@ -141,6 +141,7 @@ namespace Umbraco.Web.Mvc
|
||||
// maps model
|
||||
protected override void SetViewData(ViewDataDictionary viewData)
|
||||
{
|
||||
// if view data contains no model, nothing to do
|
||||
var source = viewData.Model;
|
||||
if (source == null)
|
||||
{
|
||||
@@ -148,6 +149,8 @@ namespace Umbraco.Web.Mvc
|
||||
return;
|
||||
}
|
||||
|
||||
// get the type of the view data model (what we have)
|
||||
// get the type of this view model (what we want)
|
||||
var sourceType = source.GetType();
|
||||
var targetType = typeof (TModel);
|
||||
|
||||
@@ -160,13 +163,15 @@ namespace Umbraco.Web.Mvc
|
||||
|
||||
// try to grab the content
|
||||
// if no content is found, return, nothing we can do
|
||||
var sourceContent = source as IPublishedContent;
|
||||
var sourceContent = source as IPublishedContent; // check if what we have is an IPublishedContent
|
||||
if (sourceContent == null && sourceType.Implements<IRenderModel>())
|
||||
{
|
||||
// else check if it's an IRenderModel => get the content
|
||||
sourceContent = ((IRenderModel)source).Content;
|
||||
}
|
||||
if (sourceContent == null)
|
||||
{
|
||||
// else check if we can convert it to a content
|
||||
var attempt = source.TryConvertTo<IPublishedContent>();
|
||||
if (attempt.Success) sourceContent = attempt.Result;
|
||||
}
|
||||
|
||||
@@ -33,5 +33,53 @@ namespace Umbraco.Web.PublishedCache
|
||||
/// <returns>The route.</returns>
|
||||
/// <remarks>The value of <paramref name="preview"/> overrides the context.</remarks>
|
||||
string GetRouteById(UmbracoContext umbracoContext, bool preview, int contentId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a content fragment.
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <param name="dataValues">The content property raw values.</param>
|
||||
/// <param name="isPreviewing">A value indicating whether the fragment is previewing.</param>
|
||||
/// <param name="managed">A value indicating whether the fragment is managed by the cache.</param>
|
||||
/// <returns>The newly created content fragment.</returns>
|
||||
//
|
||||
// notes
|
||||
//
|
||||
// in XmlPublishedCache, IPublishedContent instances are not meant to survive longer
|
||||
// that a request or else we cannot guarantee that the converted property values will
|
||||
// be properly managed - because XmlPublishedProperty just stores the result of the
|
||||
// conversion locally.
|
||||
//
|
||||
// in DrippingPublishedCache, IPublishedContent instances are meant to survive for as
|
||||
// long as the content itself has not been modified, and the property respects the
|
||||
// converter's indication ie whether the converted value should be cached at
|
||||
// .Content - cache until the content changes
|
||||
// .ContentCache - cache until any content changes
|
||||
// .Request - cache for the current request
|
||||
//
|
||||
// a fragment can be either "detached" or "managed".
|
||||
// detached: created from code, managed by code, converted property values are
|
||||
// cached within the fragment itself for as long as the fragment lives
|
||||
// managed: created from a property converter as part of a content, managed by
|
||||
// the cache, converted property values can be cached...
|
||||
//
|
||||
// XmlPublishedCache: same as content properties, store the result of the
|
||||
// conversion locally, neither content nor fragments should survive longer
|
||||
// than a request
|
||||
// DrippingPublishedCache: depends
|
||||
// .Content: cache within the fragment
|
||||
// .ContentCache, .Request: cache within the cache
|
||||
//
|
||||
// in the latter case, use a fragment-owned guid as the cache key. because we
|
||||
// don't really have any other choice. this opens potential memory leaks: if the
|
||||
// fragment is re-created on each request and has a property that caches its
|
||||
// converted value at .ContentCache level then we'll flood that cache with data
|
||||
// that's never removed (as long as no content is edited).
|
||||
//
|
||||
// so a requirement should be that any converter that creates fragment, should
|
||||
// be marked .Content -- and nothing else
|
||||
//
|
||||
IPublishedContent CreateFragment(string contentTypeAlias, IDictionary<string, object> dataValues,
|
||||
bool isPreviewing, bool managed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,5 +460,15 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fragments
|
||||
|
||||
public IPublishedContent CreateFragment(string contentTypeAlias, IDictionary<string, object> dataValues,
|
||||
bool isPreviewing, bool managed)
|
||||
{
|
||||
return new PublishedFragment(contentTypeAlias, dataValues, isPreviewing, managed);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
class PublishedFragment : PublishedContentBase
|
||||
{
|
||||
private readonly PublishedContentType _contentType;
|
||||
private readonly IPublishedProperty[] _properties;
|
||||
|
||||
public PublishedFragment(string contentTypeAlias, IDictionary<string, object> dataValues,
|
||||
bool isPreviewing, bool managed)
|
||||
{
|
||||
IsPreviewing = isPreviewing;
|
||||
_contentType = PublishedContentType.Get(PublishedItemType.Content, contentTypeAlias);
|
||||
|
||||
// we don't care about managed because in both cases, XmlPublishedCache stores
|
||||
// converted property values in the IPublishedContent, which is not meant to
|
||||
// survive the request
|
||||
|
||||
var dataValues2 = new Dictionary<string, object>();
|
||||
foreach (var kvp in dataValues)
|
||||
dataValues2[kvp.Key.ToLowerInvariant()] = kvp.Value;
|
||||
|
||||
_properties = _contentType.PropertyTypes
|
||||
.Select(x =>
|
||||
{
|
||||
object dataValue;
|
||||
return dataValues2.TryGetValue(x.PropertyTypeAlias.ToLowerInvariant(), out dataValue)
|
||||
? new PublishedFragmentProperty(x, this, dataValue)
|
||||
: new PublishedFragmentProperty(x, this);
|
||||
})
|
||||
.Cast<IPublishedProperty>()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
#region IPublishedContent
|
||||
|
||||
public override int Id
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override int DocumentTypeId
|
||||
{
|
||||
get { return _contentType.Id; }
|
||||
}
|
||||
|
||||
public override string DocumentTypeAlias
|
||||
{
|
||||
get { return _contentType.Alias; }
|
||||
}
|
||||
|
||||
public override PublishedItemType ItemType
|
||||
{
|
||||
get { return PublishedItemType.Content; }
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override int Level
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override string Path
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override int SortOrder
|
||||
{
|
||||
// note - could a published fragment have a sort order?
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override Guid Version
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override int TemplateId
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override string UrlName
|
||||
{
|
||||
get { return string.Empty; }
|
||||
}
|
||||
|
||||
public override DateTime CreateDate
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override DateTime UpdateDate
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override int CreatorId
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override string CreatorName
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override int WriterId
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override string WriterName
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override bool IsDraft
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override IPublishedContent Parent
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override IEnumerable<IPublishedContent> Children
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override ICollection<IPublishedProperty> Properties
|
||||
{
|
||||
get { return _properties; }
|
||||
}
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
{
|
||||
return _properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias));
|
||||
}
|
||||
|
||||
public override PublishedContentType ContentType
|
||||
{
|
||||
get { return _contentType; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal
|
||||
|
||||
// used by PublishedFragmentProperty
|
||||
internal bool IsPreviewing { get; private set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
class PublishedFragmentProperty : PublishedPropertyBase
|
||||
{
|
||||
private readonly object _dataValue;
|
||||
private readonly PublishedFragment _content;
|
||||
|
||||
private readonly Lazy<object> _sourceValue;
|
||||
private readonly Lazy<object> _objectValue;
|
||||
private readonly Lazy<object> _xpathValue;
|
||||
|
||||
public PublishedFragmentProperty(PublishedPropertyType propertyType, PublishedFragment content)
|
||||
: this(propertyType, content, null)
|
||||
{ }
|
||||
|
||||
public PublishedFragmentProperty(PublishedPropertyType propertyType, PublishedFragment content, object dataValue)
|
||||
: base(propertyType)
|
||||
{
|
||||
_dataValue = dataValue;
|
||||
_content = content;
|
||||
|
||||
_sourceValue = new Lazy<object>(() => PropertyType.ConvertDataToSource(_dataValue, _content.IsPreviewing));
|
||||
_objectValue = new Lazy<object>(() => PropertyType.ConvertSourceToObject(_sourceValue.Value, _content.IsPreviewing));
|
||||
_xpathValue = new Lazy<object>(() => PropertyType.ConvertSourceToXPath(_sourceValue.Value, _content.IsPreviewing));
|
||||
}
|
||||
|
||||
public override bool HasValue
|
||||
{
|
||||
get { return _dataValue != null && ((_dataValue is string) == false || string.IsNullOrWhiteSpace((string)_dataValue) == false); }
|
||||
}
|
||||
|
||||
public override object DataValue
|
||||
{
|
||||
get { return _dataValue; }
|
||||
}
|
||||
|
||||
public override object Value { get { return _objectValue.Value; } }
|
||||
public override object XPathValue { get { return _xpathValue.Value; } }
|
||||
}
|
||||
}
|
||||
@@ -152,12 +152,21 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
else
|
||||
{
|
||||
// look for the first domain that would be the base of the hint
|
||||
var hintWithSlash = current.EndPathWithSlash();
|
||||
// look for the first domain that would be the base of the current url
|
||||
// ie current is www.example.com/foo/bar, look for domain www.example.com
|
||||
var currentWithSlash = current.EndPathWithSlash();
|
||||
domainAndUri = domainsAndUris
|
||||
.FirstOrDefault(d => d.Uri.EndPathWithSlash().IsBaseOf(hintWithSlash));
|
||||
.FirstOrDefault(d => d.Uri.EndPathWithSlash().IsBaseOf(currentWithSlash));
|
||||
if (domainAndUri != null) return domainAndUri;
|
||||
|
||||
// look for the first domain that the current url would be the base of
|
||||
// ie current is www.example.com, look for domain www.example.com/foo/bar
|
||||
domainAndUri = domainsAndUris
|
||||
.FirstOrDefault(d => currentWithSlash.IsBaseOf(d.Uri.EndPathWithSlash()));
|
||||
if (domainAndUri != null) return domainAndUri;
|
||||
|
||||
// if none matches, then try to run the filter to pick a domain
|
||||
if (domainAndUri == null && filter != null)
|
||||
if (filter != null)
|
||||
{
|
||||
domainAndUri = filter(domainsAndUris);
|
||||
// if still nothing, pick the first one?
|
||||
|
||||
@@ -312,6 +312,16 @@ namespace Umbraco.Web.Routing
|
||||
TemplateModel = template;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the template.
|
||||
/// </summary>
|
||||
/// <remarks>The <c>RenderingEngine</c> becomes unknown.</remarks>
|
||||
public void ResetTemplate()
|
||||
{
|
||||
EnsureWriteable();
|
||||
TemplateModel = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content request has a template.
|
||||
/// </summary>
|
||||
|
||||
41
src/Umbraco.Web/Standalone/PowershellAssemblyResolver.cs
Normal file
41
src/Umbraco.Web/Standalone/PowershellAssemblyResolver.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Web.Standalone
|
||||
{
|
||||
public static class PowershellAssemblyResolver
|
||||
{
|
||||
private static readonly Dictionary<string, string> Assemblies;
|
||||
private static readonly object Locko = new object();
|
||||
|
||||
static PowershellAssemblyResolver()
|
||||
{
|
||||
var comparer = StringComparer.CurrentCultureIgnoreCase;
|
||||
Assemblies = new Dictionary<string,string>(comparer);
|
||||
AppDomain.CurrentDomain.AssemblyResolve += ResolveHandler;
|
||||
}
|
||||
|
||||
public static void AddAssemblyLocation(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException("Arg is null or empty.", "path");
|
||||
|
||||
lock (Locko)
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(path);
|
||||
Assemblies.Add(name, path);
|
||||
}
|
||||
}
|
||||
|
||||
private static Assembly ResolveHandler(object sender, ResolveEventArgs args)
|
||||
{
|
||||
var assemblyName = new AssemblyName(args.Name);
|
||||
string assemblyFile;
|
||||
return Assemblies.TryGetValue(assemblyName.Name, out assemblyFile)
|
||||
? Assembly.LoadFrom(assemblyFile)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,15 @@ namespace Umbraco.Web.Standalone
|
||||
if (noerr) return;
|
||||
throw new InvalidOperationException("Application has already started.");
|
||||
}
|
||||
Application_Start(this, EventArgs.Empty);
|
||||
try
|
||||
{
|
||||
Application_Start(this, EventArgs.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
TerminateInternal();
|
||||
throw;
|
||||
}
|
||||
_started = true;
|
||||
}
|
||||
}
|
||||
@@ -74,14 +82,24 @@ namespace Umbraco.Web.Standalone
|
||||
throw new InvalidOperationException("Application has already been terminated.");
|
||||
}
|
||||
|
||||
TerminateInternal();
|
||||
}
|
||||
}
|
||||
|
||||
private void TerminateInternal()
|
||||
{
|
||||
if (ApplicationContext.Current != null)
|
||||
{
|
||||
ApplicationContext.Current.DisposeIfDisposable(); // should reset resolution, clear caches & resolvers...
|
||||
ApplicationContext.Current = null;
|
||||
}
|
||||
if (UmbracoContext.Current != null)
|
||||
{
|
||||
UmbracoContext.Current.DisposeIfDisposable(); // dunno
|
||||
UmbracoContext.Current = null;
|
||||
|
||||
_started = false;
|
||||
_application = null;
|
||||
}
|
||||
_started = false;
|
||||
_application = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
262
src/Umbraco.Web/Standalone/WriteableConfigSystem.cs
Normal file
262
src/Umbraco.Web/Standalone/WriteableConfigSystem.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Configuration;
|
||||
using System.Configuration.Internal;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.Web.Standalone
|
||||
{
|
||||
// see http://stackoverflow.com/questions/15653621/how-to-update-add-modify-delete-keys-in-appsettings-section-of-web-config-at-r
|
||||
// see http://www.codeproject.com/Articles/69364/Override-Configuration-Manager
|
||||
|
||||
public sealed class WriteableConfigSystem : IInternalConfigSystem
|
||||
{
|
||||
private static readonly ReaderWriterLockSlim RwLock = new ReaderWriterLockSlim();
|
||||
private static WriteableConfigSystem _installed;
|
||||
private static IInternalConfigSystem _clientConfigSystem;
|
||||
private object _appsettings;
|
||||
private object _connectionStrings;
|
||||
private static object _sInitStateOrig;
|
||||
private static object _sConfigSystemOrig;
|
||||
|
||||
public static bool Installed
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
RwLock.EnterReadLock();
|
||||
return _installed != null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
RwLock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Re-initializes the ConfigurationManager, allowing us to merge in the settings from Core.Config
|
||||
/// </summary>
|
||||
public static void Install()
|
||||
{
|
||||
try
|
||||
{
|
||||
RwLock.EnterWriteLock();
|
||||
|
||||
if (_installed != null)
|
||||
throw new InvalidOperationException("ConfigSystem is already installed.");
|
||||
|
||||
FieldInfo[] fiStateValues = null;
|
||||
var tInitState = typeof(ConfigurationManager).GetNestedType("InitState", BindingFlags.NonPublic);
|
||||
|
||||
if (tInitState != null)
|
||||
fiStateValues = tInitState.GetFields();
|
||||
// 0: NotStarted
|
||||
// 1: Started
|
||||
// 2: Usable
|
||||
// 3: Completed
|
||||
|
||||
var fiInit = typeof(ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var fiSystem = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
if (fiInit != null && fiSystem != null && fiStateValues != null)
|
||||
{
|
||||
_sInitStateOrig = fiInit.GetValue(null);
|
||||
_sConfigSystemOrig = fiSystem.GetValue(null);
|
||||
fiInit.SetValue(null, fiStateValues[1].GetValue(null)); // set to Started
|
||||
fiSystem.SetValue(null, null); // clear current config system
|
||||
}
|
||||
|
||||
_installed = new WriteableConfigSystem();
|
||||
|
||||
var configFactoryType = Type.GetType("System.Configuration.Internal.InternalConfigSettingsFactory, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", true);
|
||||
var configSettingsFactory = (IInternalConfigSettingsFactory)Activator.CreateInstance(configFactoryType, true);
|
||||
// just does ConfigurationManager.SetConfigurationSystem(_installed, false);
|
||||
// 'false' turns initState to 2 ie usable (vs 3 ie completed)
|
||||
configSettingsFactory.SetConfigurationSystem(_installed, false);
|
||||
|
||||
// note: prob. don't need the factory... see how we uninstall...
|
||||
|
||||
var clientConfigSystemType = Type.GetType("System.Configuration.ClientConfigurationSystem, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", true);
|
||||
_clientConfigSystem = (IInternalConfigSystem)Activator.CreateInstance(clientConfigSystemType, true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
RwLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uninstall()
|
||||
{
|
||||
try
|
||||
{
|
||||
RwLock.EnterWriteLock();
|
||||
|
||||
if (_installed == null)
|
||||
throw new InvalidOperationException("ConfigSystem is not installed.");
|
||||
|
||||
FieldInfo[] fiStateValues = null;
|
||||
var tInitState = typeof(ConfigurationManager).GetNestedType("InitState", BindingFlags.NonPublic);
|
||||
|
||||
if (tInitState != null)
|
||||
fiStateValues = tInitState.GetFields();
|
||||
|
||||
var fiInit = typeof(ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var fiSystem = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
if (fiInit != null && fiSystem != null && fiStateValues != null)
|
||||
{
|
||||
// reset - the hard way
|
||||
fiInit.SetValue(null, _sInitStateOrig);
|
||||
fiSystem.SetValue(null, _sConfigSystemOrig);
|
||||
}
|
||||
|
||||
_installed = null;
|
||||
_clientConfigSystem = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
RwLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
try
|
||||
{
|
||||
RwLock.EnterWriteLock();
|
||||
|
||||
if (_installed == null)
|
||||
throw new InvalidOperationException("ConfigSystem is not installed.");
|
||||
|
||||
_installed._appsettings = null;
|
||||
_installed._connectionStrings = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
RwLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
#region IInternalConfigSystem Members
|
||||
|
||||
public object GetSection(string configKey)
|
||||
{
|
||||
// get the section from the default location (web.config or app.config)
|
||||
var section = _clientConfigSystem.GetSection(configKey);
|
||||
|
||||
try
|
||||
{
|
||||
RwLock.EnterReadLock();
|
||||
|
||||
switch (configKey)
|
||||
{
|
||||
case "appSettings":
|
||||
// Return cached version if exists
|
||||
if (_appsettings != null)
|
||||
return _appsettings;
|
||||
|
||||
// create a new collection because the underlying collection is read-only
|
||||
var cfg = new NameValueCollection();
|
||||
|
||||
// If an AppSettings section exists in Web.config, read and add values from it
|
||||
var nvSection = section as NameValueCollection;
|
||||
if (nvSection != null)
|
||||
{
|
||||
var localSettings = nvSection;
|
||||
foreach (string key in localSettings)
|
||||
cfg.Add(key, localSettings[key]);
|
||||
}
|
||||
|
||||
//// --------------------------------------------------------------------
|
||||
//// Here I read and decrypt keys and add them to secureConfig dictionary
|
||||
//// To test assume the following line is a key stored in secure sotrage.
|
||||
////secureConfig = SecureConfig.LoadConfig();
|
||||
//secureConfig.Add("ACriticalKey", "VeryCriticalValue");
|
||||
//// --------------------------------------------------------------------
|
||||
//foreach (KeyValuePair<string, string> item in secureConfig)
|
||||
//{
|
||||
// if (cfg.AllKeys.Contains(item.Key))
|
||||
// {
|
||||
// cfg[item.Key] = item.Value;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// cfg.Add(item.Key, item.Value);
|
||||
// }
|
||||
//}
|
||||
//// --------------------------------------------------------------------
|
||||
|
||||
|
||||
// Cach the settings for future use
|
||||
|
||||
_appsettings = cfg;
|
||||
// return the merged version of the items from secure storage and appsettings
|
||||
section = _appsettings;
|
||||
break;
|
||||
|
||||
case "connectionStrings":
|
||||
// Return cached version if exists
|
||||
if (_connectionStrings != null)
|
||||
return _connectionStrings;
|
||||
|
||||
// create a new collection because the underlying collection is read-only
|
||||
var connectionStringsSection = new ConnectionStringsSection();
|
||||
|
||||
// copy the existing connection strings into the new collection
|
||||
foreach (
|
||||
ConnectionStringSettings connectionStringSetting in
|
||||
((ConnectionStringsSection)section).ConnectionStrings)
|
||||
connectionStringsSection.ConnectionStrings.Add(connectionStringSetting);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Again Load connection strings from secure storage and merge like below
|
||||
// connectionStringsSection.ConnectionStrings.Add(connectionStringSetting);
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Cach the settings for future use
|
||||
_connectionStrings = connectionStringsSection;
|
||||
// return the merged version of the items from secure storage and appsettings
|
||||
section = _connectionStrings;
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
RwLock.ExitReadLock();
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
public void RefreshConfig(string sectionName)
|
||||
{
|
||||
try
|
||||
{
|
||||
RwLock.EnterWriteLock();
|
||||
|
||||
if (sectionName == "appSettings")
|
||||
{
|
||||
_appsettings = null;
|
||||
}
|
||||
|
||||
if (sectionName == "connectionStrings")
|
||||
{
|
||||
_connectionStrings = null;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
RwLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
_clientConfigSystem.RefreshConfig(sectionName);
|
||||
}
|
||||
|
||||
public bool SupportsUserConfig { get { return _clientConfigSystem.SupportsUserConfig; } }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -299,6 +299,8 @@
|
||||
<Compile Include="Models\ChangingPasswordModel.cs" />
|
||||
<Compile Include="Models\IRenderModel.cs" />
|
||||
<Compile Include="Models\PostRedirectModel.cs" />
|
||||
<Compile Include="PublishedCache\XmlPublishedCache\PublishedFragment.cs" />
|
||||
<Compile Include="PublishedCache\XmlPublishedCache\PublishedFragmentProperty.cs" />
|
||||
<Compile Include="Models\RenderModelOfTContent.cs" />
|
||||
<Compile Include="Mvc\EnsurePublishedContentRequestAttribute.cs" />
|
||||
<Compile Include="Mvc\UmbracoTemplatePageOfTContent.cs" />
|
||||
@@ -322,6 +324,7 @@
|
||||
<Compile Include="Security\Providers\MembersRoleProvider.cs" />
|
||||
<Compile Include="Security\Providers\UmbracoMembershipProvider.cs" />
|
||||
<Compile Include="Security\Providers\UsersMembershipProvider.cs" />
|
||||
<Compile Include="Standalone\PowershellAssemblyResolver.cs" />
|
||||
<Compile Include="Standalone\ServiceContextManager.cs" />
|
||||
<Compile Include="Standalone\StandaloneApplication.cs" />
|
||||
<Compile Include="Standalone\StandaloneBootManager.cs" />
|
||||
@@ -397,6 +400,7 @@
|
||||
<Compile Include="Search\LuceneIndexerExtensions.cs" />
|
||||
<Compile Include="Security\ValidateRequestAttempt.cs" />
|
||||
<Compile Include="Security\WebSecurity.cs" />
|
||||
<Compile Include="Standalone\WriteableConfigSystem.cs" />
|
||||
<Compile Include="Strategies\Migrations\ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs" />
|
||||
<Compile Include="Strategies\Migrations\RebuildMediaXmlCacheAfterUpgrade.cs" />
|
||||
<Compile Include="Strategies\PublicAccessEventHandler.cs" />
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace umbraco.presentation.cache
|
||||
/// <returns></returns>
|
||||
public ICacheRefresher[] GetAll()
|
||||
{
|
||||
return CacheRefreshersResolver.Current.CacheResolvers.ToArray();
|
||||
return CacheRefreshersResolver.Current.CacheRefreshers.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace umbraco.presentation.webservices
|
||||
{
|
||||
var xd = new XmlDocument();
|
||||
xd.LoadXml("<cacheRefreshers/>");
|
||||
foreach (var cr in CacheRefreshersResolver.Current.CacheResolvers)
|
||||
foreach (var cr in CacheRefreshersResolver.Current.CacheRefreshers)
|
||||
{
|
||||
var n = xmlHelper.addTextNode(xd, "cacheRefresher", cr.Name);
|
||||
n.Attributes.Append(xmlHelper.addAttribute(xd, "uniqueIdentifier", cr.UniqueIdentifier.ToString()));
|
||||
|
||||
@@ -532,5 +532,24 @@ namespace umbraco.cms.businesslogic
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
// zb023 - utility method
|
||||
public static string ReplaceKey(string text)
|
||||
{
|
||||
if (text.StartsWith("#") == false)
|
||||
return text;
|
||||
|
||||
var lang = Language.GetByCultureCode(Thread.CurrentThread.CurrentCulture.Name);
|
||||
|
||||
if (lang == null)
|
||||
return "[" + text + "]";
|
||||
|
||||
if (DictionaryItem.hasKey(text.Substring(1, text.Length - 1)) == false)
|
||||
return "[" + text + "]";
|
||||
|
||||
var di = new DictionaryItem(text.Substring(1, text.Length - 1));
|
||||
return di.Value(lang.id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,7 @@ namespace umbraco.cms.businesslogic.web
|
||||
return GetDomains(false);
|
||||
}
|
||||
|
||||
internal static IEnumerable<Domain> GetDomains(bool includeWildcards)
|
||||
public static IEnumerable<Domain> GetDomains(bool includeWildcards)
|
||||
{
|
||||
var domains = ApplicationContext.Current.ApplicationCache.GetCacheItem(
|
||||
CacheKeys.DomainCacheKey,
|
||||
@@ -191,6 +191,11 @@ namespace umbraco.cms.businesslogic.web
|
||||
return GetDomains().Where(d => d._root == nodeId).ToArray();
|
||||
}
|
||||
|
||||
public static Domain[] GetDomainsById(int nodeId, bool includeWildcards)
|
||||
{
|
||||
return GetDomains(includeWildcards).Where(d => d._root == nodeId).ToArray();
|
||||
}
|
||||
|
||||
public static bool Exists(string DomainName)
|
||||
{
|
||||
return GetDomain(DomainName) != null;
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace umbraco.editorControls
|
||||
{
|
||||
foreach (object key in _prevalues.Keys)
|
||||
{
|
||||
this.Items.Add(new ListItem(dropdown.DictionaryReplace(_prevalues[key].ToString()), key.ToString()));
|
||||
this.Items.Add(new ListItem(Dictionary.ReplaceKey(_prevalues[key].ToString()), key.ToString()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -67,7 +67,7 @@ namespace umbraco.editorControls
|
||||
{
|
||||
foreach (KeyValuePair<int, String> item in Prevalues)
|
||||
{
|
||||
this.Items.Add(new ListItem(dropdown.DictionaryReplace(item.Value), item.Key.ToString()));
|
||||
this.Items.Add(new ListItem(Dictionary.ReplaceKey(item.Value), item.Key.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,26 +76,5 @@ namespace umbraco.editorControls
|
||||
if (_data != null && _data.Value != null)
|
||||
this.SelectedValue = _data.Value.ToString();
|
||||
}
|
||||
|
||||
static string DictionaryReplace(string text)
|
||||
{
|
||||
if (!text.StartsWith("#"))
|
||||
return text;
|
||||
else
|
||||
{
|
||||
Language lang = Language.GetByCultureCode(System.Threading.Thread.CurrentThread.CurrentCulture.Name);
|
||||
if (lang != null)
|
||||
{
|
||||
if (Dictionary.DictionaryItem.hasKey(text.Substring(1, text.Length - 1)))
|
||||
{
|
||||
Dictionary.DictionaryItem di = new Dictionary.DictionaryItem(text.Substring(1, text.Length - 1));
|
||||
return di.Value(lang.id);
|
||||
}
|
||||
}
|
||||
|
||||
return "[" + text + "]";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user