Url encoding (2)
//
// System.Net.HttpUtility
//
// Author:
// Gonzalo Paniagua Javier (gonzalo@novell.com)
//
// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Globalization;
using System.IO;
using System.Text;
namespace Tavis.Http {
public sealed class HttpUtility {
private HttpUtility() {
}
public static string UrlDecode(string s) {
return UrlDecode(s, null);
}
static char[] GetChars(MemoryStream b, Encoding e) {
return e.GetChars(b.GetBuffer(), 0, (int)b.Length);
}
public static string UrlDecode(string s, Encoding e) {
if (null == s)
return null;
if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1)
return s;
if (e == null)
e = Encoding.GetEncoding(28591);
StringBuilder output = new StringBuilder();
long len = s.Length;
NumberStyles hexa = NumberStyles.HexNumber;
MemoryStream bytes = new MemoryStream();
for (int i = 0; i < len; i++) {
if (s[i] == '%' && i + 2 < len) {
if (s[i + 1] == 'u' && i + 5 < len) {
if (bytes.Length > 0) {
output.Append(GetChars(bytes, e));
bytes.SetLength(0);
}
output.Append((char)Int32.Parse(s.Substring(i + 2, 4), hexa));
i += 5;
} else {
bytes.WriteByte((byte)Int32.Parse(s.Substring(i + 1, 2), hexa));
i += 2;
}
continue;
}
if (bytes.Length > 0) {
output.Append(GetChars(bytes, e));
bytes.SetLength(0);
}
if (s[i] == '+') {
output.Append(' ');
} else {
output.Append(s[i]);
}
}
if (bytes.Length > 0) {
output.Append(GetChars(bytes, e));
}
bytes = null;
return output.ToString();
}
public static string UrlEncode(string str) {
return UrlEncode(str, Encoding.UTF8);
}
public static string UrlEncode(string s, Encoding Enc) {
if (s == null)
return null;
if (s == "")
return "";
byte[] bytes = Enc.GetBytes(s);
return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, 0, bytes.Length));
}
public static string UrlEncode(byte[] bytes) {
if (bytes == null)
return null;
if (bytes.Length == 0)
return "";
return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, 0, bytes.Length));
}
public static string UrlEncode(byte[] bytes, int offset, int count) {
if (bytes == null)
return null;
if (bytes.Length == 0)
return "";
return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, offset, count));
}
public static byte[] UrlEncodeToBytes(string str) {
return UrlEncodeToBytes(str, Encoding.UTF8);
}
public static byte[] UrlEncodeToBytes(string str, Encoding e) {
if (str == null)
return null;
if (str == "")
return new byte[0];
byte[] bytes = e.GetBytes(str);
return UrlEncodeToBytes(bytes, 0, bytes.Length);
}
public static byte[] UrlEncodeToBytes(byte[] bytes) {
if (bytes == null)
return null;
if (bytes.Length == 0)
return new byte[0];
return UrlEncodeToBytes(bytes, 0, bytes.Length);
}
static char[] hexChars = "0123456789abcdef".ToCharArray();
const string notEncoded = "!'()*-._";
static void UrlEncodeChar(char c, Stream result, bool isUnicode) {
if (c > 255) {
//FIXME: what happens when there is an internal error?
//if (!isUnicode)
// throw new ArgumentOutOfRangeException ("c", c, "c must be less than 256");
int idx;
int i = (int)c;
result.WriteByte((byte)'%');
result.WriteByte((byte)'u');
idx = i >> 12;
result.WriteByte((byte)hexChars[idx]);
idx = (i >> 8) & 0x0F;
result.WriteByte((byte)hexChars[idx]);
idx = (i >> 4) & 0x0F;
result.WriteByte((byte)hexChars[idx]);
idx = i & 0x0F;
result.WriteByte((byte)hexChars[idx]);
return;
}
if (c > ' ' && notEncoded.IndexOf(c) != -1) {
result.WriteByte((byte)c);
return;
}
if (c == ' ') {
result.WriteByte((byte)'+');
return;
}
if ((c < '0') ||
(c < 'A' && c > '9') ||
(c > 'Z' && c < 'a') ||
(c > 'z')) {
if (isUnicode && c > 127) {
result.WriteByte((byte)'%');
result.WriteByte((byte)'u');
result.WriteByte((byte)'0');
result.WriteByte((byte)'0');
} else
result.WriteByte((byte)'%');
int idx = ((int)c) >> 4;
result.WriteByte((byte)hexChars[idx]);
idx = ((int)c) & 0x0F;
result.WriteByte((byte)hexChars[idx]);
} else
result.WriteByte((byte)c);
}
public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) {
if (bytes == null)
return null;
int len = bytes.Length;
if (len == 0)
return new byte[0];
if (offset < 0 || offset >= len)
throw new ArgumentOutOfRangeException("offset");
if (count < 0 || count > len - offset)
throw new ArgumentOutOfRangeException("count");
MemoryStream result = new MemoryStream(count);
int end = offset + count;
for (int i = offset; i < end; i++)
UrlEncodeChar((char)bytes[i], result, false);
return result.ToArray();
}
public static string UrlEncodeUnicode(string str) {
if (str == null)
return null;
return Encoding.ASCII.GetString(UrlEncodeUnicodeToBytes(str));
}
public static byte[] UrlEncodeUnicodeToBytes(string str) {
if (str == null)
return null;
if (str == "")
return new byte[0];
MemoryStream result = new MemoryStream(str.Length);
foreach (char c in str) {
UrlEncodeChar(c, result, true);
}
return result.ToArray();
}
}
}
Related examples in the same category