Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Orckestra/C1-CMS.git
Browse files Browse the repository at this point in the history
  • Loading branch information
CompositeC1 committed Oct 28, 2015
2 parents ddd665d + e2fa45d commit 89fe34a
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 15 deletions.
71 changes: 71 additions & 0 deletions Composite/Core/WebClient/UrlUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Web;
using System.Web.Hosting;
using System.Collections.Generic;
using Composite.Core.Collections.Generic;
using Composite.Core.Extensions;
using Composite.Core.WebClient.State;
using Composite.Data;
Expand Down Expand Up @@ -370,5 +371,75 @@ public static bool TryExpandGuid(string urlPart, out Guid guid)
}
}


/// <exclude />
public static string EncodeUrlInvalidCharacters(string value)
{
const char separator = '|';
const char spaceReplacement = '-';

var symbolsToEncode = new Hashset<char>(new[] { '<', '>', '*', '%', '&', '\\', '?' });

symbolsToEncode.Add(separator);
symbolsToEncode.Add(spaceReplacement);

var sb = new StringBuilder(value.Length);

foreach (var ch in value)
{
if (!symbolsToEncode.Contains(ch))
{
sb.Append(ch);
continue;
}

int code = (int)ch;
Verify.That(code <= 256, "1 byte ASCII code expected");

sb.Append(separator).Append(code.ToString("X2"));
}

return sb.Replace(' ', spaceReplacement).ToString();
}


/// <exclude />
public static string DecodeUrlInvalidCharacters(string value)
{
const char separator = '|';
const char spaceReplacement = '-';

var sb = new StringBuilder(value.Length);
;
for (int position = 0; position < value.Length; position++)
{
var ch = value[position];
if (ch == spaceReplacement)
{
sb.Append(' ');
continue;
}

if (ch == separator && position + 2 < value.Length)
{
var hexCode = value.Substring(position + 1, 2).ToLowerInvariant();
const string hexadecimalDigits = "0123456789abcdef";

int firstDigit = hexadecimalDigits.IndexOf(hexCode[0]);
int secondDigit = hexadecimalDigits.IndexOf(hexCode[1]);

if (firstDigit > -1 && secondDigit > -1)
{
sb.Append((char) ((firstDigit << 4) + secondDigit));
position += 2;
continue;
}
}

sb.Append(ch);
}

return sb.ToString();
}
}
}
50 changes: 35 additions & 15 deletions Composite/Functions/PathInfoRoutedDataUrlMapper.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Composite.C1Console.Elements.ElementProviderHelpers.DataGroupingProviderHelper;
using Composite.Core.Extensions;
using Composite.Core.Linq;
using Composite.Core.Routing;
using Composite.Core.Routing.Foundation.PluginFacades;
using Composite.Core.Types;
using Composite.Core.WebClient;
using Composite.Data;

using DataRouteKind = Composite.Functions.RoutedData.DataRouteKind;
Expand Down Expand Up @@ -36,7 +38,14 @@ public PathInfoRoutedDataUrlMapper(Guid pageId, DataRouteKind dataRouteKind)

if ((dataRouteKind & DataRouteKind.Label) > 0 && _labelPropertyInfo == null)
{
_labelPropertyInfo = typeof(T).GetLabelPropertyInfo();
var labelPropertyInfo = typeof(T).GetLabelPropertyInfo();
Verify.IsNotNull(labelPropertyInfo, "No label property defined for type '{0}'", typeof(T));

Verify.That(labelPropertyInfo.PropertyType == typeof(string),
"Not string label fields aren't supported. Label property '{0}', data type '{1}'",
labelPropertyInfo.Name, typeof(T));

_labelPropertyInfo = labelPropertyInfo;
}
}

Expand Down Expand Up @@ -97,7 +106,7 @@ public RoutedDataModel GetRouteDataModel(PageUrlData pageUrlData)
return new RoutedDataModel();
}

string label = pathInfo.Substring(1);
string label = UrlUtils.DecodeUrlInvalidCharacters(pathInfo.Substring(1));

var data = GetDataByLabel(label);
return new RoutedDataModel(data);
Expand Down Expand Up @@ -133,7 +142,7 @@ public PageUrlData BuildItemUrl(IData dataItem)

if ((_dataRouteKind & DataRouteKind.Label) > 0)
{
labelUrlPart = GetUrlLabel(dataItem);
labelUrlPart = GetUrlLabel(dataItem, _dataRouteKind == DataRouteKind.KeyAndLabel);
}

string pathInfo;
Expand All @@ -159,26 +168,37 @@ public PageUrlData BuildItemUrl(IData dataItem)

private static T GetDataByLabel(string label)
{
foreach (var data in DataFacade.GetData<T>())
var query = DataFacade.GetData<T>();

var parameterExpression = Expression.Parameter(typeof (T));
var labelPropertyExpression = Expression.Property(parameterExpression, _labelPropertyInfo);
var equalsExpression = Expression.Equal(labelPropertyExpression, Expression.Constant(label));

var lambdaExpression = Expression.Lambda<Func<T, bool>>(equalsExpression, parameterExpression);

var list = query.Where(lambdaExpression).Take(2).ToList();

if (list.Count == 0)
{
string urlLabel = GetUrlLabel(data);
if (string.IsNullOrEmpty(urlLabel)) continue;
return null;
}

if (label.Equals(urlLabel, StringComparison.OrdinalIgnoreCase))
{
return data;
}
if (list.Count > 1)
{
throw new DataUrlCollisionException(typeof(T), new RelativeRoute {PathSegments = new []{label}});
}

return null;
return list[0];
}

private static string LabelToUrlPart(string partnerName)
private static string LabelToUrlPart(string label, bool allowDataLoss)
{
return UrlFormattersPluginFacade.FormatUrl(partnerName, true);
return allowDataLoss
? UrlFormattersPluginFacade.FormatUrl(label, true)
: UrlUtils.EncodeUrlInvalidCharacters(label);
}

private static string GetUrlLabel(IData data)
private static string GetUrlLabel(IData data, bool allowDataLoss)
{
object labelValue = _labelPropertyInfo.GetValue(data);
if (labelValue == null)
Expand All @@ -188,7 +208,7 @@ private static string GetUrlLabel(IData data)

string label = ValueTypeConverter.Convert<string>(labelValue);

return string.IsNullOrEmpty(label) ? null : LabelToUrlPart(label);
return string.IsNullOrEmpty(label) ? null : LabelToUrlPart(label, allowDataLoss);
}

private static string GetUrlKey(IData data)
Expand Down

0 comments on commit 89fe34a

Please sign in to comment.