diff options
Diffstat (limited to 'SocketHttpListener/Ext.cs')
| -rw-r--r-- | SocketHttpListener/Ext.cs | 947 |
1 files changed, 0 insertions, 947 deletions
diff --git a/SocketHttpListener/Ext.cs b/SocketHttpListener/Ext.cs deleted file mode 100644 index 2b3c67071..000000000 --- a/SocketHttpListener/Ext.cs +++ /dev/null @@ -1,947 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Model.Services; -using HttpStatusCode = SocketHttpListener.Net.HttpStatusCode; -using WebSocketState = System.Net.WebSockets.WebSocketState; - -namespace SocketHttpListener -{ - /// <summary> - /// Provides a set of static methods for the websocket-sharp. - /// </summary> - public static class Ext - { - #region Private Const Fields - - private const string _tspecials = "()<>@,;:\\\"/[]?={} \t"; - - #endregion - - #region Private Methods - - private static MemoryStream compress(this Stream stream) - { - var output = new MemoryStream(); - if (stream.Length == 0) - return output; - - stream.Position = 0; - using (var ds = new DeflateStream(output, CompressionMode.Compress, true)) - { - stream.CopyTo(ds); - //ds.Close(); // "BFINAL" set to 1. - output.Position = 0; - - return output; - } - } - - private static byte[] decompress(this byte[] value) - { - if (value.Length == 0) - return value; - - using (var input = new MemoryStream(value)) - { - return input.decompressToArray(); - } - } - - private static MemoryStream decompress(this Stream stream) - { - var output = new MemoryStream(); - if (stream.Length == 0) - return output; - - stream.Position = 0; - using (var ds = new DeflateStream(stream, CompressionMode.Decompress, true)) - { - ds.CopyTo(output, true); - return output; - } - } - - private static byte[] decompressToArray(this Stream stream) - { - using (var decomp = stream.decompress()) - { - return decomp.ToArray(); - } - } - - private static async Task<byte[]> ReadBytesAsync(this Stream stream, byte[] buffer, int offset, int length) - { - var len = await stream.ReadAsync(buffer, offset, length).ConfigureAwait(false); - if (len < 1) - return buffer.SubArray(0, offset); - - var tmp = 0; - while (len < length) - { - tmp = await stream.ReadAsync(buffer, offset + len, length - len).ConfigureAwait(false); - if (tmp < 1) - { - break; - } - - len += tmp; - } - - return len < length - ? buffer.SubArray(0, offset + len) - : buffer; - } - - private static async Task<bool> ReadBytesAsync(this Stream stream, byte[] buffer, int offset, int length, Stream dest) - { - var bytes = await stream.ReadBytesAsync(buffer, offset, length).ConfigureAwait(false); - var len = bytes.Length; - dest.Write(bytes, 0, len); - - return len == offset + length; - } - - #endregion - - #region Internal Methods - - internal static async Task<byte[]> AppendAsync(this ushort code, string reason) - { - using (var buffer = new MemoryStream()) - { - var tmp = code.ToByteArrayInternally(ByteOrder.Big); - await buffer.WriteAsync(tmp, 0, 2).ConfigureAwait(false); - if (reason != null && reason.Length > 0) - { - tmp = Encoding.UTF8.GetBytes(reason); - await buffer.WriteAsync(tmp, 0, tmp.Length).ConfigureAwait(false); - } - - return buffer.ToArray(); - } - } - - internal static string CheckIfClosable(this WebSocketState state) - { - return state == WebSocketState.CloseSent - ? "While closing the WebSocket connection." - : state == WebSocketState.Closed - ? "The WebSocket connection has already been closed." - : null; - } - - internal static string CheckIfOpen(this WebSocketState state) - { - return state == WebSocketState.Connecting - ? "A WebSocket connection isn't established." - : state == WebSocketState.CloseSent - ? "While closing the WebSocket connection." - : state == WebSocketState.Closed - ? "The WebSocket connection has already been closed." - : null; - } - - internal static string CheckIfValidControlData(this byte[] data, string paramName) - { - return data.Length > 125 - ? string.Format("'{0}' length must be less.", paramName) - : null; - } - - internal static Stream Compress(this Stream stream, CompressionMethod method) - { - return method == CompressionMethod.Deflate - ? stream.compress() - : stream; - } - - internal static bool Contains<T>(this IEnumerable<T> source, Func<T, bool> condition) - { - foreach (T elm in source) - if (condition(elm)) - return true; - - return false; - } - - internal static void CopyTo(this Stream src, Stream dest, bool setDefaultPosition) - { - var readLen = 0; - var bufferLen = 256; - var buffer = new byte[bufferLen]; - while ((readLen = src.Read(buffer, 0, bufferLen)) > 0) - { - dest.Write(buffer, 0, readLen); - } - - if (setDefaultPosition) - dest.Position = 0; - } - - internal static byte[] Decompress(this byte[] value, CompressionMethod method) - { - return method == CompressionMethod.Deflate - ? value.decompress() - : value; - } - - internal static byte[] DecompressToArray(this Stream stream, CompressionMethod method) - { - return method == CompressionMethod.Deflate - ? stream.decompressToArray() - : stream.ToByteArray(); - } - - /// <summary> - /// Determines whether the specified <see cref="int"/> equals the specified <see cref="char"/>, - /// and invokes the specified Action<int> delegate at the same time. - /// </summary> - /// <returns> - /// <c>true</c> if <paramref name="value"/> equals <paramref name="c"/>; - /// otherwise, <c>false</c>. - /// </returns> - /// <param name="value"> - /// An <see cref="int"/> to compare. - /// </param> - /// <param name="c"> - /// A <see cref="char"/> to compare. - /// </param> - /// <param name="action"> - /// An Action<int> delegate that references the method(s) called at - /// the same time as comparing. An <see cref="int"/> parameter to pass to - /// the method(s) is <paramref name="value"/>. - /// </param> - /// <exception cref="ArgumentOutOfRangeException"> - /// <paramref name="value"/> isn't between 0 and 255. - /// </exception> - internal static bool EqualsWith(this int value, char c, Action<int> action) - { - if (value < 0 || value > 255) - throw new ArgumentOutOfRangeException(nameof(value)); - - action(value); - return value == c - 0; - } - - internal static string GetMessage(this CloseStatusCode code) - { - return code == CloseStatusCode.ProtocolError - ? "A WebSocket protocol error has occurred." - : code == CloseStatusCode.IncorrectData - ? "An incorrect data has been received." - : code == CloseStatusCode.Abnormal - ? "An exception has occurred." - : code == CloseStatusCode.InconsistentData - ? "An inconsistent data has been received." - : code == CloseStatusCode.PolicyViolation - ? "A policy violation has occurred." - : code == CloseStatusCode.TooBig - ? "A too big data has been received." - : code == CloseStatusCode.IgnoreExtension - ? "WebSocket client did not receive expected extension(s)." - : code == CloseStatusCode.ServerError - ? "WebSocket server got an internal error." - : code == CloseStatusCode.TlsHandshakeFailure - ? "An error has occurred while handshaking." - : string.Empty; - } - - internal static string GetNameInternal(this string nameAndValue, string separator) - { - var i = nameAndValue.IndexOf(separator); - return i > 0 - ? nameAndValue.Substring(0, i).Trim() - : null; - } - - internal static string GetValueInternal(this string nameAndValue, string separator) - { - var i = nameAndValue.IndexOf(separator); - return i >= 0 && i < nameAndValue.Length - 1 - ? nameAndValue.Substring(i + 1).Trim() - : null; - } - - internal static bool IsCompressionExtension(this string value, CompressionMethod method) - { - return value.StartsWith(method.ToExtensionString()); - } - - internal static bool IsPortNumber(this int value) - { - return value > 0 && value < 65536; - } - - internal static bool IsReserved(this ushort code) - { - return code == (ushort)CloseStatusCode.Undefined || - code == (ushort)CloseStatusCode.NoStatusCode || - code == (ushort)CloseStatusCode.Abnormal || - code == (ushort)CloseStatusCode.TlsHandshakeFailure; - } - - internal static bool IsReserved(this CloseStatusCode code) - { - return code == CloseStatusCode.Undefined || - code == CloseStatusCode.NoStatusCode || - code == CloseStatusCode.Abnormal || - code == CloseStatusCode.TlsHandshakeFailure; - } - - internal static bool IsText(this string value) - { - var len = value.Length; - for (var i = 0; i < len; i++) - { - char c = value[i]; - if (c < 0x20 && !"\r\n\t".Contains(c)) - return false; - - if (c == 0x7f) - return false; - - if (c == '\n' && ++i < len) - { - c = value[i]; - if (!" \t".Contains(c)) - return false; - } - } - - return true; - } - - internal static bool IsToken(this string value) - { - foreach (char c in value) - if (c < 0x20 || c >= 0x7f || _tspecials.Contains(c)) - return false; - - return true; - } - - internal static string Quote(this string value) - { - return value.IsToken() - ? value - : string.Format("\"{0}\"", value.Replace("\"", "\\\"")); - } - - internal static Task<byte[]> ReadBytesAsync(this Stream stream, int length) - => stream.ReadBytesAsync(new byte[length], 0, length); - - internal static async Task<byte[]> ReadBytesAsync(this Stream stream, long length, int bufferLength) - { - using (var result = new MemoryStream()) - { - var count = length / bufferLength; - var rem = (int)(length % bufferLength); - - var buffer = new byte[bufferLength]; - var end = false; - for (long i = 0; i < count; i++) - { - if (!await stream.ReadBytesAsync(buffer, 0, bufferLength, result).ConfigureAwait(false)) - { - end = true; - break; - } - } - - if (!end && rem > 0) - { - await stream.ReadBytesAsync(new byte[rem], 0, rem, result).ConfigureAwait(false); - } - - return result.ToArray(); - } - } - - internal static string RemovePrefix(this string value, params string[] prefixes) - { - var i = 0; - foreach (var prefix in prefixes) - { - if (value.StartsWith(prefix)) - { - i = prefix.Length; - break; - } - } - - return i > 0 - ? value.Substring(i) - : value; - } - - internal static T[] Reverse<T>(this T[] array) - { - var len = array.Length; - T[] reverse = new T[len]; - - var end = len - 1; - for (var i = 0; i <= end; i++) - reverse[i] = array[end - i]; - - return reverse; - } - - internal static IEnumerable<string> SplitHeaderValue( - this string value, params char[] separator) - { - var len = value.Length; - var separators = new string(separator); - - var buffer = new StringBuilder(32); - var quoted = false; - var escaped = false; - - char c; - for (var i = 0; i < len; i++) - { - c = value[i]; - if (c == '"') - { - if (escaped) - escaped = !escaped; - else - quoted = !quoted; - } - else if (c == '\\') - { - if (i < len - 1 && value[i + 1] == '"') - escaped = true; - } - else if (separators.Contains(c)) - { - if (!quoted) - { - yield return buffer.ToString(); - buffer.Length = 0; - - continue; - } - } - else - { - } - - buffer.Append(c); - } - - if (buffer.Length > 0) - yield return buffer.ToString(); - } - - internal static byte[] ToByteArray(this Stream stream) - { - using (var output = new MemoryStream()) - { - stream.Position = 0; - stream.CopyTo(output); - - return output.ToArray(); - } - } - - internal static byte[] ToByteArrayInternally(this ushort value, ByteOrder order) - { - var bytes = BitConverter.GetBytes(value); - if (!order.IsHostOrder()) - Array.Reverse(bytes); - - return bytes; - } - - internal static byte[] ToByteArrayInternally(this ulong value, ByteOrder order) - { - var bytes = BitConverter.GetBytes(value); - if (!order.IsHostOrder()) - Array.Reverse(bytes); - - return bytes; - } - - internal static string ToExtensionString( - this CompressionMethod method, params string[] parameters) - { - if (method == CompressionMethod.None) - return string.Empty; - - var m = string.Format("permessage-{0}", method.ToString().ToLowerInvariant()); - if (parameters == null || parameters.Length == 0) - return m; - - return string.Format("{0}; {1}", m, parameters.ToString("; ")); - } - - internal static ushort ToUInt16(this byte[] src, ByteOrder srcOrder) - { - src.ToHostOrder(srcOrder); - return BitConverter.ToUInt16(src, 0); - } - - internal static ulong ToUInt64(this byte[] src, ByteOrder srcOrder) - { - src.ToHostOrder(srcOrder); - return BitConverter.ToUInt64(src, 0); - } - - internal static string TrimEndSlash(this string value) - { - value = value.TrimEnd('/'); - return value.Length > 0 - ? value - : "/"; - } - - internal static string Unquote(this string value) - { - var start = value.IndexOf('\"'); - var end = value.LastIndexOf('\"'); - if (start < end) - value = value.Substring(start + 1, end - start - 1).Replace("\\\"", "\""); - - return value.Trim(); - } - - internal static void WriteBytes(this Stream stream, byte[] value) - { - using (var src = new MemoryStream(value)) - { - src.CopyTo(stream); - } - } - - #endregion - - #region Public Methods - - /// <summary> - /// Determines whether the specified <see cref="string"/> contains any of characters - /// in the specified array of <see cref="char"/>. - /// </summary> - /// <returns> - /// <c>true</c> if <paramref name="value"/> contains any of <paramref name="chars"/>; - /// otherwise, <c>false</c>. - /// </returns> - /// <param name="value"> - /// A <see cref="string"/> to test. - /// </param> - /// <param name="chars"> - /// An array of <see cref="char"/> that contains characters to find. - /// </param> - public static bool Contains(this string value, params char[] chars) - { - return chars == null || chars.Length == 0 - ? true - : value == null || value.Length == 0 - ? false - : value.IndexOfAny(chars) != -1; - } - - /// <summary> - /// Determines whether the specified <see cref="QueryParamCollection"/> contains the entry - /// with the specified <paramref name="name"/>. - /// </summary> - /// <returns> - /// <c>true</c> if <paramref name="collection"/> contains the entry - /// with <paramref name="name"/>; otherwise, <c>false</c>. - /// </returns> - /// <param name="collection"> - /// A <see cref="QueryParamCollection"/> to test. - /// </param> - /// <param name="name"> - /// A <see cref="string"/> that represents the key of the entry to find. - /// </param> - public static bool Contains(this QueryParamCollection collection, string name) - { - return collection == null || collection.Count == 0 - ? false - : collection[name] != null; - } - - /// <summary> - /// Determines whether the specified <see cref="QueryParamCollection"/> contains the entry - /// with the specified both <paramref name="name"/> and <paramref name="value"/>. - /// </summary> - /// <returns> - /// <c>true</c> if <paramref name="collection"/> contains the entry - /// with both <paramref name="name"/> and <paramref name="value"/>; - /// otherwise, <c>false</c>. - /// </returns> - /// <param name="collection"> - /// A <see cref="QueryParamCollection"/> to test. - /// </param> - /// <param name="name"> - /// A <see cref="string"/> that represents the key of the entry to find. - /// </param> - /// <param name="value"> - /// A <see cref="string"/> that represents the value of the entry to find. - /// </param> - public static bool Contains(this QueryParamCollection collection, string name, string value) - { - if (collection == null || collection.Count == 0) - return false; - - var values = collection[name]; - if (values == null) - return false; - - foreach (var v in values.Split(',')) - if (v.Trim().Equals(value, StringComparison.OrdinalIgnoreCase)) - return true; - - return false; - } - - /// <summary> - /// Emits the specified <c>EventHandler<TEventArgs></c> delegate - /// if it isn't <see langword="null"/>. - /// </summary> - /// <param name="eventHandler"> - /// An <c>EventHandler<TEventArgs></c> to emit. - /// </param> - /// <param name="sender"> - /// An <see cref="object"/> from which emits this <paramref name="eventHandler"/>. - /// </param> - /// <param name="e"> - /// A <c>TEventArgs</c> that represents the event data. - /// </param> - /// <typeparam name="TEventArgs"> - /// The type of the event data generated by the event. - /// </typeparam> - public static void Emit<TEventArgs>( - this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e) - where TEventArgs : EventArgs - { - if (eventHandler != null) - eventHandler(sender, e); - } - - /// <summary> - /// Gets the description of the specified HTTP status <paramref name="code"/>. - /// </summary> - /// <returns> - /// A <see cref="string"/> that represents the description of the HTTP status code. - /// </returns> - /// <param name="code"> - /// One of <see cref="HttpStatusCode"/> enum values, indicates the HTTP status codes. - /// </param> - public static string GetDescription(this HttpStatusCode code) - { - return ((int)code).GetStatusDescription(); - } - - /// <summary> - /// Gets the description of the specified HTTP status <paramref name="code"/>. - /// </summary> - /// <returns> - /// A <see cref="string"/> that represents the description of the HTTP status code. - /// </returns> - /// <param name="code"> - /// An <see cref="int"/> that represents the HTTP status code. - /// </param> - public static string GetStatusDescription(this int code) - { - switch (code) - { - case 100: return "Continue"; - case 101: return "Switching Protocols"; - case 102: return "Processing"; - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 207: return "Multi-Status"; - case 300: return "Multiple Choices"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; - case 307: return "Temporary Redirect"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Timeout"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Request Entity Too Large"; - case 414: return "Request-Uri Too Long"; - case 415: return "Unsupported Media Type"; - case 416: return "Requested Range Not Satisfiable"; - case 417: return "Expectation Failed"; - case 422: return "Unprocessable Entity"; - case 423: return "Locked"; - case 424: return "Failed Dependency"; - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Timeout"; - case 505: return "Http Version Not Supported"; - case 507: return "Insufficient Storage"; - } - - return string.Empty; - } - - /// <summary> - /// Determines whether the specified <see cref="ByteOrder"/> is host - /// (this computer architecture) byte order. - /// </summary> - /// <returns> - /// <c>true</c> if <paramref name="order"/> is host byte order; - /// otherwise, <c>false</c>. - /// </returns> - /// <param name="order"> - /// One of the <see cref="ByteOrder"/> enum values, to test. - /// </param> - public static bool IsHostOrder(this ByteOrder order) - { - // true : !(true ^ true) or !(false ^ false) - // false: !(true ^ false) or !(false ^ true) - return !(BitConverter.IsLittleEndian ^ (order == ByteOrder.Little)); - } - - /// <summary> - /// Determines whether the specified <see cref="string"/> is a predefined scheme. - /// </summary> - /// <returns> - /// <c>true</c> if <paramref name="value"/> is a predefined scheme; otherwise, <c>false</c>. - /// </returns> - /// <param name="value"> - /// A <see cref="string"/> to test. - /// </param> - public static bool IsPredefinedScheme(this string value) - { - if (value == null || value.Length < 2) - return false; - - var c = value[0]; - if (c == 'h') - return value == "http" || value == "https"; - - if (c == 'w') - return value == "ws" || value == "wss"; - - if (c == 'f') - return value == "file" || value == "ftp"; - - if (c == 'n') - { - c = value[1]; - return c == 'e' - ? value == "news" || value == "net.pipe" || value == "net.tcp" - : value == "nntp"; - } - - return (c == 'g' && value == "gopher") || (c == 'm' && value == "mailto"); - } - - /// <summary> - /// Determines whether the specified <see cref="string"/> is a URI string. - /// </summary> - /// <returns> - /// <c>true</c> if <paramref name="value"/> may be a URI string; otherwise, <c>false</c>. - /// </returns> - /// <param name="value"> - /// A <see cref="string"/> to test. - /// </param> - public static bool MaybeUri(this string value) - { - if (value == null || value.Length == 0) - return false; - - var i = value.IndexOf(':'); - if (i == -1) - return false; - - if (i >= 10) - return false; - - return value.Substring(0, i).IsPredefinedScheme(); - } - - /// <summary> - /// Retrieves a sub-array from the specified <paramref name="array"/>. - /// A sub-array starts at the specified element position. - /// </summary> - /// <returns> - /// An array of T that receives a sub-array, or an empty array of T if any problems - /// with the parameters. - /// </returns> - /// <param name="array"> - /// An array of T that contains the data to retrieve a sub-array. - /// </param> - /// <param name="startIndex"> - /// An <see cref="int"/> that contains the zero-based starting position of a sub-array - /// in <paramref name="array"/>. - /// </param> - /// <param name="length"> - /// An <see cref="int"/> that contains the number of elements to retrieve a sub-array. - /// </param> - /// <typeparam name="T"> - /// The type of elements in the <paramref name="array"/>. - /// </typeparam> - public static T[] SubArray<T>(this T[] array, int startIndex, int length) - { - if (array == null || array.Length == 0) - return new T[0]; - - if (startIndex < 0 || length <= 0) - return new T[0]; - - if (startIndex + length > array.Length) - return new T[0]; - - if (startIndex == 0 && array.Length == length) - return array; - - T[] subArray = new T[length]; - Array.Copy(array, startIndex, subArray, 0, length); - - return subArray; - } - - /// <summary> - /// Converts the order of the specified array of <see cref="byte"/> to the host byte order. - /// </summary> - /// <returns> - /// An array of <see cref="byte"/> converted from <paramref name="src"/>. - /// </returns> - /// <param name="src"> - /// An array of <see cref="byte"/> to convert. - /// </param> - /// <param name="srcOrder"> - /// One of the <see cref="ByteOrder"/> enum values, indicates the byte order of - /// <paramref name="src"/>. - /// </param> - /// <exception cref="ArgumentNullException"> - /// <paramref name="src"/> is <see langword="null"/>. - /// </exception> - public static void ToHostOrder(this byte[] src, ByteOrder srcOrder) - { - if (src == null) - { - throw new ArgumentNullException(nameof(src)); - } - - if (src.Length > 1 && !srcOrder.IsHostOrder()) - { - Array.Reverse(src); - } - } - - /// <summary> - /// Converts the specified <paramref name="array"/> to a <see cref="string"/> that - /// concatenates the each element of <paramref name="array"/> across the specified - /// <paramref name="separator"/>. - /// </summary> - /// <returns> - /// A <see cref="string"/> converted from <paramref name="array"/>, - /// or <see cref="String.Empty"/> if <paramref name="array"/> is empty. - /// </returns> - /// <param name="array"> - /// An array of T to convert. - /// </param> - /// <param name="separator"> - /// A <see cref="string"/> that represents the separator string. - /// </param> - /// <typeparam name="T"> - /// The type of elements in <paramref name="array"/>. - /// </typeparam> - /// <exception cref="ArgumentNullException"> - /// <paramref name="array"/> is <see langword="null"/>. - /// </exception> - public static string ToString<T>(this T[] array, string separator) - { - if (array == null) - throw new ArgumentNullException(nameof(array)); - - var len = array.Length; - if (len == 0) - return string.Empty; - - if (separator == null) - separator = string.Empty; - - var buff = new StringBuilder(64); - (len - 1).Times(i => buff.AppendFormat("{0}{1}", array[i].ToString(), separator)); - - buff.Append(array[len - 1].ToString()); - return buff.ToString(); - } - - /// <summary> - /// Executes the specified <c>Action<int></c> delegate <paramref name="n"/> times. - /// </summary> - /// <param name="n"> - /// An <see cref="int"/> is the number of times to execute. - /// </param> - /// <param name="action"> - /// An <c>Action<int></c> delegate that references the method(s) to execute. - /// An <see cref="int"/> parameter to pass to the method(s) is the zero-based count of - /// iteration. - /// </param> - public static void Times(this int n, Action<int> action) - { - if (n > 0 && action != null) - for (int i = 0; i < n; i++) - action(i); - } - - /// <summary> - /// Converts the specified <see cref="string"/> to a <see cref="Uri"/>. - /// </summary> - /// <returns> - /// A <see cref="Uri"/> converted from <paramref name="uriString"/>, or <see langword="null"/> - /// if <paramref name="uriString"/> isn't successfully converted. - /// </returns> - /// <param name="uriString"> - /// A <see cref="string"/> to convert. - /// </param> - public static Uri ToUri(this string uriString) - { - return Uri.TryCreate( - uriString, uriString.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out var res) - ? res - : null; - } - - /// <summary> - /// URL-decodes the specified <see cref="string"/>. - /// </summary> - /// <returns> - /// A <see cref="string"/> that receives the decoded string, or the <paramref name="value"/> - /// if it's <see langword="null"/> or empty. - /// </returns> - /// <param name="value"> - /// A <see cref="string"/> to decode. - /// </param> - public static string UrlDecode(this string value) - { - return value == null || value.Length == 0 - ? value - : WebUtility.UrlDecode(value); - } - - #endregion - } -} |
