Merge branch 'dev-v7' into 7.3.0

Conflicts:
	build/UmbracoVersion.txt
	src/Umbraco.Core/Configuration/UmbracoVersion.cs
	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
This commit is contained in:
Shannon
2015-03-24 15:10:45 +11:00
10 changed files with 122 additions and 300 deletions

View File

@@ -47,85 +47,31 @@ if ($project) {
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
}
$copyWebconfig = $false
# SJ - What can I say: big up for James Newton King for teaching us a hack for detecting if this is a new install vs. an upgrade!
# https://github.com/JamesNK/Newtonsoft.Json/pull/387 - would never have seen this without the controversial pull request..
Try
$copyWebconfig = $true
$destinationWebConfig = Join-Path $projectDestinationPath "Web.config"
if(Test-Path $destinationWebConfig)
{
# see if user is installing from VS NuGet console
# get reference to the window, the console host and the input history
# copy web.config if "install-package UmbracoCms" was last input
# this is in a try-catch as they might be using the regular NuGet dialog
# instead of package manager console
$dte2 = Get-Interface $dte ([EnvDTE80.DTE2])
$consoleWindow = $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow])
Try
{
[xml]$config = Get-Content $destinationWebConfig
$props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
$prop = $props | ? { $_.Name -eq "ActiveHostInfo" } | select -first 1
$hostInfo = $prop.GetValue($consoleWindow)
$history = $hostInfo.WpfConsole.InputHistory.History
$lastCommand = $history | select -last 1
if ($lastCommand)
{
$lastCommand = $lastCommand.Trim().ToLower()
if ($lastCommand.StartsWith("install-package") -and $lastCommand.Contains("umbracocms"))
{
$copyWebconfig = $true
$config.configuration.appSettings.ChildNodes | ForEach-Object {
if($_.key -eq "umbracoConfigurationStatus")
{
# The web.config has an umbraco-specific appSetting in it
# don't overwrite it and let config transforms do their thing
$copyWebconfig = $false
}
}
}
}
Catch { }
}
Catch { }
Try
{
# user is installing from VS NuGet dialog
# get reference to the window, then smart output console provider
# copy web.config if messages in buffered console contains "installing...UmbracoCms" in last operation
$instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::NonPublic)
$consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
$instance = $instanceField.GetValue($null)
$consoleProvider = $consoleField.GetValue($instance)
$console = $consoleProvider.CreateOutputConsole($false)
$messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
$messages = $messagesField.GetValue($console)
$operations = $messages -split "=============================="
$lastOperation = $operations | select -last 1
if ($lastOperation)
{
$lastOperation = $lastOperation.ToLower()
$lines = $lastOperation -split "`r`n"
$installMatch = $lines | ? { $_.Contains("...umbracocms ") } | select -first 1
if ($installMatch)
{
$copyWebconfig = $true
}
}
}
Catch { }
if($copyWebconfig -eq $true)
{
$packageWebConfigSource = Join-Path $rootPath "UmbracoFiles\Web.config"
$destinationWebConfig = Join-Path $projectDestinationPath "Web.config"
Copy-Item $packageWebConfigSource $destinationWebConfig -Force
}

View File

@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.2.4")]
[assembly: AssemblyInformationalVersion("7.2.4")]
[assembly: AssemblyFileVersion("7.2.5")]
[assembly: AssemblyInformationalVersion("7.2.5")]

View File

@@ -505,7 +505,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IContent> GetPagedChildren(int id, int pageIndex, int pageSize, out int totalChildren,
string orderBy, Direction orderDirection, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageSize");
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
using (var repository = RepositoryFactory.CreateContentRepository(UowProvider.GetUnitOfWork()))
{
@@ -535,7 +535,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
public IEnumerable<IContent> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageSize");
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
using (var repository = RepositoryFactory.CreateContentRepository(UowProvider.GetUnitOfWork()))
{

View File

@@ -20,12 +20,83 @@ namespace Umbraco.Core.Services
//TODO: See other notes in this class, this is purely a hack because we store 2 letter culture file names that contain 4 letter cultures :(
private readonly Dictionary<string, CultureInfo> _twoLetterCultureConverter = new Dictionary<string, CultureInfo>();
private readonly Lazy<Dictionary<CultureInfo, Lazy<XDocument>>> _xmlSources;
public LocalizedTextServiceFileSources(IRuntimeCacheProvider cache, DirectoryInfo fileSourceFolder)
{
if (cache == null) throw new ArgumentNullException("cache");
if (fileSourceFolder == null) throw new ArgumentNullException("fileSourceFolder");
_cache = cache;
//Create the lazy source for the _xmlSources
_xmlSources = new Lazy<Dictionary<CultureInfo, Lazy<XDocument>>>(() =>
{
var result = new Dictionary<CultureInfo, Lazy<XDocument>>();
if (_fileSourceFolder == null) return result;
foreach (var fileInfo in _fileSourceFolder.GetFiles("*.xml"))
{
var localCopy = fileInfo;
var filename = Path.GetFileNameWithoutExtension(localCopy.FullName).Replace("_", "-");
//TODO: Fix this nonsense... would have to wait until v8 to store the language files with their correct
// names instead of storing them as 2 letters but actually having a 4 letter culture. wtf. So now, we
// need to check if the file is 2 letters, then open it to try to find it's 4 letter culture, then use that
// if it's successful. We're going to assume (though it seems assuming in the legacy logic is never a great idea)
// that any 4 letter file is named with the actual culture that it is!
CultureInfo culture = null;
if (filename.Length == 2)
{
//we need to open the file to see if we can read it's 'real' culture, we'll use XmlReader since we don't
//want to load in the entire doc into mem just to read a single value
using (var fs = fileInfo.OpenRead())
using (var reader = XmlReader.Create(fs))
{
if (reader.IsStartElement())
{
if (reader.Name == "language")
{
if (reader.MoveToAttribute("culture"))
{
var cultureVal = reader.Value;
try
{
culture = CultureInfo.GetCultureInfo(cultureVal);
//add to the tracked dictionary
_twoLetterCultureConverter[filename] = culture;
}
catch (CultureNotFoundException)
{
LogHelper.Warn<LocalizedTextServiceFileSources>(
string.Format("The culture {0} found in the file {1} is not a valid culture", cultureVal, fileInfo.FullName));
//If the culture in the file is invalid, we'll just hope the file name is a valid culture below, otherwise
// an exception will be thrown.
}
}
}
}
}
}
if (culture == null)
{
culture = CultureInfo.GetCultureInfo(filename);
}
//get the lazy value from cache
result.Add(culture, new Lazy<XDocument>(() => _cache.GetCacheItem<XDocument>(
string.Format("{0}-{1}", typeof(LocalizedTextServiceFileSources).Name, culture.Name), () =>
{
using (var fs = localCopy.OpenRead())
{
return XDocument.Load(fs);
}
}, isSliding: true, timeout: TimeSpan.FromMinutes(10), dependentFiles: new[] { localCopy.FullName })));
}
return result;
});
if (fileSourceFolder.Exists == false)
{
LogHelper.Warn<LocalizedTextServiceFileSources>("The folder does not exist: {0}, therefore no sources will be discovered", () => fileSourceFolder.FullName);
@@ -42,69 +113,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public IDictionary<CultureInfo, Lazy<XDocument>> GetXmlSources()
{
var result = new Dictionary<CultureInfo, Lazy<XDocument>>();
if (_fileSourceFolder == null) return result;
foreach (var fileInfo in _fileSourceFolder.GetFiles("*.xml"))
{
var localCopy = fileInfo;
var filename = Path.GetFileNameWithoutExtension(localCopy.FullName).Replace("_", "-");
//TODO: Fix this nonsense... would have to wait until v8 to store the language files with their correct
// names instead of storing them as 2 letters but actually having a 4 letter culture. wtf. So now, we
// need to check if the file is 2 letters, then open it to try to find it's 4 letter culture, then use that
// if it's successful. We're going to assume (though it seems assuming in the legacy logic is never a great idea)
// that any 4 letter file is named with the actual culture that it is!
CultureInfo culture = null;
if (filename.Length == 2)
{
//we need to open the file to see if we can read it's 'real' culture, we'll use XmlReader since we don't
//want to load in the entire doc into mem just to read a single value
using (var fs = fileInfo.OpenRead())
using (var reader = XmlReader.Create(fs))
{
if (reader.IsStartElement())
{
if (reader.Name == "language")
{
if (reader.MoveToAttribute("culture"))
{
var cultureVal = reader.Value;
try
{
culture = CultureInfo.GetCultureInfo(cultureVal);
//add to the tracked dictionary
_twoLetterCultureConverter[filename] = culture;
}
catch (CultureNotFoundException)
{
LogHelper.Warn<LocalizedTextServiceFileSources>(
string.Format("The culture {0} found in the file {1} is not a valid culture", cultureVal, fileInfo.FullName));
//If the culture in the file is invalid, we'll just hope the file name is a valid culture below, otherwise
// an exception will be thrown.
}
}
}
}
}
}
if (culture == null)
{
culture = CultureInfo.GetCultureInfo(filename);
}
//get the lazy value from cache
result.Add(culture, new Lazy<XDocument>(() => _cache.GetCacheItem<XDocument>(
string.Format("{0}-{1}", typeof (LocalizedTextServiceFileSources).Name, culture.Name), () =>
{
using (var fs = localCopy.OpenRead())
{
return XDocument.Load(fs);
}
}, isSliding: true, timeout: TimeSpan.FromMinutes(10), dependentFiles: new[] {localCopy.FullName})));
}
return result;
return _xmlSources.Value;
}
//TODO: See other notes in this class, this is purely a hack because we store 2 letter culture file names that contain 4 letter cultures :(
@@ -112,6 +121,9 @@ namespace Umbraco.Core.Services
{
if (twoLetterCulture.Length != 2) Attempt<CultureInfo>.Fail();
//This needs to be resolved before continuing so that the _twoLetterCultureConverter cache is initialized
var resolved = _xmlSources.Value;
return _twoLetterCultureConverter.ContainsKey(twoLetterCulture)
? Attempt.Succeed(_twoLetterCultureConverter[twoLetterCulture])
: Attempt<CultureInfo>.Fail();

View File

@@ -415,7 +415,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMedia> GetPagedChildren(int id, int pageIndex, int pageSize, out int totalChildren,
string orderBy, Direction orderDirection, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageSize");
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
using (var repository = RepositoryFactory.CreateMediaRepository(UowProvider.GetUnitOfWork()))
{
@@ -444,7 +444,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
public IEnumerable<IMedia> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageSize");
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
using (var repository = RepositoryFactory.CreateMediaRepository(UowProvider.GetUnitOfWork()))
{

View File

@@ -9,13 +9,26 @@
*/
function LegacyController($scope, $routeParams, $element) {
var url = decodeURIComponent($routeParams.url.toLowerCase().trimStart("javascript:"));
var toClean = "*(){}[];:<>\\|'\"";
for (var i = 0; i < toClean.length; i++) {
var reg = new RegExp("\\" + toClean[i], "g");
url = url.replace(reg, "");
var url = decodeURIComponent($routeParams.url.toLowerCase().replace(/javascript\:/g, ""));
//split into path and query
var urlParts = url.split("?");
var extIndex = urlParts[0].lastIndexOf(".");
var ext = extIndex === -1 ? "" : urlParts[0].substr(extIndex);
//path cannot be a js file
if (ext !== ".js" || ext === "") {
//path cannot contain any of these chars
var toClean = "*(){}[];:<>\\|'\"";
for (var i = 0; i < toClean.length; i++) {
var reg = new RegExp("\\" + toClean[i], "g");
urlParts[0] = urlParts[0].replace(reg, "");
}
//join cleaned path and query back together
url = urlParts[0] + (urlParts.length === 1 ? "" : ("?" + urlParts[1]));
$scope.legacyPath = url;
}
else {
throw "Invalid url";
}
$scope.legacyPath = url;
}
angular.module("umbraco").controller('Umbraco.LegacyController', LegacyController);

View File

@@ -1884,7 +1884,6 @@
<Content Include="Umbraco\Plugins\Tinymce3\insertChar.aspx" />
<Content Include="Umbraco\Webservices\TreeClientService.asmx" />
<Content Include="Umbraco_Client\Application\NamespaceManager.js" />
<Content Include="Umbraco_Client\PasswordStrength\passwordstrength.js" />
<Content Include="Umbraco_Client\Ui\jQueryWresize.js" />
<Content Include="Umbraco\Search\quickSearch.js" />
<Content Include="Umbraco\Members\search.aspx" />
@@ -2553,7 +2552,7 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7240</DevelopmentServerPort>
<DevelopmentServerPort>7300</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7300</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>

View File

@@ -107,7 +107,7 @@
<p>
<strong>Please note:</strong> Installing a package containing several items and
files can take some time. Do not refresh the page or navigate away before, the installer
notifies you the install is completed.
notifies you once the install is completed.
</p>
</div>
@@ -280,9 +280,9 @@
<cc1:PropertyPanel runat="server">
<p>
All items in the package has been installed</p>
All items in the package have been installed</p>
<p>
Overview of what was installed can found under "installed package" in the developer
Overview of what was installed can be found under "installed package" in the developer
section.</p>
<p>
Uninstall is available at the same location.</p>

View File

@@ -1,148 +0,0 @@
//
// password_strength_plugin.js
// Copyright (c) 2009 myPocket technologies (www.mypocket-technologies.com)
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// View the GNU General Public License <http://www.gnu.org/licenses/>.
// @author Darren Mason (djmason9@gmail.com)
// @date 1/23/2009
// @projectDescription Password Strength Meter is a jQuery plug-in provide you smart algorithm to detect a password strength. Based on Firas Kassem orginal plugin - http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
// @version 1.0.0
//
// @requires jquery.js (tested with 1.3.1)
// @param shortPass: "shortPass", //optional
// @param badPass: "badPass", //optional
// @param goodPass: "goodPass", //optional
// @param strongPass: "strongPass", //optional
// @param baseStyle: "testresult", //optional
// @param userid: "", //required override
// @param messageloc: 1 //before == 0 or after == 1
//
(function ($) {
$.fn.shortPass = 'The password is too short';
$.fn.badPass = 'The password is weak';
$.fn.goodPass = 'Good password';
$.fn.strongPass = 'Strong password';
$.fn.samePassword = 'User name and Password are identical.';
$.fn.resultStyle = "";
$.fn.passStrength = function (options) {
var defaults = {
shortPass: 'shortPass', //optional
badPass: 'badPass', //optional
goodPass: 'goodPass', //optional
strongPass: 'strongPass', //optional
baseStyle: 'testresult', //optional
userid: '', //required override
messageloc: 1, //before == 0 or after == 1
minLength: 7
};
var opts = $.extend(defaults, options);
return this.each(function () {
var obj = $(this);
$(obj).unbind().keyup(function () {
var results = $.fn.teststrength($(this).val(), opts.userid, opts);
var fieldSpan = this.parent;
if (opts.messageloc === 1) {
$(this).parent().next("." + opts.baseStyle).remove();
$(this).parent().after("<span class=\"" + opts.baseStyle + "\"><strong></strong></span>");
$(this).parent().next("." + opts.baseStyle).addClass($(this).resultStyle).find("strong").text(results);
}
else {
$(this).prev("." + opts.baseStyle).remove();
$(this).before("<span class=\"" + opts.baseStyle + "\"><strong></strong></span>");
$(this).prev("." + opts.baseStyle).addClass($(this).resultStyle).find("strong").text(results);
}
});
//FUNCTIONS
$.fn.teststrength = function (password, username, option) {
var score = 0;
//password < minLength
if (password.length < option.minLength) { this.resultStyle = option.shortPass; return $(this).shortPass; }
//password == user name
if (password.toLowerCase() == username.toLowerCase()) { this.resultStyle = option.badPass; return $(this).samePassword; }
//password length
score += password.length // 4;
score += ($.fn.checkRepetition(1, password).length - password.length) // 1;
score += ($.fn.checkRepetition(2, password).length - password.length) // 1;
score += ($.fn.checkRepetition(3, password).length - password.length) // 1;
score += ($.fn.checkRepetition(4, password).length - password.length) // 1;
//password has 3 numbers
if (password.match(/(.*[0-9].*[0-9].*[0-9])/)) { score += 5; }
//password has 2 symbols
if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) { score += 5; }
//password has Upper and Lower chars
if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)) { score += 10; }
//password has number and chars
if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/)) { score += 15; }
//
//password has number and symbol
if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/)) { score += 15; }
//password has char and symbol
if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/)) { score += 15; }
//password is just a numbers or chars
if (password.match(/^\w+$/) || password.match(/^\d+$/)) { score -= 10; }
//verifying 0 < score < 100
if (score < 0) { score = 0; }
if (score > 100) { score = 100; }
if (score < 34) { this.resultStyle = option.badPass; return $(this).badPass; }
if (score < 68) { this.resultStyle = option.goodPass; return $(this).goodPass; }
this.resultStyle = option.strongPass;
return $(this).strongPass;
};
});
};
})(jQuery);
$.fn.checkRepetition = function(pLen, str) {
var res = '';
for (var i = 0; i < str.length; i++) {
var repeated = true;
for (var j = 0; j < pLen && (j + i + pLen) < str.length; j++) {
repeated = repeated && (str.charAt(j + i) == str.charAt(j + i + pLen));
}
if (j < pLen) { repeated = false; }
if (repeated) {
i += pLen - 1;
repeated = false;
}
else {
res += str.charAt(i);
}
}
return res;
};

View File

@@ -221,7 +221,7 @@ namespace umbraco.presentation.developer.packages
var packageId = 0;
int.TryParse(Request.GetItemAsString("pId"), out packageId);
switch (currentStep)
switch (currentStep.ToLowerInvariant())
{
case "businesslogic":
//first load in the config from the temporary directory
@@ -242,7 +242,7 @@ namespace umbraco.presentation.developer.packages
Response.Redirect("installer.aspx?installing=refresh&dir=" + dir + "&pId=" + packageId.ToString() + "&customUrl=" + Server.UrlEncode(_installer.Url));
}
break;
case "customInstaller":
case "custominstaller":
var customControl = Request.GetItemAsString("customControl");
if (customControl.IsNullOrWhiteSpace() == false)