using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Globalization; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using AngleSharp.Dom; using AngleSharp.Html; using Jackett.Common.Helpers; namespace Jackett.Common.Utils { public static class StringUtil { public static string StripNonAlphaNumeric(this string str, string replacement = "") { return StripRegex(str, "[^a-zA-Z0-9 -]", replacement); } public static string StripRegex(string str, string regex, string replacement = "") { Regex rgx = new Regex(regex); str = rgx.Replace(str, replacement); return str; } // replaces culture specific characters with the corresponding base characters (e.g. è becomes e). public static String RemoveDiacritics(String s) { String normalizedString = s.Normalize(NormalizationForm.FormD); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < normalizedString.Length; i++) { Char c = normalizedString[i]; if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) stringBuilder.Append(c); } return stringBuilder.ToString(); } public static string FromBase64(string str) { return Encoding.UTF8.GetString(Convert.FromBase64String(str)); } /// /// Convert an array of bytes to a string of hex digits /// /// array of bytes /// String of hex digits public static string HexStringFromBytes(byte[] bytes) { var sb = new StringBuilder(); foreach (byte b in bytes) { var hex = b.ToString("x2"); sb.Append(hex); } return sb.ToString(); } /// /// Compute hash for string encoded as UTF8 /// /// String to be hashed /// 40-character hex string public static string HashSHA1(string s) { var sha1 = SHA1.Create(); byte[] bytes = Encoding.UTF8.GetBytes(s); byte[] hashBytes = sha1.ComputeHash(bytes); return HexStringFromBytes(hashBytes); } public static string Hash(string s) { // Use input string to calculate MD5 hash MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(s); byte[] hashBytes = md5.ComputeHash(inputBytes); return HexStringFromBytes(hashBytes); } public static string GetExceptionDetails(this Exception exception) { var properties = exception.GetType() .GetProperties(); var fields = properties .Select(property => new { Name = property.Name, Value = property.GetValue(exception, null) }) .Select(x => String.Format( "{0} = {1}", x.Name, x.Value != null ? x.Value.ToString() : String.Empty )); return String.Join("\n", fields); } static char[] MakeValidFileName_invalids; /// Replaces characters in text that are not allowed in /// file names with the specified replacement character. /// Text to make into a valid filename. The same string is returned if it is valid already. /// Replacement character, or null to simply remove bad characters. /// Whether to replace quotes and slashes with the non-ASCII characters ” and ⁄. /// A string that can be used as a filename. If the output string would otherwise be empty, returns "_". public static string MakeValidFileName(string text, char? replacement = '_', bool fancy = true) { StringBuilder sb = new StringBuilder(text.Length); var invalids = MakeValidFileName_invalids ?? (MakeValidFileName_invalids = Path.GetInvalidFileNameChars()); bool changed = false; for (int i = 0; i < text.Length; i++) { char c = text[i]; if (invalids.Contains(c)) { changed = true; var repl = replacement ?? '\0'; if (fancy) { if (c == '"') repl = '”'; // U+201D right double quotation mark else if (c == '\'') repl = '’'; // U+2019 right single quotation mark else if (c == '/') repl = '⁄'; // U+2044 fraction slash } if (repl != '\0') sb.Append(repl); } else sb.Append(c); } if (sb.Length == 0) return "_"; return changed ? sb.ToString() : text; } public static string GetQueryString(this NameValueCollection collection, Encoding encoding = null) { if (encoding == null) encoding = Encoding.UTF8; return string.Join("&", collection.AllKeys.Select(a => a + "=" + WebUtilityHelpers.UrlEncode(collection[a], encoding))); } public static string GetQueryString(this ICollection> collection, Encoding encoding = null) { if (encoding == null) encoding = Encoding.UTF8; return string.Join("&", collection.Select(a => a.Key + "=" + WebUtilityHelpers.UrlEncode(a.Value, encoding))); } public static void Add(this ICollection> collection, string key, string value) { collection.Add(new KeyValuePair(key, value)); } public static string ToHtmlPretty(this IElement element) { if (element == null) return ""; StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); var formatter = new PrettyMarkupFormatter(); element.ToHtml(sw, formatter); return sb.ToString(); } public static string GenerateRandom(int length) { var chars = "abcdefghijklmnopqrstuvwxyz0123456789"; var randBytes = new byte[length]; using (var rngCsp = new RNGCryptoServiceProvider()) { rngCsp.GetBytes(randBytes); var key = ""; foreach (var b in randBytes) { key += chars[b % chars.Length]; } return key; } } } }