using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Web; using System.Xml; using Umbraco.Core.Configuration; using System.Web.Security; using Umbraco.Core.Strings; using Umbraco.Core.CodeAnnotations; namespace Umbraco.Core { /// /// String extension methods /// public static class StringExtensions { [UmbracoWillObsolete("Do not use this constants. See IShortStringHelper.CleanStringForSafeAliasJavaScriptCode.")] public const string UmbracoValidAliasCharacters = "_-abcdefghijklmnopqrstuvwxyz1234567890"; [UmbracoWillObsolete("Do not use this constants. See IShortStringHelper.CleanStringForSafeAliasJavaScriptCode.")] public const string UmbracoInvalidFirstCharacters = "01234567890"; internal static string ReplaceNonAlphanumericChars(this string input, char replacement) { //any character that is not alphanumeric, convert to a hyphen var mName = input; foreach (var c in mName.ToCharArray().Where(c => !char.IsLetterOrDigit(c))) { mName = mName.Replace(c, replacement); } return mName; } public static string ExceptChars(this string str, HashSet toExclude) { var sb = new StringBuilder(str.Length); foreach (var c in str.Where(c => toExclude.Contains(c) == false)) { sb.Append(c); } return sb.ToString(); } /// /// Encrypt the string using the MachineKey in medium trust /// /// The string value to be encrypted. /// The encrypted string. public static string EncryptWithMachineKey(this string value) { if (value == null) return null; string valueToEncrypt = value; List parts = new List(); const int EncrpytBlockSize = 500; while (valueToEncrypt.Length > EncrpytBlockSize) { parts.Add(valueToEncrypt.Substring(0, EncrpytBlockSize)); valueToEncrypt = valueToEncrypt.Remove(0, EncrpytBlockSize); } if (valueToEncrypt.Length > 0) { parts.Add(valueToEncrypt); } StringBuilder encrpytedValue = new StringBuilder(); foreach (var part in parts) { var encrpytedBlock = FormsAuthentication.Encrypt(new FormsAuthenticationTicket(0, string.Empty, DateTime.Now, DateTime.MaxValue, false, part)); encrpytedValue.AppendLine(encrpytedBlock); } return encrpytedValue.ToString().TrimEnd(); } /// /// Decrypt the encrypted string using the Machine key in medium trust /// /// The string value to be decrypted /// The decrypted string. public static string DecryptWithMachineKey(this string value) { if (value == null) return null; string[] parts = value.Split('\n'); StringBuilder decryptedValue = new StringBuilder(); foreach (var part in parts) { decryptedValue.Append(FormsAuthentication.Decrypt(part.TrimEnd()).UserData); } return decryptedValue.ToString(); } //this is from SqlMetal and just makes it a bit of fun to allow pluralisation public static string MakePluralName(this string name) { if ((name.EndsWith("x", StringComparison.OrdinalIgnoreCase) || name.EndsWith("ch", StringComparison.OrdinalIgnoreCase)) || (name.EndsWith("ss", StringComparison.OrdinalIgnoreCase) || name.EndsWith("sh", StringComparison.OrdinalIgnoreCase))) { name = name + "es"; return name; } if ((name.EndsWith("y", StringComparison.OrdinalIgnoreCase) && (name.Length > 1)) && !IsVowel(name[name.Length - 2])) { name = name.Remove(name.Length - 1, 1); name = name + "ies"; return name; } if (!name.EndsWith("s", StringComparison.OrdinalIgnoreCase)) { name = name + "s"; } return name; } public static bool IsVowel(this char c) { switch (c) { case 'O': case 'U': case 'Y': case 'A': case 'E': case 'I': case 'o': case 'u': case 'y': case 'a': case 'e': case 'i': return true; } return false; } /// /// Trims the specified value from a string; accepts a string input whereas the in-built implementation only accepts char or char[]. /// /// The value. /// For removing. /// public static string Trim(this string value, string forRemoving) { if (string.IsNullOrEmpty(value)) return value; return value.TrimEnd(forRemoving).TrimStart(forRemoving); } public static string EncodeJsString(this string s) { var sb = new StringBuilder(); foreach (var c in s) { switch (c) { case '\"': sb.Append("\\\""); break; case '\\': sb.Append("\\\\"); break; case '\b': sb.Append("\\b"); break; case '\f': sb.Append("\\f"); break; case '\n': sb.Append("\\n"); break; case '\r': sb.Append("\\r"); break; case '\t': sb.Append("\\t"); break; default: int i = (int)c; if (i < 32 || i > 127) { sb.AppendFormat("\\u{0:X04}", i); } else { sb.Append(c); } break; } } return sb.ToString(); } public static string TrimEnd(this string value, string forRemoving) { if (string.IsNullOrEmpty(value)) return value; if (string.IsNullOrEmpty(forRemoving)) return value; while (value.EndsWith(forRemoving, StringComparison.InvariantCultureIgnoreCase)) { value = value.Remove(value.LastIndexOf(forRemoving, StringComparison.InvariantCultureIgnoreCase)); } return value; } public static string TrimStart(this string value, string forRemoving) { if (string.IsNullOrEmpty(value)) return value; if (string.IsNullOrEmpty(forRemoving)) return value; while (value.StartsWith(forRemoving, StringComparison.InvariantCultureIgnoreCase)) { value = value.Substring(forRemoving.Length); } return value; } public static string EnsureStartsWith(this string input, string toStartWith) { if (input.StartsWith(toStartWith)) return input; return toStartWith + input.TrimStart(toStartWith.ToArray()); // Ensure each char is removed first from input, e.g. ~/ plus /Path will equal ~/Path not ~//Path } public static string EnsureStartsWith(this string input, char value) { return input.StartsWith(value.ToString(CultureInfo.InvariantCulture)) ? input : value + input; } public static string EnsureEndsWith(this string input, char value) { return input.EndsWith(value.ToString(CultureInfo.InvariantCulture)) ? input : input + value; } public static bool IsLowerCase(this char ch) { return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToLowerInvariant(); } public static bool IsUpperCase(this char ch) { return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToUpperInvariant(); } /// Is null or white space. /// The str. /// The is null or white space. public static bool IsNullOrWhiteSpace(this string str) { return (str == null) || (str.Trim().Length == 0); } public static string IfNullOrWhiteSpace(this string str, string defaultValue) { return str.IsNullOrWhiteSpace() ? defaultValue : str; } /// The to delimited list. /// The list. /// The delimiter. /// the list [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed", Justification = "By design")] public static IList ToDelimitedList(this string list, string delimiter = ",") { var delimiters = new[] { delimiter }; return !list.IsNullOrWhiteSpace() ? list.Split(delimiters, StringSplitOptions.RemoveEmptyEntries) .Select(i => i.Trim()) .ToList() : new List(); } /// enum try parse. /// The str type. /// The ignore case. /// The result. /// The type /// The enum try parse. [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "By Design")] [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "By Design")] public static bool EnumTryParse(this string strType, bool ignoreCase, out T result) { try { result = (T)Enum.Parse(typeof(T), strType, ignoreCase); return true; } catch { result = default(T); return false; } } /// /// Parse string to Enum /// /// The enum type /// The string to parse /// The ignore case /// The parsed enum [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "By Design")] [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "By Design")] public static T EnumParse(this string strType, bool ignoreCase) { return (T)Enum.Parse(typeof(T), strType, ignoreCase); } /// /// Strips all html from a string. /// /// The text. /// Returns the string without any html tags. public static string StripHtml(this string text) { const string pattern = @"<(.|\n)*?>"; return Regex.Replace(text, pattern, String.Empty); } /// /// Encodes as GUID. /// /// The input. /// public static Guid EncodeAsGuid(this string input) { if (string.IsNullOrWhiteSpace(input)) throw new ArgumentNullException("input"); var convertToHex = input.ConvertToHex(); var hexLength = convertToHex.Length < 32 ? convertToHex.Length : 32; var hex = convertToHex.Substring(0, hexLength).PadLeft(32, '0'); var output = Guid.Empty; return Guid.TryParse(hex, out output) ? output : Guid.Empty; } /// /// Converts to hex. /// /// The input. /// public static string ConvertToHex(this string input) { if (String.IsNullOrEmpty(input)) return String.Empty; var sb = new StringBuilder(input.Length); foreach (char c in input) { int tmp = c; sb.AppendFormat("{0:x2}", Convert.ToUInt32(c)); } return sb.ToString(); } /// /// Encodes a string to a safe URL base64 string /// /// /// public static string ToUrlBase64(this string input) { if (input == null) throw new ArgumentNullException("input"); if (String.IsNullOrEmpty(input)) return String.Empty; var bytes = Encoding.UTF8.GetBytes(input); return UrlTokenEncode(bytes); //return Convert.ToBase64String(bytes).Replace(".", "-").Replace("/", "_").Replace("=", ","); } /// /// Decodes a URL safe base64 string back /// /// /// public static string FromUrlBase64(this string input) { if (input == null) throw new ArgumentNullException("input"); //if (input.IsInvalidBase64()) return null; try { //var decodedBytes = Convert.FromBase64String(input.Replace("-", ".").Replace("_", "/").Replace(",", "=")); byte[] decodedBytes = UrlTokenDecode(input); return decodedBytes != null ? Encoding.UTF8.GetString(decodedBytes) : null; } catch (FormatException ex) { return null; } } /// /// formats the string with invariant culture /// /// The format. /// The args. /// public static string InvariantFormat(this string format, params object[] args) { return String.Format(CultureInfo.InvariantCulture, format, args); } /// /// Compares 2 strings with invariant culture and case ignored /// /// The compare. /// The compare to. /// public static bool InvariantEquals(this string compare, string compareTo) { return String.Equals(compare, compareTo, StringComparison.InvariantCultureIgnoreCase); } public static bool InvariantStartsWith(this string compare, string compareTo) { return compare.StartsWith(compareTo, StringComparison.InvariantCultureIgnoreCase); } public static bool InvariantContains(this string compare, string compareTo) { return compare.IndexOf(compareTo, StringComparison.OrdinalIgnoreCase) >= 0; } public static bool InvariantContains(this IEnumerable compare, string compareTo) { return compare.Contains(compareTo, new DelegateEqualityComparer((source, dest) => source.Equals(dest, StringComparison.InvariantCultureIgnoreCase), x => x.GetHashCode())); } /// /// Determines if the string is a Guid /// /// /// /// public static bool IsGuid(this string str, bool withHyphens) { var isGuid = false; if (!String.IsNullOrEmpty(str)) { Regex guidRegEx; if (withHyphens) { guidRegEx = new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$"); } else { guidRegEx = new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}([0-9a-fA-F]){4}([0-9a-fA-F]){4}([0-9a-fA-F]){4}([0-9a-fA-F]){12}\}{0,1})$"); } isGuid = guidRegEx.IsMatch(str); } return isGuid; } /// /// Tries to parse a string into the supplied type by finding and using the Type's "Parse" method /// /// /// /// public static T ParseInto(this string val) { return (T)val.ParseInto(typeof(T)); } /// /// Tries to parse a string into the supplied type by finding and using the Type's "Parse" method /// /// /// /// public static object ParseInto(this string val, Type type) { if (!String.IsNullOrEmpty(val)) { TypeConverter tc = TypeDescriptor.GetConverter(type); return tc.ConvertFrom(val); } return val; } /// /// Converts the string to MD5 /// /// referrs to itself /// the md5 hashed string public static string ToMd5(this string stringToConvert) { //create an instance of the MD5CryptoServiceProvider var md5Provider = new MD5CryptoServiceProvider(); //convert our string into byte array var byteArray = Encoding.UTF8.GetBytes(stringToConvert); //get the hashed values created by our MD5CryptoServiceProvider var hashedByteArray = md5Provider.ComputeHash(byteArray); //create a StringBuilder object var stringBuilder = new StringBuilder(); //loop to each each byte foreach (var b in hashedByteArray) { //append it to our StringBuilder stringBuilder.Append(b.ToString("x2").ToLower()); } //return the hashed value return stringBuilder.ToString(); } /// /// Decodes a string that was encoded with UrlTokenEncode /// /// /// internal static byte[] UrlTokenDecode(string input) { if (input == null) { throw new ArgumentNullException("input"); } int length = input.Length; if (length < 1) { return new byte[0]; } int num2 = input[length - 1] - '0'; if ((num2 < 0) || (num2 > 10)) { return null; } char[] inArray = new char[(length - 1) + num2]; for (int i = 0; i < (length - 1); i++) { char ch = input[i]; switch (ch) { case '-': inArray[i] = '+'; break; case '_': inArray[i] = '/'; break; default: inArray[i] = ch; break; } } for (int j = length - 1; j < inArray.Length; j++) { inArray[j] = '='; } return Convert.FromBase64CharArray(inArray, 0, inArray.Length); } /// /// Encodes a string so that it is 'safe' for URLs, files, etc.. /// /// /// internal static string UrlTokenEncode(byte[] input) { if (input == null) { throw new ArgumentNullException("input"); } if (input.Length < 1) { return String.Empty; } string str = null; int index = 0; char[] chArray = null; str = Convert.ToBase64String(input); if (str == null) { return null; } index = str.Length; while (index > 0) { if (str[index - 1] != '=') { break; } index--; } chArray = new char[index + 1]; chArray[index] = (char)((0x30 + str.Length) - index); for (int i = 0; i < index; i++) { char ch = str[i]; switch (ch) { case '+': chArray[i] = '-'; break; case '/': chArray[i] = '_'; break; case '=': chArray[i] = ch; break; default: chArray[i] = ch; break; } } return new string(chArray); } /// /// Ensures that the folder path endds with a DirectorySeperatorChar /// /// /// public static string NormaliseDirectoryPath(this string currentFolder) { currentFolder = currentFolder .IfNull(x => String.Empty) .TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar; return currentFolder; } /// /// Truncates the specified text string. /// /// The text. /// Length of the max. /// The suffix. /// public static string Truncate(this string text, int maxLength, string suffix = "...") { // replaces the truncated string to a ... var truncatedString = text; if (maxLength <= 0) return truncatedString; var strLength = maxLength - suffix.Length; if (strLength <= 0) return truncatedString; if (text == null || text.Length <= maxLength) return truncatedString; truncatedString = text.Substring(0, strLength); truncatedString = truncatedString.TrimEnd(); truncatedString += suffix; return truncatedString; } /// /// Strips carrage returns and line feeds from the specified text. /// /// The input. /// public static string StripNewLines(this string input) { return input.Replace("\r", "").Replace("\n", ""); } public static string OrIfNullOrWhiteSpace(this string input, string alternative) { return !string.IsNullOrWhiteSpace(input) ? input : alternative; } /// /// Returns a copy of the string with the first character converted to uppercase. /// /// The string. /// The converted string. public static string ToFirstUpper(this string input) { return string.IsNullOrWhiteSpace(input) ? input : input.Substring(0, 1).ToUpper() + input.Substring(1); } /// /// Returns a copy of the string with the first character converted to lowercase. /// /// The string. /// The converted string. public static string ToFirstLower(this string input) { return string.IsNullOrWhiteSpace(input) ? input : input.Substring(0, 1).ToLower() + input.Substring(1); } /// /// Returns a copy of the string with the first character converted to uppercase using the casing rules of the specified culture. /// /// The string. /// The culture. /// The converted string. public static string ToFirstUpper(this string input, CultureInfo culture) { return string.IsNullOrWhiteSpace(input) ? input : input.Substring(0, 1).ToUpper(culture) + input.Substring(1); } /// /// Returns a copy of the string with the first character converted to lowercase using the casing rules of the specified culture. /// /// The string. /// The culture. /// The converted string. public static string ToFirstLower(this string input, CultureInfo culture) { return string.IsNullOrWhiteSpace(input) ? input : input.Substring(0, 1).ToLower(culture) + input.Substring(1); } /// /// Returns a copy of the string with the first character converted to uppercase using the casing rules of the invariant culture. /// /// The string. /// The converted string. public static string ToFirstUpperInvariant(this string input) { return string.IsNullOrWhiteSpace(input) ? input : input.Substring(0, 1).ToUpperInvariant() + input.Substring(1); } /// /// Returns a copy of the string with the first character converted to lowercase using the casing rules of the invariant culture. /// /// The string. /// The converted string. public static string ToFirstLowerInvariant(this string input) { return string.IsNullOrWhiteSpace(input) ? input : input.Substring(0, 1).ToLowerInvariant() + input.Substring(1); } /// /// Gets the short string helper. /// /// This is so that unit tests that do not initialize the resolver do not /// fail and fall back to defaults. When running the whole Umbraco, CoreBootManager /// does initialise the resolver. private static IShortStringHelper ShortStringHelper { get { return ShortStringHelperResolver.HasCurrent ? ShortStringHelperResolver.Current.Helper : new LegacyShortStringHelper(); } } /// /// Returns a new string in which all occurences of specified strings are replaced by other specified strings. /// /// The string to filter. /// The replacements definition. /// The filtered string. public static string ReplaceMany(this string text, IDictionary replacements) { return ShortStringHelper.ReplaceMany(text, replacements); } /// /// Returns a new string in which all occurences of specified characters are replaced by a specified character. /// /// The string to filter. /// The characters to replace. /// The replacement character. /// The filtered string. public static string ReplaceMany(this string text, char[] chars, char replacement) { return ShortStringHelper.ReplaceMany(text, chars, replacement); } // FORMAT STRINGS // note: LegacyShortStringHelper will produce a 100% backward-compatible output for ToUrlAlias. // this is the only reason why we keep the method, otherwise it should be removed, and with any other // helper we fallback to ToUrlSegment anyway. /// /// Converts string to a URL alias. /// /// The value. /// The char replacements. /// if set to true replace double dashes. /// if set to true strip non ASCII. /// if set to true URL encode. /// /// /// This ensures that ONLY ascii chars are allowed and of those ascii chars, only digits and lowercase chars, all /// punctuation, etc... are stripped out, however this method allows you to pass in string's to replace with the /// specified replacement character before the string is converted to ascii and it has invalid characters stripped out. /// This allows you to replace strings like & , etc.. with your replacement character before the automatic /// reduction. /// [UmbracoWillObsolete("This method should be removed. Use ToUrlSegment instead.")] public static string ToUrlAlias(this string value, IDictionary charReplacements, bool replaceDoubleDashes, bool stripNonAscii, bool urlEncode) { var helper = ShortStringHelper; var legacy = helper as LegacyShortStringHelper; return legacy != null ? legacy.LegacyToUrlAlias(value, charReplacements, replaceDoubleDashes, stripNonAscii, urlEncode) : helper.CleanStringForUrlSegment(value); } // note: LegacyShortStringHelper will produce a 100% backward-compatible output for FormatUrl. // this is the only reason why we keep the method, otherwise it should be removed, and with any other // helper we fallback to ToUrlSegment anyway. /// /// Cleans a string to produce a string that can safely be used in an url segment. /// /// The text to filter. /// The safe url segment. /// /// When using the legacy ShortStringHelper, uses UmbracoSettings.UrlReplaceCharacters /// and UmbracoSettings.RemoveDoubleDashesFromUrlReplacing. /// Other helpers may use different parameters. /// [UmbracoWillObsolete("This method should be removed. Use ToUrlSegment instead.")] public static string FormatUrl(this string url) { var helper = ShortStringHelper; var legacy = helper as LegacyShortStringHelper; return legacy != null ? legacy.LegacyFormatUrl(url) : helper.CleanStringForUrlSegment(url); } // note: LegacyShortStringHelper will produce a 100% backward-compatible output for ToSafeAlias // other helpers may not. DefaultShortStringHelper produces better, but non-compatible, results. /// /// Cleans a string to produce a string that can safely be used in an alias. /// /// The text to filter. /// The safe alias. public static string ToSafeAlias(this string alias) { return ShortStringHelper.CleanStringForSafeAlias(alias); } /// /// Cleans a string, in the context of a specified culture, to produce a string that can safely be used in an alias. /// /// The text to filter. /// The culture. /// The safe alias. public static string ToSafeAlias(this string alias, CultureInfo culture) { return ShortStringHelper.CleanStringForSafeAlias(alias, culture); } /// /// Cleans (but only if required) a string to produce a string that can safely be used in an alias. /// /// The text to filter. /// The safe alias. /// Checks UmbracoSettings.ForceSafeAliases to determine whether it should filter the text. public static string ToSafeAliasWithForcingCheck(this string alias) { return UmbracoSettings.ForceSafeAliases ? alias.ToSafeAlias() : alias; } /// /// Cleans (but only if required) a string, in the context of a specified culture, to produce a string that can safely be used in an alias. /// /// The text to filter. /// The culture. /// The safe alias. /// Checks UmbracoSettings.ForceSafeAliases to determine whether it should filter the text. public static string ToSafeAliasWithForcingCheck(this string alias, CultureInfo culture) { return UmbracoSettings.ForceSafeAliases ? alias.ToSafeAlias(culture) : alias; } // note: LegacyShortStringHelper will produce a 100% backward-compatible output for ToUmbracoAlias. // this is the only reason why we keep the method, otherwise it should be removed, and with any other // helper we fallback to ToSafeAlias anyway. /// /// Cleans a string to produce a string that can safely be used in an alias. /// /// The text to filter. /// The case type. THIS PARAMETER IS IGNORED. /// Indicates whether spaces should be removed. THIS PARAMETER IS IGNORED. /// The safe alias. /// CamelCase, and remove spaces, whatever the parameters. [UmbracoWillObsolete("This method should be removed. Use ToSafeAlias instead.")] public static string ToUmbracoAlias(this string phrase, StringAliasCaseType caseType = StringAliasCaseType.CamelCase, bool removeSpaces = false) { var helper = ShortStringHelper; var legacy = helper as LegacyShortStringHelper; return legacy != null ? legacy.LegacyCleanStringForUmbracoAlias(phrase) : helper.CleanStringForSafeAlias(phrase); } // the new methods to get a url segment /// /// Cleans a string to produce a string that can safely be used in an url segment. /// /// The text to filter. /// The safe url segment. public static string ToUrlSegment(this string text) { return ShortStringHelper.CleanStringForUrlSegment(text); } /// /// Cleans a string, in the context of a specified culture, to produce a string that can safely be used in an url segment. /// /// The text to filter. /// The culture. /// The safe url segment. public static string ToUrlSegment(this string text, CultureInfo culture) { return ShortStringHelper.CleanStringForUrlSegment(text, culture); } // note: LegacyShortStringHelper will produce 100% backward-compatible output for ConvertCase. // this is the only reason why we keep the method, otherwise it should be removed, and with any other // helper we fallback to CleanString(ascii, alias) anyway. /// /// Filters a string to convert case, and more. /// /// the text to filter. /// The string case type. /// The filtered text. /// /// This is the legacy method, so we can't really change it, although it has issues (see unit tests). /// It does more than "converting the case", and also remove spaces, etc. /// [UmbracoWillObsolete("This method should be removed. Use CleanString instead.")] public static string ConvertCase(this string phrase, StringAliasCaseType cases) { var helper = ShortStringHelper; var legacy = helper as LegacyShortStringHelper; var cases2 = cases.ToCleanStringType() & CleanStringType.CaseMask; return legacy != null ? legacy.LegacyConvertStringCase(phrase, cases2) : helper.CleanString(phrase, CleanStringType.Ascii | CleanStringType.Alias | cases2); } // the new methods to clean a string (to alias, url segment...) /// /// Cleans a string. /// /// The text to clean. /// A flag indicating the target casing and encoding of the string. By default, /// strings are cleaned up to camelCase and Ascii. /// The clean string. /// The string is cleaned in the context of the IShortStringHelper default culture. public static string ToCleanString(string text, CleanStringType stringType) { return ShortStringHelper.CleanString(text, stringType); } /// /// Cleans a string, using a specified separator. /// /// The text to clean. /// A flag indicating the target casing and encoding of the string. By default, /// strings are cleaned up to camelCase and Ascii. /// The separator. /// The clean string. /// The string is cleaned in the context of the IShortStringHelper default culture. public static string ToCleanString(string text, CleanStringType stringType, char separator) { return ShortStringHelper.CleanString(text, stringType, separator); } /// /// Cleans a string in the context of a specified culture. /// /// The text to clean. /// A flag indicating the target casing and encoding of the string. By default, /// strings are cleaned up to camelCase and Ascii. /// The culture. /// The clean string. public static string ToCleanString(string text, CleanStringType stringType, CultureInfo culture) { return ShortStringHelper.CleanString(text, stringType, culture); } /// /// Cleans a string in the context of a specified culture, using a specified separator. /// /// The text to clean. /// A flag indicating the target casing and encoding of the string. By default, /// strings are cleaned up to camelCase and Ascii. /// The separator. /// The culture. /// The clean string. public static string ToCleanString(string text, CleanStringType stringType, char separator, CultureInfo culture) { return ShortStringHelper.CleanString(text, stringType, separator, culture); } // note: LegacyShortStringHelper will produce 100% backward-compatible output for SplitPascalCasing. // other helpers may not. DefaultShortStringHelper produces better, but non-compatible, results. /// /// Splits a Pascal cased string into a phrase seperated by spaces. /// /// The text to split. /// The splitted text. public static string SplitPascalCasing(this string phrase) { return ShortStringHelper.SplitPascalCasing(phrase, ' '); } /// /// Cleans a string, in the context of the invariant culture, to produce a string that can safely be used as a filename, /// both internally (on disk) and externally (as a url). /// /// The text to filter. /// The safe filename. public static string ToSafeFileName(this string text) { return ShortStringHelper.CleanStringForSafeFileName(text); } /// /// Cleans a string, in the context of the invariant culture, to produce a string that can safely be used as a filename, /// both internally (on disk) and externally (as a url). /// /// The text to filter. /// The culture. /// The safe filename. public static string ToSafeFileName(this string text, CultureInfo culture) { return ShortStringHelper.CleanStringForSafeFileName(text, culture); } /// /// An extension method that returns a new string in which all occurrences of a /// specified string in the current instance are replaced with another specified string. /// StringComparison specifies the type of search to use for the specified string. /// /// Current instance of the string /// Specified string to replace /// Specified string to inject /// String Comparison object to specify search type /// Updated string public static string Replace(this string source, string oldString, string newString, StringComparison stringComparison) { var index = source.IndexOf(oldString, stringComparison); // Determine if we found a match var matchFound = index >= 0; if (matchFound) { // Remove the old text source = source.Remove(index, oldString.Length); // Add the replacemenet text source = source.Insert(index, newString); } return source; } } }