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.compatibility; 18 19 import static android.util.Patterns.GOOD_IRI_CHAR; 20 21 import java.util.Locale; 22 import java.util.regex.Matcher; 23 import java.util.regex.Pattern; 24 25 /** 26 * Web Address Parser 27 * 28 * This is called WebAddress, rather than URL or URI, because it 29 * attempts to parse the stuff that a user will actually type into a 30 * browser address widget. 31 * 32 * Unlike java.net.uri, this parser will not choke on URIs missing 33 * schemes. It will only throw a IllegalArgumentException if the input is 34 * really hosed. 35 * 36 * If given an https scheme but no port, fills in port 37 * 38 */ 39 public class WebAddress { 40 41 private String mScheme; 42 private String mHost; 43 private int mPort; 44 private String mPath; 45 private String mAuthInfo; 46 47 static final int MATCH_GROUP_SCHEME = 1; 48 static final int MATCH_GROUP_AUTHORITY = 2; 49 static final int MATCH_GROUP_HOST = 3; 50 static final int MATCH_GROUP_PORT = 4; 51 static final int MATCH_GROUP_PATH = 5; 52 53 static Pattern sAddressPattern = Pattern.compile( 54 /* scheme */ "(?:(http|https|file)\\:\\/\\/)?" + 55 /* authority */ "(?:([-A-Za-z0-9$_.+!*'(),;?&=]+(?:\\:[-A-Za-z0-9$_.+!*'(),;?&=]+)?)@)?" + 56 /* host */ "([" + GOOD_IRI_CHAR + "%_-][" + GOOD_IRI_CHAR + "%_\\.-]*|\\[[0-9a-fA-F:\\.]+\\])?" + 57 /* port */ "(?:\\:([0-9]*))?" + 58 /* path */ "(\\/?[^#]*)?" + 59 /* anchor */ ".*", Pattern.CASE_INSENSITIVE); 60 61 /** parses given uriString. */ WebAddress(String address)62 public WebAddress(String address) throws IllegalArgumentException { 63 if (address == null) { 64 throw new NullPointerException(); 65 } 66 67 // android.util.Log.d(LOGTAG, "WebAddress: " + address); 68 69 mScheme = ""; 70 mHost = ""; 71 mPort = -1; 72 mPath = "/"; 73 mAuthInfo = ""; 74 75 Matcher m = sAddressPattern.matcher(address); 76 String t; 77 if (m.matches()) { 78 t = m.group(MATCH_GROUP_SCHEME); 79 if (t != null) mScheme = t.toLowerCase(Locale.ROOT); 80 t = m.group(MATCH_GROUP_AUTHORITY); 81 if (t != null) mAuthInfo = t; 82 t = m.group(MATCH_GROUP_HOST); 83 if (t != null) mHost = t; 84 t = m.group(MATCH_GROUP_PORT); 85 if (t != null && t.length() > 0) { 86 // The ':' character is not returned by the regex. 87 try { 88 mPort = Integer.parseInt(t); 89 } catch (NumberFormatException ex) { 90 throw new IllegalArgumentException("Bad port"); 91 } 92 } 93 t = m.group(MATCH_GROUP_PATH); 94 if (t != null && t.length() > 0) { 95 /* handle busted myspace frontpage redirect with 96 missing initial "/" */ 97 if (t.charAt(0) == '/') { 98 mPath = t; 99 } else { 100 mPath = "/" + t; 101 } 102 } 103 104 } else { 105 // nothing found... outa here 106 throw new IllegalArgumentException("Bad address"); 107 } 108 109 /* Get port from scheme or scheme from port, if necessary and 110 possible */ 111 if (mPort == 443 && mScheme.equals("")) { 112 mScheme = "https"; 113 } else if (mPort == -1) { 114 if (mScheme.equals("https")) 115 mPort = 443; 116 else 117 mPort = 80; // default 118 } 119 if (mScheme.equals("")) mScheme = "http"; 120 } 121 122 @Override toString()123 public String toString() { 124 String port = ""; 125 if ((mPort != 443 && mScheme.equals("https")) || 126 (mPort != 80 && mScheme.equals("http"))) { 127 port = ":" + Integer.toString(mPort); 128 } 129 String authInfo = ""; 130 if (mAuthInfo.length() > 0) { 131 authInfo = mAuthInfo + "@"; 132 } 133 134 return mScheme + "://" + authInfo + mHost + port + mPath; 135 } 136 setScheme(String scheme)137 public void setScheme(String scheme) { 138 mScheme = scheme; 139 } 140 getScheme()141 public String getScheme() { 142 return mScheme; 143 } 144 setHost(String host)145 public void setHost(String host) { 146 mHost = host; 147 } 148 getHost()149 public String getHost() { 150 return mHost; 151 } 152 setPort(int port)153 public void setPort(int port) { 154 mPort = port; 155 } 156 getPort()157 public int getPort() { 158 return mPort; 159 } 160 setPath(String path)161 public void setPath(String path) { 162 mPath = path; 163 } 164 getPath()165 public String getPath() { 166 return mPath; 167 } 168 setAuthInfo(String authInfo)169 public void setAuthInfo(String authInfo) { 170 mAuthInfo = authInfo; 171 } 172 getAuthInfo()173 public String getAuthInfo() { 174 return mAuthInfo; 175 } 176 } 177