You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
4.6 KiB
172 lines
4.6 KiB
/* |
|
* Copyright 2014 A.C.R. Development |
|
*/ |
|
package acr.browser.lightning.download; |
|
|
|
import android.support.annotation.NonNull; |
|
import android.support.annotation.Nullable; |
|
|
|
import java.util.Locale; |
|
import java.util.regex.Matcher; |
|
import java.util.regex.Pattern; |
|
|
|
import static android.util.Patterns.GOOD_IRI_CHAR; |
|
|
|
/** |
|
* Web Address Parser |
|
* <p/> |
|
* This is called WebAddress, rather than URL or URI, because it attempts to |
|
* parse the stuff that a user will actually type into a browser address widget. |
|
* <p/> |
|
* Unlike java.net.uri, this parser will not choke on URIs missing schemes. It |
|
* will only throw a ParseException if the input is really hosed. |
|
* <p/> |
|
* If given an https scheme but no port, fills in port |
|
*/ |
|
class WebAddress { |
|
|
|
private String mScheme; |
|
private String mHost; |
|
private int mPort; |
|
private String mPath; |
|
private String mAuthInfo; |
|
private static final int MATCH_GROUP_SCHEME = 1; |
|
private static final int MATCH_GROUP_AUTHORITY = 2; |
|
private static final int MATCH_GROUP_HOST = 3; |
|
private static final int MATCH_GROUP_PORT = 4; |
|
private static final int MATCH_GROUP_PATH = 5; |
|
private static final 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:\\.]+\\])?" + |
|
/* port */"(?::([0-9]*))?" + |
|
/* path */"(/?[^#]*)?" + |
|
/* anchor */".*", Pattern.CASE_INSENSITIVE); |
|
|
|
/** |
|
* Parses given URI-like string. |
|
*/ |
|
public WebAddress(@Nullable String address) throws IllegalArgumentException { |
|
|
|
if (address == null) { |
|
throw new IllegalArgumentException("address can't be null"); |
|
} |
|
|
|
mScheme = ""; |
|
mHost = ""; |
|
mPort = -1; |
|
mPath = "/"; |
|
mAuthInfo = ""; |
|
|
|
Matcher m = sAddressPattern.matcher(address); |
|
String t; |
|
if (!m.matches()) { |
|
throw new IllegalArgumentException("Parsing of address '" + address + "' failed"); |
|
} |
|
|
|
t = m.group(MATCH_GROUP_SCHEME); |
|
if (t != null) { |
|
mScheme = t.toLowerCase(Locale.ROOT); |
|
} |
|
t = m.group(MATCH_GROUP_AUTHORITY); |
|
if (t != null) { |
|
mAuthInfo = t; |
|
} |
|
t = m.group(MATCH_GROUP_HOST); |
|
if (t != null) { |
|
mHost = t; |
|
} |
|
t = m.group(MATCH_GROUP_PORT); |
|
if (t != null && !t.isEmpty()) { |
|
// The ':' character is not returned by the regex. |
|
try { |
|
mPort = Integer.parseInt(t); |
|
} catch (NumberFormatException ex) { |
|
throw new RuntimeException("Parsing of port number failed", ex); |
|
} |
|
} |
|
t = m.group(MATCH_GROUP_PATH); |
|
if (t != null && !t.isEmpty()) { |
|
/* |
|
* handle busted myspace frontpage redirect with missing initial "/" |
|
*/ |
|
if (t.charAt(0) == '/') { |
|
mPath = t; |
|
} else { |
|
mPath = '/' + t; |
|
} |
|
} |
|
|
|
/* |
|
* Get port from scheme or scheme from port, if necessary and possible |
|
*/ |
|
if (mPort == 443 && mScheme != null && mScheme.isEmpty()) { |
|
mScheme = "https"; |
|
} else if (mPort == -1) { |
|
if ("https".equals(mScheme)) { |
|
mPort = 443; |
|
} else { |
|
mPort = 80; // default |
|
} |
|
} |
|
if (mScheme != null && mScheme.isEmpty()) { |
|
mScheme = "http"; |
|
} |
|
} |
|
|
|
@NonNull |
|
@Override |
|
public String toString() { |
|
|
|
String port = ""; |
|
if ((mPort != 443 && "https".equals(mScheme)) || (mPort != 80 && "http".equals(mScheme))) { |
|
port = ':' + Integer.toString(mPort); |
|
} |
|
String authInfo = ""; |
|
if (!mAuthInfo.isEmpty()) { |
|
authInfo = mAuthInfo + '@'; |
|
} |
|
|
|
return mScheme + "://" + authInfo + mHost + port + mPath; |
|
} |
|
|
|
public void setScheme(String scheme) { |
|
mScheme = scheme; |
|
} |
|
|
|
public String getScheme() { |
|
return mScheme; |
|
} |
|
|
|
public void setHost(@NonNull String host) { |
|
mHost = host; |
|
} |
|
|
|
public String getHost() { |
|
return mHost; |
|
} |
|
|
|
public void setPort(int port) { |
|
mPort = port; |
|
} |
|
|
|
public int getPort() { |
|
return mPort; |
|
} |
|
|
|
public void setPath(String path) { |
|
mPath = path; |
|
} |
|
|
|
public String getPath() { |
|
return mPath; |
|
} |
|
|
|
public void setAuthInfo(String authInfo) { |
|
mAuthInfo = authInfo; |
|
} |
|
|
|
public String getAuthInfo() { |
|
return mAuthInfo; |
|
} |
|
}
|
|
|