Merge branch '7.0.1' of https://github.com/umbraco/Umbraco-CMS into 7.0.1

This commit is contained in:
perploug
2013-12-06 10:07:29 +01:00
28 changed files with 510 additions and 190 deletions

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
namespace Umbraco.Core.Macros
{
@@ -10,7 +11,7 @@ namespace Umbraco.Core.Macros
/// </summary>
internal class MacroTagParser
{
private static readonly Regex MacroRteContent = new Regex(@"(<div.*?>.*?<!--\s*?)(<\?UMBRACO_MACRO.*?/>)(.*?</div>)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
private static readonly Regex MacroRteContent = new Regex(@"(<!--\s*?)(<\?UMBRACO_MACRO.*?/>)(\s*?-->)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
private static readonly Regex MacroPersistedFormat = new Regex(@"(<\?UMBRACO_MACRO macroAlias=[""'](\w+?)[""'].+?)(?:/>|>.*?</\?UMBRACO_MACRO>)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
/// <summary>
@@ -88,7 +89,33 @@ namespace Umbraco.Core.Macros
/// </remarks>
internal static string FormatRichTextContentForPersistence(string rteContent)
{
return MacroRteContent.Replace(rteContent, match =>
if (string.IsNullOrEmpty(rteContent))
{
return string.Empty;
}
var html = new HtmlDocument();
html.LoadHtml(rteContent);
//get all the comment nodes we want
var commentNodes = html.DocumentNode.SelectNodes("//comment()[contains(., '<?UMBRACO_MACRO')]");
if (commentNodes == null)
{
return string.Empty;
}
//replace each containing parent <div> with the comment node itself.
foreach (var c in commentNodes)
{
var div = c.ParentNode;
var divContainer = div.ParentNode;
divContainer.ReplaceChild(c, div);
}
var parsed = html.DocumentNode.OuterHtml;
//now replace all the <!-- and --> with nothing
return MacroRteContent.Replace(parsed, match =>
{
if (match.Groups.Count >= 3)
{
@@ -96,7 +123,7 @@ namespace Umbraco.Core.Macros
return match.Groups[2].Value;
}
//replace with nothing if we couldn't find the syntax for whatever reason
return "";
return string.Empty;
});
}

View File

@@ -27,7 +27,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
public IDeleteColumnFromTableSyntax Column(string columnName)
{
var expression = _databaseProviders == null
var expression = _databaseProviders == null
? new DeleteColumnExpression { ColumnNames = { columnName } }
: new DeleteColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders) { ColumnNames = { columnName } };
_context.Expressions.Add(expression);
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
public IDeleteForeignKeyFromTableSyntax ForeignKey()
{
var expression = _databaseProviders == null
var expression = _databaseProviders == null
? new DeleteForeignKeyExpression()
: new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders);
_context.Expressions.Add(expression);
@@ -45,7 +45,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
public IDeleteForeignKeyOnTableSyntax ForeignKey(string foreignKeyName)
{
var expression = _databaseProviders == null
var expression = _databaseProviders == null
? new DeleteForeignKeyExpression { ForeignKey = { Name = foreignKeyName } }
: new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders) { ForeignKey = { Name = foreignKeyName } };
_context.Expressions.Add(expression);
@@ -68,17 +68,17 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
public IDeleteIndexForTableSyntax Index(string indexName)
{
var expression = new DeleteIndexExpression {Index = {Name = indexName}};
var expression = new DeleteIndexExpression { Index = { Name = indexName } };
_context.Expressions.Add(expression);
return new DeleteIndexBuilder(expression);
}
public IDeleteConstraintOnTableSyntax PrimaryKey(string primaryKeyName)
{
var expression = new DeleteConstraintExpression(ConstraintType.PrimaryKey)
{
Constraint = { ConstraintName = primaryKeyName }
};
var expression = new DeleteConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, ConstraintType.PrimaryKey)
{
Constraint = { ConstraintName = primaryKeyName }
};
_context.Expressions.Add(expression);
return new DeleteConstraintBuilder(expression);
}
@@ -86,16 +86,16 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
public IDeleteConstraintOnTableSyntax UniqueConstraint(string constraintName)
{
var expression = new DeleteConstraintExpression(ConstraintType.Unique)
{
Constraint = { ConstraintName = constraintName }
};
{
Constraint = { ConstraintName = constraintName }
};
_context.Expressions.Add(expression);
return new DeleteConstraintBuilder(expression);
}
public IDeleteDefaultConstraintOnTableSyntax DefaultConstraint()
{
var expression = _databaseProviders == null
var expression = _databaseProviders == null
? new DeleteDefaultConstraintExpression()
: new DeleteDefaultConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders);
_context.Expressions.Add(expression);

View File

@@ -10,13 +10,40 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
Constraint = new ConstraintDefinition(type);
}
public DeleteConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ConstraintType type)
: base(current, databaseProviders)
{
Constraint = new ConstraintDefinition(type);
}
public ConstraintDefinition Constraint { get; private set; }
public override string ToString()
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
// Test for MySQL primary key situation.
if (CurrentDatabaseProvider == DatabaseProviders.MySql)
{
if (Constraint.IsPrimaryKeyConstraint)
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
"PRIMARY KEY",
"");
}
else
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
"FOREIGN KEY",
"");
}
}
else
{
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(Constraint.ConstraintName));
}
}
}
}

View File

@@ -27,7 +27,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
if (ForeignKey.ForeignTable == null)
throw new ArgumentNullException("Table name not specified, ensure you have appended the OnTable extension. Format should be Delete.ForeignKey(KeyName).OnTable(TableName)");
if(CurrentDatabaseProvider == DatabaseProviders.MySql)
if (CurrentDatabaseProvider == DatabaseProviders.MySql)
{
//MySql naming "convention" for foreignkeys, which aren't explicitly named
if (string.IsNullOrEmpty(ForeignKey.Name))
@@ -35,7 +35,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(ForeignKey.ForeignTable),
"FOREIGN KEY ",
"FOREIGN KEY",
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(ForeignKey.Name));
}

View File

@@ -26,11 +26,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
//create a new col which we will make a foreign key, but first needs to be populated with data.
Alter.Table("cmsTagRelationship").AddColumn("propertyTypeId").AsInt32().Nullable();
//drop the foreign key on umbracoNode. Must drop foreign key first before primary key can be removed in MySql.
Delete.ForeignKey("FK_cmsTagRelationship_umbracoNode_id").OnTable("cmsTagRelationship");
//we need to drop the primary key
Delete.PrimaryKey("PK_cmsTagRelationship").FromTable("cmsTagRelationship");
//drop the foreign key on umbracoNode
Delete.ForeignKey("FK_cmsTagRelationship_umbracoNode_id").OnTable("cmsTagRelationship");
}
private void Upgrade()
@@ -57,9 +57,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
var propertyTypes = propertyTypeIdRef.Where(x => x.NodeId == tr.NodeId).ToArray();
if (propertyTypes.Length == 0)
{
LogHelper.Warn<AlterTagRelationsTable>("There was no cmsContent reference for cmsTagRelationship for nodeId "
LogHelper.Warn<AlterTagRelationsTable>("There was no cmsContent reference for cmsTagRelationship for nodeId "
+ tr.NodeId +
". The new tag system only supports tags with references to content in the cmsContent and cmsPropertyType tables. This row will be deleted: "
". The new tag system only supports tags with references to content in the cmsContent and cmsPropertyType tables. This row will be deleted: "
+ string.Format("nodeId: {0}, tagId: {1}", tr.NodeId, tr.TagId));
Delete.FromTable("cmsTagRelationship").Row(new { nodeId = tr.NodeId, tagId = tr.TagId });
}
@@ -92,7 +92,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
Alter.Table("cmsTagRelationship").AlterColumn("propertyTypeId").AsInt32().NotNullable();
//we need to re-add the new primary key on all 3 columns
Create.PrimaryKey("PK_cmsTagRelationship").OnTable("cmsTagRelationship").Columns(new[] {"nodeId", "propertyTypeId", "tagId"});
Create.PrimaryKey("PK_cmsTagRelationship").OnTable("cmsTagRelationship").Columns(new[] { "nodeId", "propertyTypeId", "tagId" });
//now we need to add a foreign key to the propertyTypeId column and change it's constraints
Create.ForeignKey("FK_cmsTagRelationship_cmsPropertyType")
@@ -102,7 +102,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
.PrimaryColumn("id")
.OnDelete(Rule.None)
.OnUpdate(Rule.None);
//now we need to add a foreign key to the nodeId column to cmsContent (intead of the original umbracoNode)
Create.ForeignKey("FK_cmsTagRelationship_cmsContent")
.FromTable("cmsTagRelationship")

View File

@@ -33,7 +33,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
TimeColumnDefinition = "time";
DecimalColumnDefinition = "decimal(38,6)";
GuidColumnDefinition = "char(36)";
InitColumnTypeMap();
DefaultValueFormat = "DEFAULT '{0}'";
@@ -48,7 +48,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = @TableSchema",
new {TableSchema = db.Connection.Database});
new { TableSchema = db.Connection.Database });
list = items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
}
finally
@@ -67,7 +67,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @TableSchema",
new {TableSchema = db.Connection.Database});
new { TableSchema = db.Connection.Database });
list =
items.Select(
item =>
@@ -90,7 +90,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = @TableSchema",
new {TableSchema = db.Connection.Database});
new { TableSchema = db.Connection.Database });
list = items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
}
finally
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = @TableSchema",
new {TableSchema = db.Connection.Database});
new { TableSchema = db.Connection.Database });
list =
items.Select(
item =>
@@ -133,7 +133,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES " +
"WHERE TABLE_NAME = @TableName AND " +
"TABLE_SCHEMA = @TableSchema",
new {TableName = tableName, TableSchema = db.Connection.Database});
new { TableName = tableName, TableSchema = db.Connection.Database });
}
finally
@@ -213,7 +213,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return string.Format(CreateIndex,
GetQuotedName(name),
GetQuotedTableName(index.TableName),
GetQuotedTableName(index.TableName),
columns);
}
@@ -290,7 +290,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
{
get
{
throw new NotSupportedException("Default constraints are not supported in MySql");
return "ALTER TABLE {0} ALTER COLUMN {1} DROP DEFAULT";
}
}
@@ -303,7 +303,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public override string CreateForeignKeyConstraint { get { return "ALTER TABLE {0} ADD FOREIGN KEY ({1}) REFERENCES {2} ({3}){4}{5}"; } }
public override string DeleteConstraint { get { return "ALTER TABLE {0} DROP {1}{2}"; } }
public override string DeleteConstraint { get { return "ALTER TABLE {0} DROP {1} {2}"; } }
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
@@ -318,11 +318,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
db.OpenSharedConnection();
// Need 4 @ signs as it is regarded as a parameter, @@ escapes it once, @@@@ escapes it twice
var lowerCaseTableNames = db.Fetch<int>("SELECT @@@@Global.lower_case_table_names");
if(lowerCaseTableNames.Any())
if (lowerCaseTableNames.Any())
supportsCaseInsensitiveQueries = lowerCaseTableNames.First() == 1;
}
catch(Exception ex)
catch (Exception ex)
{
Logging.LogHelper.Error<MySqlSyntaxProvider>("Error querying for lower_case support", ex);
}

View File

@@ -309,7 +309,7 @@ namespace Umbraco.Core
//return false but specify this exception type so we can detect it
if (typeElement == null)
return Attempt<IEnumerable<string>>.Fail(new CachedPluginNotFoundInFile());
return Attempt<IEnumerable<string>>.Fail(new CachedPluginNotFoundInFileException());
//return success
return Attempt.Succeed(typeElement.Elements("add")
@@ -459,24 +459,24 @@ namespace Umbraco.Core
private readonly HashSet<TypeList> _types = new HashSet<TypeList>();
private IEnumerable<Assembly> _assemblies;
/// <summary>
/// Returns all found property editors
/// Returns all found property editors (based on the resolved Iparameter editors - this saves a scan)
/// </summary>
internal IEnumerable<Type> ResolvePropertyEditors()
{
//return all proeprty editor types found except for the base property editor type
return ResolveTypes<PropertyEditor>().ToArray()
.Except(new[] {typeof (PropertyEditor)});
return ResolveTypes<IParameterEditor>()
.Where(x => x.IsType<PropertyEditor>())
.Except(new[] { typeof(PropertyEditor) });
}
/// <summary>
/// Returns all found parameter editors
/// Returns all found parameter editors (which includes property editors)
/// </summary>
internal IEnumerable<Type> ResolveParameterEditors()
{
//return all paramter editor types found except for the base property editor type
return ResolveTypes<IParameterEditor>().ToArray()
return ResolveTypes<IParameterEditor>()
.Except(new[] { typeof(ParameterEditor), typeof(PropertyEditor) });
}
@@ -671,8 +671,15 @@ namespace Umbraco.Core
{
//check if the TypeList already exists, if so return it, if not we'll create it
var typeList = _types.SingleOrDefault(x => x.IsTypeList<T>(resolutionType));
//need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505
if (cacheResult && typeList != null)
{
LogHelper.Debug<PluginManager>("Existing typeList found for {0} with resolution type {1}", () => typeof(T), () => resolutionType);
}
//if we're not caching the result then proceed, or if the type list doesn't exist then proceed
if (!cacheResult || typeList == null)
if (cacheResult == false || typeList == null)
{
//upgrade to a write lock since we're adding to the collection
readLock.UpgradeToWriteLock();
@@ -681,15 +688,17 @@ namespace Umbraco.Core
//we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory).
//if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file.
if (!HaveAssembliesChanged && File.Exists(GetPluginListFilePath()))
if (HaveAssembliesChanged == false && File.Exists(GetPluginListFilePath()))
{
var fileCacheResult = TryGetCachedPluginsFromFile<T>(resolutionType);
//here we need to identify if the CachedPluginNotFoundInFile was the exception, if it was then we need to re-scan
//in some cases the plugin will not have been scanned for on application startup, but the assemblies haven't changed
//so in this instance there will never be a result.
if (fileCacheResult.Exception != null && fileCacheResult.Exception is CachedPluginNotFoundInFile)
if (fileCacheResult.Exception != null && fileCacheResult.Exception is CachedPluginNotFoundInFileException)
{
LogHelper.Debug<PluginManager>("Tried to find typelist for type {0} and resolution {1} in file cache but the type was not found so loading types by assembly scan ", () => typeof(T), () => resolutionType);
//we don't have a cache for this so proceed to look them up by scanning
LoadViaScanningAndUpdateCacheFile<T>(typeList, resolutionType, finder);
}
@@ -717,20 +726,22 @@ namespace Umbraco.Core
break;
}
}
if (!successfullyLoadedFromCache)
if (successfullyLoadedFromCache == false)
{
//we need to manually load by scanning if loading from the file was not successful.
LoadViaScanningAndUpdateCacheFile<T>(typeList, resolutionType, finder);
}
else
{
LogHelper.Debug<PluginManager>("Loaded plugin types " + typeof(T).FullName + " from persisted cache");
LogHelper.Debug<PluginManager>("Loaded plugin types {0} with resolution {1} from persisted cache", () => typeof(T), () => resolutionType);
}
}
}
}
else
{
LogHelper.Debug<PluginManager>("Assembly changes detected, loading types {0} for resolution {1} by assembly scan", () => typeof(T), () => resolutionType);
//we don't have a cache for this so proceed to look them up by scanning
LoadViaScanningAndUpdateCacheFile<T>(typeList, resolutionType, finder);
}
@@ -739,7 +750,10 @@ namespace Umbraco.Core
if (cacheResult)
{
//add the type list to the collection
_types.Add(typeList);
var added = _types.Add(typeList);
LogHelper.Debug<PluginManager>("Caching of typelist for type {0} and resolution {1} was successful = {2}", () => typeof(T), () => resolutionType, () => added);
}
}
typesFound = typeList.GetTypes().ToList();
@@ -863,14 +877,14 @@ namespace Umbraco.Core
}
/// <summary>
/// Returns true if the current TypeList is of the same type and of the same type
/// Returns true if the current TypeList is of the same lookup type
/// </summary>
/// <typeparam name="TLookup"></typeparam>
/// <param name="resolutionType"></param>
/// <returns></returns>
public override bool IsTypeList<TLookup>(TypeResolutionKind resolutionType)
{
return _resolutionType == resolutionType && (typeof(T)).IsType<TLookup>();
return _resolutionType == resolutionType && (typeof(T)) == typeof(TLookup);
}
public override IEnumerable<Type> GetTypes()
@@ -883,7 +897,7 @@ namespace Umbraco.Core
/// This class is used simply to determine that a plugin was not found in the cache plugin list with the specified
/// TypeResolutionKind.
/// </summary>
internal class CachedPluginNotFoundInFile : Exception
internal class CachedPluginNotFoundInFileException : Exception
{
}

View File

@@ -166,7 +166,8 @@ namespace Umbraco.Core.Services
var uow = _uowProvider.GetUnitOfWork();
var sql = new Sql();
sql.Select("app").From<User2AppDto>().Where("[user] = @userID", new {userID = user.Id});
sql.Select("app").From<User2AppDto>()
.Where<User2AppDto>(dto => dto.UserId == (int)user.Id);
return uow.Database.Fetch<string>(sql);
}

View File

@@ -44,6 +44,9 @@
<Reference Include="AutoMapper.Net4">
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack">
<HintPath>..\packages\HtmlAgilityPack.1.4.6\lib\Net45\HtmlAgilityPack.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=1.2.11.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\log4net-mediumtrust.2.0.0\lib\log4net.dll</HintPath>

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net45" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net40" />

View File

@@ -158,5 +158,22 @@ asdfsdf
</body>
</html>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
}
[Test]
public void Format_RTE_Data_For_Persistence_Custom_Single_Entry()
{
var content = @"<div class=""umb-macro-holder Test mceNonEditable umb-macro-mce_1""><!-- <?UMBRACO_MACRO macroAlias=""Test"" content=""1089"" textArea=""asdfasdf"" title="""" bool=""0"" number="""" contentType="""" multiContentType="""" multiProperties="""" properties="""" tabs="""" multiTabs="""" /> --><ins>
<div class=""facts-box"">
<div class=""fatcs-box-header"">
<h3>null</h3>
</div>
<div class=""fatcs-box-body"">1089</div>
</div>
</ins></div>";
var result = MacroTagParser.FormatRichTextContentForPersistence(content);
Assert.AreEqual(@"<?UMBRACO_MACRO macroAlias=""Test"" content=""1089"" textArea=""asdfasdf"" title="""" bool=""0"" number="""" contentType="""" multiContentType="""" multiProperties="""" properties="""" tabs="""" multiTabs="""" />", result);
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
@@ -9,8 +10,10 @@ using NUnit.Framework;
using SqlCE4Umbraco;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.PropertyEditors;
using umbraco;
using umbraco.DataLayer;
using umbraco.MacroEngines;
@@ -333,6 +336,29 @@ namespace Umbraco.Tests
var types = PluginManager.Current.ResolveXsltExtensions();
Assert.AreEqual(3, types.Count());
}
/// <summary>
/// This demonstrates this issue: http://issues.umbraco.org/issue/U4-3505 - the TypeList was returning a list of assignable types
/// not explicit types which is sort of ideal but is confusing so we'll do it the less confusing way.
/// </summary>
[Test]
public void TypeList_Resolves_Explicit_Types()
{
var types = new HashSet<PluginManager.TypeList>();
var propEditors = new PluginManager.TypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes);
propEditors.AddType(typeof (LabelPropertyEditor));
types.Add(propEditors);
var found = types.SingleOrDefault(x => x.IsTypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
Assert.IsNotNull(found);
//This should not find a type list of this type
var shouldNotFind = types.SingleOrDefault(x => x.IsTypeList<IParameterEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
Assert.IsNull(shouldNotFind);
}
[XsltExtension("Blah.Blah")]
public class MyXsltExtension

View File

@@ -647,11 +647,6 @@
<None Include="Config\404handlers.Release.config">
<DependentUpon>404handlers.config</DependentUpon>
</None>
<Content Include="Config\appSettings.config" />
<None Include="Config\appSettings.Release.config">
<SubType>Designer</SubType>
<DependentUpon>appSettings.config</DependentUpon>
</None>
<None Include="Config\ClientDependency.Release.config">
<DependentUpon>ClientDependency.config</DependentUpon>
<SubType>Designer</SubType>
@@ -662,10 +657,6 @@
<None Include="Config\BaseRestExtensions.Release.config">
<DependentUpon>BaseRestExtensions.config</DependentUpon>
</None>
<Content Include="Config\connectionStrings.config" />
<None Include="Config\connectionStrings.Release.config">
<DependentUpon>connectionStrings.config</DependentUpon>
</None>
<None Include="Config\log4net.Release.config">
<DependentUpon>log4net.config</DependentUpon>
</None>
@@ -2654,10 +2645,6 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
<Target Name="BeforeBuild">
<!-- Create web.config file from Template if it doesn't exist -->
<Copy SourceFiles="$(ProjectDir)web.Template.config" DestinationFiles="$(ProjectDir)Web.config" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="false" Condition="!Exists('$(ProjectDir)Web.config')" />
<!-- Create connectionStrings.config file from Template if it doesn't exist -->
<Copy SourceFiles="$(ProjectDir)config\connectionStrings.Release.config" DestinationFiles="$(ProjectDir)config\connectionStrings.config" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="false" Condition="!Exists('$(ProjectDir)config\connectionStrings.config')" />
<!-- Create appSettings.config file from Template if it doesn't exist -->
<Copy SourceFiles="$(ProjectDir)config\appSettings.Release.config" DestinationFiles="$(ProjectDir)config\appSettings.config" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="false" Condition="!Exists('$(ProjectDir)config\appSettings.config')" />
<!-- Transform the local Web.config file in Visual Studio -->
<TransformXml Source="$(ProjectDir)Web.config" Transform="$(ProjectDir)web.Template.$(Configuration).config" Destination="$(ProjectDir)Web.$(Configuration).config.transformed" Condition="$(BuildingInsideVisualStudio) == true" />
<!-- Always transform the Template file when not in VS (ie: build.bat) -->

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<!--
Umbraco web.config configuration documentation can be found here:
http://our.umbraco.org/documentation/using-umbraco/config-files/#webconfig
-->
<add key="umbracoConfigurationStatus" value="" />
<add key="umbracoReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd" />
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
<add key="umbracoPath" value="~/umbraco" />
<add key="umbracoHideTopLevelNodeFromPath" value="true" />
<add key="umbracoUseDirectoryUrls" value="true" />
<add key="umbracoTimeOutInMinutes" value="20" />
<add key="umbracoDefaultUILanguage" value="en" />
<add key="umbracoUseSSL" value="false" />
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
<add key="webpages:Enabled" value="false"/>
<add key="enableSimpleMembership" value="false"/>
<add key="autoFormsAuthentication" value="false"/>
<add key="log4net.Config" value="config\log4net.config" />
</appSettings>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
<remove name="umbracoDbDSN"/>
<add name="umbracoDbDSN" connectionString="" providerName="" />
<!-- Important: If you're upgrading Umbraco, do not clear the connection string / provider name during your web.config merge. -->
</connectionStrings>

View File

@@ -13,7 +13,6 @@
The transforms in this file only apply to debugging, not to the web.config that will be released, see web.Template.Release.config for that
2012-11-08 SJ - Add Medium trust for everybody so we'll see any MedTrust related errors early on
-->
@@ -46,11 +45,29 @@
<dashBoard configSource="config\Dashboard.config"/>
</umbracoConfiguration>
<appSettings xdt:Transform="Remove" />
<appSettings configSource="config\appSettings.config" xdt:Transform="InsertAfter(/configuration/umbracoConfiguration)" />
<appSettings xdt:Transform="Remove" xdt:Locator="Condition(@configSource != '')" />
<appSettings xdt:Transform="InsertIfMissing" >
<add key="umbracoConfigurationStatus" value="" />
<add key="umbracoReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd" />
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
<add key="umbracoPath" value="~/umbraco" />
<add key="umbracoHideTopLevelNodeFromPath" value="true" />
<add key="umbracoUseDirectoryUrls" value="true" />
<add key="umbracoTimeOutInMinutes" value="20" />
<add key="umbracoDefaultUILanguage" value="en" />
<add key="umbracoUseSSL" value="false" />
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
<add key="webpages:Enabled" value="false"/>
<add key="enableSimpleMembership" value="false"/>
<add key="autoFormsAuthentication" value="false"/>
<add key="log4net.Config" value="config\log4net.config" />
</appSettings>
<connectionStrings xdt:Transform="Remove" />
<connectionStrings configSource="config\connectionStrings.config" xdt:Transform="InsertAfter(/configuration/appSettings)" />
<connectionStrings xdt:Transform="Remove" xdt:Locator="Condition(@configSource != '')" />
<connectionStrings xdt:Transform="InsertIfMissing">
<remove name="umbracoDbDSN"/>
<add name="umbracoDbDSN" connectionString="" providerName="" />
</connectionStrings>
<system.web>
<xhtmlConformance xdt:Transform="Remove"/>

View File

@@ -29,8 +29,34 @@
<ExamineLuceneIndexSets configSource="config\ExamineIndex.config" />
<log4net configSource="config\log4net.config" />
<appSettings configSource="config\appSettings.config" />
<connectionStrings configSource="config\connectionStrings.config" />
<appSettings>
<!--
Umbraco web.config configuration documentation can be found here:
http://our.umbraco.org/documentation/using-umbraco/config-files/#webconfig
-->
<add key="umbracoConfigurationStatus" value="" />
<add key="umbracoReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd" />
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
<add key="umbracoPath" value="~/umbraco" />
<add key="umbracoHideTopLevelNodeFromPath" value="true" />
<add key="umbracoUseDirectoryUrls" value="true" />
<add key="umbracoTimeOutInMinutes" value="20" />
<add key="umbracoDefaultUILanguage" value="en" />
<add key="umbracoUseSSL" value="false" />
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
<add key="webpages:Enabled" value="false"/>
<add key="enableSimpleMembership" value="false"/>
<add key="autoFormsAuthentication" value="false"/>
<add key="log4net.Config" value="config\log4net.config" />
</appSettings>
<connectionStrings>
<remove name="umbracoDbDSN"/>
<add name="umbracoDbDSN" connectionString="" providerName="" />
<!-- Important: If you're upgrading Umbraco, do not clear the connection string / provider name during your web.config merge. -->
</connectionStrings>
<system.data>
<DbProviderFactories>

View File

@@ -28,18 +28,9 @@ namespace Umbraco.Web.Editors
/// </summary>
[PluginController("UmbracoApi")]
[ValidationFilter]
[AngularJsonOnlyConfiguration]
public class AuthenticationController : UmbracoApiController
{
/// <summary>
/// Remove the xml formatter... only support JSON!
/// </summary>
/// <param name="controllerContext"></param>
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
controllerContext.EnsureJsonOutputOnly();
}
/// <summary>
/// This is a special method that will return the current users' remaining session seconds, the reason

View File

@@ -12,6 +12,7 @@ namespace Umbraco.Web.Editors
/// methods that are not called by Angular or don't contain a valid csrf header will NOT work.
/// </remarks>
[ValidateAngularAntiForgeryToken]
[AngularJsonOnlyConfiguration]
public abstract class UmbracoAuthorizedJsonController : UmbracoAuthorizedApiController
{
protected UmbracoAuthorizedJsonController()
@@ -22,17 +23,5 @@ namespace Umbraco.Web.Editors
{
}
/// <summary>
/// Remove the xml formatter... only support JSON!
/// </summary>
/// <param name="controllerContext"></param>
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
controllerContext.EnsureJsonOutputOnly();
}
}
}

View File

@@ -20,21 +20,10 @@ using umbraco;
namespace Umbraco.Web.Trees
{
[AngularJsonOnlyConfiguration]
[PluginController("UmbracoTrees")]
public class ApplicationTreeController : UmbracoAuthorizedApiController
{
/// <summary>
/// Remove the xml formatter... only support JSON!
/// </summary>
/// <param name="controllerContext"></param>
protected override void Initialize(global::System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
controllerContext.EnsureJsonOutputOnly();
}
/// <summary>
/// Returns the tree nodes for an application
/// </summary>

View File

@@ -15,18 +15,9 @@ namespace Umbraco.Web.Trees
/// A base controller reference for non-attributed trees (un-registered). Developers should inherit from
/// TreeController.
/// </summary>
[AngularJsonOnlyConfiguration]
public abstract class TreeControllerBase : UmbracoAuthorizedApiController
{
/// <summary>
/// Remove the xml formatter... only support JSON!
/// </summary>
/// <param name="controllerContext"></param>
protected override void Initialize(global::System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
controllerContext.EnsureJsonOutputOnly();
}
/// <summary>
/// The method called to render the contents of the tree structure
/// </summary>

View File

@@ -976,35 +976,32 @@ namespace Umbraco.Web
{
var doc = new HtmlDocument();
doc.LoadHtml("<p>" + html + "</p>");
using (var ms = new MemoryStream())
{
var targets = new List<HtmlNode>();
var targets = new List<HtmlNode>();
var nodes = doc.DocumentNode.FirstChild.SelectNodes(".//*");
if (nodes != null)
{
foreach (var node in nodes)
{
//is element
if (node.NodeType != HtmlNodeType.Element) continue;
var filterAllTags = (tags == null || !tags.Any());
if (filterAllTags || tags.Any(tag => string.Equals(tag, node.Name, StringComparison.CurrentCultureIgnoreCase)))
{
targets.Add(node);
}
}
foreach (var target in targets)
{
HtmlNode content = doc.CreateTextNode(target.InnerText);
target.ParentNode.ReplaceChild(content, target);
}
}
else
{
return new HtmlString(html);
}
return new HtmlString(doc.DocumentNode.FirstChild.InnerHtml);
}
var nodes = doc.DocumentNode.FirstChild.SelectNodes(".//*");
if (nodes != null)
{
foreach (var node in nodes)
{
//is element
if (node.NodeType != HtmlNodeType.Element) continue;
var filterAllTags = (tags == null || !tags.Any());
if (filterAllTags || tags.Any(tag => string.Equals(tag, node.Name, StringComparison.CurrentCultureIgnoreCase)))
{
targets.Add(node);
}
}
foreach (var target in targets)
{
HtmlNode content = doc.CreateTextNode(target.InnerText);
target.ParentNode.ReplaceChild(content, target);
}
}
else
{
return new HtmlString(html);
}
return new HtmlString(doc.DocumentNode.FirstChild.InnerHtml);
}
public string Coalesce(params object[] args)

View File

@@ -96,22 +96,38 @@ namespace Umbraco.Web.WebApi
jsonFormatter.SerializerSettings.Converters.Add(new CustomDateTimeConvertor("yyyy-MM-dd HH:mm:ss"));
}
/// <summary>
/// Removes the xml formatter so it only outputs angularized json (with the json vulnerability prefix added)
/// </summary>
/// <param name="controllerContext"></param>
internal static void EnsureJsonOutputOnly(this HttpControllerContext controllerContext)
{
///// <summary>
///// Removes the xml formatter so it only outputs angularized json (with the json vulnerability prefix added)
///// </summary>
///// <param name="controllerContext"></param>
//internal static void EnsureJsonOutputOnly(this HttpControllerContext controllerContext)
//{
// controllerContext.Configuration.Formatters = new MediaTypeFormatterCollection();
// //remove all json/xml formatters then add our custom one
// var toRemove = controllerContext.Configuration.Formatters.Where(t => (t is JsonMediaTypeFormatter) || (t is XmlMediaTypeFormatter)).ToList();
// foreach (var r in toRemove)
// {
// controllerContext.Configuration.Formatters.Remove(r);
// }
// controllerContext.Configuration.Formatters.Add(new AngularJsonMediaTypeFormatter());
//}
}
/// <summary>
/// Applying this attribute to any webapi controller will ensure that it only contains one json formatter compatible with the angular json vulnerability prevention.
/// </summary>
public class AngularJsonOnlyConfigurationAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
//remove all json/xml formatters then add our custom one
for (var i = 0; i < controllerContext.Configuration.Formatters.Count;i++)
var toRemove = controllerSettings.Formatters.Where(t => (t is JsonMediaTypeFormatter) || (t is XmlMediaTypeFormatter)).ToList();
foreach (var r in toRemove)
{
if ((controllerContext.Configuration.Formatters[i] is JsonMediaTypeFormatter)
|| (controllerContext.Configuration.Formatters[i] is XmlMediaTypeFormatter))
{
controllerContext.Configuration.Formatters.RemoveAt(i);
}
controllerSettings.Formatters.Remove(r);
}
controllerContext.Configuration.Formatters.Add(new AngularJsonMediaTypeFormatter());
controllerSettings.Formatters.Add(new AngularJsonMediaTypeFormatter());
}
}
}

View File

@@ -796,7 +796,9 @@ namespace umbraco
{
if (attributes.ContainsKey(mp.Key.ToLower()))
{
mp.Value = attributes[mp.Key.ToLower()].ToString();
var item = attributes[mp.Key.ToLower()];
mp.Value = item == null ? string.Empty : item.ToString();
}
else
{

View File

@@ -7,6 +7,7 @@ using System.Web;
using System.Web.Compilation;
using System.Web.WebPages;
using Umbraco.Core;
using umbraco.MacroEngines.Resources;
using umbraco.cms.businesslogic.macro;
using umbraco.interfaces;
using Umbraco.Core.IO;
@@ -16,6 +17,7 @@ namespace umbraco.MacroEngines
public class RazorMacroEngine : IMacroEngine, IMacroEngineResultStatus {
public const string RazorTempDirectory = "~/App_Data/TEMP/Razor/";
private const string RazorWebConfig = "~/App_Data/TEMP/Razor/web.config";
public string GetVirtualPathFromPhysicalPath(string physicalPath) {
string rootpath = HttpContext.Current.Server.MapPath("~/");
@@ -40,6 +42,7 @@ namespace umbraco.MacroEngines
var relativePath = RazorTempDirectory + fileName;
var physicalPath = IOHelper.MapPath(relativePath);
var physicalDirectoryPath = IOHelper.MapPath(RazorTempDirectory);
var webconfig = IOHelper.MapPath(RazorWebConfig);
if (skipIfFileExists && File.Exists(physicalPath))
return relativePath;
@@ -47,6 +50,16 @@ namespace umbraco.MacroEngines
File.Delete(physicalPath);
if (!Directory.Exists(physicalDirectoryPath))
Directory.CreateDirectory(physicalDirectoryPath);
//Ensure the correct razor web.config is there
if (File.Exists(webconfig) == false)
{
using (var writer = File.CreateText(webconfig))
{
writer.Write(Strings.WebConfig);
}
}
using (var file = new StreamWriter(physicalPath, false, Encoding.UTF8))
{
file.Write(razorSyntax);

View File

@@ -0,0 +1,78 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34003
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace umbraco.MacroEngines.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Strings {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Strings() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("umbraco.MacroEngines.Resources.Strings", typeof(Strings).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot;?&gt;
///&lt;configuration&gt;
///
/// &lt;configSections&gt;
/// &lt;sectionGroup name=&quot;system.web.webPages.razor&quot; type=&quot;System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&quot;&gt;
/// &lt;section name=&quot;host&quot; type=&quot;System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&quot; requirePermission=&quot;false&quot; /&gt;
/// &lt;section name=&quot;page [rest of string was truncated]&quot;;.
/// </summary>
internal static string WebConfig {
get {
return ResourceManager.GetString("WebConfig", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="WebConfig" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\umbraco.web.ui\macroscripts\web.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View File

@@ -180,6 +180,11 @@
<Compile Include="RazorCore\RazorMacroEngine.cs" />
<Compile Include="RazorDynamicNode\Res.cs" />
<Compile Include="RazorDynamicNode\Signature.cs" />
<Compile Include="Resources\Strings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Strings.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
@@ -216,8 +221,17 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="..\Umbraco.Web.UI\MacroScripts\Web.config">
<Link>Resources\Web.config</Link>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Strings.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Strings.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>