<http://webkit.org/b/36878> REGRESSION: Trailing colon on hostnames (with no port specified) causes "Not allowed to use restricted network port"

Reviewed by Darin Adler.

WebCore:

* platform/KURL.cpp:
(WebCore::KURL::port): Explicitly handle the case of a colon being present in the URL after the host name but with
no port number before the path.  This is handled in the same manner as the colon and port being omitted completely.

LayoutTests:

Add explicit tests for handling of allowed ports.  We currently only test the ports that map to port 80: 0, 80, and "".

* platform/mac/security/block-test-expected.txt:
* security/block-test.html:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@56879 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 5cf3728..f50336a 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2010-03-31  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Darin Adler.
+
+        <http://webkit.org/b/36878> REGRESSION: Trailing colon on hostnames (with no port specified) causes "Not allowed to use restricted network port"
+
+        Add explicit tests for handling of allowed ports.  We currently only test the ports that map to port 80: 0, 80, and "".
+
+        * platform/mac/security/block-test-expected.txt:
+        * security/block-test.html:
+
 2010-03-31  Andrew Scherkus  <scherkus@chromium.org>
 
         Reviewed by Dmitry Titov.
diff --git a/LayoutTests/platform/mac/security/block-test-expected.txt b/LayoutTests/platform/mac/security/block-test-expected.txt
index 883b4b8..56a5de2 100644
--- a/LayoutTests/platform/mac/security/block-test-expected.txt
+++ b/LayoutTests/platform/mac/security/block-test-expected.txt
@@ -135,6 +135,12 @@
 http://255.255.255.255:4294967295/test.jpg - didFailLoadingWithError: <NSError domain WebKitErrorDomain, code 103, failing URL "http://255.255.255.255:4294967295/test.jpg">
 http://255.255.255.255:4294967296/test.jpg - willSendRequest <NSURLRequest URL http://255.255.255.255:4294967296/test.jpg, main document URL block-test.html, http method GET> redirectResponse (null)
 http://255.255.255.255:4294967296/test.jpg - didFailLoadingWithError: <NSError domain WebKitErrorDomain, code 103, failing URL "http://255.255.255.255:4294967296/test.jpg">
+http://255.255.255.255:0/test.jpg - willSendRequest <NSURLRequest URL http://255.255.255.255:0/test.jpg, main document URL block-test.html, http method GET> redirectResponse (null)
+http://255.255.255.255:0/test.jpg - didFailLoadingWithError: <NSError domain NSURLErrorDomain, code -1004, failing URL "http://255.255.255.255:0/test.jpg">
+http://255.255.255.255:80/test.jpg - willSendRequest <NSURLRequest URL http://255.255.255.255:80/test.jpg, main document URL block-test.html, http method GET> redirectResponse (null)
+http://255.255.255.255:80/test.jpg - didFailLoadingWithError: <NSError domain NSURLErrorDomain, code -1004, failing URL "http://255.255.255.255:80/test.jpg">
+http://255.255.255.255:/test.jpg - willSendRequest <NSURLRequest URL http://255.255.255.255:/test.jpg, main document URL block-test.html, http method GET> redirectResponse (null)
+http://255.255.255.255:/test.jpg - didFailLoadingWithError: <NSError domain NSURLErrorDomain, code -1004, failing URL "http://255.255.255.255:/test.jpg">
 ftp://255.255.255.255/test.jpg - willSendRequest <NSURLRequest URL ftp://255.255.255.255/test.jpg, main document URL block-test.html, http method GET> redirectResponse (null)
 ftp://255.255.255.255/test.jpg - didFailLoadingWithError: <NSError domain NSURLErrorDomain, code -1, failing URL "ftp://255.255.255.255/test.jpg">
 ftp://255.255.255.255:21/test.jpg - willSendRequest <NSURLRequest URL ftp://255.255.255.255:21/test.jpg, main document URL block-test.html, http method GET> redirectResponse (null)
diff --git a/LayoutTests/security/block-test.html b/LayoutTests/security/block-test.html
index 1b338eb..ad411a7 100644
--- a/LayoutTests/security/block-test.html
+++ b/LayoutTests/security/block-test.html
@@ -1,7 +1,7 @@
 <html>
 <script>
     // Note that port "1" is tested by the initial load.
-    var blockedPorts = new Array(7, 9, 11, 13, 15, 17, 19, 20,
+    var blockedPorts = [7, 9, 11, 13, 15, 17, 19, 20,
       21, 22, 23, 25, 37, 42, 43, 53, 77, 79, 87, 95, 101, 102,
       103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 139,
       143, 179, 389, 465, 512, 513, 514, 515, 526, 530, 531, 532,
@@ -9,47 +9,58 @@
       6000, 6665, 6666, 6667, 6668, 6669,
 
       // Port numbers that we consider to be invalid due to being out of range.
-      Math.pow(2, 16) - 1, Math.pow(2, 16), Math.pow(2, 32) - 1, Math.pow(2, 32),
+      Math.pow(2, 16) - 1, Math.pow(2, 16), Math.pow(2, 32) - 1, Math.pow(2, 32)];
 
-      // A port number of 0 indicates to nextTest that it should test the FTP exemptions.
-      0);
-    
+    var allowedPorts = [0, 80, ""];
+
     var baseURL = "255.255.255.255";
     var currentPort = 0;
-    
+
     if (window.layoutTestController) {
         layoutTestController.waitUntilDone();
         layoutTestController.dumpResourceLoadCallbacks();
     }
-        
-    function nextTest() {
-        if (!blockedPorts[currentPort]) {
-            ftpTest();
+
+    function nextBlockedPortTest() {
+        if (!(currentPort in blockedPorts)) {
+            currentPort = 0;
+            nextAllowedPortTest();
             return;
         }
         var newURL = "http://" + baseURL + ":" + blockedPorts[currentPort] + "/test.jpg";
         currentPort++;
         testIMG.src = newURL;
     }
-    
+
+    function nextAllowedPortTest() {
+        if (!(currentPort in allowedPorts)) {
+            ftpTest();
+            return;
+        }
+        var newURL = "http://" + baseURL + ":" + allowedPorts[currentPort] + "/test.jpg";
+        currentPort++;
+        testIMG.setAttribute("onError", "nextAllowedPortTest();");
+        testIMG.src = newURL;
+    }
+
     function ftpTest() {
         testIMG.setAttribute("onError", "ftp21Test();");
         var newURL = "ftp://" + baseURL + "/test.jpg";
         testIMG.src = newURL;
     }
-    
+
     function ftp21Test() {
         testIMG.setAttribute("onError", "ftp22Test();");
         var newURL = "ftp://" + baseURL + ":21/test.jpg";
         testIMG.src = newURL;
     }
-    
+
     function ftp22Test() {
         testIMG.setAttribute("onError", "finishTesting();");
         var newURL = "ftp://" + baseURL + ":22/test.jpg";
         testIMG.src = newURL;
     }
-    
+
     function finishTesting() {
         if (window.layoutTestController) {
             layoutTestController.dumpAsText();
@@ -62,6 +73,6 @@
 correct error for them - blocked instead of cannot find.  It also tries the FTP ports for exemptions.  Due to the 
 nature of this test, the results can only be processed automatically via DumpRenderTree
 </p>
-<img id="testIMG" src="http://255.255.255.255:1/test.jpg" onError="nextTest();"></img>
+<img id="testIMG" src="http://255.255.255.255:1/test.jpg" onError="nextBlockedPortTest();"></img>
 </body>
 </html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 7de2a9c..ca3719e 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,13 @@
+2010-03-31  Mark Rowe  <mrowe@apple.com>
+
+        Reviewed by Darin Adler.
+
+        <http://webkit.org/b/36878> REGRESSION: Trailing colon on hostnames (with no port specified) causes "Not allowed to use restricted network port"
+
+        * platform/KURL.cpp:
+        (WebCore::KURL::port): Explicitly handle the case of a colon being present in the URL after the host name but with
+        no port number before the path.  This is handled in the same manner as the colon and port being omitted completely.
+
 2010-03-31  Gavin Barraclough  <barraclough@apple.com>
 
         Reviewed by Oliver Hunt.
diff --git a/WebCore/platform/KURL.cpp b/WebCore/platform/KURL.cpp
index 052067f..12ba4a2 100644
--- a/WebCore/platform/KURL.cpp
+++ b/WebCore/platform/KURL.cpp
@@ -576,7 +576,10 @@
 
 unsigned short KURL::port() const
 {
-    if (m_hostEnd == m_portEnd)
+    // We return a port of 0 if there is no port specified. This can happen in two situations:
+    // 1) The URL contains no colon after the host name and before the path component of the URL.
+    // 2) The URL contains a colon but there's no port number before the path component of the URL begins.
+    if (m_hostEnd == m_portEnd || m_hostEnd == m_portEnd - 1)
         return 0;
 
     const UChar* stringData = m_string.characters();