2009-07-28 Gonzalo Paniagua Javier <gonzalo@novell.com>
[mono.git] / mcs / class / System.Web / System.Web / HttpUtility.cs
index a0533df3e197fd6617c6867939eedee03f5284f1..fe54758eac0e2d5631dca95d962b402b2083d411 100644 (file)
@@ -37,6 +37,10 @@ using System.Security.Permissions;
 using System.Text;
 using System.Web.Util;
 
+#if NET_2_0
+using System.Collections.Generic;
+#endif
+
 namespace System.Web {
 
        // CAS - no InheritanceDemand here as the class is sealed
@@ -376,11 +380,20 @@ namespace System.Web {
                        return UrlDecode(str, Encoding.UTF8);
                }
        
-               private static char [] GetChars (MemoryStream b, Encoding e)
+               static char [] GetChars (MemoryStream b, Encoding e)
                {
                        return e.GetChars (b.GetBuffer (), 0, (int) b.Length);
                }
 
+               static void WriteCharBytes (IList buf, char ch, Encoding e)
+               {
+                       if (ch > 255) {
+                               foreach (byte b in e.GetBytes (new char[] { ch }))
+                                       buf.Add (b);
+                       } else
+                               buf.Add ((byte)ch);
+               }
+               
                public static string UrlDecode (string s, Encoding e)
                {
                        if (null == s) 
@@ -388,57 +401,53 @@ namespace System.Web {
 
                        if (s.IndexOf ('%') == -1 && s.IndexOf ('+') == -1)
                                return s;
-
+                       
                        if (e == null)
                                e = Encoding.UTF8;
-       
-                       StringBuilder output = new StringBuilder ();
+
                        long len = s.Length;
-                       MemoryStream bytes = new MemoryStream ();
+#if NET_2_0
+                       var bytes = new List <byte> ();
+#else
+                       ArrayList bytes = new ArrayList ();
+#endif
                        int xchar;
-       
+                       char ch;
+                       
                        for (int i = 0; i < len; i++) {
-                               if (s [i] == '%' && i + 2 < len && s [i + 1] != '%') {
+                               ch = s [i];
+                               if (ch == '%' && i + 2 < len && s [i + 1] != '%') {
                                        if (s [i + 1] == 'u' && i + 5 < len) {
-                                               if (bytes.Length > 0) {
-                                                       output.Append (GetChars (bytes, e));
-                                                       bytes.SetLength (0);
-                                               }
-
+                                               // unicode hex sequence
                                                xchar = GetChar (s, i + 2, 4);
                                                if (xchar != -1) {
-                                                       output.Append ((char) xchar);
+                                                       WriteCharBytes (bytes, (char)xchar, e);
                                                        i += 5;
-                                               } else {
-                                                       output.Append ('%');
-                                               }
+                                               } else
+                                                       WriteCharBytes (bytes, '%', e);
                                        } else if ((xchar = GetChar (s, i + 1, 2)) != -1) {
-                                               bytes.WriteByte ((byte) xchar);
+                                               WriteCharBytes (bytes, (char)xchar, e);
                                                i += 2;
                                        } else {
-                                               output.Append ('%');
+                                               WriteCharBytes (bytes, '%', e);
                                        }
                                        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));
+                               if (ch == '+')
+                                       WriteCharBytes (bytes, ' ', e);
+                               else
+                                       WriteCharBytes (bytes, ch, e);
                        }
-
+                       
+#if NET_2_0
+                       byte[] buf = bytes.ToArray ();
+#else
+                       byte[] buf = (byte[])bytes.ToArray (typeof (byte));
+#endif
                        bytes = null;
-                       return output.ToString ();
+                       return e.GetString (buf);
+                       
                }
        
                public static string UrlDecode (byte [] bytes, Encoding e)
@@ -449,7 +458,7 @@ namespace System.Web {
                        return UrlDecode (bytes, 0, bytes.Length, e);
                }
 
-               private static int GetInt (byte b)
+               static int GetInt (byte b)
                {
                        char c = (char) b;
                        if (c >= '0' && c <= '9')
@@ -464,7 +473,7 @@ namespace System.Web {
                        return -1;
                }
 
-               private static int GetChar (byte [] bytes, int offset, int length)
+               static int GetChar (byte [] bytes, int offset, int length)
                {
                        int value = 0;
                        int end = length + offset;
@@ -478,7 +487,7 @@ namespace System.Web {
                        return value;
                }
 
-               private static int GetChar (string str, int offset, int length)
+               static int GetChar (string str, int offset, int length)
                {
                        int val = 0;
                        int end = length + offset;
@@ -1033,6 +1042,23 @@ namespace System.Web {
 #endif
 
 #if NET_2_0
+               class HttpQSCollection : NameValueCollection {
+                       public override string ToString ()
+                       {
+                               int count = Count;
+                               if (count == 0)
+                                       return "";
+                               StringBuilder sb = new StringBuilder ();
+                               string [] keys = AllKeys;
+                               for (int i = 0; i < count; i++) {
+                                       sb.AppendFormat ("{0}={1}&", keys [i], this [keys [i]]);
+                               }
+                               if (sb.Length > 0)
+                                       sb.Length--;
+                               return sb.ToString ();
+                       }
+               }
+
                public static NameValueCollection ParseQueryString (string query)
                {
                        return ParseQueryString (query, Encoding.UTF8);
@@ -1049,7 +1075,7 @@ namespace System.Web {
                        if (query[0] == '?')
                                query = query.Substring (1);
                                
-                       NameValueCollection result = new NameValueCollection ();
+                       NameValueCollection result = new HttpQSCollection ();
                        ParseQueryString (query, encoding, result);
                        return result;
                }