1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net; 18 19 import static android.util.Patterns.GOOD_IRI_CHAR; 20 21 import android.annotation.SystemApi; 22 23 import java.util.Locale; 24 import java.util.regex.Matcher; 25 import java.util.regex.Pattern; 26 27 /** 28 * {@hide} 29 * 30 * Web Address Parser 31 * 32 * This is called WebAddress, rather than URL or URI, because it 33 * attempts to parse the stuff that a user will actually type into a 34 * browser address widget. 35 * 36 * Unlike java.net.uri, this parser will not choke on URIs missing 37 * schemes. It will only throw a ParseException if the input is 38 * really hosed. 39 * 40 * If given an https scheme but no port, fills in port 41 * 42 */ 43 // TODO(igsolla): remove WebAddress from the system SDK once the WebView apk does not 44 // longer need to be binary compatible with the API 21 version of the framework. 45 @SystemApi 46 public class WebAddress { 47 48 private String mScheme; 49 private String mHost; 50 private int mPort; 51 private String mPath; 52 private String mAuthInfo; 53 54 static final int MATCH_GROUP_SCHEME = 1; 55 static final int MATCH_GROUP_AUTHORITY = 2; 56 static final int MATCH_GROUP_HOST = 3; 57 static final int MATCH_GROUP_PORT = 4; 58 static final int MATCH_GROUP_PATH = 5; 59 60 static Pattern sAddressPattern = Pattern.compile( 61 /* scheme */ "(?:(http|https|file)\\:\\/\\/)?" + 62 /* authority */ "(?:([-A-Za-z0-9$_.+!*'(),;?&=]+(?:\\:[-A-Za-z0-9$_.+!*'(),;?&=]+)?)@)?" + 63 /* host */ "([" + GOOD_IRI_CHAR + "%_-][" + GOOD_IRI_CHAR + "%_\\.-]*|\\[[0-9a-fA-F:\\.]+\\])?" + 64 /* port */ "(?:\\:([0-9]*))?" + 65 /* path */ "(\\/?[^#]*)?" + 66 /* anchor */ ".*", Pattern.CASE_INSENSITIVE); 67 68 /** parses given uriString. */ WebAddress(String address)69 public WebAddress(String address) throws ParseException { 70 if (address == null) { 71 throw new NullPointerException(); 72 } 73 74 // android.util.Log.d(LOGTAG, "WebAddress: " + address); 75 76 mScheme = ""; 77 mHost = ""; 78 mPort = -1; 79 mPath = "/"; 80 mAuthInfo = ""; 81 82 Matcher m = sAddressPattern.matcher(address); 83 String t; 84 if (m.matches()) { 85 t = m.group(MATCH_GROUP_SCHEME); 86 if (t != null) mScheme = t.toLowerCase(Locale.ROOT); 87 t = m.group(MATCH_GROUP_AUTHORITY); 88 if (t != null) mAuthInfo = t; 89 t = m.group(MATCH_GROUP_HOST); 90 if (t != null) mHost = t; 91 t = m.group(MATCH_GROUP_PORT); 92 if (t != null && t.length() > 0) { 93 // The ':' character is not returned by the regex. 94 try { 95 mPort = Integer.parseInt(t); 96 } catch (NumberFormatException ex) { 97 throw new ParseException("Bad port"); 98 } 99 } 100 t = m.group(MATCH_GROUP_PATH); 101 if (t != null && t.length() > 0) { 102 /* handle busted myspace frontpage redirect with 103 missing initial "/" */ 104 if (t.charAt(0) == '/') { 105 mPath = t; 106 } else { 107 mPath = "/" + t; 108 } 109 } 110 111 } else { 112 // nothing found... outa here 113 throw new ParseException("Bad address"); 114 } 115 116 /* Get port from scheme or scheme from port, if necessary and 117 possible */ 118 if (mPort == 443 && mScheme.equals("")) { 119 mScheme = "https"; 120 } else if (mPort == -1) { 121 if (mScheme.equals("https")) 122 mPort = 443; 123 else 124 mPort = 80; // default 125 } 126 if (mScheme.equals("")) mScheme = "http"; 127 } 128 129 @Override toString()130 public String toString() { 131 String port = ""; 132 if ((mPort != 443 && mScheme.equals("https")) || 133 (mPort != 80 && mScheme.equals("http"))) { 134 port = ":" + Integer.toString(mPort); 135 } 136 String authInfo = ""; 137 if (mAuthInfo.length() > 0) { 138 authInfo = mAuthInfo + "@"; 139 } 140 141 return mScheme + "://" + authInfo + mHost + port + mPath; 142 } 143 144 /** {@hide} */ setScheme(String scheme)145 public void setScheme(String scheme) { 146 mScheme = scheme; 147 } 148 149 /** {@hide} */ getScheme()150 public String getScheme() { 151 return mScheme; 152 } 153 154 /** {@hide} */ setHost(String host)155 public void setHost(String host) { 156 mHost = host; 157 } 158 159 /** {@hide} */ getHost()160 public String getHost() { 161 return mHost; 162 } 163 164 /** {@hide} */ setPort(int port)165 public void setPort(int port) { 166 mPort = port; 167 } 168 169 /** {@hide} */ getPort()170 public int getPort() { 171 return mPort; 172 } 173 174 /** {@hide} */ setPath(String path)175 public void setPath(String path) { 176 mPath = path; 177 } 178 179 /** {@hide} */ getPath()180 public String getPath() { 181 return mPath; 182 } 183 184 /** {@hide} */ setAuthInfo(String authInfo)185 public void setAuthInfo(String authInfo) { 186 mAuthInfo = authInfo; 187 } 188 189 /** {@hide} */ getAuthInfo()190 public String getAuthInfo() { 191 return mAuthInfo; 192 } 193 } 194