using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SocialKit.LightRest
{
///
/// Provides helper methods for common tasks.
///
public static class RestUtility
{
static string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
///
/// Represents the System.Text.Encoding.Default.
///
public static readonly Encoding DefaultEncoding = Encoding.Default;
///
/// Encodes a URL string with UTF8 encoding.
///
/// The text to encode.
///
public static string UrlEncode(string source)
{
return UrlEncode(source, Encoding.UTF8);
}
///
/// Encodes a URL string with the specified encoding.
///
/// The text to encode.
/// The System.Text.Encoding object that specifies the encoding scheme.
///
public static string UrlEncode(string source, Encoding encoding)
{
if (source == null)
return null;
if (string.IsNullOrEmpty(source))
return string.Empty;
if (encoding == null)
encoding = DefaultEncoding;
var buffer = new StringBuilder();
foreach (var b in encoding.GetBytes(source))
{
if (b < 128 && unreservedChars.IndexOf((char)b) != -1)
{
buffer.Append((char)b);
}
else
{
buffer.AppendFormat("%{0:X2}", b);
}
}
return buffer.ToString();
}
///
/// Converts a string that has been encoded for transmission in a URL into a decoded string.
///
/// The URL-encoded string to decode.
///
public static string UrlDecode(string source)
{
return UrlDecode(source, Encoding.UTF8);
}
///
/// Converts a URL-encoded string into a decoded string, using the specified encoding object.
///
/// The URL-encoded string to decode.
/// The System.Text.Encoding object that specifies the encoding scheme.
///
public static string UrlDecode(string source, Encoding encoding)
{
if (source == null)
return null;
if (string.IsNullOrEmpty(source))
return string.Empty;
if (encoding == null)
encoding = DefaultEncoding;
var bytes = new List();
for (int i = 0; i < source.Length; i++)
{
var c = source[i];
if (unreservedChars.IndexOf(c) != -1)
{
bytes.Add((byte)c);
}
else if (c == '%' && i < source.Length - 2)
{
var n1 = HexToInt(source[i + 1]);
var n2 = HexToInt(source[i + 2]);
if (n1 >= 0 && n2 >= 0)
{
var b = (byte)((n1 << 4) | n2);
i += 2;
bytes.Add(b);
}
}
}
return encoding.GetString(bytes.ToArray(), 0, bytes.Count);
}
///
/// Converts an hex char to an integer.
///
///
///
static int HexToInt(char c)
{
if ((c >= '0') && (c <= '9'))
{
return (c - '0');
}
if ((c >= 'a') && (c <= 'f'))
{
return ((c - 'a') + 10);
}
if ((c >= 'A') && (c <= 'F'))
{
return ((c - 'A') + 10);
}
return -1;
}
///
/// Parse the query string in the URI into a KeyValuePair<string, string> collection.
/// The keys and values will be URL decoded.
///
/// The query string to parse.
/// A keys and values collection.
public static IEnumerable> ParseQueryString(string query)
{
if (query == null)
throw new ArgumentNullException("query");
if (query.StartsWith("?"))
query = query.Substring(1);
if (string.IsNullOrEmpty(query))
return new KeyValuePair[] { };
var values = new List>();
int length = query.Length;
int startIndex, equalIndex;
for (int i = 0; i < length; i++)
{
startIndex = i;
equalIndex = -1;
while (i < length)
{
char c = query[i];
if (c == '=')
{
if (equalIndex < 0)
{
equalIndex = i;
}
}
else if (c == '&')
{
break;
}
i++;
}
string key = null;
string value = null;
if (equalIndex >= 0)
{
key = query.Substring(startIndex, equalIndex - startIndex);
value = query.Substring(equalIndex + 1, (i - equalIndex) - 1);
}
else
{
//standalone value is key or value?
key = query.Substring(startIndex, i - startIndex);
}
if (value == null)
{
value = string.Empty;
}
values.Add(new KeyValuePair(UrlDecode(key), UrlDecode(value)));
}
return values;
}
///
/// Gets a string indicates the URI without query string.
///
/// The URI to normalize.
/// The host and path of the URI.
public static string NormalizeUriWithoutQuery(Uri uri)
{
if (!uri.IsAbsoluteUri)
throw new ArgumentOutOfRangeException("uri", "The relative URI is not supported.");
var normalizedUri = string.Format("{0}://{1}", uri.Scheme, uri.Host);
if (!((uri.Scheme == "http" && uri.Port == 80) || (uri.Scheme == "https" && uri.Port == 443)))
{
normalizedUri += ":" + uri.Port;
}
normalizedUri += uri.AbsolutePath;
return normalizedUri;
}
///
/// Extract encoding from the contentType string, or returns the fallback value.
///
/// The contentType string.
/// If no encoding found, returns this value.
/// A System.Text.Encoding value.
public static Encoding ExtractEncoding(string contentType, Encoding fallback)
{
if (string.IsNullOrEmpty(contentType))
{
return fallback;
}
//find charset
var values = contentType.Split(';');
var charsetPair = values.FirstOrDefault(v => v.Trim().StartsWith("charset", StringComparison.InvariantCultureIgnoreCase));
if (charsetPair == null)
return fallback;
var charset = charsetPair.Split('=')[1];
return Encoding.GetEncoding(charset);
}
///
/// Extract encoding from the contentType string.
///
/// The contentType string.
/// A System.Text.Encoding value.
public static Encoding ExtractEncoding(string contentType)
{
return ExtractEncoding(contentType, Encoding.Default);
}
}
}