19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.net; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport static android.util.Patterns.GOOD_IRI_CHAR; 2051c02dbf75fede9b2829af5b821f10e0bc2af124Shimeng (Simon) Wang 21451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Sollaimport android.annotation.SystemApi; 22451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla 23cb64d430627b71221c588ef5f23599dd34a89ee9Elliott Hughesimport java.util.Locale; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Matcher; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Pattern; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Web Address Parser 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is called WebAddress, rather than URL or URI, because it 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * attempts to parse the stuff that a user will actually type into a 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * browser address widget. 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unlike java.net.uri, this parser will not choke on URIs missing 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * schemes. It will only throw a ParseException if the input is 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * really hosed. 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If given an https scheme but no port, fills in port 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 43451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla// TODO(igsolla): remove WebAddress from the system SDK once the WebView apk does not 44451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla// longer need to be binary compatible with the API 21 version of the framework. 45451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla@SystemApi 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class WebAddress { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 48eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert private String mScheme; 49eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert private String mHost; 50eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert private int mPort; 51eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert private String mPath; 52eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert private String mAuthInfo; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int MATCH_GROUP_SCHEME = 1; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int MATCH_GROUP_AUTHORITY = 2; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int MATCH_GROUP_HOST = 3; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int MATCH_GROUP_PORT = 4; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int MATCH_GROUP_PATH = 5; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static Pattern sAddressPattern = Pattern.compile( 619253446922d925f6a5453b60d539beed292921a7Patrick Scott /* scheme */ "(?:(http|https|file)\\:\\/\\/)?" + 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* authority */ "(?:([-A-Za-z0-9$_.+!*'(),;?&=]+(?:\\:[-A-Za-z0-9$_.+!*'(),;?&=]+)?)@)?" + 63582deec1f3c8f51b431bb2ad685c9217ffd9eaadSteve Block /* host */ "([" + GOOD_IRI_CHAR + "%_-][" + GOOD_IRI_CHAR + "%_\\.-]*|\\[[0-9a-fA-F:\\.]+\\])?" + 642257440f4b261cfc3251a6fc0f3cbd1fa1e548b1Steve Block /* port */ "(?:\\:([0-9]*))?" + 65fa4039e4fc680920bc53528c4a76e09210f1dcd6Patrick Scott /* path */ "(\\/?[^#]*)?" + 669253446922d925f6a5453b60d539beed292921a7Patrick Scott /* anchor */ ".*", Pattern.CASE_INSENSITIVE); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** parses given uriString. */ 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public WebAddress(String address) throws ParseException { 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (address == null) { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new NullPointerException(); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // android.util.Log.d(LOGTAG, "WebAddress: " + address); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScheme = ""; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHost = ""; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPort = -1; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPath = "/"; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAuthInfo = ""; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Matcher m = sAddressPattern.matcher(address); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String t; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (m.matches()) { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t = m.group(MATCH_GROUP_SCHEME); 86cb64d430627b71221c588ef5f23599dd34a89ee9Elliott Hughes if (t != null) mScheme = t.toLowerCase(Locale.ROOT); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t = m.group(MATCH_GROUP_AUTHORITY); 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t != null) mAuthInfo = t; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t = m.group(MATCH_GROUP_HOST); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t != null) mHost = t; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t = m.group(MATCH_GROUP_PORT); 922257440f4b261cfc3251a6fc0f3cbd1fa1e548b1Steve Block if (t != null && t.length() > 0) { 932257440f4b261cfc3251a6fc0f3cbd1fa1e548b1Steve Block // The ':' character is not returned by the regex. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPort = Integer.parseInt(t); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException ex) { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ParseException("Bad port"); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t = m.group(MATCH_GROUP_PATH); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t != null && t.length() > 0) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* handle busted myspace frontpage redirect with 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project missing initial "/" */ 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t.charAt(0) == '/') { 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPath = t; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPath = "/" + t; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // nothing found... outa here 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ParseException("Bad address"); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Get port from scheme or scheme from port, if necessary and 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project possible */ 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPort == 443 && mScheme.equals("")) { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mScheme = "https"; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mPort == -1) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mScheme.equals("https")) 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPort = 443; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPort = 80; // default 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mScheme.equals("")) mScheme = "http"; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 129eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert @Override 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String port = ""; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mPort != 443 && mScheme.equals("https")) || 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (mPort != 80 && mScheme.equals("http"))) { 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project port = ":" + Integer.toString(mPort); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String authInfo = ""; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAuthInfo.length() > 0) { 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project authInfo = mAuthInfo + "@"; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mScheme + "://" + authInfo + mHost + port + mPath; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 143eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 144451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 145eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public void setScheme(String scheme) { 146eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert mScheme = scheme; 147eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 148eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 149451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 150eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public String getScheme() { 151eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert return mScheme; 152eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 153eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 154451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 155eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public void setHost(String host) { 156eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert mHost = host; 157eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 158eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 159451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 160eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public String getHost() { 161eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert return mHost; 162eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 163eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 164451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 165eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public void setPort(int port) { 166eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert mPort = port; 167eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 168eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 169451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 170eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public int getPort() { 171eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert return mPort; 172eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 173eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 174451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 175eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public void setPath(String path) { 176eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert mPath = path; 177eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 178eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 179451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 180eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public String getPath() { 181eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert return mPath; 182eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 183eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 184451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 185eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public void setAuthInfo(String authInfo) { 186eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert mAuthInfo = authInfo; 187eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 188eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert 189451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla /** {@hide} */ 190eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert public String getAuthInfo() { 191eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert return mAuthInfo; 192eb8be973c7982fe3ece0aeaeca379c3b3cdced0cBjorn Bringert } 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 194