src/java.base/share/classes/sun/net/util/IPAddressUtil.java
author chegar
Thu, 17 Oct 2019 20:54:25 +0100
branchdatagramsocketimpl-branch
changeset 58679 9c3209ff7550
parent 58678 9cf78a70fa4f
parent 55711 0c143aaa2c99
permissions -rw-r--r--
datagramsocketimpl-branch: merge with default
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
32271
d6cb1602f271 8087190: Regression in sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String)
robm
parents: 25859
diff changeset
     2
 * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.net.util;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
55375
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    28
import java.io.IOException;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    29
import java.io.UncheckedIOException;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    30
import java.net.Inet6Address;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    31
import java.net.InetAddress;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    32
import java.net.InetSocketAddress;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    33
import java.net.NetworkInterface;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    34
import java.net.SocketException;
55711
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
    35
import java.net.URL;
55375
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    36
import java.security.AccessController;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    37
import java.security.PrivilegedExceptionAction;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    38
import java.security.PrivilegedActionException;
55711
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
    39
import java.util.Arrays;
55375
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    40
import java.util.List;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    41
import java.util.concurrent.ConcurrentHashMap;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    42
import java.util.stream.Collectors;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
    43
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
public class IPAddressUtil {
32649
2ee9017c7597 8136583: Core libraries should use blessed modifier order
martin
parents: 32271
diff changeset
    45
    private static final int INADDR4SZ = 4;
2ee9017c7597 8136583: Core libraries should use blessed modifier order
martin
parents: 32271
diff changeset
    46
    private static final int INADDR16SZ = 16;
2ee9017c7597 8136583: Core libraries should use blessed modifier order
martin
parents: 32271
diff changeset
    47
    private static final int INT16SZ = 2;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
     * Converts IPv4 address in its textual presentation form
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
     * into its numeric binary form.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
     * @param src a String representing an IPv4 address in standard format
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
     * @return a byte array representing the IPv4 numeric address
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
     */
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    56
    @SuppressWarnings("fallthrough")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    public static byte[] textToNumericFormatV4(String src)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    {
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    59
        byte[] res = new byte[INADDR4SZ];
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    60
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    61
        long tmpValue = 0;
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    62
        int currByte = 0;
32271
d6cb1602f271 8087190: Regression in sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String)
robm
parents: 25859
diff changeset
    63
        boolean newOctet = true;
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    64
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    65
        int len = src.length();
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    66
        if (len == 0 || len > 15) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
        }
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    69
        /*
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    70
         * When only one part is given, the value is stored directly in
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    71
         * the network address without any byte rearrangement.
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    72
         *
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    73
         * When a two part address is supplied, the last part is
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    74
         * interpreted as a 24-bit quantity and placed in the right
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    75
         * most three bytes of the network address. This makes the
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    76
         * two part address format convenient for specifying Class A
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    77
         * network addresses as net.host.
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    78
         *
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    79
         * When a three part address is specified, the last part is
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    80
         * interpreted as a 16-bit quantity and placed in the right
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    81
         * most two bytes of the network address. This makes the
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    82
         * three part address format convenient for specifying
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    83
         * Class B net- work addresses as 128.net.host.
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    84
         *
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    85
         * When four parts are specified, each is interpreted as a
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    86
         * byte of data and assigned, from left to right, to the
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    87
         * four bytes of an IPv4 address.
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    88
         *
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    89
         * We determine and parse the leading parts, if any, as single
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    90
         * byte values in one pass directly into the resulting byte[],
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    91
         * then the remainder is treated as a 8-to-32-bit entity and
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    92
         * translated into the remaining bytes in the array.
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    93
         */
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    94
        for (int i = 0; i < len; i++) {
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    95
            char c = src.charAt(i);
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
    96
            if (c == '.') {
32271
d6cb1602f271 8087190: Regression in sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String)
robm
parents: 25859
diff changeset
    97
                if (newOctet || tmpValue < 0 || tmpValue > 0xff || currByte == 3) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
                }
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   100
                res[currByte++] = (byte) (tmpValue & 0xff);
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   101
                tmpValue = 0;
32271
d6cb1602f271 8087190: Regression in sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String)
robm
parents: 25859
diff changeset
   102
                newOctet = true;
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   103
            } else {
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   104
                int digit = Character.digit(c, 10);
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   105
                if (digit < 0) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
                }
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   108
                tmpValue *= 10;
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   109
                tmpValue += digit;
32271
d6cb1602f271 8087190: Regression in sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String)
robm
parents: 25859
diff changeset
   110
                newOctet = false;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            }
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   112
        }
32271
d6cb1602f271 8087190: Regression in sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String)
robm
parents: 25859
diff changeset
   113
        if (newOctet || tmpValue < 0 || tmpValue >= (1L << ((4 - currByte) * 8))) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
        }
24042
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   116
        switch (currByte) {
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   117
            case 0:
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   118
                res[0] = (byte) ((tmpValue >> 24) & 0xff);
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   119
            case 1:
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   120
                res[1] = (byte) ((tmpValue >> 16) & 0xff);
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   121
            case 2:
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   122
                res[2] = (byte) ((tmpValue >>  8) & 0xff);
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   123
            case 3:
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   124
                res[3] = (byte) ((tmpValue >>  0) & 0xff);
82290278c4af 8040747: Improve performance of IP address parsing
mduigou
parents: 5506
diff changeset
   125
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
        return res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     * Convert IPv6 presentation level address to network order binary form.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     * credit:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     *  Converted from C code from Solaris 8 (inet_pton)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
     * Any component of the string following a per-cent % is ignored.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     * @param src a String representing an IPv6 address in textual format
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     * @return a byte array representing the IPv6 numeric address
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    public static byte[] textToNumericFormatV6(String src)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        // Shortest valid string is "::", hence at least 2 chars
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        if (src.length() < 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        int colonp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
        char ch;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
        boolean saw_xdigit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
        int val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        char[] srcb = src.toCharArray();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        byte[] dst = new byte[INADDR16SZ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        int srcb_length = srcb.length;
24685
215fa91e1b4c 8044461: Cleanup new Boolean and single character strings
rriggs
parents: 24042
diff changeset
   154
        int pc = src.indexOf ('%');
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
        if (pc == srcb_length -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        if (pc != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            srcb_length = pc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        colonp = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        int i = 0, j = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        /* Leading :: requires some special handling. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        if (srcb[i] == ':')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
            if (srcb[++i] != ':')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        int curtok = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        saw_xdigit = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        val = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        while (i < srcb_length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
            ch = srcb[i++];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            int chval = Character.digit(ch, 16);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
            if (chval != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                val <<= 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
                val |= chval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
                if (val > 0xffff)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                saw_xdigit = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
            if (ch == ':') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                curtok = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                if (!saw_xdigit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                    if (colonp != -1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
                    colonp = j;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                    continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
                } else if (i == srcb_length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
                if (j + INT16SZ > INADDR16SZ)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
                dst[j++] = (byte) ((val >> 8) & 0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
                dst[j++] = (byte) (val & 0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
                saw_xdigit = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                val = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            if (ch == '.' && ((j + INADDR4SZ) <= INADDR16SZ)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
                String ia4 = src.substring(curtok, srcb_length);
52499
768b1c612100 8213490: Networking area typos and inconsistencies cleanup
prappo
parents: 47216
diff changeset
   203
                /* check this IPv4 address has 3 dots, i.e. A.B.C.D */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                int dot_count = 0, index=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                while ((index = ia4.indexOf ('.', index)) != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                    dot_count ++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                    index ++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                if (dot_count != 3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                byte[] v4addr = textToNumericFormatV4(ia4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                if (v4addr == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
                for (int k = 0; k < INADDR4SZ; k++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                    dst[j++] = v4addr[k];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                saw_xdigit = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                break;  /* '\0' was seen by inet_pton4(). */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
        if (saw_xdigit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
            if (j + INT16SZ > INADDR16SZ)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            dst[j++] = (byte) ((val >> 8) & 0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
            dst[j++] = (byte) (val & 0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        if (colonp != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
            int n = j - colonp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
            if (j == INADDR16SZ)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
            for (i = 1; i <= n; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                dst[INADDR16SZ - i] = dst[colonp + n - i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                dst[colonp + n - i] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
            j = INADDR16SZ;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        if (j != INADDR16SZ)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
        byte[] newdst = convertFromIPv4MappedAddress(dst);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
        if (newdst != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
            return newdst;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
            return dst;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
     * @param src a String representing an IPv4 address in textual format
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
     * @return a boolean indicating whether src is an IPv4 literal address
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    public static boolean isIPv4LiteralAddress(String src) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        return textToNumericFormatV4(src) != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
     * @param src a String representing an IPv6 address in textual format
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
     * @return a boolean indicating whether src is an IPv6 literal address
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
    public static boolean isIPv6LiteralAddress(String src) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        return textToNumericFormatV6(src) != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
     * Convert IPv4-Mapped address to IPv4 address. Both input and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     * returned value are in network order binary form.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
     * @param src a String representing an IPv4-Mapped address in textual format
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
     * @return a byte array representing the IPv4 numeric address
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
    public static byte[] convertFromIPv4MappedAddress(byte[] addr) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        if (isIPv4MappedAddress(addr)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            byte[] newAddr = new byte[INADDR4SZ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            System.arraycopy(addr, 12, newAddr, 0, INADDR4SZ);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            return newAddr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
     * Utility routine to check if the InetAddress is an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     * IPv4 mapped IPv6 address.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     * @return a <code>boolean</code> indicating if the InetAddress is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     * an IPv4 mapped IPv6 address; or false if address is IPv4 address.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
    private static boolean isIPv4MappedAddress(byte[] addr) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        if (addr.length < INADDR16SZ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        if ((addr[0] == 0x00) && (addr[1] == 0x00) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
            (addr[2] == 0x00) && (addr[3] == 0x00) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            (addr[4] == 0x00) && (addr[5] == 0x00) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            (addr[6] == 0x00) && (addr[7] == 0x00) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
            (addr[8] == 0x00) && (addr[9] == 0x00) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            (addr[10] == (byte)0xff) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            (addr[11] == (byte)0xff))  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
    }
55375
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   306
    /**
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   307
     * Mapping from unscoped local Inet(6)Address to the same address
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   308
     * including the correct scope-id, determined from NetworkInterface.
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   309
     */
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   310
    private final static ConcurrentHashMap<InetAddress,InetAddress>
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   311
        cache = new ConcurrentHashMap<>();
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   312
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   313
    /**
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   314
     * Returns a scoped version of the supplied local, link-local ipv6 address
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   315
     * if that scope-id can be determined from local NetworkInterfaces.
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   316
     * If the address already has a scope-id or if the address is not local, ipv6
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   317
     * or link local, then the original address is returned.
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   318
     *
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   319
     * @param addr
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   320
     * @exception SocketException if the given ipv6 link local address is found
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   321
     *            on more than one local interface
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   322
     * @return
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   323
     */
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   324
    public static InetAddress toScopedAddress(InetAddress address)
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   325
        throws SocketException {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   326
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   327
        if (address instanceof Inet6Address && address.isLinkLocalAddress()
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   328
            && ((Inet6Address) address).getScopeId() == 0) {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   329
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   330
            InetAddress cached = null;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   331
            try {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   332
                cached = cache.computeIfAbsent(address, k -> findScopedAddress(k));
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   333
            } catch (UncheckedIOException e) {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   334
                throw (SocketException)e.getCause();
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   335
            }
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   336
            return cached != null ? cached : address;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   337
        } else {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   338
            return address;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   339
        }
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   340
    }
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   341
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   342
    /**
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   343
     * Same as above for InetSocketAddress
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   344
     */
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   345
    public static InetSocketAddress toScopedAddress(InetSocketAddress address)
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   346
        throws SocketException {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   347
        InetAddress addr;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   348
        InetAddress orig = address.getAddress();
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   349
        if ((addr = toScopedAddress(orig)) == orig) {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   350
            return address;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   351
        } else {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   352
            return new InetSocketAddress(addr, address.getPort());
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   353
        }
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   354
    }
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   355
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   356
    private static InetAddress findScopedAddress(InetAddress address) {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   357
        PrivilegedExceptionAction<List<InetAddress>> pa = () -> NetworkInterface.networkInterfaces()
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   358
                .flatMap(NetworkInterface::inetAddresses)
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   359
                .filter(a -> (a instanceof Inet6Address)
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   360
                        && address.equals(a)
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   361
                        && ((Inet6Address) a).getScopeId() != 0)
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   362
                .collect(Collectors.toList());
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   363
        List<InetAddress> result;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   364
        try {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   365
            result = AccessController.doPrivileged(pa);
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   366
            var sz = result.size();
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   367
            if (sz == 0)
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   368
                return null;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   369
            if (sz > 1)
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   370
                throw new UncheckedIOException(new SocketException(
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   371
                    "Duplicate link local addresses: must specify scope-id"));
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   372
            return result.get(0);
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   373
        } catch (PrivilegedActionException pae) {
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   374
            return null;
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   375
        }
96c7427456f9 8216417: cleanup of IPv6 scope-id handling
michaelm
parents: 52499
diff changeset
   376
    }
55711
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   377
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   378
    // See java.net.URI for more details on how to generate these
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   379
    // masks.
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   380
    //
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   381
    // square brackets
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   382
    private static final long L_IPV6_DELIMS = 0x0L; // "[]"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   383
    private static final long H_IPV6_DELIMS = 0x28000000L; // "[]"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   384
    // RFC 3986 gen-delims
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   385
    private static final long L_GEN_DELIMS = 0x8400800800000000L; // ":/?#[]@"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   386
    private static final long H_GEN_DELIMS = 0x28000001L; // ":/?#[]@"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   387
    // These gen-delims can appear in authority
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   388
    private static final long L_AUTH_DELIMS = 0x400000000000000L; // "@[]:"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   389
    private static final long H_AUTH_DELIMS = 0x28000001L; // "@[]:"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   390
    // colon is allowed in userinfo
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   391
    private static final long L_COLON = 0x400000000000000L; // ":"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   392
    private static final long H_COLON = 0x0L; // ":"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   393
    // slash should be encoded in authority
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   394
    private static final long L_SLASH = 0x800000000000L; // "/"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   395
    private static final long H_SLASH = 0x0L; // "/"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   396
    // backslash should always be encoded
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   397
    private static final long L_BACKSLASH = 0x0L; // "\"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   398
    private static final long H_BACKSLASH = 0x10000000L; // "\"
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   399
    // ASCII chars 0-31 + 127 - various controls + CRLF + TAB
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   400
    private static final long L_NON_PRINTABLE = 0xffffffffL;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   401
    private static final long H_NON_PRINTABLE = 0x8000000000000000L;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   402
    // All of the above
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   403
    private static final long L_EXCLUDE = 0x84008008ffffffffL;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   404
    private static final long H_EXCLUDE = 0x8000000038000001L;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   405
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   406
    private static final char[] OTHERS = {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   407
            8263,8264,8265,8448,8449,8453,8454,10868,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   408
            65109,65110,65119,65131,65283,65295,65306,65311,65312
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   409
    };
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   410
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   411
    // Tell whether the given character is found by the given mask pair
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   412
    public static boolean match(char c, long lowMask, long highMask) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   413
        if (c < 64)
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   414
            return ((1L << c) & lowMask) != 0;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   415
        if (c < 128)
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   416
            return ((1L << (c - 64)) & highMask) != 0;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   417
        return false; // other non ASCII characters are not filtered
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   418
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   419
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   420
    // returns -1 if the string doesn't contain any characters
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   421
    // from the mask, the index of the first such character found
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   422
    // otherwise.
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   423
    public static int scan(String s, long lowMask, long highMask) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   424
        int i = -1, len;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   425
        if (s == null || (len = s.length()) == 0) return -1;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   426
        boolean match = false;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   427
        while (++i < len && !(match = match(s.charAt(i), lowMask, highMask)));
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   428
        if (match) return i;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   429
        return -1;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   430
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   431
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   432
    public static int scan(String s, long lowMask, long highMask, char[] others) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   433
        int i = -1, len;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   434
        if (s == null || (len = s.length()) == 0) return -1;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   435
        boolean match = false;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   436
        char c, c0 = others[0];
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   437
        while (++i < len && !(match = match((c=s.charAt(i)), lowMask, highMask))) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   438
            if (c >= c0 && (Arrays.binarySearch(others, c) > -1)) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   439
                match = true; break;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   440
            }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   441
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   442
        if (match) return i;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   443
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   444
        return -1;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   445
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   446
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   447
    private static String describeChar(char c) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   448
        if (c < 32 || c == 127) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   449
            if (c == '\n') return "LF";
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   450
            if (c == '\r') return "CR";
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   451
            return "control char (code=" + (int)c + ")";
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   452
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   453
        if (c == '\\') return "'\\'";
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   454
        return "'" + c + "'";
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   455
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   456
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   457
    private static String checkUserInfo(String str) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   458
        // colon is permitted in user info
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   459
        int index = scan(str, L_EXCLUDE & ~L_COLON,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   460
                H_EXCLUDE & ~H_COLON);
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   461
        if (index >= 0) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   462
            return "Illegal character found in user-info: "
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   463
                    + describeChar(str.charAt(index));
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   464
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   465
        return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   466
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   467
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   468
    private static String checkHost(String str) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   469
        int index;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   470
        if (str.startsWith("[") && str.endsWith("]")) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   471
            str = str.substring(1, str.length() - 1);
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   472
            if (isIPv6LiteralAddress(str)) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   473
                index = str.indexOf('%');
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   474
                if (index >= 0) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   475
                    index = scan(str = str.substring(index),
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   476
                            L_NON_PRINTABLE | L_IPV6_DELIMS,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   477
                            H_NON_PRINTABLE | H_IPV6_DELIMS);
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   478
                    if (index >= 0) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   479
                        return "Illegal character found in IPv6 scoped address: "
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   480
                                + describeChar(str.charAt(index));
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   481
                    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   482
                }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   483
                return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   484
            }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   485
            return "Unrecognized IPv6 address format";
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   486
        } else {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   487
            index = scan(str, L_EXCLUDE, H_EXCLUDE);
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   488
            if (index >= 0) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   489
                return "Illegal character found in host: "
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   490
                        + describeChar(str.charAt(index));
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   491
            }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   492
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   493
        return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   494
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   495
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   496
    private static String checkAuth(String str) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   497
        int index = scan(str,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   498
                L_EXCLUDE & ~L_AUTH_DELIMS,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   499
                H_EXCLUDE & ~H_AUTH_DELIMS);
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   500
        if (index >= 0) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   501
            return "Illegal character found in authority: "
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   502
                    + describeChar(str.charAt(index));
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   503
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   504
        return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   505
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   506
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   507
    // check authority of hierarchical URL. Appropriate for
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   508
    // HTTP-like protocol handlers
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   509
    public static String checkAuthority(URL url) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   510
        String s, u, h;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   511
        if (url == null) return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   512
        if ((s = checkUserInfo(u = url.getUserInfo())) != null) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   513
            return s;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   514
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   515
        if ((s = checkHost(h = url.getHost())) != null) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   516
            return s;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   517
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   518
        if (h == null && u == null) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   519
            return checkAuth(url.getAuthority());
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   520
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   521
        return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   522
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   523
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   524
    // minimal syntax checks - deeper check may be performed
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   525
    // by the appropriate protocol handler
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   526
    public static String checkExternalForm(URL url) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   527
        String s;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   528
        if (url == null) return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   529
        int index = scan(s = url.getUserInfo(),
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   530
                L_NON_PRINTABLE | L_SLASH,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   531
                H_NON_PRINTABLE | H_SLASH);
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   532
        if (index >= 0) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   533
            return "Illegal character found in authority: "
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   534
                    + describeChar(s.charAt(index));
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   535
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   536
        if ((s = checkHostString(url.getHost())) != null) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   537
            return s;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   538
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   539
        return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   540
    }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   541
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   542
    public static String checkHostString(String host) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   543
        if (host == null) return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   544
        int index = scan(host,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   545
                L_NON_PRINTABLE | L_SLASH,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   546
                H_NON_PRINTABLE | H_SLASH,
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   547
                OTHERS);
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   548
        if (index >= 0) {
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   549
            return "Illegal character found in host: "
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   550
                    + describeChar(host.charAt(index));
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   551
        }
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   552
        return null;
0c143aaa2c99 8221518: Normalize normalization
dfuchs
parents: 55375
diff changeset
   553
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
}