Merge with 4.11.9
This commit is contained in:
@@ -17,7 +17,72 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public class XmlHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether a specified string contains only xml whitespace characters.
|
||||
/// </summary>
|
||||
/// <param name="s">The string.</param>
|
||||
/// <returns><c>true</c> if the string contains only xml whitespace characters.</returns>
|
||||
/// <remarks>As per XML 1.1 specs, space, \t, \r and \n.</remarks>
|
||||
public static bool IsXmlWhitespace(string s)
|
||||
{
|
||||
// as per xml 1.1 specs - anything else is significant whitespace
|
||||
s = s.Trim(' ', '\t', '\r', '\n');
|
||||
return s.Length == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <c>XPathDocument</c> from an xml string.
|
||||
/// </summary>
|
||||
/// <param name="xml">The xml string.</param>
|
||||
/// <returns>An <c>XPathDocument</c> created from the xml string.</returns>
|
||||
public static XPathDocument CreateXPathDocument(string xml)
|
||||
{
|
||||
return new XPathDocument(new XmlTextReader(new StringReader(xml)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to create a new <c>XPathDocument</c> from an xml string.
|
||||
/// </summary>
|
||||
/// <param name="xml">The xml string.</param>
|
||||
/// <param name="doc">The XPath document.</param>
|
||||
/// <returns>A value indicating whether it has been possible to create the document.</returns>
|
||||
public static bool TryCreateXPathDocument(string xml, out XPathDocument doc)
|
||||
{
|
||||
try
|
||||
{
|
||||
doc = new XPathDocument(new XmlTextReader(new StringReader(xml)));
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
doc = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to create a new <c>XPathDocument</c> from a property value.
|
||||
/// </summary>
|
||||
/// <param name="alias">The alias of the property.</param>
|
||||
/// <param name="value">The value of the property.</param>
|
||||
/// <param name="doc">The XPath document.</param>
|
||||
/// <returns>A value indicating whether it has been possible to create the document.</returns>
|
||||
public static bool TryCreateXPathDocumentFromPropertyValue(string alias, object value, out XPathDocument doc)
|
||||
{
|
||||
// In addition, DynamicNode strips dashes in elements or attributes
|
||||
// names but really, this is ugly enough, and using dashes should be
|
||||
// illegal in content type or property aliases anyway.
|
||||
|
||||
doc = null;
|
||||
var xml = value as string;
|
||||
if (xml == null) return false;
|
||||
xml = xml.Trim();
|
||||
if (xml.StartsWith("<") == false || xml.EndsWith(">") == false || xml.Contains('/') == false) return false;
|
||||
if (UmbracoSettings.NotDynamicXmlDocumentElements.Any(x => x.InvariantEquals(alias))) return false;
|
||||
return TryCreateXPathDocument(xml, out doc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts the children of the parentNode that match the xpath selector
|
||||
/// </summary>
|
||||
/// <param name="parentNode"></param>
|
||||
@@ -72,7 +137,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static string StripDashesInElementOrAttributeNames(string xml)
|
||||
{
|
||||
using (var outputms = new MemoryStream())
|
||||
@@ -126,6 +191,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Imports a XML node from text.
|
||||
/// </summary>
|
||||
@@ -222,11 +288,11 @@ namespace Umbraco.Core
|
||||
/// </returns>
|
||||
public static bool CouldItBeXml(string xml)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(xml))
|
||||
if (string.IsNullOrEmpty(xml) == false)
|
||||
{
|
||||
xml = xml.Trim();
|
||||
|
||||
if (xml.StartsWith("<") && xml.EndsWith(">"))
|
||||
if (xml.StartsWith("<") && xml.EndsWith(">") && xml.Contains("/"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -293,9 +293,9 @@ namespace Umbraco.Web
|
||||
//ok it doesn't exist, we might assume now that Examine didn't index this property because the index is not set up correctly
|
||||
//so before we go loading this from the database, we can check if the alias exists on the content type at all, this information
|
||||
//is cached so will be quicker to look up.
|
||||
if (dd.Properties.Any(x => x.Alias == "__NodeTypeAlias"))
|
||||
if (dd.Properties.Any(x => x.Alias == UmbracoContentIndexer.NodeTypeAliasFieldName))
|
||||
{
|
||||
var aliasesAndNames = ContentType.GetAliasesAndNames(dd.Properties.First(x => x.Alias.InvariantEquals("__NodeTypeAlias")).Value.ToString());
|
||||
var aliasesAndNames = ContentType.GetAliasesAndNames(dd.Properties.First(x => x.Alias.InvariantEquals(UmbracoContentIndexer.NodeTypeAliasFieldName)).Value.ToString());
|
||||
if (aliasesAndNames != null)
|
||||
{
|
||||
if (!aliasesAndNames.ContainsKey(alias))
|
||||
@@ -317,7 +317,12 @@ namespace Umbraco.Web
|
||||
}
|
||||
}
|
||||
|
||||
return dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
//We've made it here which means that the value is stored in the Examine index.
|
||||
//We are going to check for a special field however, that is because in some cases we store a 'Raw'
|
||||
//value in the index such as for xml/html.
|
||||
var rawValue = dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals("__Raw_" + alias));
|
||||
return rawValue
|
||||
?? dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Examine.Providers;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web;
|
||||
@@ -15,6 +17,8 @@ namespace umbraco.presentation.umbraco.Search
|
||||
public class ExamineEvents : IApplicationEventHandler
|
||||
{
|
||||
|
||||
private const string RawFieldPrefix = "__Raw_";
|
||||
|
||||
public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
|
||||
{
|
||||
}
|
||||
@@ -51,12 +55,13 @@ namespace umbraco.presentation.umbraco.Search
|
||||
var contentIndexer = ExamineManager.Instance.IndexProviderCollection["InternalIndexer"] as UmbracoContentIndexer;
|
||||
if (contentIndexer != null)
|
||||
{
|
||||
contentIndexer.DocumentWriting += indexer_DocumentWriting;
|
||||
contentIndexer.GatheringNodeData += ContentIndexerGatheringNodeData;
|
||||
contentIndexer.DocumentWriting += IndexerDocumentWriting;
|
||||
}
|
||||
var memberIndexer = ExamineManager.Instance.IndexProviderCollection["InternalMemberIndexer"] as UmbracoMemberIndexer;
|
||||
if (memberIndexer != null)
|
||||
{
|
||||
memberIndexer.DocumentWriting += indexer_DocumentWriting;
|
||||
memberIndexer.DocumentWriting += IndexerDocumentWriting;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,16 +141,64 @@ namespace umbraco.presentation.umbraco.Search
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler to create a lower cased version of the node name, this is so we can support case-insensitive searching and still
|
||||
/// use the Whitespace Analyzer
|
||||
/// This checks if any user data might be xml/html, if so we will duplicate the field and store the raw value
|
||||
/// so we can retreive the raw value when required.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void indexer_DocumentWriting(object sender, Examine.LuceneEngine.DocumentWritingEventArgs e)
|
||||
/// <remarks>
|
||||
/// This is regarding this issue: http://issues.umbraco.org/issue/U4-644
|
||||
/// The underlying UmbracoContentIndexer strips the HTML values before this event is even fired
|
||||
/// so we need to check in the underlying 'node' document for the value.
|
||||
/// </remarks>
|
||||
static void ContentIndexerGatheringNodeData(object sender, IndexingNodeDataEventArgs e)
|
||||
{
|
||||
if (e.Fields.Keys.Contains("nodeName"))
|
||||
var indexer = sender as UmbracoContentIndexer;
|
||||
if (indexer == null) return;
|
||||
|
||||
//loop through each field that is defined as a UserField for the index
|
||||
foreach (var field in indexer.IndexerData.UserFields)
|
||||
{
|
||||
//add the lower cased version
|
||||
if (e.Fields.ContainsKey(field.Name))
|
||||
{
|
||||
//get the original value from the node
|
||||
var node = e.Node.Descendants(field.Name).FirstOrDefault();
|
||||
if (node == null) continue;
|
||||
|
||||
//check if the node value has html
|
||||
if (XmlHelper.CouldItBeXml(node.Value))
|
||||
{
|
||||
//First save the raw value to a raw field, we will change the policy of this field by detecting the prefix later
|
||||
e.Fields[RawFieldPrefix + field.Name] = node.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler to create a lower cased version of the node name, this is so we can support case-insensitive searching and still
|
||||
/// use the Whitespace Analyzer. This also ensures the 'Raw' values are added to the document.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
static void IndexerDocumentWriting(object sender, Examine.LuceneEngine.DocumentWritingEventArgs e)
|
||||
{
|
||||
//This ensures that the special __Raw_ fields are indexed
|
||||
var d = e.Document;
|
||||
foreach (var f in e.Fields.Where(x => x.Key.StartsWith(RawFieldPrefix)))
|
||||
{
|
||||
d.Add(new Field(
|
||||
f.Key,
|
||||
f.Value,
|
||||
Field.Store.YES,
|
||||
Field.Index.NO, //don't index this field, we never want to search by it
|
||||
Field.TermVector.NO));
|
||||
}
|
||||
|
||||
//add the lower cased version
|
||||
if (e.Fields.Keys.Contains("nodeName"))
|
||||
{
|
||||
e.Document.Add(new Field("__nodeName",
|
||||
e.Fields["nodeName"].ToLower(),
|
||||
Field.Store.YES,
|
||||
|
||||
@@ -790,18 +790,18 @@ namespace umbraco.MacroEngines
|
||||
if (result != null)
|
||||
{
|
||||
//a really rough check to see if this may be valid xml
|
||||
if (sResult.StartsWith("<") && sResult.EndsWith(">") && sResult.Contains("/"))
|
||||
if (XmlHelper.CouldItBeXml(sResult))
|
||||
{
|
||||
try
|
||||
{
|
||||
XElement e = XElement.Parse(DynamicXml.StripDashesInElementOrAttributeNames(sResult), LoadOptions.None);
|
||||
XElement e = XElement.Parse(XmlHelper.StripDashesInElementOrAttributeNames(sResult), LoadOptions.None);
|
||||
if (e != null)
|
||||
{
|
||||
//check that the document element is not one of the disallowed elements
|
||||
//allows RTE to still return as html if it's valid xhtml
|
||||
string documentElement = e.Name.LocalName;
|
||||
if (!UmbracoSettings.NotDynamicXmlDocumentElements.Any(tag =>
|
||||
string.Equals(tag, documentElement, StringComparison.CurrentCultureIgnoreCase)))
|
||||
if (UmbracoSettings.NotDynamicXmlDocumentElements.Any(tag =>
|
||||
string.Equals(tag, documentElement, StringComparison.CurrentCultureIgnoreCase)) == false)
|
||||
{
|
||||
result = new DynamicXml(e);
|
||||
return true;
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Xml.XPath;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace umbraco.MacroEngines
|
||||
{
|
||||
@@ -381,9 +382,10 @@ namespace umbraco.MacroEngines
|
||||
return test(this) ? new HtmlString(valueIfTrue) : new HtmlString(valueIfFalse);
|
||||
}
|
||||
|
||||
[Obsolete("Use XmlHelper.StripDashesInElementOrAttributeNames instead")]
|
||||
public static string StripDashesInElementOrAttributeNames(string xml)
|
||||
{
|
||||
return Umbraco.Core.Dynamics.DynamicXml.StripDashesInElementOrAttributeNames(xml);
|
||||
return XmlHelper.StripDashesInElementOrAttributeNames(xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,13 +467,18 @@ namespace umbraco.MacroEngines
|
||||
public IProperty GetProperty(string alias, out bool propertyExists)
|
||||
{
|
||||
string value = null;
|
||||
if (Values.TryGetValue(alias, out value))
|
||||
|
||||
//First, try to get the 'raw' value, if that doesn't work try to get the normal one
|
||||
if (Values.TryGetValue("__Raw_" + alias, out value)
|
||||
|| Values.TryGetValue(alias, out value))
|
||||
{
|
||||
propertyExists = true;
|
||||
return new PropertyResult(alias, value, Guid.Empty);
|
||||
}
|
||||
|
||||
propertyExists = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user