Reviewed by Darin.
authorap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Jul 2007 04:17:17 +0000 (04:17 +0000)
committerap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Jul 2007 04:17:17 +0000 (04:17 +0000)
        http://bugs.webkit.org/show_bug.cgi?id=14584
        XMLHttpRequest treats null login/password incorrectly

        Test: http/tests/xmlhttprequest/null-auth.php

        * xml/xmlhttprequest.cpp:
        (WebCore::XMLHttpRequest::open):
        * xml/xmlhttprequest.h:
        Split the open() method into three to distinguish between missing and null credentials.

        * bindings/js/JSXMLHttpRequest.cpp:
        (KJS::JSXMLHttpRequestPrototypeFunction::callAsFunction): Call the appropriate open().

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@24227 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/http/tests/xmlhttprequest/basic-auth.html
LayoutTests/http/tests/xmlhttprequest/null-auth-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/null-auth.php [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/resources/basic-auth/basic-auth.php [moved from LayoutTests/http/tests/xmlhttprequest/resources/basic-auth.php with 100% similarity]
LayoutTests/http/tests/xmlhttprequest/resources/echo-auth.php [new file with mode: 0644]
WebCore/ChangeLog
WebCore/bindings/js/JSXMLHttpRequest.cpp
WebCore/xml/xmlhttprequest.cpp
WebCore/xml/xmlhttprequest.h

index 5a1a92eef8009b649e18dd84f430a015282c64c3..bbc80e9724f6967e3cf16c747df20396e7bca7ec 100644 (file)
@@ -1,3 +1,21 @@
+2007-07-11  Alexey Proskuryakov  <ap@webkit.org>
+
+        Reviewed by Darin.
+
+        http://bugs.webkit.org/show_bug.cgi?id=14584
+        XMLHttpRequest treats null login/password incorrectly
+
+        * http/tests/xmlhttprequest/null-auth-expected.txt: Added.
+        * http/tests/xmlhttprequest/null-auth.php: Added.
+        * http/tests/xmlhttprequest/resources/echo-auth.php: Added.
+
+        * http/tests/xmlhttprequest/basic-auth.html:
+        * http/tests/xmlhttprequest/resources/basic-auth: Added.
+        * http/tests/xmlhttprequest/resources/basic-auth.php: Removed.
+        * http/tests/xmlhttprequest/resources/basic-auth/basic-auth.php: Copied from LayoutTests/http/tests/xmlhttprequest/resources/basic-auth.php.
+        Moved this test's protected resource to its own subdirectory, so that accessing it doesn't set
+        default credentials for the whole resources directory.
+
 2007-07-11  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Geoff.
index ef1341d938fd701389b868b1688bc17bfc99b35d..9625e033fb4169bbf5f7c4e2feb9a7ecb24ea2e9 100644 (file)
 
     // sync
     req = new XMLHttpRequest;
-    req.open("GET", "resources/basic-auth.php?uid=sync", false, "sync", "123");
+    req.open("GET", "resources/basic-auth/basic-auth.php?uid=sync", false, "sync", "123");
     req.send("");
     log('sync: ' + req.responseText);
 
-    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=sync2"), false, "sync2", "123");
+    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=sync2"), false, "sync2", "123");
     req.send("");
     log('sync2: ' + req.responseText);
 
-    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=sync3").replace("http://", "http://sync3:123@"), false);
+    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=sync3").replace("http://", "http://sync3:123@"), false);
     req.send("");
     log('sync3: ' + req.responseText);
 
-    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=sync4").replace("http://", "http://incorrect:incorrect@"), false, "sync4", "123");
+    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=sync4").replace("http://", "http://incorrect:incorrect@"), false, "sync4", "123");
     req.send("");
     log('sync4: ' + req.responseText);
 
-    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=sync5").replace("http://", "http://sync5:123@"), false, undefined, undefined);
+    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=sync5").replace("http://", "http://sync5:123@"), false, undefined, undefined);
     req.send("");
     log('sync5: ' + req.responseText);
 
-    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=sync6").replace("http://", "http://sync6:123@"), false, undefined);
+    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=sync6").replace("http://", "http://sync6:123@"), false, undefined);
     req.send("");
     log('sync6: ' + req.responseText);
 
-    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=sync7").replace("http://", "http://sync7:123@"), false, undefined, "incorrect");
+    req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=sync7").replace("http://", "http://sync7:123@"), false, undefined, "incorrect");
     req.send("");
     log('sync7: ' + req.responseText);
 
@@ -51,7 +51,7 @@
     var asyncStep = 1;
 
     req.onreadystatechange = processStateChange;
-    req.open("GET", "resources/basic-auth.php?uid=async", true, "async", "123");
+    req.open("GET", "resources/basic-auth/basic-auth.php?uid=async", true, "async", "123");
     req.send("");
 
     function processStateChange() {
             asyncStep = 2;
             log('async: ' + req.responseText);
             req.onreadystatechange = processStateChange;
-            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=async2"), true, "async2", "123");
+            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=async2"), true, "async2", "123");
             req.send("");
           } else if (asyncStep == 2) {
             asyncStep = 3;
             log('async2: ' + req.responseText);
             req.onreadystatechange = processStateChange;
-            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=async3").replace("http://", "http://async3:123@"), true, "async3", "123");
+            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=async3").replace("http://", "http://async3:123@"), true, "async3", "123");
             req.send("");
           } else if (asyncStep == 3) {
             asyncStep = 4;
             log('async3: ' + req.responseText);
             req.onreadystatechange = processStateChange;
-            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=async4").replace("http://", "http://incorrect:incorrect@"), true, "async4", "123");
+            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=async4").replace("http://", "http://incorrect:incorrect@"), true, "async4", "123");
             req.send("");
           } else if (asyncStep == 4) {
             asyncStep = 5;
             log('async4: ' + req.responseText);
             req.onreadystatechange = processStateChange;
-            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=async5").replace("http://", "http://async5:123@"), true, undefined, undefined);
+            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=async5").replace("http://", "http://async5:123@"), true, undefined, undefined);
             req.send("");
           } else if (asyncStep == 5) {
             asyncStep = 6;
             log('async5: ' + req.responseText);
             req.onreadystatechange = processStateChange;
-            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=async6").replace("http://", "http://async6:123@"), true, undefined);
+            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=async6").replace("http://", "http://async6:123@"), true, undefined);
             req.send("");
           } else if (asyncStep == 6) {
             asyncStep = 7;
             log('async6: ' + req.responseText);
             req.onreadystatechange = processStateChange;
-            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth.php?uid=async7").replace("http://", "http://async7:123@"), true, undefined, "incorrect");
+            req.open("GET", document.URL.replace("basic-auth.html", "resources/basic-auth/basic-auth.php?uid=async7").replace("http://", "http://async7:123@"), true, undefined, "incorrect");
             req.send("");
           } else if (asyncStep == 7) {
             log('async7: ' + req.responseText);
diff --git a/LayoutTests/http/tests/xmlhttprequest/null-auth-expected.txt b/LayoutTests/http/tests/xmlhttprequest/null-auth-expected.txt
new file mode 100644 (file)
index 0000000..5a62485
--- /dev/null
@@ -0,0 +1,5 @@
+Test that null values in XHR login/password parameters are treated correctly.
+
+No auth tokens should be sent with this request.
+
+No authentication
diff --git a/LayoutTests/http/tests/xmlhttprequest/null-auth.php b/LayoutTests/http/tests/xmlhttprequest/null-auth.php
new file mode 100644 (file)
index 0000000..3f32c70
--- /dev/null
@@ -0,0 +1,12 @@
+<p>Test that null values in XHR login/password parameters are treated correctly.</p>
+<p>No auth tokens should be sent with this request.</p>
+<pre id='syncResult'> </pre>
+<script>
+if (window.layoutTestController)
+  layoutTestController.dumpAsText();
+
+req = new XMLHttpRequest;
+req.open('POST', '<?php echo 'http://foo:bar@' . $_SERVER['HTTP_HOST'] . '/xmlhttprequest/resources/echo-auth.php' ?>', false, null, null);
+req.send();
+document.getElementById('syncResult').firstChild.nodeValue = req.responseText;
+</script>
diff --git a/LayoutTests/http/tests/xmlhttprequest/resources/echo-auth.php b/LayoutTests/http/tests/xmlhttprequest/resources/echo-auth.php
new file mode 100644 (file)
index 0000000..32013b4
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+  if (!isset($_SERVER['PHP_AUTH_USER'])) {
+   echo 'No authentication';
+  } else {
+   echo "User: {$_SERVER['PHP_AUTH_USER']}, password: {$_SERVER['PHP_AUTH_PW']}.";
+  }
+?>
index 0020faae4b41751e3968241c2918008f83d0c29e..f3bcd6aead7c9a12f9bcaf9040dcdadfb3a196e0 100644 (file)
@@ -1,3 +1,20 @@
+2007-07-11  Alexey Proskuryakov  <ap@webkit.org>
+
+        Reviewed by Darin.
+
+        http://bugs.webkit.org/show_bug.cgi?id=14584
+        XMLHttpRequest treats null login/password incorrectly
+
+        Test: http/tests/xmlhttprequest/null-auth.php
+
+        * xml/xmlhttprequest.cpp:
+        (WebCore::XMLHttpRequest::open):
+        * xml/xmlhttprequest.h:
+        Split the open() method into three to distinguish between missing and null credentials.
+
+        * bindings/js/JSXMLHttpRequest.cpp:
+        (KJS::JSXMLHttpRequestPrototypeFunction::callAsFunction): Call the appropriate open().
+
 2007-07-11  Oliver Hunt  <oliver@apple.com>
 
         Build fix for windows
index 735210dbb23d5a8c5c67e9b7c559b1baecb40576..4d42db97213ab4f1816ca1ac3a603e06aee8730a 100644 (file)
@@ -224,18 +224,18 @@ JSValue* JSXMLHttpRequestPrototypeFunction::callAsFunction(ExecState* exec, JSOb
             if (args.size() >= 3)
                 async = args[2]->toBoolean(exec);
 
-            String user;
-            String password;
             if (args.size() >= 4 && !args[3]->isUndefined()) {
-                user = args[3]->toString(exec);
+                String user = valueToStringWithNullCheck(exec, args[3]);
 
-                if (args.size() >= 5 && !args[4]->isUndefined())
-                    password = args[4]->toString(exec);
-            }
+                if (args.size() >= 5 && !args[4]->isUndefined()) {
+                    String password = valueToStringWithNullCheck(exec, args[4]);
+                    request->m_impl->open(method, url, async, user, password, ec);
+                } else
+                    request->m_impl->open(method, url, async, user, ec);
+            } else
+                request->m_impl->open(method, url, async, ec);
 
-            request->m_impl->open(method, url, async, user, password, ec);
             setDOMException(exec, ec);
-
             return jsUndefined();
         }
         case JSXMLHttpRequest::Send: {
index 492025de24d422dd0efa25c352dc80e387462c33..cd3e68fd1c5cd24fa6e9ecc30a911e494a69b74f 100644 (file)
@@ -371,7 +371,7 @@ bool XMLHttpRequest::urlMatchesDocumentDomain(const KURL& url) const
     return false;
 }
 
-void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, const String& password, ExceptionCode& ec)
+void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionCode& ec)
 {
     abort();
     m_aborted = false;
@@ -397,12 +397,6 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, con
     
     m_url = url;
 
-    if (!user.isNull())
-        m_url.setUser(user.deprecatedString());
-
-    if (!password.isNull())
-        m_url.setPass(password.deprecatedString());
-
     // Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same.
     String methodUpper(method.upper());
     if (methodUpper == "CONNECT" || methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD"
@@ -418,6 +412,23 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, con
     changeState(Open);
 }
 
+void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, ExceptionCode& ec)
+{
+    KURL urlWithCredentials(url);
+    urlWithCredentials.setUser(user.deprecatedString());
+    
+    open(method, urlWithCredentials, async, ec);
+}
+
+void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, const String& password, ExceptionCode& ec)
+{
+    KURL urlWithCredentials(url);
+    urlWithCredentials.setUser(user.deprecatedString());
+    urlWithCredentials.setPass(password.deprecatedString());
+    
+    open(method, urlWithCredentials, async, ec);
+}
+
 void XMLHttpRequest::send(const String& body, ExceptionCode& ec)
 {
     if (!m_doc)
index 19542bb101b78f8ed515e1acf5b70eb334b5748e..fcc2dcfd0be069ae46727b01ec3b5aaf92cded1a 100644 (file)
@@ -72,7 +72,9 @@ public:
     String getStatusText(ExceptionCode&) const;
     int getStatus(ExceptionCode&) const;
     XMLHttpRequestState getReadyState() const;
-    void open(const String& method, const KURL& url, bool async, const String& user, const String& password, ExceptionCode& ec);
+    void open(const String& method, const KURL&, bool async, ExceptionCode&);
+    void open(const String& method, const KURL&, bool async, const String& user, ExceptionCode&);
+    void open(const String& method, const KURL&, bool async, const String& user, const String& password, ExceptionCode&);
     void send(const String& body, ExceptionCode&);
     void abort();
     void setRequestHeader(const String& name, const String& value, ExceptionCode&);