Fixes a problem with URL parsing when the host ends with a dot

The WebAddress class provides a lenient parser for URLs. Currently, it
identifies the host portion with the regex [<chars>]+(\.[<chars>]+)* where
<chars> is the set of characters valid for the host name. This pattern excludes
the case where the host ends with a dot, which is valid possibility. As a
result, any trailing dot is pushed into the path component. Since we add a
leading slash to the path if one is missing, the result is a path that begins
with '/.'.

This fix changes the host regex to [<chars>]+[<chars>\.]* which allows trailing
dots and fixes the problem.

Bug: 2337042
Change-Id: I310512531787e0f742988f5d815ad944fd39e059
diff --git a/core/java/android/net/WebAddress.java b/core/java/android/net/WebAddress.java
index 4101ab4..9c4d6e8 100644
--- a/core/java/android/net/WebAddress.java
+++ b/core/java/android/net/WebAddress.java
@@ -56,7 +56,7 @@
     static Pattern sAddressPattern = Pattern.compile(
             /* scheme    */ "(?:(http|https|file)\\:\\/\\/)?" +
             /* authority */ "(?:([-A-Za-z0-9$_.+!*'(),;?&=]+(?:\\:[-A-Za-z0-9$_.+!*'(),;?&=]+)?)@)?" +
-            /* host      */ "([-" + GOOD_IRI_CHAR + "%_]+(?:\\.[-" + GOOD_IRI_CHAR + "%_]+)*|\\[[0-9a-fA-F:\\.]+\\])?" +
+            /* host      */ "([" + GOOD_IRI_CHAR + "%_-][" + GOOD_IRI_CHAR + "%_\\.-]*|\\[[0-9a-fA-F:\\.]+\\])?" +
             /* port      */ "(?:\\:([0-9]*))?" +
             /* path      */ "(\\/?[^#]*)?" +
             /* anchor    */ ".*", Pattern.CASE_INSENSITIVE);
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index fe608b5..60c3c76 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -286,6 +286,13 @@
     }
 
     @SmallTest
+    public void testHostWithTrailingDot() {
+        Uri uri = Uri.parse("http://google.com./b/c/g");
+        assertEquals("google.com.", uri.getHost());
+        assertEquals("/b/c/g", uri.getPath());
+    }
+
+    @SmallTest
     public void testSchemeOnly() {
         Uri uri = Uri.parse("empty:");
         assertEquals("empty", uri.getScheme());
diff --git a/core/tests/coretests/src/android/net/WebAddressTest.java b/core/tests/coretests/src/android/net/WebAddressTest.java
new file mode 100644
index 0000000..7ca1e62
--- /dev/null
+++ b/core/tests/coretests/src/android/net/WebAddressTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.WebAddress;
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+public class WebAddressTest extends TestCase {
+
+    @SmallTest
+    public void testHostWithTrailingDot() {
+        WebAddress webAddress = new WebAddress("http://google.com./b/c/g");
+        assertEquals("google.com.", webAddress.mHost);
+        assertEquals("/b/c/g", webAddress.mPath);
+    }
+}