try new-method
This commit is contained in:
parent
78237d9c80
commit
52b4651f1a
3812 changed files with 228702 additions and 223704 deletions
158
src/com/google/common/net/HostAndPort.java
Normal file
158
src/com/google/common/net/HostAndPort.java
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.net;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Beta
|
||||
@Immutable
|
||||
@GwtCompatible
|
||||
public final class HostAndPort
|
||||
implements Serializable {
|
||||
private static final int NO_PORT = -1;
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final boolean hasBracketlessColons;
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private HostAndPort(String host, int port, boolean hasBracketlessColons) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.hasBracketlessColons = hasBracketlessColons;
|
||||
}
|
||||
|
||||
public String getHostText() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
public boolean hasPort() {
|
||||
return this.port >= 0;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
Preconditions.checkState(this.hasPort());
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public int getPortOrDefault(int defaultPort) {
|
||||
return this.hasPort() ? this.port : defaultPort;
|
||||
}
|
||||
|
||||
public static HostAndPort fromParts(String host, int port) {
|
||||
Preconditions.checkArgument(HostAndPort.isValidPort(port), "Port out of range: %s", port);
|
||||
HostAndPort parsedHost = HostAndPort.fromString(host);
|
||||
Preconditions.checkArgument(!parsedHost.hasPort(), "Host has a port: %s", host);
|
||||
return new HostAndPort(parsedHost.host, port, parsedHost.hasBracketlessColons);
|
||||
}
|
||||
|
||||
public static HostAndPort fromHost(String host) {
|
||||
HostAndPort parsedHost = HostAndPort.fromString(host);
|
||||
Preconditions.checkArgument(!parsedHost.hasPort(), "Host has a port: %s", host);
|
||||
return parsedHost;
|
||||
}
|
||||
|
||||
public static HostAndPort fromString(String hostPortString) {
|
||||
String host;
|
||||
Preconditions.checkNotNull(hostPortString);
|
||||
String portString = null;
|
||||
boolean hasBracketlessColons = false;
|
||||
if (hostPortString.startsWith("[")) {
|
||||
String[] hostAndPort = HostAndPort.getHostAndPortFromBracketedHost(hostPortString);
|
||||
host = hostAndPort[0];
|
||||
portString = hostAndPort[1];
|
||||
} else {
|
||||
int colonPos = hostPortString.indexOf(58);
|
||||
if (colonPos >= 0 && hostPortString.indexOf(58, colonPos + 1) == -1) {
|
||||
host = hostPortString.substring(0, colonPos);
|
||||
portString = hostPortString.substring(colonPos + 1);
|
||||
} else {
|
||||
host = hostPortString;
|
||||
hasBracketlessColons = colonPos >= 0;
|
||||
}
|
||||
}
|
||||
int port = -1;
|
||||
if (!Strings.isNullOrEmpty(portString)) {
|
||||
Preconditions.checkArgument(!portString.startsWith("+"), "Unparseable port number: %s", hostPortString);
|
||||
try {
|
||||
port = Integer.parseInt(portString);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
String string = String.valueOf(hostPortString);
|
||||
throw new IllegalArgumentException(string.length() != 0 ? "Unparseable port number: ".concat(string) : new String("Unparseable port number: "));
|
||||
}
|
||||
Preconditions.checkArgument(HostAndPort.isValidPort(port), "Port number out of range: %s", hostPortString);
|
||||
}
|
||||
return new HostAndPort(host, port, hasBracketlessColons);
|
||||
}
|
||||
|
||||
private static String[] getHostAndPortFromBracketedHost(String hostPortString) {
|
||||
int colonIndex = 0;
|
||||
int closeBracketIndex = 0;
|
||||
Preconditions.checkArgument(hostPortString.charAt(0) == '[', "Bracketed host-port string must start with a bracket: %s", hostPortString);
|
||||
colonIndex = hostPortString.indexOf(58);
|
||||
closeBracketIndex = hostPortString.lastIndexOf(93);
|
||||
Preconditions.checkArgument(colonIndex > -1 && closeBracketIndex > colonIndex, "Invalid bracketed host/port: %s", hostPortString);
|
||||
String host = hostPortString.substring(1, closeBracketIndex);
|
||||
if (closeBracketIndex + 1 == hostPortString.length()) {
|
||||
return new String[]{host, ""};
|
||||
}
|
||||
Preconditions.checkArgument(hostPortString.charAt(closeBracketIndex + 1) == ':', "Only a colon may follow a close bracket: %s", hostPortString);
|
||||
for (int i = closeBracketIndex + 2; i < hostPortString.length(); ++i) {
|
||||
Preconditions.checkArgument(Character.isDigit(hostPortString.charAt(i)), "Port must be numeric: %s", hostPortString);
|
||||
}
|
||||
return new String[]{host, hostPortString.substring(closeBracketIndex + 2)};
|
||||
}
|
||||
|
||||
public HostAndPort withDefaultPort(int defaultPort) {
|
||||
Preconditions.checkArgument(HostAndPort.isValidPort(defaultPort));
|
||||
if (this.hasPort() || this.port == defaultPort) {
|
||||
return this;
|
||||
}
|
||||
return new HostAndPort(this.host, defaultPort, this.hasBracketlessColons);
|
||||
}
|
||||
|
||||
public HostAndPort requireBracketsForIPv6() {
|
||||
Preconditions.checkArgument(!this.hasBracketlessColons, "Possible bracketless IPv6 literal: %s", this.host);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other instanceof HostAndPort) {
|
||||
HostAndPort that = (HostAndPort)other;
|
||||
return Objects.equal(this.host, that.host) && this.port == that.port && this.hasBracketlessColons == that.hasBracketlessColons;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.host, this.port, this.hasBracketlessColons);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder(this.host.length() + 8);
|
||||
if (this.host.indexOf(58) >= 0) {
|
||||
builder.append('[').append(this.host).append(']');
|
||||
} else {
|
||||
builder.append(this.host);
|
||||
}
|
||||
if (this.hasPort()) {
|
||||
builder.append(':').append(this.port);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static boolean isValidPort(int port) {
|
||||
return port >= 0 && port <= 65535;
|
||||
}
|
||||
}
|
85
src/com/google/common/net/HostSpecifier.java
Normal file
85
src/com/google/common/net/HostSpecifier.java
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.net;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import java.net.InetAddress;
|
||||
import java.text.ParseException;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
public final class HostSpecifier {
|
||||
private final String canonicalForm;
|
||||
|
||||
private HostSpecifier(String canonicalForm) {
|
||||
this.canonicalForm = canonicalForm;
|
||||
}
|
||||
|
||||
public static HostSpecifier fromValid(String specifier) {
|
||||
HostAndPort parsedHost = HostAndPort.fromString(specifier);
|
||||
Preconditions.checkArgument(!parsedHost.hasPort());
|
||||
String host = parsedHost.getHostText();
|
||||
InetAddress addr = null;
|
||||
try {
|
||||
addr = InetAddresses.forString(host);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// empty catch block
|
||||
}
|
||||
if (addr != null) {
|
||||
return new HostSpecifier(InetAddresses.toUriString(addr));
|
||||
}
|
||||
InternetDomainName domain = InternetDomainName.from(host);
|
||||
if (domain.hasPublicSuffix()) {
|
||||
return new HostSpecifier(domain.toString());
|
||||
}
|
||||
String string = String.valueOf(host);
|
||||
throw new IllegalArgumentException(string.length() != 0 ? "Domain name does not have a recognized public suffix: ".concat(string) : new String("Domain name does not have a recognized public suffix: "));
|
||||
}
|
||||
|
||||
public static HostSpecifier from(String specifier) throws ParseException {
|
||||
try {
|
||||
return HostSpecifier.fromValid(specifier);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
String string = String.valueOf(specifier);
|
||||
ParseException parseException = new ParseException(string.length() != 0 ? "Invalid host specifier: ".concat(string) : new String("Invalid host specifier: "), 0);
|
||||
parseException.initCause(e);
|
||||
throw parseException;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isValid(String specifier) {
|
||||
try {
|
||||
HostSpecifier.fromValid(specifier);
|
||||
return true;
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other instanceof HostSpecifier) {
|
||||
HostSpecifier that = (HostSpecifier)other;
|
||||
return this.canonicalForm.equals(that.canonicalForm);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.canonicalForm.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.canonicalForm;
|
||||
}
|
||||
}
|
98
src/com/google/common/net/HttpHeaders.java
Normal file
98
src/com/google/common/net/HttpHeaders.java
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.net;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@GwtCompatible
|
||||
public final class HttpHeaders {
|
||||
public static final String CACHE_CONTROL = "Cache-Control";
|
||||
public static final String CONTENT_LENGTH = "Content-Length";
|
||||
public static final String CONTENT_TYPE = "Content-Type";
|
||||
public static final String DATE = "Date";
|
||||
public static final String PRAGMA = "Pragma";
|
||||
public static final String VIA = "Via";
|
||||
public static final String WARNING = "Warning";
|
||||
public static final String ACCEPT = "Accept";
|
||||
public static final String ACCEPT_CHARSET = "Accept-Charset";
|
||||
public static final String ACCEPT_ENCODING = "Accept-Encoding";
|
||||
public static final String ACCEPT_LANGUAGE = "Accept-Language";
|
||||
public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
|
||||
public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
|
||||
public static final String AUTHORIZATION = "Authorization";
|
||||
public static final String CONNECTION = "Connection";
|
||||
public static final String COOKIE = "Cookie";
|
||||
public static final String EXPECT = "Expect";
|
||||
public static final String FROM = "From";
|
||||
@Beta
|
||||
public static final String FOLLOW_ONLY_WHEN_PRERENDER_SHOWN = "Follow-Only-When-Prerender-Shown";
|
||||
public static final String HOST = "Host";
|
||||
public static final String IF_MATCH = "If-Match";
|
||||
public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
|
||||
public static final String IF_NONE_MATCH = "If-None-Match";
|
||||
public static final String IF_RANGE = "If-Range";
|
||||
public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
|
||||
public static final String LAST_EVENT_ID = "Last-Event-ID";
|
||||
public static final String MAX_FORWARDS = "Max-Forwards";
|
||||
public static final String ORIGIN = "Origin";
|
||||
public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
|
||||
public static final String RANGE = "Range";
|
||||
public static final String REFERER = "Referer";
|
||||
public static final String TE = "TE";
|
||||
public static final String UPGRADE = "Upgrade";
|
||||
public static final String USER_AGENT = "User-Agent";
|
||||
public static final String ACCEPT_RANGES = "Accept-Ranges";
|
||||
public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
|
||||
public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
|
||||
public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
|
||||
public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
|
||||
public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
|
||||
public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
|
||||
public static final String AGE = "Age";
|
||||
public static final String ALLOW = "Allow";
|
||||
public static final String CONTENT_DISPOSITION = "Content-Disposition";
|
||||
public static final String CONTENT_ENCODING = "Content-Encoding";
|
||||
public static final String CONTENT_LANGUAGE = "Content-Language";
|
||||
public static final String CONTENT_LOCATION = "Content-Location";
|
||||
public static final String CONTENT_MD5 = "Content-MD5";
|
||||
public static final String CONTENT_RANGE = "Content-Range";
|
||||
public static final String CONTENT_SECURITY_POLICY = "Content-Security-Policy";
|
||||
public static final String CONTENT_SECURITY_POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only";
|
||||
public static final String ETAG = "ETag";
|
||||
public static final String EXPIRES = "Expires";
|
||||
public static final String LAST_MODIFIED = "Last-Modified";
|
||||
public static final String LINK = "Link";
|
||||
public static final String LOCATION = "Location";
|
||||
public static final String P3P = "P3P";
|
||||
public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
|
||||
public static final String REFRESH = "Refresh";
|
||||
public static final String RETRY_AFTER = "Retry-After";
|
||||
public static final String SERVER = "Server";
|
||||
public static final String SET_COOKIE = "Set-Cookie";
|
||||
public static final String SET_COOKIE2 = "Set-Cookie2";
|
||||
public static final String STRICT_TRANSPORT_SECURITY = "Strict-Transport-Security";
|
||||
public static final String TIMING_ALLOW_ORIGIN = "Timing-Allow-Origin";
|
||||
public static final String TRAILER = "Trailer";
|
||||
public static final String TRANSFER_ENCODING = "Transfer-Encoding";
|
||||
public static final String VARY = "Vary";
|
||||
public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
|
||||
public static final String DNT = "DNT";
|
||||
public static final String X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options";
|
||||
public static final String X_DO_NOT_TRACK = "X-Do-Not-Track";
|
||||
public static final String X_FORWARDED_FOR = "X-Forwarded-For";
|
||||
public static final String X_FORWARDED_PROTO = "X-Forwarded-Proto";
|
||||
public static final String X_FRAME_OPTIONS = "X-Frame-Options";
|
||||
public static final String X_POWERED_BY = "X-Powered-By";
|
||||
@Beta
|
||||
public static final String PUBLIC_KEY_PINS = "Public-Key-Pins";
|
||||
@Beta
|
||||
public static final String PUBLIC_KEY_PINS_REPORT_ONLY = "Public-Key-Pins-Report-Only";
|
||||
public static final String X_REQUESTED_WITH = "X-Requested-With";
|
||||
public static final String X_USER_IP = "X-User-IP";
|
||||
public static final String X_XSS_PROTECTION = "X-XSS-Protection";
|
||||
|
||||
private HttpHeaders() {
|
||||
}
|
||||
}
|
480
src/com/google/common/net/InetAddresses.java
Normal file
480
src/com/google/common/net/InetAddresses.java
Normal file
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.net;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.primitives.Ints;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
public final class InetAddresses {
|
||||
private static final int IPV4_PART_COUNT = 4;
|
||||
private static final int IPV6_PART_COUNT = 8;
|
||||
private static final Inet4Address LOOPBACK4 = (Inet4Address)InetAddresses.forString("127.0.0.1");
|
||||
private static final Inet4Address ANY4 = (Inet4Address)InetAddresses.forString("0.0.0.0");
|
||||
|
||||
private InetAddresses() {
|
||||
}
|
||||
|
||||
private static Inet4Address getInet4Address(byte[] bytes) {
|
||||
Preconditions.checkArgument(bytes.length == 4, "Byte array has invalid length for an IPv4 address: %s != 4.", bytes.length);
|
||||
return (Inet4Address)InetAddresses.bytesToInetAddress(bytes);
|
||||
}
|
||||
|
||||
public static InetAddress forString(String ipString) {
|
||||
byte[] addr = InetAddresses.ipStringToBytes(ipString);
|
||||
if (addr == null) {
|
||||
throw new IllegalArgumentException(String.format("'%s' is not an IP string literal.", ipString));
|
||||
}
|
||||
return InetAddresses.bytesToInetAddress(addr);
|
||||
}
|
||||
|
||||
public static boolean isInetAddress(String ipString) {
|
||||
return InetAddresses.ipStringToBytes(ipString) != null;
|
||||
}
|
||||
|
||||
private static byte[] ipStringToBytes(String ipString) {
|
||||
boolean hasColon = false;
|
||||
boolean hasDot = false;
|
||||
for (int i = 0; i < ipString.length(); ++i) {
|
||||
char c = ipString.charAt(i);
|
||||
if (c == '.') {
|
||||
hasDot = true;
|
||||
continue;
|
||||
}
|
||||
if (c == ':') {
|
||||
if (hasDot) {
|
||||
return null;
|
||||
}
|
||||
hasColon = true;
|
||||
continue;
|
||||
}
|
||||
if (Character.digit(c, 16) != -1) continue;
|
||||
return null;
|
||||
}
|
||||
if (hasColon) {
|
||||
if (hasDot && (ipString = InetAddresses.convertDottedQuadToHex(ipString)) == null) {
|
||||
return null;
|
||||
}
|
||||
return InetAddresses.textToNumericFormatV6(ipString);
|
||||
}
|
||||
if (hasDot) {
|
||||
return InetAddresses.textToNumericFormatV4(ipString);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static byte[] textToNumericFormatV4(String ipString) {
|
||||
String[] address = ipString.split("\\.", 5);
|
||||
if (address.length != 4) {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = new byte[4];
|
||||
try {
|
||||
for (int i = 0; i < bytes.length; ++i) {
|
||||
bytes[i] = InetAddresses.parseOctet(address[i]);
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
return null;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static byte[] textToNumericFormatV6(String ipString) {
|
||||
int partsLo;
|
||||
int partsHi;
|
||||
String[] parts = ipString.split(":", 10);
|
||||
if (parts.length < 3 || parts.length > 9) {
|
||||
return null;
|
||||
}
|
||||
int skipIndex = -1;
|
||||
for (int i = 1; i < parts.length - 1; ++i) {
|
||||
if (parts[i].length() != 0) continue;
|
||||
if (skipIndex >= 0) {
|
||||
return null;
|
||||
}
|
||||
skipIndex = i;
|
||||
}
|
||||
if (skipIndex >= 0) {
|
||||
partsHi = skipIndex;
|
||||
partsLo = parts.length - skipIndex - 1;
|
||||
if (parts[0].length() == 0 && --partsHi != 0) {
|
||||
return null;
|
||||
}
|
||||
if (parts[parts.length - 1].length() == 0 && --partsLo != 0) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
partsHi = parts.length;
|
||||
partsLo = 0;
|
||||
}
|
||||
int partsSkipped = 8 - (partsHi + partsLo);
|
||||
if (!(skipIndex < 0 ? partsSkipped == 0 : partsSkipped >= 1)) {
|
||||
return null;
|
||||
}
|
||||
ByteBuffer rawBytes = ByteBuffer.allocate(16);
|
||||
try {
|
||||
int i;
|
||||
for (i = 0; i < partsHi; ++i) {
|
||||
rawBytes.putShort(InetAddresses.parseHextet(parts[i]));
|
||||
}
|
||||
for (i = 0; i < partsSkipped; ++i) {
|
||||
rawBytes.putShort((short)0);
|
||||
}
|
||||
for (i = partsLo; i > 0; --i) {
|
||||
rawBytes.putShort(InetAddresses.parseHextet(parts[parts.length - i]));
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
return null;
|
||||
}
|
||||
return rawBytes.array();
|
||||
}
|
||||
|
||||
private static String convertDottedQuadToHex(String ipString) {
|
||||
int lastColon = ipString.lastIndexOf(58);
|
||||
String initialPart = ipString.substring(0, lastColon + 1);
|
||||
String dottedQuad = ipString.substring(lastColon + 1);
|
||||
byte[] quad = InetAddresses.textToNumericFormatV4(dottedQuad);
|
||||
if (quad == null) {
|
||||
return null;
|
||||
}
|
||||
String penultimate = Integer.toHexString((quad[0] & 0xFF) << 8 | quad[1] & 0xFF);
|
||||
String ultimate = Integer.toHexString((quad[2] & 0xFF) << 8 | quad[3] & 0xFF);
|
||||
String string = String.valueOf(String.valueOf(initialPart));
|
||||
String string2 = String.valueOf(String.valueOf(penultimate));
|
||||
String string3 = String.valueOf(String.valueOf(ultimate));
|
||||
return new StringBuilder(1 + string.length() + string2.length() + string3.length()).append(string).append(string2).append(":").append(string3).toString();
|
||||
}
|
||||
|
||||
private static byte parseOctet(String ipPart) {
|
||||
int octet = Integer.parseInt(ipPart);
|
||||
if (octet > 255 || ipPart.startsWith("0") && ipPart.length() > 1) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
return (byte)octet;
|
||||
}
|
||||
|
||||
private static short parseHextet(String ipPart) {
|
||||
int hextet = Integer.parseInt(ipPart, 16);
|
||||
if (hextet > 65535) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
return (short)hextet;
|
||||
}
|
||||
|
||||
private static InetAddress bytesToInetAddress(byte[] addr) {
|
||||
try {
|
||||
return InetAddress.getByAddress(addr);
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
throw new AssertionError((Object)e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toAddrString(InetAddress ip) {
|
||||
Preconditions.checkNotNull(ip);
|
||||
if (ip instanceof Inet4Address) {
|
||||
return ip.getHostAddress();
|
||||
}
|
||||
Preconditions.checkArgument(ip instanceof Inet6Address);
|
||||
byte[] bytes = ip.getAddress();
|
||||
int[] hextets = new int[8];
|
||||
for (int i = 0; i < hextets.length; ++i) {
|
||||
hextets[i] = Ints.fromBytes((byte)0, (byte)0, bytes[2 * i], bytes[2 * i + 1]);
|
||||
}
|
||||
InetAddresses.compressLongestRunOfZeroes(hextets);
|
||||
return InetAddresses.hextetsToIPv6String(hextets);
|
||||
}
|
||||
|
||||
private static void compressLongestRunOfZeroes(int[] hextets) {
|
||||
int bestRunStart = -1;
|
||||
int bestRunLength = -1;
|
||||
int runStart = -1;
|
||||
for (int i = 0; i < hextets.length + 1; ++i) {
|
||||
if (i < hextets.length && hextets[i] == 0) {
|
||||
if (runStart >= 0) continue;
|
||||
runStart = i;
|
||||
continue;
|
||||
}
|
||||
if (runStart < 0) continue;
|
||||
int runLength = i - runStart;
|
||||
if (runLength > bestRunLength) {
|
||||
bestRunStart = runStart;
|
||||
bestRunLength = runLength;
|
||||
}
|
||||
runStart = -1;
|
||||
}
|
||||
if (bestRunLength >= 2) {
|
||||
Arrays.fill(hextets, bestRunStart, bestRunStart + bestRunLength, -1);
|
||||
}
|
||||
}
|
||||
|
||||
private static String hextetsToIPv6String(int[] hextets) {
|
||||
StringBuilder buf = new StringBuilder(39);
|
||||
boolean lastWasNumber = false;
|
||||
for (int i = 0; i < hextets.length; ++i) {
|
||||
boolean thisIsNumber;
|
||||
boolean bl = thisIsNumber = hextets[i] >= 0;
|
||||
if (thisIsNumber) {
|
||||
if (lastWasNumber) {
|
||||
buf.append(':');
|
||||
}
|
||||
buf.append(Integer.toHexString(hextets[i]));
|
||||
} else if (i == 0 || lastWasNumber) {
|
||||
buf.append("::");
|
||||
}
|
||||
lastWasNumber = thisIsNumber;
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String toUriString(InetAddress ip) {
|
||||
if (ip instanceof Inet6Address) {
|
||||
String string = String.valueOf(String.valueOf(InetAddresses.toAddrString(ip)));
|
||||
return new StringBuilder(2 + string.length()).append("[").append(string).append("]").toString();
|
||||
}
|
||||
return InetAddresses.toAddrString(ip);
|
||||
}
|
||||
|
||||
public static InetAddress forUriString(String hostAddr) {
|
||||
int expectBytes;
|
||||
String ipString;
|
||||
Preconditions.checkNotNull(hostAddr);
|
||||
if (hostAddr.startsWith("[") && hostAddr.endsWith("]")) {
|
||||
ipString = hostAddr.substring(1, hostAddr.length() - 1);
|
||||
expectBytes = 16;
|
||||
} else {
|
||||
ipString = hostAddr;
|
||||
expectBytes = 4;
|
||||
}
|
||||
byte[] addr = InetAddresses.ipStringToBytes(ipString);
|
||||
if (addr == null || addr.length != expectBytes) {
|
||||
throw new IllegalArgumentException(String.format("Not a valid URI IP literal: '%s'", hostAddr));
|
||||
}
|
||||
return InetAddresses.bytesToInetAddress(addr);
|
||||
}
|
||||
|
||||
public static boolean isUriInetAddress(String ipString) {
|
||||
try {
|
||||
InetAddresses.forUriString(ipString);
|
||||
return true;
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCompatIPv4Address(Inet6Address ip) {
|
||||
if (!ip.isIPv4CompatibleAddress()) {
|
||||
return false;
|
||||
}
|
||||
byte[] bytes = ip.getAddress();
|
||||
return bytes[12] != 0 || bytes[13] != 0 || bytes[14] != 0 || bytes[15] != 0 && bytes[15] != 1;
|
||||
}
|
||||
|
||||
public static Inet4Address getCompatIPv4Address(Inet6Address ip) {
|
||||
Preconditions.checkArgument(InetAddresses.isCompatIPv4Address(ip), "Address '%s' is not IPv4-compatible.", InetAddresses.toAddrString(ip));
|
||||
return InetAddresses.getInet4Address(Arrays.copyOfRange(ip.getAddress(), 12, 16));
|
||||
}
|
||||
|
||||
public static boolean is6to4Address(Inet6Address ip) {
|
||||
byte[] bytes = ip.getAddress();
|
||||
return bytes[0] == 32 && bytes[1] == 2;
|
||||
}
|
||||
|
||||
public static Inet4Address get6to4IPv4Address(Inet6Address ip) {
|
||||
Preconditions.checkArgument(InetAddresses.is6to4Address(ip), "Address '%s' is not a 6to4 address.", InetAddresses.toAddrString(ip));
|
||||
return InetAddresses.getInet4Address(Arrays.copyOfRange(ip.getAddress(), 2, 6));
|
||||
}
|
||||
|
||||
public static boolean isTeredoAddress(Inet6Address ip) {
|
||||
byte[] bytes = ip.getAddress();
|
||||
return bytes[0] == 32 && bytes[1] == 1 && bytes[2] == 0 && bytes[3] == 0;
|
||||
}
|
||||
|
||||
public static TeredoInfo getTeredoInfo(Inet6Address ip) {
|
||||
Preconditions.checkArgument(InetAddresses.isTeredoAddress(ip), "Address '%s' is not a Teredo address.", InetAddresses.toAddrString(ip));
|
||||
byte[] bytes = ip.getAddress();
|
||||
Inet4Address server = InetAddresses.getInet4Address(Arrays.copyOfRange(bytes, 4, 8));
|
||||
int flags = ByteStreams.newDataInput(bytes, 8).readShort() & 0xFFFF;
|
||||
int port = ~ByteStreams.newDataInput(bytes, 10).readShort() & 0xFFFF;
|
||||
byte[] clientBytes = Arrays.copyOfRange(bytes, 12, 16);
|
||||
for (int i = 0; i < clientBytes.length; ++i) {
|
||||
clientBytes[i] = ~clientBytes[i];
|
||||
}
|
||||
Inet4Address client = InetAddresses.getInet4Address(clientBytes);
|
||||
return new TeredoInfo(server, client, port, flags);
|
||||
}
|
||||
|
||||
public static boolean isIsatapAddress(Inet6Address ip) {
|
||||
if (InetAddresses.isTeredoAddress(ip)) {
|
||||
return false;
|
||||
}
|
||||
byte[] bytes = ip.getAddress();
|
||||
if ((bytes[8] | 3) != 3) {
|
||||
return false;
|
||||
}
|
||||
return bytes[9] == 0 && bytes[10] == 94 && bytes[11] == -2;
|
||||
}
|
||||
|
||||
public static Inet4Address getIsatapIPv4Address(Inet6Address ip) {
|
||||
Preconditions.checkArgument(InetAddresses.isIsatapAddress(ip), "Address '%s' is not an ISATAP address.", InetAddresses.toAddrString(ip));
|
||||
return InetAddresses.getInet4Address(Arrays.copyOfRange(ip.getAddress(), 12, 16));
|
||||
}
|
||||
|
||||
public static boolean hasEmbeddedIPv4ClientAddress(Inet6Address ip) {
|
||||
return InetAddresses.isCompatIPv4Address(ip) || InetAddresses.is6to4Address(ip) || InetAddresses.isTeredoAddress(ip);
|
||||
}
|
||||
|
||||
public static Inet4Address getEmbeddedIPv4ClientAddress(Inet6Address ip) {
|
||||
if (InetAddresses.isCompatIPv4Address(ip)) {
|
||||
return InetAddresses.getCompatIPv4Address(ip);
|
||||
}
|
||||
if (InetAddresses.is6to4Address(ip)) {
|
||||
return InetAddresses.get6to4IPv4Address(ip);
|
||||
}
|
||||
if (InetAddresses.isTeredoAddress(ip)) {
|
||||
return InetAddresses.getTeredoInfo(ip).getClient();
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("'%s' has no embedded IPv4 address.", InetAddresses.toAddrString(ip)));
|
||||
}
|
||||
|
||||
public static boolean isMappedIPv4Address(String ipString) {
|
||||
byte[] bytes = InetAddresses.ipStringToBytes(ipString);
|
||||
if (bytes != null && bytes.length == 16) {
|
||||
int i;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
if (bytes[i] == 0) continue;
|
||||
return false;
|
||||
}
|
||||
for (i = 10; i < 12; ++i) {
|
||||
if (bytes[i] == -1) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Inet4Address getCoercedIPv4Address(InetAddress ip) {
|
||||
if (ip instanceof Inet4Address) {
|
||||
return (Inet4Address)ip;
|
||||
}
|
||||
byte[] bytes = ip.getAddress();
|
||||
boolean leadingBytesOfZero = true;
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
if (bytes[i] == 0) continue;
|
||||
leadingBytesOfZero = false;
|
||||
break;
|
||||
}
|
||||
if (leadingBytesOfZero && bytes[15] == 1) {
|
||||
return LOOPBACK4;
|
||||
}
|
||||
if (leadingBytesOfZero && bytes[15] == 0) {
|
||||
return ANY4;
|
||||
}
|
||||
Inet6Address ip6 = (Inet6Address)ip;
|
||||
long addressAsLong = 0L;
|
||||
addressAsLong = InetAddresses.hasEmbeddedIPv4ClientAddress(ip6) ? (long)InetAddresses.getEmbeddedIPv4ClientAddress(ip6).hashCode() : ByteBuffer.wrap(ip6.getAddress(), 0, 8).getLong();
|
||||
int coercedHash = Hashing.murmur3_32().hashLong(addressAsLong).asInt();
|
||||
if ((coercedHash |= 0xE0000000) == -1) {
|
||||
coercedHash = -2;
|
||||
}
|
||||
return InetAddresses.getInet4Address(Ints.toByteArray(coercedHash));
|
||||
}
|
||||
|
||||
public static int coerceToInteger(InetAddress ip) {
|
||||
return ByteStreams.newDataInput(InetAddresses.getCoercedIPv4Address(ip).getAddress()).readInt();
|
||||
}
|
||||
|
||||
public static Inet4Address fromInteger(int address) {
|
||||
return InetAddresses.getInet4Address(Ints.toByteArray(address));
|
||||
}
|
||||
|
||||
public static InetAddress fromLittleEndianByteArray(byte[] addr) throws UnknownHostException {
|
||||
byte[] reversed = new byte[addr.length];
|
||||
for (int i = 0; i < addr.length; ++i) {
|
||||
reversed[i] = addr[addr.length - i - 1];
|
||||
}
|
||||
return InetAddress.getByAddress(reversed);
|
||||
}
|
||||
|
||||
public static InetAddress decrement(InetAddress address) {
|
||||
int i;
|
||||
byte[] addr = address.getAddress();
|
||||
for (i = addr.length - 1; i >= 0 && addr[i] == 0; --i) {
|
||||
addr[i] = -1;
|
||||
}
|
||||
Preconditions.checkArgument(i >= 0, "Decrementing %s would wrap.", address);
|
||||
int n = i;
|
||||
addr[n] = (byte)(addr[n] - 1);
|
||||
return InetAddresses.bytesToInetAddress(addr);
|
||||
}
|
||||
|
||||
public static InetAddress increment(InetAddress address) {
|
||||
int i;
|
||||
byte[] addr = address.getAddress();
|
||||
for (i = addr.length - 1; i >= 0 && addr[i] == -1; --i) {
|
||||
addr[i] = 0;
|
||||
}
|
||||
Preconditions.checkArgument(i >= 0, "Incrementing %s would wrap.", address);
|
||||
int n = i;
|
||||
addr[n] = (byte)(addr[n] + 1);
|
||||
return InetAddresses.bytesToInetAddress(addr);
|
||||
}
|
||||
|
||||
public static boolean isMaximum(InetAddress address) {
|
||||
byte[] addr = address.getAddress();
|
||||
for (int i = 0; i < addr.length; ++i) {
|
||||
if (addr[i] == -1) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static final class TeredoInfo {
|
||||
private final Inet4Address server;
|
||||
private final Inet4Address client;
|
||||
private final int port;
|
||||
private final int flags;
|
||||
|
||||
public TeredoInfo(@Nullable Inet4Address server, @Nullable Inet4Address client, int port, int flags) {
|
||||
Preconditions.checkArgument(port >= 0 && port <= 65535, "port '%s' is out of range (0 <= port <= 0xffff)", port);
|
||||
Preconditions.checkArgument(flags >= 0 && flags <= 65535, "flags '%s' is out of range (0 <= flags <= 0xffff)", flags);
|
||||
this.server = MoreObjects.firstNonNull(server, ANY4);
|
||||
this.client = MoreObjects.firstNonNull(client, ANY4);
|
||||
this.port = port;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public Inet4Address getServer() {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
public Inet4Address getClient() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public int getFlags() {
|
||||
return this.flags;
|
||||
}
|
||||
}
|
||||
}
|
179
src/com/google/common/net/InternetDomainName.java
Normal file
179
src/com/google/common/net/InternetDomainName.java
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.net;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.thirdparty.publicsuffix.PublicSuffixPatterns;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public final class InternetDomainName {
|
||||
private static final CharMatcher DOTS_MATCHER = CharMatcher.anyOf(".\u3002\uff0e\uff61");
|
||||
private static final Splitter DOT_SPLITTER = Splitter.on('.');
|
||||
private static final Joiner DOT_JOINER = Joiner.on('.');
|
||||
private static final int NO_PUBLIC_SUFFIX_FOUND = -1;
|
||||
private static final String DOT_REGEX = "\\.";
|
||||
private static final int MAX_PARTS = 127;
|
||||
private static final int MAX_LENGTH = 253;
|
||||
private static final int MAX_DOMAIN_PART_LENGTH = 63;
|
||||
private final String name;
|
||||
private final ImmutableList<String> parts;
|
||||
private final int publicSuffixIndex;
|
||||
private static final CharMatcher DASH_MATCHER = CharMatcher.anyOf("-_");
|
||||
private static final CharMatcher PART_CHAR_MATCHER = CharMatcher.JAVA_LETTER_OR_DIGIT.or(DASH_MATCHER);
|
||||
|
||||
InternetDomainName(String name) {
|
||||
name = Ascii.toLowerCase(DOTS_MATCHER.replaceFrom((CharSequence)name, '.'));
|
||||
if (name.endsWith(".")) {
|
||||
name = name.substring(0, name.length() - 1);
|
||||
}
|
||||
Preconditions.checkArgument(name.length() <= 253, "Domain name too long: '%s':", name);
|
||||
this.name = name;
|
||||
this.parts = ImmutableList.copyOf(DOT_SPLITTER.split(name));
|
||||
Preconditions.checkArgument(this.parts.size() <= 127, "Domain has too many parts: '%s'", name);
|
||||
Preconditions.checkArgument(InternetDomainName.validateSyntax(this.parts), "Not a valid domain name: '%s'", name);
|
||||
this.publicSuffixIndex = this.findPublicSuffix();
|
||||
}
|
||||
|
||||
private int findPublicSuffix() {
|
||||
int partsSize = this.parts.size();
|
||||
for (int i = 0; i < partsSize; ++i) {
|
||||
String ancestorName = DOT_JOINER.join(this.parts.subList(i, partsSize));
|
||||
if (PublicSuffixPatterns.EXACT.containsKey(ancestorName)) {
|
||||
return i;
|
||||
}
|
||||
if (PublicSuffixPatterns.EXCLUDED.containsKey(ancestorName)) {
|
||||
return i + 1;
|
||||
}
|
||||
if (!InternetDomainName.matchesWildcardPublicSuffix(ancestorName)) continue;
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static InternetDomainName from(String domain) {
|
||||
return new InternetDomainName(Preconditions.checkNotNull(domain));
|
||||
}
|
||||
|
||||
private static boolean validateSyntax(List<String> parts) {
|
||||
int lastIndex = parts.size() - 1;
|
||||
if (!InternetDomainName.validatePart(parts.get(lastIndex), true)) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < lastIndex; ++i) {
|
||||
String part = parts.get(i);
|
||||
if (InternetDomainName.validatePart(part, false)) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean validatePart(String part, boolean isFinalPart) {
|
||||
if (part.length() < 1 || part.length() > 63) {
|
||||
return false;
|
||||
}
|
||||
String asciiChars = CharMatcher.ASCII.retainFrom(part);
|
||||
if (!PART_CHAR_MATCHER.matchesAllOf(asciiChars)) {
|
||||
return false;
|
||||
}
|
||||
if (DASH_MATCHER.matches(part.charAt(0)) || DASH_MATCHER.matches(part.charAt(part.length() - 1))) {
|
||||
return false;
|
||||
}
|
||||
return !isFinalPart || !CharMatcher.DIGIT.matches(part.charAt(0));
|
||||
}
|
||||
|
||||
public ImmutableList<String> parts() {
|
||||
return this.parts;
|
||||
}
|
||||
|
||||
public boolean isPublicSuffix() {
|
||||
return this.publicSuffixIndex == 0;
|
||||
}
|
||||
|
||||
public boolean hasPublicSuffix() {
|
||||
return this.publicSuffixIndex != -1;
|
||||
}
|
||||
|
||||
public InternetDomainName publicSuffix() {
|
||||
return this.hasPublicSuffix() ? this.ancestor(this.publicSuffixIndex) : null;
|
||||
}
|
||||
|
||||
public boolean isUnderPublicSuffix() {
|
||||
return this.publicSuffixIndex > 0;
|
||||
}
|
||||
|
||||
public boolean isTopPrivateDomain() {
|
||||
return this.publicSuffixIndex == 1;
|
||||
}
|
||||
|
||||
public InternetDomainName topPrivateDomain() {
|
||||
if (this.isTopPrivateDomain()) {
|
||||
return this;
|
||||
}
|
||||
Preconditions.checkState(this.isUnderPublicSuffix(), "Not under a public suffix: %s", this.name);
|
||||
return this.ancestor(this.publicSuffixIndex - 1);
|
||||
}
|
||||
|
||||
public boolean hasParent() {
|
||||
return this.parts.size() > 1;
|
||||
}
|
||||
|
||||
public InternetDomainName parent() {
|
||||
Preconditions.checkState(this.hasParent(), "Domain '%s' has no parent", this.name);
|
||||
return this.ancestor(1);
|
||||
}
|
||||
|
||||
private InternetDomainName ancestor(int levels) {
|
||||
return InternetDomainName.from(DOT_JOINER.join(this.parts.subList(levels, this.parts.size())));
|
||||
}
|
||||
|
||||
public InternetDomainName child(String leftParts) {
|
||||
String string = String.valueOf(String.valueOf(Preconditions.checkNotNull(leftParts)));
|
||||
String string2 = String.valueOf(String.valueOf(this.name));
|
||||
return InternetDomainName.from(new StringBuilder(1 + string.length() + string2.length()).append(string).append(".").append(string2).toString());
|
||||
}
|
||||
|
||||
public static boolean isValid(String name) {
|
||||
try {
|
||||
InternetDomainName.from(name);
|
||||
return true;
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean matchesWildcardPublicSuffix(String domain) {
|
||||
String[] pieces = domain.split(DOT_REGEX, 2);
|
||||
return pieces.length == 2 && PublicSuffixPatterns.UNDER.containsKey(pieces[1]);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object object) {
|
||||
if (object == this) {
|
||||
return true;
|
||||
}
|
||||
if (object instanceof InternetDomainName) {
|
||||
InternetDomainName that = (InternetDomainName)object;
|
||||
return this.name.equals(that.name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.name.hashCode();
|
||||
}
|
||||
}
|
398
src/com/google/common/net/MediaType.java
Normal file
398
src/com/google/common/net/MediaType.java
Normal file
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.net;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
@Immutable
|
||||
public final class MediaType {
|
||||
private static final String CHARSET_ATTRIBUTE = "charset";
|
||||
private static final ImmutableListMultimap<String, String> UTF_8_CONSTANT_PARAMETERS = ImmutableListMultimap.of("charset", Ascii.toLowerCase(Charsets.UTF_8.name()));
|
||||
private static final CharMatcher TOKEN_MATCHER = CharMatcher.ASCII.and(CharMatcher.JAVA_ISO_CONTROL.negate()).and(CharMatcher.isNot(' ')).and(CharMatcher.noneOf("()<>@,;:\\\"/[]?="));
|
||||
private static final CharMatcher QUOTED_TEXT_MATCHER = CharMatcher.ASCII.and(CharMatcher.noneOf("\"\\\r"));
|
||||
private static final CharMatcher LINEAR_WHITE_SPACE = CharMatcher.anyOf(" \t\r\n");
|
||||
private static final String APPLICATION_TYPE = "application";
|
||||
private static final String AUDIO_TYPE = "audio";
|
||||
private static final String IMAGE_TYPE = "image";
|
||||
private static final String TEXT_TYPE = "text";
|
||||
private static final String VIDEO_TYPE = "video";
|
||||
private static final String WILDCARD = "*";
|
||||
private static final Map<MediaType, MediaType> KNOWN_TYPES = Maps.newHashMap();
|
||||
public static final MediaType ANY_TYPE = MediaType.createConstant("*", "*");
|
||||
public static final MediaType ANY_TEXT_TYPE = MediaType.createConstant("text", "*");
|
||||
public static final MediaType ANY_IMAGE_TYPE = MediaType.createConstant("image", "*");
|
||||
public static final MediaType ANY_AUDIO_TYPE = MediaType.createConstant("audio", "*");
|
||||
public static final MediaType ANY_VIDEO_TYPE = MediaType.createConstant("video", "*");
|
||||
public static final MediaType ANY_APPLICATION_TYPE = MediaType.createConstant("application", "*");
|
||||
public static final MediaType CACHE_MANIFEST_UTF_8 = MediaType.createConstantUtf8("text", "cache-manifest");
|
||||
public static final MediaType CSS_UTF_8 = MediaType.createConstantUtf8("text", "css");
|
||||
public static final MediaType CSV_UTF_8 = MediaType.createConstantUtf8("text", "csv");
|
||||
public static final MediaType HTML_UTF_8 = MediaType.createConstantUtf8("text", "html");
|
||||
public static final MediaType I_CALENDAR_UTF_8 = MediaType.createConstantUtf8("text", "calendar");
|
||||
public static final MediaType PLAIN_TEXT_UTF_8 = MediaType.createConstantUtf8("text", "plain");
|
||||
public static final MediaType TEXT_JAVASCRIPT_UTF_8 = MediaType.createConstantUtf8("text", "javascript");
|
||||
public static final MediaType TSV_UTF_8 = MediaType.createConstantUtf8("text", "tab-separated-values");
|
||||
public static final MediaType VCARD_UTF_8 = MediaType.createConstantUtf8("text", "vcard");
|
||||
public static final MediaType WML_UTF_8 = MediaType.createConstantUtf8("text", "vnd.wap.wml");
|
||||
public static final MediaType XML_UTF_8 = MediaType.createConstantUtf8("text", "xml");
|
||||
public static final MediaType BMP = MediaType.createConstant("image", "bmp");
|
||||
public static final MediaType CRW = MediaType.createConstant("image", "x-canon-crw");
|
||||
public static final MediaType GIF = MediaType.createConstant("image", "gif");
|
||||
public static final MediaType ICO = MediaType.createConstant("image", "vnd.microsoft.icon");
|
||||
public static final MediaType JPEG = MediaType.createConstant("image", "jpeg");
|
||||
public static final MediaType PNG = MediaType.createConstant("image", "png");
|
||||
public static final MediaType PSD = MediaType.createConstant("image", "vnd.adobe.photoshop");
|
||||
public static final MediaType SVG_UTF_8 = MediaType.createConstantUtf8("image", "svg+xml");
|
||||
public static final MediaType TIFF = MediaType.createConstant("image", "tiff");
|
||||
public static final MediaType WEBP = MediaType.createConstant("image", "webp");
|
||||
public static final MediaType MP4_AUDIO = MediaType.createConstant("audio", "mp4");
|
||||
public static final MediaType MPEG_AUDIO = MediaType.createConstant("audio", "mpeg");
|
||||
public static final MediaType OGG_AUDIO = MediaType.createConstant("audio", "ogg");
|
||||
public static final MediaType WEBM_AUDIO = MediaType.createConstant("audio", "webm");
|
||||
public static final MediaType MP4_VIDEO = MediaType.createConstant("video", "mp4");
|
||||
public static final MediaType MPEG_VIDEO = MediaType.createConstant("video", "mpeg");
|
||||
public static final MediaType OGG_VIDEO = MediaType.createConstant("video", "ogg");
|
||||
public static final MediaType QUICKTIME = MediaType.createConstant("video", "quicktime");
|
||||
public static final MediaType WEBM_VIDEO = MediaType.createConstant("video", "webm");
|
||||
public static final MediaType WMV = MediaType.createConstant("video", "x-ms-wmv");
|
||||
public static final MediaType APPLICATION_XML_UTF_8 = MediaType.createConstantUtf8("application", "xml");
|
||||
public static final MediaType ATOM_UTF_8 = MediaType.createConstantUtf8("application", "atom+xml");
|
||||
public static final MediaType BZIP2 = MediaType.createConstant("application", "x-bzip2");
|
||||
public static final MediaType EOT = MediaType.createConstant("application", "vnd.ms-fontobject");
|
||||
public static final MediaType EPUB = MediaType.createConstant("application", "epub+zip");
|
||||
public static final MediaType FORM_DATA = MediaType.createConstant("application", "x-www-form-urlencoded");
|
||||
public static final MediaType KEY_ARCHIVE = MediaType.createConstant("application", "pkcs12");
|
||||
public static final MediaType APPLICATION_BINARY = MediaType.createConstant("application", "binary");
|
||||
public static final MediaType GZIP = MediaType.createConstant("application", "x-gzip");
|
||||
public static final MediaType JAVASCRIPT_UTF_8 = MediaType.createConstantUtf8("application", "javascript");
|
||||
public static final MediaType JSON_UTF_8 = MediaType.createConstantUtf8("application", "json");
|
||||
public static final MediaType KML = MediaType.createConstant("application", "vnd.google-earth.kml+xml");
|
||||
public static final MediaType KMZ = MediaType.createConstant("application", "vnd.google-earth.kmz");
|
||||
public static final MediaType MBOX = MediaType.createConstant("application", "mbox");
|
||||
public static final MediaType APPLE_MOBILE_CONFIG = MediaType.createConstant("application", "x-apple-aspen-config");
|
||||
public static final MediaType MICROSOFT_EXCEL = MediaType.createConstant("application", "vnd.ms-excel");
|
||||
public static final MediaType MICROSOFT_POWERPOINT = MediaType.createConstant("application", "vnd.ms-powerpoint");
|
||||
public static final MediaType MICROSOFT_WORD = MediaType.createConstant("application", "msword");
|
||||
public static final MediaType OCTET_STREAM = MediaType.createConstant("application", "octet-stream");
|
||||
public static final MediaType OGG_CONTAINER = MediaType.createConstant("application", "ogg");
|
||||
public static final MediaType OOXML_DOCUMENT = MediaType.createConstant("application", "vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
public static final MediaType OOXML_PRESENTATION = MediaType.createConstant("application", "vnd.openxmlformats-officedocument.presentationml.presentation");
|
||||
public static final MediaType OOXML_SHEET = MediaType.createConstant("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
public static final MediaType OPENDOCUMENT_GRAPHICS = MediaType.createConstant("application", "vnd.oasis.opendocument.graphics");
|
||||
public static final MediaType OPENDOCUMENT_PRESENTATION = MediaType.createConstant("application", "vnd.oasis.opendocument.presentation");
|
||||
public static final MediaType OPENDOCUMENT_SPREADSHEET = MediaType.createConstant("application", "vnd.oasis.opendocument.spreadsheet");
|
||||
public static final MediaType OPENDOCUMENT_TEXT = MediaType.createConstant("application", "vnd.oasis.opendocument.text");
|
||||
public static final MediaType PDF = MediaType.createConstant("application", "pdf");
|
||||
public static final MediaType POSTSCRIPT = MediaType.createConstant("application", "postscript");
|
||||
public static final MediaType PROTOBUF = MediaType.createConstant("application", "protobuf");
|
||||
public static final MediaType RDF_XML_UTF_8 = MediaType.createConstantUtf8("application", "rdf+xml");
|
||||
public static final MediaType RTF_UTF_8 = MediaType.createConstantUtf8("application", "rtf");
|
||||
public static final MediaType SFNT = MediaType.createConstant("application", "font-sfnt");
|
||||
public static final MediaType SHOCKWAVE_FLASH = MediaType.createConstant("application", "x-shockwave-flash");
|
||||
public static final MediaType SKETCHUP = MediaType.createConstant("application", "vnd.sketchup.skp");
|
||||
public static final MediaType TAR = MediaType.createConstant("application", "x-tar");
|
||||
public static final MediaType WOFF = MediaType.createConstant("application", "font-woff");
|
||||
public static final MediaType XHTML_UTF_8 = MediaType.createConstantUtf8("application", "xhtml+xml");
|
||||
public static final MediaType XRD_UTF_8 = MediaType.createConstantUtf8("application", "xrd+xml");
|
||||
public static final MediaType ZIP = MediaType.createConstant("application", "zip");
|
||||
private final String type;
|
||||
private final String subtype;
|
||||
private final ImmutableListMultimap<String, String> parameters;
|
||||
private static final Joiner.MapJoiner PARAMETER_JOINER = Joiner.on("; ").withKeyValueSeparator("=");
|
||||
|
||||
private static MediaType createConstant(String type, String subtype) {
|
||||
return MediaType.addKnownType(new MediaType(type, subtype, ImmutableListMultimap.<String, String>of()));
|
||||
}
|
||||
|
||||
private static MediaType createConstantUtf8(String type, String subtype) {
|
||||
return MediaType.addKnownType(new MediaType(type, subtype, UTF_8_CONSTANT_PARAMETERS));
|
||||
}
|
||||
|
||||
private static MediaType addKnownType(MediaType mediaType) {
|
||||
KNOWN_TYPES.put(mediaType, mediaType);
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
private MediaType(String type, String subtype, ImmutableListMultimap<String, String> parameters) {
|
||||
this.type = type;
|
||||
this.subtype = subtype;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public String type() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public String subtype() {
|
||||
return this.subtype;
|
||||
}
|
||||
|
||||
public ImmutableListMultimap<String, String> parameters() {
|
||||
return this.parameters;
|
||||
}
|
||||
|
||||
private Map<String, ImmutableMultiset<String>> parametersAsMap() {
|
||||
return Maps.transformValues(this.parameters.asMap(), new Function<Collection<String>, ImmutableMultiset<String>>(){
|
||||
|
||||
@Override
|
||||
public ImmutableMultiset<String> apply(Collection<String> input) {
|
||||
return ImmutableMultiset.copyOf(input);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Optional<Charset> charset() {
|
||||
ImmutableSet charsetValues = ImmutableSet.copyOf(this.parameters.get((Object)CHARSET_ATTRIBUTE));
|
||||
switch (charsetValues.size()) {
|
||||
case 0: {
|
||||
return Optional.absent();
|
||||
}
|
||||
case 1: {
|
||||
return Optional.of(Charset.forName((String)Iterables.getOnlyElement(charsetValues)));
|
||||
}
|
||||
}
|
||||
String string = String.valueOf(String.valueOf(charsetValues));
|
||||
throw new IllegalStateException(new StringBuilder(33 + string.length()).append("Multiple charset values defined: ").append(string).toString());
|
||||
}
|
||||
|
||||
public MediaType withoutParameters() {
|
||||
return this.parameters.isEmpty() ? this : MediaType.create(this.type, this.subtype);
|
||||
}
|
||||
|
||||
public MediaType withParameters(Multimap<String, String> parameters) {
|
||||
return MediaType.create(this.type, this.subtype, parameters);
|
||||
}
|
||||
|
||||
public MediaType withParameter(String attribute, String value) {
|
||||
Preconditions.checkNotNull(attribute);
|
||||
Preconditions.checkNotNull(value);
|
||||
String normalizedAttribute = MediaType.normalizeToken(attribute);
|
||||
ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder();
|
||||
for (Map.Entry entry : this.parameters.entries()) {
|
||||
String key = (String)entry.getKey();
|
||||
if (normalizedAttribute.equals(key)) continue;
|
||||
builder.put(key, entry.getValue());
|
||||
}
|
||||
builder.put(normalizedAttribute, MediaType.normalizeParameterValue(normalizedAttribute, value));
|
||||
MediaType mediaType = new MediaType(this.type, this.subtype, (ImmutableListMultimap<String, String>)builder.build());
|
||||
return MoreObjects.firstNonNull(KNOWN_TYPES.get(mediaType), mediaType);
|
||||
}
|
||||
|
||||
public MediaType withCharset(Charset charset) {
|
||||
Preconditions.checkNotNull(charset);
|
||||
return this.withParameter(CHARSET_ATTRIBUTE, charset.name());
|
||||
}
|
||||
|
||||
public boolean hasWildcard() {
|
||||
return WILDCARD.equals(this.type) || WILDCARD.equals(this.subtype);
|
||||
}
|
||||
|
||||
public boolean is(MediaType mediaTypeRange) {
|
||||
return !(!mediaTypeRange.type.equals(WILDCARD) && !mediaTypeRange.type.equals(this.type) || !mediaTypeRange.subtype.equals(WILDCARD) && !mediaTypeRange.subtype.equals(this.subtype) || !((AbstractCollection)this.parameters.entries()).containsAll(mediaTypeRange.parameters.entries()));
|
||||
}
|
||||
|
||||
public static MediaType create(String type, String subtype) {
|
||||
return MediaType.create(type, subtype, ImmutableListMultimap.<String, String>of());
|
||||
}
|
||||
|
||||
static MediaType createApplicationType(String subtype) {
|
||||
return MediaType.create(APPLICATION_TYPE, subtype);
|
||||
}
|
||||
|
||||
static MediaType createAudioType(String subtype) {
|
||||
return MediaType.create(AUDIO_TYPE, subtype);
|
||||
}
|
||||
|
||||
static MediaType createImageType(String subtype) {
|
||||
return MediaType.create(IMAGE_TYPE, subtype);
|
||||
}
|
||||
|
||||
static MediaType createTextType(String subtype) {
|
||||
return MediaType.create(TEXT_TYPE, subtype);
|
||||
}
|
||||
|
||||
static MediaType createVideoType(String subtype) {
|
||||
return MediaType.create(VIDEO_TYPE, subtype);
|
||||
}
|
||||
|
||||
private static MediaType create(String type, String subtype, Multimap<String, String> parameters) {
|
||||
Preconditions.checkNotNull(type);
|
||||
Preconditions.checkNotNull(subtype);
|
||||
Preconditions.checkNotNull(parameters);
|
||||
String normalizedType = MediaType.normalizeToken(type);
|
||||
String normalizedSubtype = MediaType.normalizeToken(subtype);
|
||||
Preconditions.checkArgument(!WILDCARD.equals(normalizedType) || WILDCARD.equals(normalizedSubtype), "A wildcard type cannot be used with a non-wildcard subtype");
|
||||
ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder();
|
||||
for (Map.Entry<String, String> entry : parameters.entries()) {
|
||||
String attribute = MediaType.normalizeToken(entry.getKey());
|
||||
builder.put(attribute, MediaType.normalizeParameterValue(attribute, entry.getValue()));
|
||||
}
|
||||
MediaType mediaType = new MediaType(normalizedType, normalizedSubtype, (ImmutableListMultimap<String, String>)builder.build());
|
||||
return MoreObjects.firstNonNull(KNOWN_TYPES.get(mediaType), mediaType);
|
||||
}
|
||||
|
||||
private static String normalizeToken(String token) {
|
||||
Preconditions.checkArgument(TOKEN_MATCHER.matchesAllOf(token));
|
||||
return Ascii.toLowerCase(token);
|
||||
}
|
||||
|
||||
private static String normalizeParameterValue(String attribute, String value) {
|
||||
return CHARSET_ATTRIBUTE.equals(attribute) ? Ascii.toLowerCase(value) : value;
|
||||
}
|
||||
|
||||
public static MediaType parse(String input) {
|
||||
Preconditions.checkNotNull(input);
|
||||
Tokenizer tokenizer = new Tokenizer(input);
|
||||
try {
|
||||
String type = tokenizer.consumeToken(TOKEN_MATCHER);
|
||||
tokenizer.consumeCharacter('/');
|
||||
String subtype = tokenizer.consumeToken(TOKEN_MATCHER);
|
||||
ImmutableListMultimap.Builder parameters = ImmutableListMultimap.builder();
|
||||
while (tokenizer.hasMore()) {
|
||||
String value;
|
||||
tokenizer.consumeCharacter(';');
|
||||
tokenizer.consumeTokenIfPresent(LINEAR_WHITE_SPACE);
|
||||
String attribute = tokenizer.consumeToken(TOKEN_MATCHER);
|
||||
tokenizer.consumeCharacter('=');
|
||||
if ('\"' == tokenizer.previewChar()) {
|
||||
tokenizer.consumeCharacter('\"');
|
||||
StringBuilder valueBuilder = new StringBuilder();
|
||||
while ('\"' != tokenizer.previewChar()) {
|
||||
if ('\\' == tokenizer.previewChar()) {
|
||||
tokenizer.consumeCharacter('\\');
|
||||
valueBuilder.append(tokenizer.consumeCharacter(CharMatcher.ASCII));
|
||||
continue;
|
||||
}
|
||||
valueBuilder.append(tokenizer.consumeToken(QUOTED_TEXT_MATCHER));
|
||||
}
|
||||
value = valueBuilder.toString();
|
||||
tokenizer.consumeCharacter('\"');
|
||||
} else {
|
||||
value = tokenizer.consumeToken(TOKEN_MATCHER);
|
||||
}
|
||||
parameters.put(attribute, value);
|
||||
}
|
||||
return MediaType.create(type, subtype, parameters.build());
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
String string = String.valueOf(String.valueOf(input));
|
||||
throw new IllegalArgumentException(new StringBuilder(18 + string.length()).append("Could not parse '").append(string).append("'").toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof MediaType) {
|
||||
MediaType that = (MediaType)obj;
|
||||
return this.type.equals(that.type) && this.subtype.equals(that.subtype) && this.parametersAsMap().equals(that.parametersAsMap());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.type, this.subtype, this.parametersAsMap());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder().append(this.type).append('/').append(this.subtype);
|
||||
if (!this.parameters.isEmpty()) {
|
||||
builder.append("; ");
|
||||
ListMultimap<String, String> quotedParameters = Multimaps.transformValues(this.parameters, new Function<String, String>(){
|
||||
|
||||
@Override
|
||||
public String apply(String value) {
|
||||
return TOKEN_MATCHER.matchesAllOf(value) ? value : MediaType.escapeAndQuote(value);
|
||||
}
|
||||
});
|
||||
PARAMETER_JOINER.appendTo(builder, (Iterable<? extends Map.Entry<?, ?>>)quotedParameters.entries());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static String escapeAndQuote(String value) {
|
||||
StringBuilder escaped = new StringBuilder(value.length() + 16).append('\"');
|
||||
for (char ch : value.toCharArray()) {
|
||||
if (ch == '\r' || ch == '\\' || ch == '\"') {
|
||||
escaped.append('\\');
|
||||
}
|
||||
escaped.append(ch);
|
||||
}
|
||||
return escaped.append('\"').toString();
|
||||
}
|
||||
|
||||
private static final class Tokenizer {
|
||||
final String input;
|
||||
int position = 0;
|
||||
|
||||
Tokenizer(String input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
String consumeTokenIfPresent(CharMatcher matcher) {
|
||||
Preconditions.checkState(this.hasMore());
|
||||
int startPosition = this.position;
|
||||
this.position = matcher.negate().indexIn(this.input, startPosition);
|
||||
return this.hasMore() ? this.input.substring(startPosition, this.position) : this.input.substring(startPosition);
|
||||
}
|
||||
|
||||
String consumeToken(CharMatcher matcher) {
|
||||
int startPosition = this.position;
|
||||
String token = this.consumeTokenIfPresent(matcher);
|
||||
Preconditions.checkState(this.position != startPosition);
|
||||
return token;
|
||||
}
|
||||
|
||||
char consumeCharacter(CharMatcher matcher) {
|
||||
Preconditions.checkState(this.hasMore());
|
||||
char c = this.previewChar();
|
||||
Preconditions.checkState(matcher.matches(c));
|
||||
++this.position;
|
||||
return c;
|
||||
}
|
||||
|
||||
char consumeCharacter(char c) {
|
||||
Preconditions.checkState(this.hasMore());
|
||||
Preconditions.checkState(this.previewChar() == c);
|
||||
++this.position;
|
||||
return c;
|
||||
}
|
||||
|
||||
char previewChar() {
|
||||
Preconditions.checkState(this.hasMore());
|
||||
return this.input.charAt(this.position);
|
||||
}
|
||||
|
||||
boolean hasMore() {
|
||||
return this.position >= 0 && this.position < this.input.length();
|
||||
}
|
||||
}
|
||||
}
|
125
src/com/google/common/net/PercentEscaper.java
Normal file
125
src/com/google/common/net/PercentEscaper.java
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.net;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.escape.UnicodeEscaper;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public final class PercentEscaper
|
||||
extends UnicodeEscaper {
|
||||
private static final char[] PLUS_SIGN = new char[]{'+'};
|
||||
private static final char[] UPPER_HEX_DIGITS = "0123456789ABCDEF".toCharArray();
|
||||
private final boolean plusForSpace;
|
||||
private final boolean[] safeOctets;
|
||||
|
||||
public PercentEscaper(String safeChars, boolean plusForSpace) {
|
||||
Preconditions.checkNotNull(safeChars);
|
||||
if (safeChars.matches(".*[0-9A-Za-z].*")) {
|
||||
throw new IllegalArgumentException("Alphanumeric characters are always 'safe' and should not be explicitly specified");
|
||||
}
|
||||
safeChars = String.valueOf(safeChars).concat("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
|
||||
if (plusForSpace && safeChars.contains(" ")) {
|
||||
throw new IllegalArgumentException("plusForSpace cannot be specified when space is a 'safe' character");
|
||||
}
|
||||
this.plusForSpace = plusForSpace;
|
||||
this.safeOctets = PercentEscaper.createSafeOctets(safeChars);
|
||||
}
|
||||
|
||||
private static boolean[] createSafeOctets(String safeChars) {
|
||||
char[] safeCharArray;
|
||||
int maxChar = -1;
|
||||
for (char c : safeCharArray = safeChars.toCharArray()) {
|
||||
maxChar = Math.max(c, maxChar);
|
||||
}
|
||||
boolean[] octets = new boolean[maxChar + 1];
|
||||
for (char c : safeCharArray) {
|
||||
octets[c] = true;
|
||||
}
|
||||
return octets;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int nextEscapeIndex(CharSequence csq, int index, int end) {
|
||||
char c;
|
||||
Preconditions.checkNotNull(csq);
|
||||
while (index < end && (c = csq.charAt(index)) < this.safeOctets.length && this.safeOctets[c]) {
|
||||
++index;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escape(String s) {
|
||||
Preconditions.checkNotNull(s);
|
||||
int slen = s.length();
|
||||
for (int index = 0; index < slen; ++index) {
|
||||
char c = s.charAt(index);
|
||||
if (c < this.safeOctets.length && this.safeOctets[c]) continue;
|
||||
return this.escapeSlow(s, index);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char[] escape(int cp) {
|
||||
if (cp < this.safeOctets.length && this.safeOctets[cp]) {
|
||||
return null;
|
||||
}
|
||||
if (cp == 32 && this.plusForSpace) {
|
||||
return PLUS_SIGN;
|
||||
}
|
||||
if (cp <= 127) {
|
||||
char[] dest = new char[3];
|
||||
dest[0] = 37;
|
||||
dest[2] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
dest[1] = UPPER_HEX_DIGITS[cp >>> 4];
|
||||
return dest;
|
||||
}
|
||||
if (cp <= 2047) {
|
||||
char[] dest = new char[6];
|
||||
dest[0] = 37;
|
||||
dest[3] = 37;
|
||||
dest[5] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
dest[4] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3];
|
||||
dest[2] = UPPER_HEX_DIGITS[(cp >>>= 2) & 0xF];
|
||||
dest[1] = UPPER_HEX_DIGITS[0xC | (cp >>>= 4)];
|
||||
return dest;
|
||||
}
|
||||
if (cp <= 65535) {
|
||||
char[] dest = new char[9];
|
||||
dest[0] = 37;
|
||||
dest[1] = 69;
|
||||
dest[3] = 37;
|
||||
dest[6] = 37;
|
||||
dest[8] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
dest[7] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3];
|
||||
dest[5] = UPPER_HEX_DIGITS[(cp >>>= 2) & 0xF];
|
||||
dest[4] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3];
|
||||
dest[2] = UPPER_HEX_DIGITS[cp >>>= 2];
|
||||
return dest;
|
||||
}
|
||||
if (cp <= 0x10FFFF) {
|
||||
char[] dest = new char[12];
|
||||
dest[0] = 37;
|
||||
dest[1] = 70;
|
||||
dest[3] = 37;
|
||||
dest[6] = 37;
|
||||
dest[9] = 37;
|
||||
dest[11] = UPPER_HEX_DIGITS[cp & 0xF];
|
||||
dest[10] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3];
|
||||
dest[8] = UPPER_HEX_DIGITS[(cp >>>= 2) & 0xF];
|
||||
dest[7] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3];
|
||||
dest[5] = UPPER_HEX_DIGITS[(cp >>>= 2) & 0xF];
|
||||
dest[4] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3];
|
||||
dest[2] = UPPER_HEX_DIGITS[(cp >>>= 2) & 7];
|
||||
return dest;
|
||||
}
|
||||
int n = cp;
|
||||
throw new IllegalArgumentException(new StringBuilder(43).append("Invalid unicode character value ").append(n).toString());
|
||||
}
|
||||
}
|
34
src/com/google/common/net/UrlEscapers.java
Normal file
34
src/com/google/common/net/UrlEscapers.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.net;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.escape.Escaper;
|
||||
import com.google.common.net.PercentEscaper;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public final class UrlEscapers {
|
||||
static final String URL_FORM_PARAMETER_OTHER_SAFE_CHARS = "-_.*";
|
||||
static final String URL_PATH_OTHER_SAFE_CHARS_LACKING_PLUS = "-._~!$'()*,;&=@:";
|
||||
private static final Escaper URL_FORM_PARAMETER_ESCAPER = new PercentEscaper("-_.*", true);
|
||||
private static final Escaper URL_PATH_SEGMENT_ESCAPER = new PercentEscaper("-._~!$'()*,;&=@:+", false);
|
||||
private static final Escaper URL_FRAGMENT_ESCAPER = new PercentEscaper("-._~!$'()*,;&=@:+/?", false);
|
||||
|
||||
private UrlEscapers() {
|
||||
}
|
||||
|
||||
public static Escaper urlFormParameterEscaper() {
|
||||
return URL_FORM_PARAMETER_ESCAPER;
|
||||
}
|
||||
|
||||
public static Escaper urlPathSegmentEscaper() {
|
||||
return URL_PATH_SEGMENT_ESCAPER;
|
||||
}
|
||||
|
||||
public static Escaper urlFragmentEscaper() {
|
||||
return URL_FRAGMENT_ESCAPER;
|
||||
}
|
||||
}
|
8
src/com/google/common/net/package-info.java
Normal file
8
src/com/google/common/net/package-info.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
package com.google.common.net;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue