Fix path reduction when %2e are used in an URI
authorSebastien Pouliot <sebastien@ximian.com>
Thu, 16 Sep 2010 18:35:32 +0000 (14:35 -0400)
committerSebastien Pouliot <sebastien@ximian.com>
Thu, 16 Sep 2010 21:32:20 +0000 (17:32 -0400)
* System/Uri.cs (Reduce): Process %2E while reducing a path. Avoid, when
possible, the creation of StringBuilder and replace ArrayList with
generics

* Test/System/UriTest2.cs: Add test case where %2e and %2E are used

mcs/class/System/System/Uri.cs
mcs/class/System/Test/System/UriTest2.cs

index d4f6e6f91c0ab1e7a8f22a400cd9b4134d29041b..c6e2c303411afa4ee84736b7dc9205ff83528340 100644 (file)
@@ -1597,6 +1597,36 @@ namespace System {
                        return false;
                }
 
+               // replace '\', %5C ('\') and %2f ('/') into '/'
+               // replace %2e ('.') into '.'
+               private static string NormalizePath (string path)
+               {
+                       StringBuilder res = new StringBuilder ();
+                       for (int i = 0; i < path.Length; i++) {
+                               char c = path [i];
+                               switch (c) {
+                               case '\\':
+                                       c = '/';
+                                       break;
+                               case '%':
+                                       if (i < path.Length - 2) {
+                                               char c1 = path [i + 1];
+                                               char c2 = Char.ToUpper (path [i + 2]);
+                                               if ((c1 == '2') && (c2 == 'E')) {
+                                                       c = '.';
+                                                       i += 2;
+                                               } else if (((c1 == '2') && (c2 == 'F')) || ((c1 == '5') && (c2 == 'C'))) {
+                                                       c = '/';
+                                                       i += 2;
+                                               }
+                                       }
+                                       break;
+                               }
+                               res.Append (c);
+                       }
+                       return res.ToString ();
+               }
+
                // This is called "compacting" in the MSDN documentation
                private static string Reduce (string path, bool compact_escaped)
                {
@@ -1604,47 +1634,22 @@ namespace System {
                        if (path == "/")
                                return path;
 
-                       StringBuilder res = new StringBuilder();
-
-                       if (compact_escaped) {
-                               // replace '\', %5C ('\') and %2f ('/') into '/'
+                       if (compact_escaped && (path.IndexOf ('%') != -1)) {
+                               // replace '\', %2f, %5c with '/' and replace %2e with '.'
                                // other escaped values seems to survive this step
-                               for (int i=0; i < path.Length; i++) {
-                                       char c = path [i];
-                                       switch (c) {
-                                       case '\\':
-                                               res.Append ('/');
-                                               break;
-                                       case '%':
-                                               if (i < path.Length - 2) {
-                                                       char c1 = path [i + 1];
-                                                       char c2 = Char.ToUpper (path [i + 2]);
-                                                       if (((c1 == '2') && (c2 == 'F')) || ((c1 == '5') && (c2 == 'C'))) {
-                                                               res.Append ('/');
-                                                               i += 2;
-                                                       } else {
-                                                               res.Append (c);
-                                                       }
-                                               } else {
-                                                       res.Append (c);
-                                               }
-                                               break;
-                                       default:
-                                               res.Append (c);
-                                               break;
-                                       }
-                               }
-                               path = res.ToString ();
+                               path = NormalizePath (path);
                        } else {
+                               // (always) replace '\' with '/'
                                path = path.Replace ('\\', '/');
                        }
 
-                       ArrayList result = new ArrayList ();
+                       List<string> result = new List<string> ();
 
                        bool begin = true;
                        for (int startpos = 0; startpos < path.Length; ) {
-                               int endpos = path.IndexOf('/', startpos);
-                               if (endpos == -1) endpos = path.Length;
+                               int endpos = path.IndexOf ('/', startpos);
+                               if (endpos == -1)
+                                       endpos = path.Length;
                                string current = path.Substring (startpos, endpos-startpos);
                                startpos = endpos + 1;
                                if ((begin && current.Length == 0) || current == "." ) {
@@ -1670,7 +1675,8 @@ namespace System {
                        if (result.Count == 0)
                                return "/";
 
-                       res.Length = 0;
+                       StringBuilder res = new StringBuilder ();
+
                        if (path [0] == '/')
                                res.Append ('/');
 
index d7851ce2dde00e015b57f32136793ddf76d938e2..8533257861b475cda309031b8181a382f4b81878 100644 (file)
@@ -869,5 +869,15 @@ TextWriter sw = Console.Out;
                        uri = new Uri ("file://host/<>%\"{}|\\^`;/?:@&=+$,[]#abc");
                        Assert.AreEqual ("/%3C%3E%25%22%7B%7D%7C/%5E%60;/%3F:@&=+$,%5B%5D", uri.AbsolutePath, "Special");
                }
+
+               [Test]
+               public void PathReduction_2e ()
+               {
+                       Uri uri = new Uri ("http://host/dir/%2e%2E/file");
+                       Assert.AreEqual ("/file", uri.AbsolutePath, "AbsolutePath");
+                       Assert.AreEqual ("http://host/file", uri.AbsoluteUri, "AbsoluteUri");
+                       Assert.AreEqual ("/", uri.Segments [0], "Segments [0]");
+                       Assert.AreEqual ("file", uri.Segments [1], "Segments [1]");
+               }
        }\r
 }\r