Title: [179933] trunk
Revision
179933
Author
[email protected]
Date
2015-02-11 10:03:42 -0800 (Wed, 11 Feb 2015)

Log Message

URL::setUser and URL::setPass don't percent encode
https://bugs.webkit.org/show_bug.cgi?id=141453
rdar://problem/14844503&16551802&19623145

Reviewed by Darin Adler.

Source/WebCore:

Tests: fast/url/url-credentials-escaping.html
       http/tests/xmlhttprequest/basic-auth-credentials-escaping.html

Start adding some code that performs escaping in a way that matches the URL Standard.
Right now, it's only used where we failed to do any escaping at all, and over time,
we'll be moving towards a new implementation.

* html/URLUtils.h:
(WebCore::URLUtils<T>::username):
(WebCore::URLUtils<T>::password):
* platform/URL.cpp:
(WebCore::isSchemeFirstChar):
(WebCore::URL::user):
(WebCore::URL::pass):
(WebCore::URL::encodedUser):
(WebCore::URL::encodedPass):
(WebCore::URL::setUser):
(WebCore::URL::setPass):
(WebCore::encodeWithURLEscapeSequences):
* platform/URL.h:

LayoutTests:

* fast/url/url-credentials-escaping-expected.txt: Added.
* fast/url/url-credentials-escaping.html: Added.
This change is most directly testable via URL API.

* http/tests/xmlhttprequest/basic-auth-credentials-escaping-expected.txt: Added.
* http/tests/xmlhttprequest/basic-auth-credentials-escaping.html: Added.
Verify that this doesn't break XMLHttpRequest authentication.

* fast/dom/DOMURL/invalid-url-getters-expected.txt: Removed.
* fast/dom/DOMURL/invalid-url-getters.html: Removed.
* fast/dom/DOMURL/url-origin-expected.txt:
* fast/dom/DOMURL/url-origin.html:
Removed tests for invalid URLs, there is no such thing with URL API.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (179932 => 179933)


--- trunk/LayoutTests/ChangeLog	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/LayoutTests/ChangeLog	2015-02-11 18:03:42 UTC (rev 179933)
@@ -1,3 +1,25 @@
+2015-02-10  Alexey Proskuryakov  <[email protected]>
+
+        URL::setUser and URL::setPass don't percent encode
+        https://bugs.webkit.org/show_bug.cgi?id=141453
+        rdar://problem/14844503&16551802&19623145
+
+        Reviewed by Darin Adler.
+
+        * fast/url/url-credentials-escaping-expected.txt: Added.
+        * fast/url/url-credentials-escaping.html: Added.
+        This change is most directly testable via URL API.
+
+        * http/tests/xmlhttprequest/basic-auth-credentials-escaping-expected.txt: Added.
+        * http/tests/xmlhttprequest/basic-auth-credentials-escaping.html: Added.
+        Verify that this doesn't break XMLHttpRequest authentication.
+
+        * fast/dom/DOMURL/invalid-url-getters-expected.txt: Removed.
+        * fast/dom/DOMURL/invalid-url-getters.html: Removed.
+        * fast/dom/DOMURL/url-origin-expected.txt:
+        * fast/dom/DOMURL/url-origin.html:
+        Removed tests for invalid URLs, there is no such thing with URL API.
+
 2015-02-11  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r179921.

Deleted: trunk/LayoutTests/fast/dom/DOMURL/invalid-url-getters-expected.txt (179932 => 179933)


--- trunk/LayoutTests/fast/dom/DOMURL/invalid-url-getters-expected.txt	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/LayoutTests/fast/dom/DOMURL/invalid-url-getters-expected.txt	2015-02-11 18:03:42 UTC (rev 179933)
@@ -1,19 +0,0 @@
-Test what getters return on an invalid URL
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS invalidURL.toString() is 'http://@@:[email protected]:22/bar?x#y'
-FAIL invalidURL.origin should be . Was null.
-PASS invalidURL.username is ''
-PASS invalidURL.password is ''
-PASS invalidURL.host is ''
-PASS invalidURL.hostname is ''
-PASS invalidURL.port is ''
-PASS invalidURL.pathname is ''
-PASS invalidURL.search is ''
-PASS invalidURL.hash is ''
-PASS successfullyParsed is true
-
-TEST COMPLETE
-

Deleted: trunk/LayoutTests/fast/dom/DOMURL/invalid-url-getters.html (179932 => 179933)


--- trunk/LayoutTests/fast/dom/DOMURL/invalid-url-getters.html	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/LayoutTests/fast/dom/DOMURL/invalid-url-getters.html	2015-02-11 18:03:42 UTC (rev 179933)
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<script src=""
-</head>
-<body>
-<script>
-
-description("Test what getters return on an invalid URL");
-
-var invalidURL = new URL("http://u:[email protected]:22/bar?x#y")
-invalidURL.username = "@@";
-
-shouldBe("invalidURL.toString()", "'http://@@:[email protected]:22/bar?x#y'");
-shouldBe("invalidURL.origin", "''");
-shouldBe("invalidURL.username", "''");
-shouldBe("invalidURL.password", "''");
-shouldBe("invalidURL.host", "''");
-shouldBe("invalidURL.hostname", "''");
-shouldBe("invalidURL.port", "''");
-shouldBe("invalidURL.pathname", "''");
-shouldBe("invalidURL.search", "''");
-shouldBe("invalidURL.hash", "''");
-
-</script>
-<script src=""
-</body>
-</html>

Modified: trunk/LayoutTests/fast/dom/DOMURL/url-origin-expected.txt (179932 => 179933)


--- trunk/LayoutTests/fast/dom/DOMURL/url-origin-expected.txt	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/LayoutTests/fast/dom/DOMURL/url-origin-expected.txt	2015-02-11 18:03:42 UTC (rev 179933)
@@ -4,5 +4,4 @@
 ftp://example.com/ttt?ggg => ftp://example.com
 file:///home/abarth => file://
 data:text/html,<b>foo</b> => null
-http://@@@www.example.com/bar => null
 

Modified: trunk/LayoutTests/fast/dom/DOMURL/url-origin.html (179932 => 179933)


--- trunk/LayoutTests/fast/dom/DOMURL/url-origin.html	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/LayoutTests/fast/dom/DOMURL/url-origin.html	2015-02-11 18:03:42 UTC (rev 179933)
@@ -5,9 +5,6 @@
 if (window.testRunner)
     testRunner.dumpAsText();
 
-var invalidURL = new URL("http://www.example.com/bar")
-invalidURL.username = "@@";
-
 var cases = [
     new URL("http://example.com/foo/bar"),
     new URL("HTTP://example.com/foo/bar"),
@@ -15,7 +12,6 @@
     new URL("ftp://example.com/ttt?ggg"),
     new URL("file:///home/abarth"),
     new URL("data:text/html,<b>foo</b>"),
-    invalidURL
 ];
 
 window._onload_ = function(e)

Added: trunk/LayoutTests/fast/url/url-credentials-escaping-expected.txt (0 => 179933)


--- trunk/LayoutTests/fast/url/url-credentials-escaping-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/url/url-credentials-escaping-expected.txt	2015-02-11 18:03:42 UTC (rev 179933)
@@ -0,0 +1,51 @@
+Test that URL username and password accessors encode/decode correctly
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Basic syntax
+PASS build('user').toString() is "http://[email protected]/"
+PASS build('user').username is "user"
+PASS build('%').toString() is "http://%@www.apple.com/"
+PASS build('%').username is "%"
+PASS build('%%').toString() is "http://%%@www.apple.com/"
+PASS build('%%').username is "%%"
+PASS build('%z').toString() is "http://%[email protected]/"
+PASS build('%z').username is "%z"
+PASS build('%61').toString() is "http://%[email protected]/"
+PASS build('%61').username is "%61"
+PASS build('%40').toString() is "http://%[email protected]/"
+PASS build('%40').username is "%40"
+
+Simple encode set
+PASS build('').toString() is "http://%[email protected]/"
+PASS build('user', '').toString() is "http://user:%[email protected]/"
+
+Default encode set additions
+PASS build(' "#><?`').toString() is "http://%20%22%23%3e%3c%[email protected]/"
+PASS build('user', ' "#><?`').toString() is "http://user:%20%22%23%3e%3c%[email protected]/"
+
+Password encode set additions
+PASS build('/@\\').toString() is "http://%2f%[email protected]/"
+PASS build('user', '/@\\').toString() is "http://user:%2f%[email protected]/"
+':' shouldn't be encoded in the password per the URL Standard, although both Firefox and Chrome encode it
+PASS build('user', ':').toString() is "http://user::@www.apple.com/"
+
+Username encode set addition
+PASS build(':').toString() is "http://%[email protected]/"
+
+8-bit
+PASS build('юзер', 'пароль').toString() is "http://%D1%8E%D0%B7%D0%B5%D1%80:%d0%bf%d0%b0%d1%80%d0%be%d0%bb%[email protected]/"
+PASS build('юзер').username is "%D1%8E%D0%B7%D0%B5%D1%80"
+PASS build('user', 'пароль').password is "%D0%BF%D0%B0%D1%80%D0%BE%D0%BB%D1%8C"
+
+Some special characters that don't get encoded when used in credentials
+PASS build('!$&*()-+~').toString() is "http://!$&*()[email protected]/"
+
+Some characters that shouldn't be encoded per the URL Standard, although both Firefox and Chrome encode them
+PASS build('^{|}[]=').toString() is "http://^{|}[][email protected]/"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Property changes on: trunk/LayoutTests/fast/url/url-credentials-escaping-expected.txt
___________________________________________________________________

Added: svn:mime-type

Added: svn:eol-style

Added: trunk/LayoutTests/fast/url/url-credentials-escaping.html (0 => 179933)


--- trunk/LayoutTests/fast/url/url-credentials-escaping.html	                        (rev 0)
+++ trunk/LayoutTests/fast/url/url-credentials-escaping.html	2015-02-11 18:03:42 UTC (rev 179933)
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+</head>
+<body>
+<script>
+
+description("Test that URL username and password accessors encode/decode correctly");
+
+function build(username, password)
+{
+    var url = "" URL("http://www.apple.com");
+    if (username)
+        url.username = username;
+    if (password)
+        url.password = password;
+    return url;
+}
+
+debug("\nBasic syntax");
+
+shouldBe("build('user').toString()", '"http://[email protected]/"');
+shouldBe("build('user').username", '"user"');
+
+shouldBe("build('%').toString()", '"http://%@www.apple.com/"');
+shouldBe("build('%').username", '"%"');
+
+shouldBe("build('%%').toString()", '"http://%%@www.apple.com/"');
+shouldBe("build('%%').username", '"%%"');
+
+shouldBe("build('%z').toString()", '"http://%[email protected]/"');
+shouldBe("build('%z').username", '"%z"');
+
+// Yes, this is weird, percent signs don't get encoded.
+shouldBe("build('%61').toString()", '"http://%[email protected]/"');
+shouldBe("build('%61').username", '"%61"');
+shouldBe("build('%40').toString()", '"http://%[email protected]/"');
+shouldBe("build('%40').username", '"%40"');
+
+debug("\nSimple encode set");
+shouldBe("build('\x07\x7f').toString()", '"http://%[email protected]/"');
+shouldBe("build('user', '\x07\x7f').toString()", '"http://user:%[email protected]/"');
+
+debug("\nDefault encode set additions");
+shouldBe("build(' \"#><?`').toString()", '"http://%20%22%23%3e%3c%[email protected]/"');
+shouldBe("build('user', ' \"#><?`').toString()", '"http://user:%20%22%23%3e%3c%[email protected]/"');
+
+debug("\nPassword encode set additions");
+shouldBe("build('/@\\\\').toString()", '"http://%2f%[email protected]/"');
+shouldBe("build('user', '/@\\\\').toString()", '"http://user:%2f%[email protected]/"');
+debug("':' shouldn't be encoded in the password per the URL Standard, although both Firefox and Chrome encode it")
+shouldBe("build('user', ':').toString()", '"http://user::@www.apple.com/"');
+
+debug("\nUsername encode set addition");
+shouldBe("build(':').toString()", '"http://%[email protected]/"');
+
+debug("\n8-bit");
+shouldBe("build('юзер', 'пароль').toString()", '"http://%D1%8E%D0%B7%D0%B5%D1%80:%d0%bf%d0%b0%d1%80%d0%be%d0%bb%[email protected]/"');
+shouldBe("build('юзер').username", '"%D1%8E%D0%B7%D0%B5%D1%80"');
+shouldBe("build('user', 'пароль').password", '"%D0%BF%D0%B0%D1%80%D0%BE%D0%BB%D1%8C"');
+
+debug("\nSome special characters that don't get encoded when used in credentials");
+shouldBe("build('!$&*()-+~').toString()", '"http://!$&*()[email protected]/"');
+
+debug("\nSome characters that shouldn't be encoded per the URL Standard, although both Firefox and Chrome encode them")
+shouldBe("build('^{|}[]=').toString()", '"http://^{|}[][email protected]/"');
+
+</script>
+</body>
+</html>
Property changes on: trunk/LayoutTests/fast/url/url-credentials-escaping.html
___________________________________________________________________

Added: svn:mime-type

Added: trunk/LayoutTests/http/tests/xmlhttprequest/basic-auth-credentials-escaping-expected.txt (0 => 179933)


--- trunk/LayoutTests/http/tests/xmlhttprequest/basic-auth-credentials-escaping-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/basic-auth-credentials-escaping-expected.txt	2015-02-11 18:03:42 UTC (rev 179933)
@@ -0,0 +1,9 @@
+Tests for XMLHttpRequest authentication.
+
+async: User: 1, password: %a%.
+async2: User: 2, password: @.
+async3: User: 3, password: @.
+async4: User: 4, password: :.
+async5: User: 5, password: .
+async6: User: 6, password: a.
+async7: User: 7, password: /@\ "#><?`.
Property changes on: trunk/LayoutTests/http/tests/xmlhttprequest/basic-auth-credentials-escaping-expected.txt
___________________________________________________________________

Added: svn:mime-type

Added: svn:eol-style

Added: trunk/LayoutTests/http/tests/xmlhttprequest/basic-auth-credentials-escaping.html (0 => 179933)


--- trunk/LayoutTests/http/tests/xmlhttprequest/basic-auth-credentials-escaping.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/basic-auth-credentials-escaping.html	2015-02-11 18:03:42 UTC (rev 179933)
@@ -0,0 +1,95 @@
+<html>
+<meta charset="utf-8">
+<body>
+<p>Tests for XMLHttpRequest authentication.
+<script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+    
+    var console_messages = document.createElement("ol");
+    document.body.appendChild(console_messages);
+    
+    function log(message)
+    {
+        var item = document.createElement("li");
+        item.appendChild(document.createTextNode(message));
+        console_messages.appendChild(item);
+    }
+
+    function sendAndLogResponse(uid, req)
+    {
+        try {
+            req.send("");
+            log(uid + ': ' + req.responseText);
+        } catch (e) {
+            log(uid + ": req.send raised exception: " + e);
+            log(uid + ": req.readyState: " + req.readyState);
+            log(uid + ": req.status: " + req.status);
+        }
+    }
+
+    // async
+    var asyncStep = 1;
+
+    req = new XMLHttpRequest;
+    req._onreadystatechange_ = processStateChange;
+    req.open("GET", "resources/basic-auth/basic-auth.php?uid=1", true, "1", "%a%");
+    req.send("");
+
+    function processStateChange() {
+    
+      if (req.readyState == 4){
+        if (req.status == 200){
+          if (asyncStep == 1) {
+            asyncStep = 2;
+            log('async: ' + req.responseText);
+            req._onreadystatechange_ = processStateChange;
+            req.open("GET", "resources/basic-auth/basic-auth.php?uid=2", true, "2", "%40");
+            req.send("");
+          } else if (asyncStep == 2) {
+            asyncStep = 3;
+            log('async2: ' + req.responseText);
+            req._onreadystatechange_ = processStateChange;
+            req.open("GET", "resources/basic-auth/basic-auth.php?uid=3", true, "3", "@");
+            req.send("");
+          } else if (asyncStep == 3) {
+            asyncStep = 4;
+            log('async3: ' + req.responseText);
+            req._onreadystatechange_ = processStateChange;
+            req.open("GET", "resources/basic-auth/basic-auth.php?uid=4", true, "4", ":");
+            req.send("");
+          } else if (asyncStep == 4) {
+            asyncStep = 5;
+            log('async4: ' + req.responseText);
+            req._onreadystatechange_ = processStateChange;
+            req.open("GET", "resources/basic-auth/basic-auth.php?uid=5", true, "5", " ");
+            req.send("");
+          } else if (asyncStep == 5) {
+            asyncStep = 6;
+            log('async5: ' + req.responseText);
+            req._onreadystatechange_ = processStateChange;
+            req.open("GET", "resources/basic-auth/basic-auth.php?uid=6", true, "6", "%61");
+            req.send("");
+          } else if (asyncStep == 6) {
+            asyncStep = 7;
+            log('async6: ' + req.responseText);
+            req._onreadystatechange_ = processStateChange;
+            req.open("GET", "resources/basic-auth/basic-auth.php?uid=7", true, "7", "/@\\ \"#><?`");
+            req.send("");
+          } else if (asyncStep == 7) {
+            log('async7: ' + req.responseText);
+            if (window.testRunner)
+              testRunner.notifyDone();
+          }
+        } else {
+            log("async" + asyncStep + " failed with unexpected status: " + req.status + ". Response: '" + req.responseText + "'.");
+            if (window.testRunner)
+              testRunner.notifyDone();
+        }
+      }
+    }
+</script>
+</body>
+</html>
Property changes on: trunk/LayoutTests/http/tests/xmlhttprequest/basic-auth-credentials-escaping.html
___________________________________________________________________

Added: svn:mime-type

Modified: trunk/Source/WebCore/ChangeLog (179932 => 179933)


--- trunk/Source/WebCore/ChangeLog	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/Source/WebCore/ChangeLog	2015-02-11 18:03:42 UTC (rev 179933)
@@ -1,3 +1,32 @@
+2015-02-10  Alexey Proskuryakov  <[email protected]>
+
+        URL::setUser and URL::setPass don't percent encode
+        https://bugs.webkit.org/show_bug.cgi?id=141453
+        rdar://problem/14844503&16551802&19623145
+
+        Reviewed by Darin Adler.
+
+        Tests: fast/url/url-credentials-escaping.html
+               http/tests/xmlhttprequest/basic-auth-credentials-escaping.html
+
+        Start adding some code that performs escaping in a way that matches the URL Standard.
+        Right now, it's only used where we failed to do any escaping at all, and over time,
+        we'll be moving towards a new implementation.
+
+        * html/URLUtils.h:
+        (WebCore::URLUtils<T>::username):
+        (WebCore::URLUtils<T>::password):
+        * platform/URL.cpp:
+        (WebCore::isSchemeFirstChar):
+        (WebCore::URL::user):
+        (WebCore::URL::pass):
+        (WebCore::URL::encodedUser):
+        (WebCore::URL::encodedPass):
+        (WebCore::URL::setUser):
+        (WebCore::URL::setPass):
+        (WebCore::encodeWithURLEscapeSequences):
+        * platform/URL.h:
+
 2015-02-11  Alex Christensen  <[email protected]>
 
         Add a few more WEBCORE_EXPORT macros for debug and iOS builds.

Modified: trunk/Source/WebCore/html/URLUtils.h (179932 => 179933)


--- trunk/Source/WebCore/html/URLUtils.h	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/Source/WebCore/html/URLUtils.h	2015-02-11 18:03:42 UTC (rev 179933)
@@ -98,7 +98,7 @@
 template <typename T>
 String URLUtils<T>::username() const
 {
-    return href().user();
+    return href().encodedUser();
 }
 
 template <typename T>
@@ -112,7 +112,7 @@
 template <typename T>
 String URLUtils<T>::password() const
 {
-    return href().pass();
+    return href().encodedPass();
 }
 
 template <typename T>

Modified: trunk/Source/WebCore/platform/URL.cpp (179932 => 179933)


--- trunk/Source/WebCore/platform/URL.cpp	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/Source/WebCore/platform/URL.cpp	2015-02-11 18:03:42 UTC (rev 179933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007, 2008, 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2007, 2008, 2011, 2012, 2013, 2015 Apple Inc. All rights reserved.
  * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -233,6 +233,108 @@
     /* 252 */ BadChar, /* 253 */ BadChar, /* 254 */ BadChar, /* 255 */ BadChar
 };
 
+enum PercentEncodeCharacterClass {
+    // Class names match the URL Standard; each class is a superset of the previous one.
+    PercentEncodeSimple = 255,
+    PercentEncodeDefault = 127,
+    PercentEncodePassword = 63,
+    PercentEncodeUsername = 31,
+};
+
+static const unsigned char percentEncodeClassTable[256] = {
+    /* 0 nul */ PercentEncodeSimple,    /* 1 soh */ PercentEncodeSimple,    /* 2 stx */ PercentEncodeSimple,    /* 3 etx */ PercentEncodeSimple,
+    /* 4 eot */ PercentEncodeSimple,    /* 5 enq */ PercentEncodeSimple,    /* 6 ack */ PercentEncodeSimple,    /* 7 bel */ PercentEncodeSimple,
+    /* 8 bs */ PercentEncodeSimple,     /* 9 ht */ PercentEncodeSimple,     /* 10 nl */ PercentEncodeSimple,    /* 11 vt */ PercentEncodeSimple,
+    /* 12 np */ PercentEncodeSimple,    /* 13 cr */ PercentEncodeSimple,    /* 14 so */ PercentEncodeSimple,    /* 15 si */ PercentEncodeSimple,
+    /* 16 dle */ PercentEncodeSimple,   /* 17 dc1 */ PercentEncodeSimple,   /* 18 dc2 */ PercentEncodeSimple,   /* 19 dc3 */ PercentEncodeSimple,
+    /* 20 dc4 */ PercentEncodeSimple,   /* 21 nak */ PercentEncodeSimple,   /* 22 syn */ PercentEncodeSimple,   /* 23 etb */ PercentEncodeSimple,
+    /* 24 can */ PercentEncodeSimple,   /* 25 em */ PercentEncodeSimple,    /* 26 sub */ PercentEncodeSimple,   /* 27 esc */ PercentEncodeSimple,
+    /* 28 fs */ PercentEncodeSimple,    /* 29 gs */ PercentEncodeSimple,    /* 30 rs */ PercentEncodeSimple,    /* 31 us */ PercentEncodeSimple,
+    /* 32 sp */ PercentEncodeDefault,
+    /* 33  ! */ 0,
+    /* 34  " */ PercentEncodeDefault,
+    /* 35  # */ PercentEncodeDefault,
+    /* 36  $ */ 0,
+    /* 37  % */ 0,
+    /* 38  & */ 0,
+    /* 39  ' */ 0,
+    /* 40  ( */ 0,
+    /* 41  ) */ 0,
+    /* 42  * */ 0,
+    /* 43  + */ 0,
+    /* 44  , */ 0,
+    /* 45  - */ 0,
+    /* 46  . */ 0,
+    /* 47  / */ PercentEncodePassword,
+    /* 48  0 */ 0,    /* 49  1 */ 0,    /* 50  2 */ 0,    /* 51  3 */ 0,
+    /* 52  4 */ 0,    /* 53  5 */ 0,    /* 54  6 */ 0,    /* 55  7 */ 0,
+    /* 56  8 */ 0,    /* 57  9 */ 0,
+    /* 58  : */ PercentEncodeUsername,
+    /* 59  ; */ 0,
+    /* 60  < */ PercentEncodeDefault,
+    /* 61  = */ 0,
+    /* 62  > */ PercentEncodeDefault,
+    /* 63  ? */ PercentEncodeDefault,
+    /* 64  @ */ PercentEncodePassword,
+    /* 65  A */ 0,    /* 66  B */ 0,    /* 67  C */ 0,    /* 68  D */ 0,
+    /* 69  E */ 0,    /* 70  F */ 0,    /* 71  G */ 0,    /* 72  H */ 0,
+    /* 73  I */ 0,    /* 74  J */ 0,    /* 75  K */ 0,    /* 76  L */ 0,
+    /* 77  M */ 0,    /* 78  N */ 0,    /* 79  O */ 0,    /* 80  P */ 0,
+    /* 81  Q */ 0,    /* 82  R */ 0,    /* 83  S */ 0,    /* 84  T */ 0,
+    /* 85  U */ 0,    /* 86  V */ 0,    /* 87  W */ 0,    /* 88  X */ 0,
+    /* 89  Y */ 0,    /* 90  Z */ 0,
+    /* 91  [ */ 0,
+    /* 92  \ */ PercentEncodePassword,
+    /* 93  ] */ 0,
+    /* 94  ^ */ 0,
+    /* 95  _ */ 0,
+    /* 96  ` */ PercentEncodeDefault,
+    /* 97  a */ 0,    /* 98  b */ 0,    /* 99  c */ 0,    /* 100  d */ 0,
+    /* 101  e */ 0,    /* 102  f */ 0,    /* 103  g */ 0,    /* 104  h */ 0,
+    /* 105  i */ 0,    /* 106  j */ 0,    /* 107  k */ 0,    /* 108  l */ 0,
+    /* 109  m */ 0,    /* 110  n */ 0,    /* 111  o */ 0,    /* 112  p */ 0,
+    /* 113  q */ 0,    /* 114  r */ 0,    /* 115  s */ 0,    /* 116  t */ 0,
+    /* 117  u */ 0,    /* 118  v */ 0,    /* 119  w */ 0,    /* 120  x */ 0,
+    /* 121  y */ 0,    /* 122  z */ 0,
+    /* 123  { */ 0,
+    /* 124  | */ 0,
+    /* 125  } */ 0,
+    /* 126  ~ */ 0,
+    /* 127 del */ PercentEncodeSimple,
+    /* 128 */ PercentEncodeSimple, /* 129 */ PercentEncodeSimple, /* 130 */ PercentEncodeSimple, /* 131 */ PercentEncodeSimple,
+    /* 132 */ PercentEncodeSimple, /* 133 */ PercentEncodeSimple, /* 134 */ PercentEncodeSimple, /* 135 */ PercentEncodeSimple,
+    /* 136 */ PercentEncodeSimple, /* 137 */ PercentEncodeSimple, /* 138 */ PercentEncodeSimple, /* 139 */ PercentEncodeSimple,
+    /* 140 */ PercentEncodeSimple, /* 141 */ PercentEncodeSimple, /* 142 */ PercentEncodeSimple, /* 143 */ PercentEncodeSimple,
+    /* 144 */ PercentEncodeSimple, /* 145 */ PercentEncodeSimple, /* 146 */ PercentEncodeSimple, /* 147 */ PercentEncodeSimple,
+    /* 148 */ PercentEncodeSimple, /* 149 */ PercentEncodeSimple, /* 150 */ PercentEncodeSimple, /* 151 */ PercentEncodeSimple,
+    /* 152 */ PercentEncodeSimple, /* 153 */ PercentEncodeSimple, /* 154 */ PercentEncodeSimple, /* 155 */ PercentEncodeSimple,
+    /* 156 */ PercentEncodeSimple, /* 157 */ PercentEncodeSimple, /* 158 */ PercentEncodeSimple, /* 159 */ PercentEncodeSimple,
+    /* 160 */ PercentEncodeSimple, /* 161 */ PercentEncodeSimple, /* 162 */ PercentEncodeSimple, /* 163 */ PercentEncodeSimple,
+    /* 164 */ PercentEncodeSimple, /* 165 */ PercentEncodeSimple, /* 166 */ PercentEncodeSimple, /* 167 */ PercentEncodeSimple,
+    /* 168 */ PercentEncodeSimple, /* 169 */ PercentEncodeSimple, /* 170 */ PercentEncodeSimple, /* 171 */ PercentEncodeSimple,
+    /* 172 */ PercentEncodeSimple, /* 173 */ PercentEncodeSimple, /* 174 */ PercentEncodeSimple, /* 175 */ PercentEncodeSimple,
+    /* 176 */ PercentEncodeSimple, /* 177 */ PercentEncodeSimple, /* 178 */ PercentEncodeSimple, /* 179 */ PercentEncodeSimple,
+    /* 180 */ PercentEncodeSimple, /* 181 */ PercentEncodeSimple, /* 182 */ PercentEncodeSimple, /* 183 */ PercentEncodeSimple,
+    /* 184 */ PercentEncodeSimple, /* 185 */ PercentEncodeSimple, /* 186 */ PercentEncodeSimple, /* 187 */ PercentEncodeSimple,
+    /* 188 */ PercentEncodeSimple, /* 189 */ PercentEncodeSimple, /* 190 */ PercentEncodeSimple, /* 191 */ PercentEncodeSimple,
+    /* 192 */ PercentEncodeSimple, /* 193 */ PercentEncodeSimple, /* 194 */ PercentEncodeSimple, /* 195 */ PercentEncodeSimple,
+    /* 196 */ PercentEncodeSimple, /* 197 */ PercentEncodeSimple, /* 198 */ PercentEncodeSimple, /* 199 */ PercentEncodeSimple,
+    /* 200 */ PercentEncodeSimple, /* 201 */ PercentEncodeSimple, /* 202 */ PercentEncodeSimple, /* 203 */ PercentEncodeSimple,
+    /* 204 */ PercentEncodeSimple, /* 205 */ PercentEncodeSimple, /* 206 */ PercentEncodeSimple, /* 207 */ PercentEncodeSimple,
+    /* 208 */ PercentEncodeSimple, /* 209 */ PercentEncodeSimple, /* 210 */ PercentEncodeSimple, /* 211 */ PercentEncodeSimple,
+    /* 212 */ PercentEncodeSimple, /* 213 */ PercentEncodeSimple, /* 214 */ PercentEncodeSimple, /* 215 */ PercentEncodeSimple,
+    /* 216 */ PercentEncodeSimple, /* 217 */ PercentEncodeSimple, /* 218 */ PercentEncodeSimple, /* 219 */ PercentEncodeSimple,
+    /* 220 */ PercentEncodeSimple, /* 221 */ PercentEncodeSimple, /* 222 */ PercentEncodeSimple, /* 223 */ PercentEncodeSimple,
+    /* 224 */ PercentEncodeSimple, /* 225 */ PercentEncodeSimple, /* 226 */ PercentEncodeSimple, /* 227 */ PercentEncodeSimple,
+    /* 228 */ PercentEncodeSimple, /* 229 */ PercentEncodeSimple, /* 230 */ PercentEncodeSimple, /* 231 */ PercentEncodeSimple,
+    /* 232 */ PercentEncodeSimple, /* 233 */ PercentEncodeSimple, /* 234 */ PercentEncodeSimple, /* 235 */ PercentEncodeSimple,
+    /* 236 */ PercentEncodeSimple, /* 237 */ PercentEncodeSimple, /* 238 */ PercentEncodeSimple, /* 239 */ PercentEncodeSimple,
+    /* 240 */ PercentEncodeSimple, /* 241 */ PercentEncodeSimple, /* 242 */ PercentEncodeSimple, /* 243 */ PercentEncodeSimple,
+    /* 244 */ PercentEncodeSimple, /* 245 */ PercentEncodeSimple, /* 246 */ PercentEncodeSimple, /* 247 */ PercentEncodeSimple,
+    /* 248 */ PercentEncodeSimple, /* 249 */ PercentEncodeSimple, /* 250 */ PercentEncodeSimple, /* 251 */ PercentEncodeSimple,
+    /* 252 */ PercentEncodeSimple, /* 253 */ PercentEncodeSimple, /* 254 */ PercentEncodeSimple, /* 255 */ PercentEncodeSimple
+};
+
 static int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd);
 static void encodeRelativeString(const String& rel, const TextEncoding&, CharBuffer& ouput);
 static String substituteBackslashes(const String&);
@@ -256,6 +358,8 @@
     return (character | 0x20) == schemeCharacter;
 }
 
+String encodeWithURLEscapeSequences(const String& notEncodedString, PercentEncodeCharacterClass whatToEncode);
+
 // Copies the source to the destination, assuming all the source characters are
 // ASCII. The destination buffer must be large enough. Null characters are allowed
 // in the source string, and no attempt is made to null-terminate the result.
@@ -598,19 +702,32 @@
     return number;
 }
 
+String URL::user() const
+{
+    return decodeURLEscapeSequences(m_string.substring(m_userStart, m_userEnd - m_userStart));
+}
+
 String URL::pass() const
 {
     if (m_passwordEnd == m_userEnd)
         return String();
 
-    return decodeURLEscapeSequences(m_string.substring(m_userEnd + 1, m_passwordEnd - m_userEnd - 1)); 
+    return decodeURLEscapeSequences(m_string.substring(m_userEnd + 1, m_passwordEnd - m_userEnd - 1));
 }
 
-String URL::user() const
+String URL::encodedUser() const
 {
-    return decodeURLEscapeSequences(m_string.substring(m_userStart, m_userEnd - m_userStart));
+    return m_string.substring(m_userStart, m_userEnd - m_userStart);
 }
 
+String URL::encodedPass() const
+{
+    if (m_passwordEnd == m_userEnd)
+        return String();
+
+    return m_string.substring(m_userEnd + 1, m_passwordEnd - m_userEnd - 1);
+}
+
 String URL::fragmentIdentifier() const
 {
     if (m_fragmentEnd == m_queryEnd)
@@ -762,7 +879,7 @@
 
     int end = m_userEnd;
     if (!user.isEmpty()) {
-        String u = user;
+        String u = encodeWithURLEscapeSequences(user, PercentEncodeUsername);
         if (m_userStart == m_schemeEnd + 1)
             u = "//" + u;
         // Add '@' if we didn't have one before.
@@ -784,12 +901,9 @@
     if (!m_isValid)
         return;
 
-    // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations,
-    // and to avoid changing more than just the user password.
-
     int end = m_passwordEnd;
     if (!password.isEmpty()) {
-        String p = ":" + password + "@";
+        String p = ":" + encodeWithURLEscapeSequences(password, PercentEncodePassword) + "@";
         if (m_userEnd == m_schemeEnd + 1)
             p = "//" + p;
         // Eat the existing '@' since we are going to add our own.
@@ -1478,6 +1592,28 @@
     return true;
 }
 
+String encodeWithURLEscapeSequences(const String& notEncodedString, PercentEncodeCharacterClass whatToEncode)
+{
+    CString asUTF8 = notEncodedString.utf8();
+
+    CharBuffer buffer(asUTF8.length() * 3 + 1);
+    char* p = buffer.data();
+
+    const char* str = asUTF8.data();
+    const char* strEnd = str + asUTF8.length();
+    while (str < strEnd) {
+        unsigned char c = *str++;
+        if (percentEncodeClassTable[c] >= whatToEncode)
+            appendEscapedChar(p, c);
+        else
+            *p++ = c;
+    }
+
+    ASSERT(p - buffer.data() <= static_cast<int>(buffer.size()));
+
+    return String(buffer.data(), p - buffer.data());
+}
+
 String encodeWithURLEscapeSequences(const String& notEncodedString)
 {
     CString asUTF8 = notEncodedString.utf8();

Modified: trunk/Source/WebCore/platform/URL.h (179932 => 179933)


--- trunk/Source/WebCore/platform/URL.h	2015-02-11 17:58:33 UTC (rev 179932)
+++ trunk/Source/WebCore/platform/URL.h	2015-02-11 18:03:42 UTC (rev 179933)
@@ -113,6 +113,11 @@
     WEBCORE_EXPORT String fragmentIdentifier() const;
     WEBCORE_EXPORT bool hasFragmentIdentifier() const;
 
+    // Unlike user() and pass(), these functions don't decode escape sequences.
+    // This is necessary for accurate round-tripping, because encoding doesn't encode '%' characters.
+    String encodedUser() const;
+    String encodedPass() const;
+
     WEBCORE_EXPORT String baseAsString() const;
 
     WEBCORE_EXPORT String fileSystemPath() const;
@@ -253,6 +258,7 @@
 WEBCORE_EXPORT String decodeURLEscapeSequences(const String&);
 String decodeURLEscapeSequences(const String&, const TextEncoding&);
 
+// FIXME: This is a wrong concept to expose, different parts of a URL need different escaping per the URL Standard.
 WEBCORE_EXPORT String encodeWithURLEscapeSequences(const String&);
 
 #if PLATFORM(IOS)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to