|
23 | 23 | import java.net.UnknownHostException;
|
24 | 24 | import java.nio.charset.Charset;
|
25 | 25 | import java.util.ArrayList;
|
26 |
| -import java.util.Arrays; |
27 | 26 | import java.util.Collections;
|
28 | 27 | import java.util.LinkedHashSet;
|
29 | 28 | import java.util.List;
|
|
33 | 32 | import okhttp3.internal.publicsuffix.PublicSuffixDatabase;
|
34 | 33 | import okio.Buffer;
|
35 | 34 |
|
| 35 | +import static okhttp3.internal.Util.decodeHexDigit; |
36 | 36 | import static okhttp3.internal.Util.delimiterOffset;
|
37 |
| -import static okhttp3.internal.Util.domainToAscii; |
38 | 37 | import static okhttp3.internal.Util.skipLeadingAsciiWhitespace;
|
39 | 38 | import static okhttp3.internal.Util.skipTrailingAsciiWhitespace;
|
40 | 39 | import static okhttp3.internal.Util.verifyAsIpAddress;
|
@@ -1589,162 +1588,7 @@ private static String canonicalizeHost(String input, int pos, int limit) {
|
1589 | 1588 | // Start by percent decoding the host. The WHATWG spec suggests doing this only after we've
|
1590 | 1589 | // checked for IPv6 square braces. But Chrome does it first, and that's more lenient.
|
1591 | 1590 | String percentDecoded = percentDecode(input, pos, limit, false);
|
1592 |
| - |
1593 |
| - // If the input contains a :, it’s an IPv6 address. |
1594 |
| - if (percentDecoded.contains(":")) { |
1595 |
| - // If the input is encased in square braces "[...]", drop 'em. |
1596 |
| - InetAddress inetAddress = percentDecoded.startsWith("[") && percentDecoded.endsWith("]") |
1597 |
| - ? decodeIpv6(percentDecoded, 1, percentDecoded.length() - 1) |
1598 |
| - : decodeIpv6(percentDecoded, 0, percentDecoded.length()); |
1599 |
| - if (inetAddress == null) return null; |
1600 |
| - byte[] address = inetAddress.getAddress(); |
1601 |
| - if (address.length == 16) return inet6AddressToAscii(address); |
1602 |
| - throw new AssertionError("Invalid IPv6 address: '" + percentDecoded + "'"); |
1603 |
| - } |
1604 |
| - |
1605 |
| - return domainToAscii(percentDecoded); |
1606 |
| - } |
1607 |
| - |
1608 |
| - /** Decodes an IPv6 address like 1111:2222:3333:4444:5555:6666:7777:8888 or ::1. */ |
1609 |
| - private static @Nullable InetAddress decodeIpv6(String input, int pos, int limit) { |
1610 |
| - byte[] address = new byte[16]; |
1611 |
| - int b = 0; |
1612 |
| - int compress = -1; |
1613 |
| - int groupOffset = -1; |
1614 |
| - |
1615 |
| - for (int i = pos; i < limit; ) { |
1616 |
| - if (b == address.length) return null; // Too many groups. |
1617 |
| - |
1618 |
| - // Read a delimiter. |
1619 |
| - if (i + 2 <= limit && input.regionMatches(i, "::", 0, 2)) { |
1620 |
| - // Compression "::" delimiter, which is anywhere in the input, including its prefix. |
1621 |
| - if (compress != -1) return null; // Multiple "::" delimiters. |
1622 |
| - i += 2; |
1623 |
| - b += 2; |
1624 |
| - compress = b; |
1625 |
| - if (i == limit) break; |
1626 |
| - } else if (b != 0) { |
1627 |
| - // Group separator ":" delimiter. |
1628 |
| - if (input.regionMatches(i, ":", 0, 1)) { |
1629 |
| - i++; |
1630 |
| - } else if (input.regionMatches(i, ".", 0, 1)) { |
1631 |
| - // If we see a '.', rewind to the beginning of the previous group and parse as IPv4. |
1632 |
| - if (!decodeIpv4Suffix(input, groupOffset, limit, address, b - 2)) return null; |
1633 |
| - b += 2; // We rewound two bytes and then added four. |
1634 |
| - break; |
1635 |
| - } else { |
1636 |
| - return null; // Wrong delimiter. |
1637 |
| - } |
1638 |
| - } |
1639 |
| - |
1640 |
| - // Read a group, one to four hex digits. |
1641 |
| - int value = 0; |
1642 |
| - groupOffset = i; |
1643 |
| - for (; i < limit; i++) { |
1644 |
| - char c = input.charAt(i); |
1645 |
| - int hexDigit = decodeHexDigit(c); |
1646 |
| - if (hexDigit == -1) break; |
1647 |
| - value = (value << 4) + hexDigit; |
1648 |
| - } |
1649 |
| - int groupLength = i - groupOffset; |
1650 |
| - if (groupLength == 0 || groupLength > 4) return null; // Group is the wrong size. |
1651 |
| - |
1652 |
| - // We've successfully read a group. Assign its value to our byte array. |
1653 |
| - address[b++] = (byte) ((value >>> 8) & 0xff); |
1654 |
| - address[b++] = (byte) (value & 0xff); |
1655 |
| - } |
1656 |
| - |
1657 |
| - // All done. If compression happened, we need to move bytes to the right place in the |
1658 |
| - // address. Here's a sample: |
1659 |
| - // |
1660 |
| - // input: "1111:2222:3333::7777:8888" |
1661 |
| - // before: { 11, 11, 22, 22, 33, 33, 00, 00, 77, 77, 88, 88, 00, 00, 00, 00 } |
1662 |
| - // compress: 6 |
1663 |
| - // b: 10 |
1664 |
| - // after: { 11, 11, 22, 22, 33, 33, 00, 00, 00, 00, 00, 00, 77, 77, 88, 88 } |
1665 |
| - // |
1666 |
| - if (b != address.length) { |
1667 |
| - if (compress == -1) return null; // Address didn't have compression or enough groups. |
1668 |
| - System.arraycopy(address, compress, address, address.length - (b - compress), b - compress); |
1669 |
| - Arrays.fill(address, compress, compress + (address.length - b), (byte) 0); |
1670 |
| - } |
1671 |
| - |
1672 |
| - try { |
1673 |
| - return InetAddress.getByAddress(address); |
1674 |
| - } catch (UnknownHostException e) { |
1675 |
| - throw new AssertionError(); |
1676 |
| - } |
1677 |
| - } |
1678 |
| - |
1679 |
| - /** Decodes an IPv4 address suffix of an IPv6 address, like 1111::5555:6666:192.168.0.1. */ |
1680 |
| - private static boolean decodeIpv4Suffix( |
1681 |
| - String input, int pos, int limit, byte[] address, int addressOffset) { |
1682 |
| - int b = addressOffset; |
1683 |
| - |
1684 |
| - for (int i = pos; i < limit; ) { |
1685 |
| - if (b == address.length) return false; // Too many groups. |
1686 |
| - |
1687 |
| - // Read a delimiter. |
1688 |
| - if (b != addressOffset) { |
1689 |
| - if (input.charAt(i) != '.') return false; // Wrong delimiter. |
1690 |
| - i++; |
1691 |
| - } |
1692 |
| - |
1693 |
| - // Read 1 or more decimal digits for a value in 0..255. |
1694 |
| - int value = 0; |
1695 |
| - int groupOffset = i; |
1696 |
| - for (; i < limit; i++) { |
1697 |
| - char c = input.charAt(i); |
1698 |
| - if (c < '0' || c > '9') break; |
1699 |
| - if (value == 0 && groupOffset != i) return false; // Reject unnecessary leading '0's. |
1700 |
| - value = (value * 10) + c - '0'; |
1701 |
| - if (value > 255) return false; // Value out of range. |
1702 |
| - } |
1703 |
| - int groupLength = i - groupOffset; |
1704 |
| - if (groupLength == 0) return false; // No digits. |
1705 |
| - |
1706 |
| - // We've successfully read a byte. |
1707 |
| - address[b++] = (byte) value; |
1708 |
| - } |
1709 |
| - |
1710 |
| - if (b != addressOffset + 4) return false; // Too few groups. We wanted exactly four. |
1711 |
| - return true; // Success. |
1712 |
| - } |
1713 |
| - |
1714 |
| - /** Encodes an IPv6 address in canonical form according to RFC 5952. */ |
1715 |
| - private static String inet6AddressToAscii(byte[] address) { |
1716 |
| - // Go through the address looking for the longest run of 0s. Each group is 2-bytes. |
1717 |
| - // A run must be longer than one group (section 4.2.2). |
1718 |
| - // If there are multiple equal runs, the first one must be used (section 4.2.3). |
1719 |
| - int longestRunOffset = -1; |
1720 |
| - int longestRunLength = 0; |
1721 |
| - for (int i = 0; i < address.length; i += 2) { |
1722 |
| - int currentRunOffset = i; |
1723 |
| - while (i < 16 && address[i] == 0 && address[i + 1] == 0) { |
1724 |
| - i += 2; |
1725 |
| - } |
1726 |
| - int currentRunLength = i - currentRunOffset; |
1727 |
| - if (currentRunLength > longestRunLength && currentRunLength >= 4) { |
1728 |
| - longestRunOffset = currentRunOffset; |
1729 |
| - longestRunLength = currentRunLength; |
1730 |
| - } |
1731 |
| - } |
1732 |
| - |
1733 |
| - // Emit each 2-byte group in hex, separated by ':'. The longest run of zeroes is "::". |
1734 |
| - Buffer result = new Buffer(); |
1735 |
| - for (int i = 0; i < address.length; ) { |
1736 |
| - if (i == longestRunOffset) { |
1737 |
| - result.writeByte(':'); |
1738 |
| - i += longestRunLength; |
1739 |
| - if (i == 16) result.writeByte(':'); |
1740 |
| - } else { |
1741 |
| - if (i > 0) result.writeByte(':'); |
1742 |
| - int group = (address[i] & 0xff) << 8 | address[i + 1] & 0xff; |
1743 |
| - result.writeHexadecimalUnsignedLong(group); |
1744 |
| - i += 2; |
1745 |
| - } |
1746 |
| - } |
1747 |
| - return result.readUtf8(); |
| 1591 | + return Util.canonicalizeHost(percentDecoded); |
1748 | 1592 | }
|
1749 | 1593 |
|
1750 | 1594 | private static int parsePort(String input, int pos, int limit) {
|
@@ -1817,13 +1661,6 @@ && decodeHexDigit(encoded.charAt(pos + 1)) != -1
|
1817 | 1661 | && decodeHexDigit(encoded.charAt(pos + 2)) != -1;
|
1818 | 1662 | }
|
1819 | 1663 |
|
1820 |
| - static int decodeHexDigit(char c) { |
1821 |
| - if (c >= '0' && c <= '9') return c - '0'; |
1822 |
| - if (c >= 'a' && c <= 'f') return c - 'a' + 10; |
1823 |
| - if (c >= 'A' && c <= 'F') return c - 'A' + 10; |
1824 |
| - return -1; |
1825 |
| - } |
1826 |
| - |
1827 | 1664 | /**
|
1828 | 1665 | * Returns a substring of {@code input} on the range {@code [pos..limit)} with the following
|
1829 | 1666 | * transformations:
|
|
0 commit comments