151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.net.www; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.BitSet; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.UnsupportedEncodingException; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.File; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.URL; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.MalformedURLException; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.URI; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.URISyntaxException; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.ByteBuffer; 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.CharBuffer; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.CharacterCodingException; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.nio.cs.ThreadLocalCoders; 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.CharsetDecoder; 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.CoderResult; 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.CodingErrorAction; 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A class that contains useful routines common to sun.net.www 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Mike McCloskey 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class ParseUtil { 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static BitSet encodedInPath; 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static { 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath = new BitSet(256); 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Set the bits corresponding to characters that are encoded in the 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // path component of a URI. 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // These characters are reserved in the path segment as described in 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // RFC2396 section 3.3. 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('='); 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set(';'); 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('?'); 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('/'); 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // These characters are defined as excluded in RFC2396 section 2.4.3 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and must be escaped if they occur in the data part of a URI. 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('#'); 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set(' '); 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('<'); 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('>'); 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('%'); 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('"'); 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('{'); 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('}'); 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('|'); 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('\\'); 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('^'); 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('['); 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set(']'); 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set('`'); 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // US ASCII control characters 00-1F and 7F. 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i=0; i<32; i++) 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set(i); 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encodedInPath.set(127); 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Constructs an encoded version of the specified path string suitable 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for use in the construction of a URL. 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A path separator is replaced by a forward slash. The string is UTF8 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoded. The % escape sequence is used for characters that are above 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 0x7F or those defined in RFC2396 as reserved or excluded in the path 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * component of a URL. 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static String encodePath(String path) { 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return encodePath(path, true); 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * flag indicates whether path uses platform dependent 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * File.separatorChar or not. True indicates path uses platform 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * dependent File.separatorChar. 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static String encodePath(String path, boolean flag) { 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char[] retCC = new char[path.length() * 2 + 16]; 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int retLen = 0; 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char[] pathCC = path.toCharArray(); 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = path.length(); 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i=0; i<n; i++) { 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = pathCC[i]; 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((!flag && c == '/') || (flag && c == File.separatorChar)) 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retCC[retLen++] = '/'; 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else { 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c <= 0x007F) { 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c >= 'a' && c <= 'z' || 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c >= 'A' && c <= 'Z' || 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c >= '0' && c <= '9') { 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retCC[retLen++] = c; 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (encodedInPath.get(c)) 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retLen = escape(retCC, c, retLen); 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retCC[retLen++] = c; 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (c > 0x07FF) { 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retLen = escape(retCC, (char)(0xE0 | ((c >> 12) & 0x0F)), retLen); 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retLen = escape(retCC, (char)(0x80 | ((c >> 6) & 0x3F)), retLen); 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retLen = escape(retCC, (char)(0x80 | ((c >> 0) & 0x3F)), retLen); 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retLen = escape(retCC, (char)(0xC0 | ((c >> 6) & 0x1F)), retLen); 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retLen = escape(retCC, (char)(0x80 | ((c >> 0) & 0x3F)), retLen); 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski //worst case scenario for character [0x7ff-] every single 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski //character will be encoded into 9 characters. 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (retLen + 9 > retCC.length) { 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int newLen = retCC.length * 2 + 16; 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (newLen < 0) { 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newLen = Integer.MAX_VALUE; 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char[] buf = new char[newLen]; 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(retCC, 0, buf, 0, retLen); 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retCC = buf; 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new String(retCC, 0, retLen); 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Appends the URL escape sequence for the specified char to the 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specified StringBuffer. 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int escape(char[] cc, char c, int index) { 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cc[index++] = '%'; 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cc[index++] = Character.forDigit((c >> 4) & 0xF, 16); 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cc[index++] = Character.forDigit(c & 0xF, 16); 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return index; 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Un-escape and return the character at position i in string s. 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static byte unescape(String s, int i) { 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (byte) Integer.parseInt(s.substring(i+1,i+3),16); 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a new String constructed from the specified String by replacing 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the URL escape sequences and UTF8 encoding with the characters they 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * represent. 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static String decode(String s) { 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = s.length(); 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((n == 0) || (s.indexOf('%') < 0)) 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return s; 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuilder sb = new StringBuilder(n); 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteBuffer bb = ByteBuffer.allocate(n); 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CharBuffer cb = CharBuffer.allocate(n); 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CharsetDecoder dec = ThreadLocalCoders.decoderFor("UTF-8") 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .onMalformedInput(CodingErrorAction.REPORT) 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .onUnmappableCharacter(CodingErrorAction.REPORT); 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = s.charAt(0); 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < n;) { 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert c == s.charAt(i); 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c != '%') { 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(c); 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (++i >= n) 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = s.charAt(i); 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bb.clear(); 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int ui = i; 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (;;) { 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert (n - i >= 2); 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bb.put(unescape(s, i)); 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (NumberFormatException e) { 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException(); 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski i += 3; 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i >= n) 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski c = s.charAt(i); 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c != '%') 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bb.flip(); 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cb.clear(); 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dec.reset(); 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CoderResult cr = dec.decode(bb, cb, true); 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (cr.isError()) 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("Error decoding percent encoded characters"); 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cr = dec.flush(cb); 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (cr.isError()) 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("Error decoding percent encoded characters"); 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(cb.flip().toString()); 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return sb.toString(); 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns a canonical version of the specified string. 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String canonizeString(String file) { 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i = 0; 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int lim = file.length(); 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Remove embedded /../ 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((i = file.indexOf("/../")) >= 0) { 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((lim = file.lastIndexOf('/', i - 1)) >= 0) { 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file = file.substring(0, lim) + file.substring(i + 3); 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file = file.substring(i + 3); 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Remove embedded /./ 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((i = file.indexOf("/./")) >= 0) { 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file = file.substring(0, i) + file.substring(i + 2); 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Remove trailing .. 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (file.endsWith("/..")) { 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski i = file.indexOf("/.."); 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((lim = file.lastIndexOf('/', i - 1)) >= 0) { 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file = file.substring(0, lim+1); 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file = file.substring(0, i); 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Remove trailing . 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (file.endsWith("/.")) 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file = file.substring(0, file.length() -1); 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return file; 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static URL fileToEncodedURL(File file) 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws MalformedURLException 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String path = file.getAbsolutePath(); 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski path = ParseUtil.encodePath(path); 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!path.startsWith("/")) { 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski path = "/" + path; 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!path.endsWith("/") && file.isDirectory()) { 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski path = path + "/"; 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new URL("file", "", path); 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static java.net.URI toURI(URL url) { 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String protocol = url.getProtocol(); 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String auth = url.getAuthority(); 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String path = url.getPath(); 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String query = url.getQuery(); 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String ref = url.getRef(); 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (path != null && !(path.startsWith("/"))) 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski path = "/" + path; 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // In java.net.URI class, a port number of -1 implies the default 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // port number. So get it stripped off before creating URI instance. 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (auth != null && auth.endsWith(":-1")) 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski auth = auth.substring(0, auth.length() - 3); 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski java.net.URI uri; 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski uri = createURI(protocol, auth, path, query, ref); 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (java.net.URISyntaxException e) { 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski uri = null; 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return uri; 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // createURI() and its auxiliary code are cloned from java.net.URI. 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Most of the code are just copy and paste, except that quote() 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // has been modified to avoid double-escape. 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Usually it is unacceptable, but we're forced to do it because 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // otherwise we need to change public API, namely java.net.URI's 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // multi-argument constructors. It turns out that the changes cause 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // incompatibilities so can't be done. 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static URI createURI(String scheme, 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String authority, 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String path, 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String query, 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String fragment) throws URISyntaxException 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = toString(scheme, null, 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski authority, null, null, -1, 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski path, query, fragment); 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkPath(s, scheme, path); 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new URI(s); 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static String toString(String scheme, 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String opaquePart, 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String authority, 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String userInfo, 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String host, 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int port, 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String path, 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String query, 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String fragment) 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(); 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (scheme != null) { 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(scheme); 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(':'); 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski appendSchemeSpecificPart(sb, opaquePart, 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski authority, userInfo, host, port, 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski path, query); 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski appendFragment(sb, fragment); 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return sb.toString(); 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static void appendSchemeSpecificPart(StringBuffer sb, 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String opaquePart, 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String authority, 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String userInfo, 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String host, 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int port, 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String path, 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String query) 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (opaquePart != null) { 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* check if SSP begins with an IPv6 address 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * because we must not quote a literal IPv6 address 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (opaquePart.startsWith("//[")) { 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int end = opaquePart.indexOf("]"); 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (end != -1 && opaquePart.indexOf(":")!=-1) { 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String doquote, dontquote; 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (end == opaquePart.length()) { 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dontquote = opaquePart; 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski doquote = ""; 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dontquote = opaquePart.substring(0,end+1); 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski doquote = opaquePart.substring(end+1); 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append (dontquote); 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(quote(doquote, L_URIC, H_URIC)); 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(quote(opaquePart, L_URIC, H_URIC)); 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski appendAuthority(sb, authority, userInfo, host, port); 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (path != null) 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(quote(path, L_PATH, H_PATH)); 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (query != null) { 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append('?'); 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(quote(query, L_URIC, H_URIC)); 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static void appendAuthority(StringBuffer sb, 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String authority, 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String userInfo, 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String host, 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int port) 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (host != null) { 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append("//"); 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (userInfo != null) { 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(quote(userInfo, L_USERINFO, H_USERINFO)); 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append('@'); 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean needBrackets = ((host.indexOf(':') >= 0) 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && !host.startsWith("[") 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && !host.endsWith("]")); 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (needBrackets) sb.append('['); 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(host); 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (needBrackets) sb.append(']'); 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (port != -1) { 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(':'); 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(port); 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (authority != null) { 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append("//"); 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (authority.startsWith("[")) { 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int end = authority.indexOf("]"); 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (end != -1 && authority.indexOf(":")!=-1) { 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String doquote, dontquote; 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (end == authority.length()) { 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dontquote = authority; 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski doquote = ""; 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dontquote = authority.substring(0,end+1); 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski doquote = authority.substring(end+1); 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append (dontquote); 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(quote(doquote, 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski L_REG_NAME | L_SERVER, 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski H_REG_NAME | H_SERVER)); 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(quote(authority, 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski L_REG_NAME | L_SERVER, 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski H_REG_NAME | H_SERVER)); 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static void appendFragment(StringBuffer sb, String fragment) { 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (fragment != null) { 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append('#'); 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(quote(fragment, L_URIC, H_URIC)); 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Quote any characters in s that are not permitted 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // by the given mask pair 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static String quote(String s, long lowMask, long highMask) { 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = s.length(); 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = null; 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean allowNonASCII = ((lowMask & L_ESCAPED) != 0); 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < s.length(); i++) { 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = s.charAt(i); 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c < '\u0080') { 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!match(c, lowMask, highMask) && !isEscaped(s, i)) { 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sb == null) { 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb = new StringBuffer(); 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(s.substring(0, i)); 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski appendEscape(sb, (byte)c); 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sb != null) 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(c); 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (allowNonASCII 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && (Character.isSpaceChar(c) 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski || Character.isISOControl(c))) { 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sb == null) { 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb = new StringBuffer(); 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(s.substring(0, i)); 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski appendEncoded(sb, c); 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sb != null) 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(c); 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (sb == null) ? s : sb.toString(); 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // To check if the given string has an escaped triplet 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // at the given position 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static boolean isEscaped(String s, int pos) { 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s == null || (s.length() <= (pos + 2))) 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return s.charAt(pos) == '%' 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && match(s.charAt(pos + 1), L_HEX, H_HEX) 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && match(s.charAt(pos + 2), L_HEX, H_HEX); 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static void appendEncoded(StringBuffer sb, char c) { 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteBuffer bb = null; 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski bb = ThreadLocalCoders.encoderFor("UTF-8") 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .encode(CharBuffer.wrap("" + c)); 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (CharacterCodingException x) { 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert false; 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (bb.hasRemaining()) { 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int b = bb.get() & 0xff; 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (b >= 0x80) 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski appendEscape(sb, (byte)b); 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append((char)b); 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final static char[] hexDigits = { 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '0', '1', '2', '3', '4', '5', '6', '7', 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static void appendEscape(StringBuffer sb, byte b) { 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append('%'); 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(hexDigits[(b >> 4) & 0x0f]); 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(hexDigits[(b >> 0) & 0x0f]); 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Tell whether the given character is permitted by the given mask pair 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static boolean match(char c, long lowMask, long highMask) { 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c < 64) 52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ((1L << c) & lowMask) != 0; 52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c < 128) 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ((1L << (c - 64)) & highMask) != 0; 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If a scheme is given then the path, if given, must be absolute 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static void checkPath(String s, String scheme, String path) 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws URISyntaxException 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (scheme != null) { 53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((path != null) 53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski && ((path.length() > 0) && (path.charAt(0) != '/'))) 53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new URISyntaxException(s, 53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "Relative path in absolute URI"); 53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // -- Character classes for parsing -- 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Compute a low-order mask for the characters 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // between first and last, inclusive 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static long lowMask(char first, char last) { 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long m = 0; 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int f = Math.max(Math.min(first, 63), 0); 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int l = Math.max(Math.min(last, 63), 0); 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = f; i <= l; i++) 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski m |= 1L << i; 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return m; 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Compute the low-order mask for the characters in the given string 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static long lowMask(String chars) { 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = chars.length(); 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long m = 0; 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < n; i++) { 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = chars.charAt(i); 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c < 64) 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski m |= (1L << c); 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return m; 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Compute a high-order mask for the characters 56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // between first and last, inclusive 56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static long highMask(char first, char last) { 56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long m = 0; 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int f = Math.max(Math.min(first, 127), 64) - 64; 57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int l = Math.max(Math.min(last, 127), 64) - 64; 57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = f; i <= l; i++) 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski m |= 1L << i; 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return m; 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Compute the high-order mask for the characters in the given string 57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static long highMask(String chars) { 57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = chars.length(); 58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski long m = 0; 58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < n; i++) { 58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char c = chars.charAt(i); 58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((c >= 64) && (c < 128)) 58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski m |= (1L << (c - 64)); 58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return m; 58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Character-class masks 59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | 59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "8" | "9" 59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_DIGIT = lowMask('0', '9'); 59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_DIGIT = 0L; 59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | 59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "a" | "b" | "c" | "d" | "e" | "f" 59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_HEX = L_DIGIT; 60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_HEX = highMask('A', 'F') | highMask('a', 'f'); 60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | 60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | 60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" 60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_UPALPHA = 0L; 60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_UPALPHA = highMask('A', 'Z'); 60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | 60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | 61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" 61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_LOWALPHA = 0L; 61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_LOWALPHA = highMask('a', 'z'); 61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // alpha = lowalpha | upalpha 61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_ALPHA = L_LOWALPHA | L_UPALPHA; 61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_ALPHA = H_LOWALPHA | H_UPALPHA; 61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // alphanum = alpha | digit 61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_ALPHANUM = L_DIGIT | L_ALPHA; 62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_ALPHANUM = H_DIGIT | H_ALPHA; 62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | 62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "(" | ")" 62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_MARK = lowMask("-_.!~*'()"); 62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_MARK = highMask("-_.!~*'()"); 62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // unreserved = alphanum | mark 62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_UNRESERVED = L_ALPHANUM | L_MARK; 62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_UNRESERVED = H_ALPHANUM | H_MARK; 63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | 63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // "$" | "," | "[" | "]" 63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Added per RFC2732: "[", "]" 63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_RESERVED = lowMask(";/?:@&=+$,[]"); 63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_RESERVED = highMask(";/?:@&=+$,[]"); 63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The zero'th bit is used to indicate that escape pairs and non-US-ASCII 63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // characters are allowed; this is handled by the scanEscape method below. 63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_ESCAPED = 1L; 64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_ESCAPED = 0L; 64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Dash, for use in domainlabel and toplabel 64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_DASH = lowMask("-"); 64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_DASH = highMask("-"); 64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // uric = reserved | unreserved | escaped 64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_URIC = L_RESERVED | L_UNRESERVED | L_ESCAPED; 64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_URIC = H_RESERVED | H_UNRESERVED | H_ESCAPED; 64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // pchar = unreserved | escaped | 65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // ":" | "@" | "&" | "=" | "+" | "$" | "," 65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_PCHAR 65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = L_UNRESERVED | L_ESCAPED | lowMask(":@&=+$,"); 65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_PCHAR 65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = H_UNRESERVED | H_ESCAPED | highMask(":@&=+$,"); 65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // All valid path characters 65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_PATH = L_PCHAR | lowMask(";/"); 65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_PATH = H_PCHAR | highMask(";/"); 66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // userinfo = *( unreserved | escaped | 66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // ";" | ":" | "&" | "=" | "+" | "$" | "," ) 66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_USERINFO 66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = L_UNRESERVED | L_ESCAPED | lowMask(";:&=+$,"); 66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_USERINFO 66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = H_UNRESERVED | H_ESCAPED | highMask(";:&=+$,"); 66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // reg_name = 1*( unreserved | escaped | "$" | "," | 66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // ";" | ":" | "@" | "&" | "=" | "+" ) 67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_REG_NAME 67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = L_UNRESERVED | L_ESCAPED | lowMask("$,;:@&=+"); 67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_REG_NAME 67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = H_UNRESERVED | H_ESCAPED | highMask("$,;:@&=+"); 67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // All valid characters for server-based authorities 67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long L_SERVER 67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = L_USERINFO | L_ALPHANUM | L_DASH | lowMask(".:@[]"); 67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final long H_SERVER 67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = H_USERINFO | H_ALPHANUM | H_DASH | highMask(".:@[]"); 68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 681