mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Removing Regex usage
--HG-- branch : 1.x
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using NUnit.Framework;
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Utility.Extensions;
|
using Orchard.Utility.Extensions;
|
||||||
|
|
||||||
@@ -34,24 +35,24 @@ namespace Orchard.Tests.Utility.Extensions {
|
|||||||
[Test]
|
[Test]
|
||||||
public void Ellipsize_ShouldTuncateToTheExactNumber() {
|
public void Ellipsize_ShouldTuncateToTheExactNumber() {
|
||||||
const string toEllipsize = "Lorem ipsum";
|
const string toEllipsize = "Lorem ipsum";
|
||||||
Assert.That(toEllipsize.Ellipsize(2, ""), Is.StringMatching("Lo"));
|
Assert.That(toEllipsize.Ellipsize(2, ""), Is.EqualTo("Lo"));
|
||||||
Assert.That(toEllipsize.Ellipsize(1, ""), Is.StringMatching("L"));
|
Assert.That(toEllipsize.Ellipsize(1, ""), Is.EqualTo("L"));
|
||||||
Assert.That(toEllipsize.Ellipsize(0, ""), Is.StringMatching(""));
|
Assert.That(toEllipsize.Ellipsize(0, ""), Is.EqualTo(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Ellipsize_TruncatedToWordBoundary() {
|
public void Ellipsize_TruncatedToWordBoundary() {
|
||||||
const string toEllipsize = "Lorem ipsum";
|
const string toEllipsize = "Lorem ipsum";
|
||||||
Assert.That(toEllipsize.Ellipsize(8, ""), Is.StringMatching("Lorem"));
|
Assert.That(toEllipsize.Ellipsize(8, ""), Is.EqualTo("Lorem"));
|
||||||
Assert.That(toEllipsize.Ellipsize(6, ""), Is.StringMatching("Lorem"));
|
Assert.That(toEllipsize.Ellipsize(6, ""), Is.EqualTo("Lorem"));
|
||||||
Assert.That(toEllipsize.Ellipsize(5, ""), Is.StringMatching("Lorem"));
|
Assert.That(toEllipsize.Ellipsize(5, ""), Is.EqualTo("Lorem"));
|
||||||
Assert.That(toEllipsize.Ellipsize(4, ""), Is.StringMatching(""));
|
Assert.That(toEllipsize.Ellipsize(4, ""), Is.EqualTo("Lore"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Ellipsize_LongStringTruncatedToNearestWord() {
|
public void Ellipsize_LongStringTruncatedToNearestWord() {
|
||||||
const string toEllipsize = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed purus quis purus orci aliquam.";
|
const string toEllipsize = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed purus quis purus orci aliquam.";
|
||||||
Assert.That(toEllipsize.Ellipsize(45), Is.StringMatching("Lorem ipsum dolor sit amet, consectetur …"));
|
Assert.That(toEllipsize.Ellipsize(46), Is.StringMatching("Lorem ipsum dolor sit amet, consectetur …"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -74,6 +75,12 @@ namespace Orchard.Tests.Utility.Extensions {
|
|||||||
const string toEllipsize = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed purus quis purus orci aliquam.";
|
const string toEllipsize = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed purus quis purus orci aliquam.";
|
||||||
Assert.That(toEllipsize.Ellipsize(45, "........"), Is.StringMatching("Lorem ipsum dolor sit amet, consectetur........"));
|
Assert.That(toEllipsize.Ellipsize(45, "........"), Is.StringMatching("Lorem ipsum dolor sit amet, consectetur........"));
|
||||||
}
|
}
|
||||||
|
[Test]
|
||||||
|
public void Ellipsize_WordBoundary() {
|
||||||
|
const string toEllipsize = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed purus quis purus orci aliquam.";
|
||||||
|
Assert.That(toEllipsize.Ellipsize(43, "..."), Is.StringMatching("Lorem ipsum dolor sit amet, consectet..."));
|
||||||
|
Assert.That(toEllipsize.Ellipsize(43, "...", true), Is.StringMatching("Lorem ipsum dolor sit amet, ..."));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void HtmlClassify_ValidReallySimpleClassNameReturnsSame() {
|
public void HtmlClassify_ValidReallySimpleClassNameReturnsSame() {
|
||||||
@@ -172,7 +179,7 @@ namespace Orchard.Tests.Utility.Extensions {
|
|||||||
[Test]
|
[Test]
|
||||||
public void ReplaceNewLinesWith_ReplaceCRLFWithHtmlPsAndCRLF() {
|
public void ReplaceNewLinesWith_ReplaceCRLFWithHtmlPsAndCRLF() {
|
||||||
const string lotsOfLineFeeds = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\r\nMaecenas sed purus quis purus orci aliquam.";
|
const string lotsOfLineFeeds = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\r\nMaecenas sed purus quis purus orci aliquam.";
|
||||||
Assert.That(lotsOfLineFeeds.ReplaceNewLinesWith(@"</p>$1<p>"), Is.StringMatching("Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>\r\n<p>Maecenas sed purus quis purus orci aliquam."));
|
Assert.That(lotsOfLineFeeds.ReplaceNewLinesWith(@"</p>{0}<p>"), Is.StringMatching("Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>\r\n<p>Maecenas sed purus quis purus orci aliquam."));
|
||||||
}
|
}
|
||||||
[Test]
|
[Test]
|
||||||
public void ReplaceNewLinesWith_EmptyStringReturnsEmptyString() {
|
public void ReplaceNewLinesWith_EmptyStringReturnsEmptyString() {
|
||||||
@@ -184,5 +191,86 @@ namespace Orchard.Tests.Utility.Extensions {
|
|||||||
const string lotsOfLineFeeds = null;
|
const string lotsOfLineFeeds = null;
|
||||||
Assert.That(lotsOfLineFeeds.ReplaceNewLinesWith("<br />"), Is.StringMatching(""));
|
Assert.That(lotsOfLineFeeds.ReplaceNewLinesWith("<br />"), Is.StringMatching(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripShouldRemoveStart() {
|
||||||
|
Assert.That("abc".Strip('a'), Is.StringMatching("bc"));
|
||||||
|
Assert.That("abc".Strip("ab".ToCharArray()), Is.StringMatching("c"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripShouldRemoveInside() {
|
||||||
|
Assert.That("abc".Strip('b'), Is.StringMatching("ac"));
|
||||||
|
Assert.That("abc".Strip("abc".ToCharArray()), Is.StringMatching(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripShouldRemoveEnd() {
|
||||||
|
Assert.That("abc".Strip('c'), Is.StringMatching("ab"));
|
||||||
|
Assert.That("abc".Strip("bc".ToCharArray()), Is.StringMatching("a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripShouldReturnIfEmpty() {
|
||||||
|
Assert.That("".Strip('a'), Is.StringMatching(""));
|
||||||
|
Assert.That("a".Strip("".ToCharArray()), Is.StringMatching("a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AnyShouldReturnTrueAtStart() {
|
||||||
|
Assert.That("abc".Any('a'), Is.True);
|
||||||
|
Assert.That("abc".Any("ab".ToCharArray()), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AnyShouldReturnTrueAtEnd() {
|
||||||
|
Assert.That("abc".Any('c'), Is.True);
|
||||||
|
Assert.That("abc".Any("bc".ToCharArray()), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AnyShouldReturnTrueAtMiddle() {
|
||||||
|
Assert.That("abc".Any('b'), Is.True);
|
||||||
|
Assert.That("abc".Any("abc".ToCharArray()), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AnyShouldReturnFalseIfNotPresent() {
|
||||||
|
Assert.That("abc".Any("".ToCharArray()), Is.False);
|
||||||
|
Assert.That("abc".Any("d".ToCharArray()), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AllShouldReturnTrueIfAllArePresent() {
|
||||||
|
Assert.That("abc".All("abc".ToCharArray()), Is.True);
|
||||||
|
Assert.That("abc".All("abcd".ToCharArray()), Is.True);
|
||||||
|
Assert.That("".All("a".ToCharArray()), Is.True);
|
||||||
|
Assert.That("abc".All("abcd".ToCharArray()), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AllShouldReturnFalseIfAnyIsNotPresent() {
|
||||||
|
Assert.That("abc".All("".ToCharArray()), Is.False);
|
||||||
|
Assert.That("abc".All("a".ToCharArray()), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TranslateShouldThrowException() {
|
||||||
|
Assert.Throws<ArgumentNullException>(() => "a".Translate("".ToCharArray(), "a".ToCharArray()));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => "a".Translate("a".ToCharArray(), "".ToCharArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TranslateShouldReturnSource() {
|
||||||
|
Assert.That("a".Translate("".ToCharArray(), "".ToCharArray()), Is.StringMatching(""));
|
||||||
|
Assert.That("".Translate("abc".ToCharArray(), "abc".ToCharArray()), Is.StringMatching(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TranslateShouldReplaceChars() {
|
||||||
|
Assert.That("abc".Translate("a".ToCharArray(), "d".ToCharArray()), Is.StringMatching("dbc"));
|
||||||
|
Assert.That("abc".Translate("d".ToCharArray(), "d".ToCharArray()), Is.StringMatching("abc"));
|
||||||
|
Assert.That("abc".Translate("abc".ToCharArray(), "def".ToCharArray()), Is.StringMatching("def"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<span class="when">@Display.CommentMetadata(ContentPart: comment)</span>
|
<span class="when">@Display.CommentMetadata(ContentPart: comment)</span>
|
||||||
</h4>
|
</h4>
|
||||||
</header>
|
</header>
|
||||||
<p class="text">@(new MvcHtmlString(Html.Encode(comment.Record.CommentText).ReplaceNewLinesWith("<br />$1")))</p>
|
<p class="text">@(new MvcHtmlString(Html.Encode(comment.Record.CommentText).Replace("\r\n", "<br />\r\n")))</p>
|
||||||
</article>
|
</article>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -9,6 +9,7 @@ using Orchard.Environment.Extensions;
|
|||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
using Orchard.FileSystems.VirtualPath;
|
using Orchard.FileSystems.VirtualPath;
|
||||||
using Orchard.UI.Resources;
|
using Orchard.UI.Resources;
|
||||||
|
using Orchard.Utility.Extensions;
|
||||||
|
|
||||||
namespace Orchard.DisplayManagement.Descriptors.ResourceBindingStrategy {
|
namespace Orchard.DisplayManagement.Descriptors.ResourceBindingStrategy {
|
||||||
// discovers .css files and turns them into Style__<filename> shapes.
|
// discovers .css files and turns them into Style__<filename> shapes.
|
||||||
@@ -16,7 +17,7 @@ namespace Orchard.DisplayManagement.Descriptors.ResourceBindingStrategy {
|
|||||||
private readonly IExtensionManager _extensionManager;
|
private readonly IExtensionManager _extensionManager;
|
||||||
private readonly ShellDescriptor _shellDescriptor;
|
private readonly ShellDescriptor _shellDescriptor;
|
||||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||||
private static readonly Regex _safeName = new Regex(@"[/:?#\[\]@!&'()*+,;=\s\""<>\.\-_]+", RegexOptions.Compiled);
|
private static readonly char[] unsafeCharList = "/:?#[]@!&'()*+,;=\r\n\t\f\" <>.-_".ToCharArray();
|
||||||
|
|
||||||
public StylesheetBindingStrategy(IExtensionManager extensionManager, ShellDescriptor shellDescriptor, IVirtualPathProvider virtualPathProvider) {
|
public StylesheetBindingStrategy(IExtensionManager extensionManager, ShellDescriptor shellDescriptor, IVirtualPathProvider virtualPathProvider) {
|
||||||
_extensionManager = extensionManager;
|
_extensionManager = extensionManager;
|
||||||
@@ -27,7 +28,8 @@ namespace Orchard.DisplayManagement.Descriptors.ResourceBindingStrategy {
|
|||||||
private static string SafeName(string name) {
|
private static string SafeName(string name) {
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
return String.Empty;
|
return String.Empty;
|
||||||
return _safeName.Replace(name, String.Empty).ToLowerInvariant();
|
|
||||||
|
return name.Strip(unsafeCharList).ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetAlternateShapeNameFromFileName(string fileName) {
|
public static string GetAlternateShapeNameFromFileName(string fileName) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using Orchard.Caching;
|
using Orchard.Caching;
|
||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
@@ -83,11 +82,21 @@ namespace Orchard.Localization.Services {
|
|||||||
// "<languagecode2>-<country/regioncode2>" or
|
// "<languagecode2>-<country/regioncode2>" or
|
||||||
// "<languagecode2>-<scripttag>-<country/regioncode2>"
|
// "<languagecode2>-<scripttag>-<country/regioncode2>"
|
||||||
public bool IsValidCulture(string cultureName) {
|
public bool IsValidCulture(string cultureName) {
|
||||||
Regex cultureRegex = new Regex(@"\w{2}(-\w{2,})*");
|
var segments = cultureName.Split('-');
|
||||||
if (cultureRegex.IsMatch(cultureName)) {
|
|
||||||
return true;
|
if(segments.Length == 0) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
if (segments.Length > 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segments.Any(s => s.Length < 2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
|
|
||||||
namespace Orchard.Utility.Extensions {
|
namespace Orchard.Utility.Extensions {
|
||||||
public static class StringExtensions {
|
public static class StringExtensions {
|
||||||
private static readonly Regex humps = new Regex("(?:^[a-zA-Z][^A-Z]*|[A-Z][^A-Z]*)");
|
|
||||||
private static readonly Regex safe = new Regex(@"[^_\-a-zA-Z\d]+");
|
|
||||||
|
|
||||||
public static string CamelFriendly(this string camel) {
|
public static string CamelFriendly(this string camel) {
|
||||||
if (String.IsNullOrWhiteSpace(camel))
|
if (String.IsNullOrWhiteSpace(camel))
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
var matches = humps.Matches(camel).OfType<Match>().Select(m => m.Value).ToArray();
|
var sb = new StringBuilder(camel);
|
||||||
return matches.Any()
|
|
||||||
? matches.Aggregate((a, b) => a + " " + b).TrimStart(' ')
|
for (int i = camel.Length-1; i>=0; i--) {
|
||||||
: camel;
|
var current = sb[i];
|
||||||
|
if('A' <= current && current <= 'Z') {
|
||||||
|
sb.Insert(i, ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Ellipsize(this string text, int characterCount) {
|
public static string Ellipsize(this string text, int characterCount) {
|
||||||
@@ -31,12 +34,23 @@ namespace Orchard.Utility.Extensions {
|
|||||||
if (characterCount < 0 || text.Length <= characterCount)
|
if (characterCount < 0 || text.Length <= characterCount)
|
||||||
return text;
|
return text;
|
||||||
|
|
||||||
var trimmed = Regex.Replace(text.Substring(0, characterCount), @"\s+\S*$", "") ;
|
// search beginning of word
|
||||||
|
var backup = characterCount;
|
||||||
if(wordBoundary) {
|
while (characterCount > 0 && text[characterCount-1].IsLetter()) {
|
||||||
trimmed = Regex.Replace(trimmed + ".", @"\W*\w*$", "");
|
characterCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search previous word
|
||||||
|
while (characterCount > 0 && text[characterCount - 1].IsSpace()) {
|
||||||
|
characterCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it was the last word, recover it, unless boundary is requested
|
||||||
|
if(characterCount == 0 && !wordBoundary) {
|
||||||
|
characterCount = backup;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trimmed = text.Substring(0, characterCount);
|
||||||
return trimmed + ellipsis;
|
return trimmed + ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +59,27 @@ namespace Orchard.Utility.Extensions {
|
|||||||
return "";
|
return "";
|
||||||
|
|
||||||
var friendlier = text.CamelFriendly();
|
var friendlier = text.CamelFriendly();
|
||||||
return Regex.Replace(friendlier, @"[^a-zA-Z]+", m => m.Index == 0 ? "" : "-").ToLowerInvariant();
|
|
||||||
|
var result = new char[friendlier.Length];
|
||||||
|
|
||||||
|
var cursor = 0;
|
||||||
|
var previousIsNotLetter = false;
|
||||||
|
for (var i = 0; i < friendlier.Length; i++) {
|
||||||
|
char current = friendlier[i];
|
||||||
|
if (IsLetter(current)) {
|
||||||
|
if(previousIsNotLetter && i != 0) {
|
||||||
|
result[cursor++] = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
result[cursor++] = Char.ToLowerInvariant(current);
|
||||||
|
previousIsNotLetter = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
previousIsNotLetter = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(result, 0, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LocalizedString OrDefault(this string text, LocalizedString defaultValue) {
|
public static LocalizedString OrDefault(this string text, LocalizedString defaultValue) {
|
||||||
@@ -55,16 +89,42 @@ namespace Orchard.Utility.Extensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static string RemoveTags(this string html) {
|
public static string RemoveTags(this string html) {
|
||||||
return String.IsNullOrEmpty(html)
|
if (String.IsNullOrEmpty(html)) {
|
||||||
? ""
|
return String.Empty;
|
||||||
: Regex.Replace(html, "<[^<>]*>", "", RegexOptions.Singleline);
|
}
|
||||||
|
|
||||||
|
var result = new char[html.Length];
|
||||||
|
|
||||||
|
var cursor = 0;
|
||||||
|
var inside = false;
|
||||||
|
for (var i = 0; i < html.Length; i++) {
|
||||||
|
char current = html[i];
|
||||||
|
|
||||||
|
switch(current) {
|
||||||
|
case '<':
|
||||||
|
inside = true;
|
||||||
|
continue;
|
||||||
|
case '>':
|
||||||
|
inside = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inside) {
|
||||||
|
result[cursor++] = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(result, 0, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// not accounting for only \r (e.g. Apple OS 9 carriage return only new lines)
|
// not accounting for only \r (e.g. Apple OS 9 carriage return only new lines)
|
||||||
public static string ReplaceNewLinesWith(this string text, string replacement) {
|
public static string ReplaceNewLinesWith(this string text, string replacement) {
|
||||||
return String.IsNullOrWhiteSpace(text)
|
return String.IsNullOrWhiteSpace(text)
|
||||||
? ""
|
? String.Empty
|
||||||
: Regex.Replace(text, @"(\r?\n)", replacement, RegexOptions.Singleline);
|
: text
|
||||||
|
.Replace("\r\n", "\r\r")
|
||||||
|
.Replace("\n", String.Format(replacement, "\r\n"))
|
||||||
|
.Replace("\r\r", String.Format(replacement, "\r\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToHexString(this byte[] bytes) {
|
public static string ToHexString(this byte[] bytes) {
|
||||||
@@ -78,6 +138,7 @@ namespace Orchard.Utility.Extensions {
|
|||||||
ToArray();
|
ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly char[] validSegmentChars = @"/?#[]@""^{}|`<>\t\r\n\f ".ToCharArray();
|
||||||
public static bool IsValidUrlSegment(this string segment) {
|
public static bool IsValidUrlSegment(this string segment) {
|
||||||
// valid isegment from rfc3987 - http://tools.ietf.org/html/rfc3987#page-8
|
// valid isegment from rfc3987 - http://tools.ietf.org/html/rfc3987#page-8
|
||||||
// the relevant bits:
|
// the relevant bits:
|
||||||
@@ -90,7 +151,7 @@ namespace Orchard.Utility.Extensions {
|
|||||||
//
|
//
|
||||||
// rough blacklist regex == m/^[^/?#[]@"^{}|\s`<>]+$/ (leaving off % to keep the regex simple)
|
// rough blacklist regex == m/^[^/?#[]@"^{}|\s`<>]+$/ (leaving off % to keep the regex simple)
|
||||||
|
|
||||||
return Regex.IsMatch(segment, @"^[^/?#[\]@""^{}|`<>\s]+$");
|
return !segment.Any(validSegmentChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -104,7 +165,13 @@ namespace Orchard.Utility.Extensions {
|
|||||||
return String.Empty;
|
return String.Empty;
|
||||||
|
|
||||||
name = RemoveDiacritics(name);
|
name = RemoveDiacritics(name);
|
||||||
name = safe.Replace(name, String.Empty);
|
name = name.Strip(c =>
|
||||||
|
c != '_'
|
||||||
|
&& c != '-'
|
||||||
|
&& !c.IsLetter()
|
||||||
|
&& !Char.IsDigit(c)
|
||||||
|
);
|
||||||
|
|
||||||
name = name.Trim();
|
name = name.Trim();
|
||||||
|
|
||||||
// don't allow non A-Z chars as first letter, as they are not allowed in prefixes
|
// don't allow non A-Z chars as first letter, as they are not allowed in prefixes
|
||||||
@@ -125,6 +192,9 @@ namespace Orchard.Utility.Extensions {
|
|||||||
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
|
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsSpace(this char c) {
|
||||||
|
return (c == '\r' || c == '\n' || c == '\t' || c == '\f' || c == ' ');
|
||||||
|
}
|
||||||
|
|
||||||
public static string RemoveDiacritics(string name) {
|
public static string RemoveDiacritics(string name) {
|
||||||
string stFormD = name.Normalize(NormalizationForm.FormD);
|
string stFormD = name.Normalize(NormalizationForm.FormD);
|
||||||
@@ -139,5 +209,110 @@ namespace Orchard.Utility.Extensions {
|
|||||||
|
|
||||||
return (sb.ToString().Normalize(NormalizationForm.FormC));
|
return (sb.ToString().Normalize(NormalizationForm.FormC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string Strip(this string subject, params char[] stripped) {
|
||||||
|
if(stripped == null || stripped.Length == 0 || String.IsNullOrEmpty(subject)) {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.Sort(stripped);
|
||||||
|
var result = new char[subject.Length];
|
||||||
|
|
||||||
|
var cursor = 0;
|
||||||
|
for (var i = 0; i < subject.Length; i++) {
|
||||||
|
char current = subject[i];
|
||||||
|
if (Array.BinarySearch(stripped, current) < 0) {
|
||||||
|
result[cursor++] = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(result, 0, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Strip(this string subject, Func<char, bool> predicate) {
|
||||||
|
|
||||||
|
var result = new char[subject.Length];
|
||||||
|
|
||||||
|
var cursor = 0;
|
||||||
|
for (var i = 0; i < subject.Length; i++) {
|
||||||
|
char current = subject[i];
|
||||||
|
if (!predicate(current)) {
|
||||||
|
result[cursor++] = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(result, 0, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Any(this string subject, params char[] chars) {
|
||||||
|
if (string.IsNullOrEmpty(subject) || chars == null || chars.Length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.Sort(chars);
|
||||||
|
|
||||||
|
for (var i = 0; i < subject.Length; i++) {
|
||||||
|
char current = subject[i];
|
||||||
|
if (Array.BinarySearch(chars, current) >= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool All(this string subject, params char[] chars) {
|
||||||
|
if (string.IsNullOrEmpty(subject)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chars == null || chars.Length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.Sort(chars);
|
||||||
|
|
||||||
|
for (var i = 0; i < subject.Length; i++) {
|
||||||
|
char current = subject[i];
|
||||||
|
if (Array.BinarySearch(chars, current) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Translate(this string subject, char[] from, char[] to) {
|
||||||
|
if (string.IsNullOrEmpty(subject)) {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from == null || to == null) {
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from.Length != to.Length) {
|
||||||
|
throw new ArgumentNullException("from", "Parameters must have the same length");
|
||||||
|
}
|
||||||
|
|
||||||
|
var map = new Dictionary<char, char>(from.Length);
|
||||||
|
for (var i = 0; i < from.Length; i++) {
|
||||||
|
map[from[i]] = to[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = new char[subject.Length];
|
||||||
|
|
||||||
|
for (var i = 0; i < subject.Length; i++) {
|
||||||
|
var current = subject[i];
|
||||||
|
if (map.ContainsKey(current)) {
|
||||||
|
result[i] = map[current];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result[i] = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user