2007-10-24 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web / HttpUtility.cs
index fe4cea09f36085cc3c9a87a283543f404895cca8..ac2f36e375a9b0fcb74147007a7a05ce71032866 100644 (file)
@@ -42,7 +42,6 @@ namespace System.Web {
        // CAS - no InheritanceDemand here as the class is sealed
        [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        public sealed class HttpUtility {
-
                #region Fields
        
                static Hashtable entities;
@@ -340,20 +339,32 @@ namespace System.Web {
                        if (null == s) 
                                return null;
        
-                       if (s.IndexOf ('&') == -1 && s.IndexOf ('"') == -1)
+                       bool needEncode = false;
+                       for (int i = 0; i < s.Length; i++) {
+                               if (s [i] == '&' || s [i] == '"' || s [i] == '<') {
+                                       needEncode = true;
+                                       break;
+                               }
+                       }
+
+                       if (!needEncode)
                                return s;
 
                        StringBuilder output = new StringBuilder ();
-                       foreach (char c in s) 
-                               switch (c) {
+                       int len = s.Length;
+                       for (int i = 0; i < len; i++)
+                               switch (s [i]) {
                                case '&' : 
                                        output.Append ("&amp;");
                                        break;
                                case '"' :
                                        output.Append ("&quot;");
                                        break;
+                               case '<':
+                                       output.Append ("&lt;");
+                                       break;
                                default:
-                                       output.Append (c);
+                                       output.Append (s [i]);
                                        break;
                                }
        
@@ -616,8 +627,26 @@ namespace System.Web {
                        if (s == "")
                                return "";
 
-                       byte [] bytes = Enc.GetBytes (s);
-                       return Encoding.ASCII.GetString (UrlEncodeToBytes (bytes, 0, bytes.Length));
+                       bool needEncode = false;
+                       int len = s.Length;
+                       for (int i = 0; i < len; i++) {
+                               char c = s [i];
+                               if ((c < '0') || (c < 'A' && c > '9') || (c > 'Z' && c < 'a') || (c > 'z')) {
+                                       if (NotEncoded (c))
+                                               continue;
+
+                                       needEncode = true;
+                                       break;
+                               }
+                       }
+
+                       if (!needEncode)
+                               return s;
+
+                       // avoided GetByteCount call
+                       byte [] bytes = new byte[Enc.GetMaxByteCount(s.Length)];
+                       int realLen = Enc.GetBytes (s, 0, s.Length, bytes, 0);
+                       return Encoding.ASCII.GetString (UrlEncodeToBytes (bytes, 0, realLen));
                }
          
                public static string UrlEncode (byte [] bytes)
@@ -671,7 +700,11 @@ namespace System.Web {
                }
 
                static char [] hexChars = "0123456789abcdef".ToCharArray ();
-               const string notEncoded = "!'()*-._";
+
+               static bool NotEncoded (char c)
+               {
+                       return (c == '!' || c == '\'' || c == '(' || c == ')' || c == '*' || c == '-' || c == '.' || c == '_');
+               }
 
                static void UrlEncodeChar (char c, Stream result, bool isUnicode) {
                        if (c > 255) {
@@ -694,7 +727,7 @@ namespace System.Web {
                                return;
                        }
                        
-                       if (c>' ' && notEncoded.IndexOf (c)!=-1) {
+                       if (c > ' ' && NotEncoded (c)) {
                                result.WriteByte ((byte)c);
                                return;
                        }
@@ -900,10 +933,23 @@ namespace System.Web {
                        if (s == null)
                                return null;
 
+                       bool needEncode = false;
+                       for (int i = 0; i < s.Length; i++) {
+                               char c = s [i];
+                               if (c == '&' || c == '"' || c == '<' || c == '>' || c > 159) {
+                                       needEncode = true;
+                                       break;
+                               }
+                       }
+
+                       if (!needEncode)
+                               return s;
+
                        StringBuilder output = new StringBuilder ();
                        
-                       foreach (char c in s) 
-                               switch (c) {
+                       int len = s.Length;
+                       for (int i = 0; i < len; i++) 
+                               switch (s [i]) {
                                case '&' :
                                        output.Append ("&amp;");
                                        break;
@@ -920,12 +966,12 @@ namespace System.Web {
                                        // MS starts encoding with &# from 160 and stops at 255.
                                        // We don't do that. One reason is the 65308/65310 unicode
                                        // characters that look like '<' and '>'.
-                                       if (c > 159) {
+                                       if (s [i] > 159) {
                                                output.Append ("&#");
-                                               output.Append (((int) c).ToString (CultureInfo.InvariantCulture));
+                                               output.Append (((int) s [i]).ToString (CultureInfo.InvariantCulture));
                                                output.Append (";");
                                        } else {
-                                               output.Append (c);
+                                               output.Append (s [i]);
                                        }
                                        break;
                                }
@@ -1007,6 +1053,7 @@ namespace System.Web {
                                return;
 
                        int namePos = 0;
+                       bool first = true;
                        while (namePos <= query.Length) {
                                int valuePos = -1, valueEnd = -1;
                                for (int q = namePos; q < query.Length; q++) {
@@ -1018,6 +1065,12 @@ namespace System.Web {
                                        }
                                }
 
+                               if (first) {
+                                       first = false;
+                                       if (query [namePos] == '?')
+                                               namePos++;
+                               }
+                               
                                string name, value;
                                if (valuePos == -1) {
                                        name = null;
@@ -1034,7 +1087,8 @@ namespace System.Web {
                                value = UrlDecode (query.Substring (valuePos, valueEnd - valuePos), encoding);
 
                                result.Add (name, value);
-                               if (namePos == -1) break;
+                               if (namePos == -1)
+                                       break;
                        }
                }
                #endregion // Methods