1 /* 2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 4922813 26 * @summary Check the new impl of encodePath will not cause regression 27 * @modules java.base/sun.net.www 28 @key randomness 29 */ 30 31 import java.util.BitSet; 32 import java.io.File; 33 import java.util.Random; 34 import sun.net.www.ParseUtil; 35 36 public class ParseUtil_4922813 { main(String[] argv)37 public static void main(String[] argv) throws Exception { 38 39 int num = 400; 40 while (num-- >= 0) { 41 String source = getTestSource(); 42 String ec = sun.net.www.ParseUtil.encodePath(source); 43 String v117 = ParseUtil_V117.encodePath(source); 44 if (!ec.equals(v117)) { 45 throw new RuntimeException("Test Failed for : \n" 46 + " source =<" 47 + getUnicodeString(source) 48 + ">"); 49 } 50 51 } 52 } 53 54 static int maxCharCount = 200; 55 static int maxCodePoint = 0x10ffff; 56 static Random random; getTestSource()57 static String getTestSource() { 58 if (random == null) { 59 long seed = System.currentTimeMillis(); 60 random = new Random(seed); 61 } 62 String source = ""; 63 int i = 0; 64 int count = random.nextInt(maxCharCount) + 1; 65 while (i < count) { 66 int codepoint = random.nextInt(127); 67 source = source + String.valueOf((char)codepoint); 68 69 codepoint = random.nextInt(0x7ff); 70 source = source + String.valueOf((char)codepoint); 71 72 codepoint = random.nextInt(maxCodePoint); 73 source = source + new String(Character.toChars(codepoint)); 74 75 i += 3; 76 } 77 return source; 78 } 79 getUnicodeString(String s)80 static String getUnicodeString(String s){ 81 String unicodeString = ""; 82 for(int j=0; j< s.length(); j++){ 83 unicodeString += "0x"+ Integer.toString(s.charAt(j), 16); 84 } 85 return unicodeString; 86 } 87 } 88 class ParseUtil_V117 { 89 static BitSet encodedInPath; 90 static { 91 encodedInPath = new BitSet(256); 92 93 // Set the bits corresponding to characters that are encoded in the 94 // path component of a URI. 95 96 // These characters are reserved in the path segment as described in 97 // RFC2396 section 3.3. 98 encodedInPath.set('='); 99 encodedInPath.set(';'); 100 encodedInPath.set('?'); 101 encodedInPath.set('/'); 102 103 // These characters are defined as excluded in RFC2396 section 2.4.3 104 // and must be escaped if they occur in the data part of a URI. 105 encodedInPath.set('#'); 106 encodedInPath.set(' '); 107 encodedInPath.set('<'); 108 encodedInPath.set('>'); 109 encodedInPath.set('%'); 110 encodedInPath.set('"'); 111 encodedInPath.set('{'); 112 encodedInPath.set('}'); 113 encodedInPath.set('|'); 114 encodedInPath.set('\\'); 115 encodedInPath.set('^'); 116 encodedInPath.set('['); 117 encodedInPath.set(']'); 118 encodedInPath.set('`'); 119 120 // US ASCII control characters 00-1F and 7F. 121 for (int i=0; i<32; i++) 122 encodedInPath.set(i); 123 encodedInPath.set(127); 124 } 125 /** 126 * Constructs an encoded version of the specified path string suitable 127 * for use in the construction of a URL. 128 * 129 * A path separator is replaced by a forward slash. The string is UTF8 130 * encoded. The % escape sequence is used for characters that are above 131 * 0x7F or those defined in RFC2396 as reserved or excluded in the path 132 * component of a URL. 133 */ encodePath(String path)134 public static String encodePath(String path) { 135 StringBuffer sb = new StringBuffer(); 136 int n = path.length(); 137 for (int i=0; i<n; i++) { 138 char c = path.charAt(i); 139 if (c == File.separatorChar) 140 sb.append('/'); 141 else { 142 if (c <= 0x007F) { 143 if (encodedInPath.get(c)) 144 escape(sb, c); 145 else 146 sb.append(c); 147 } else if (c > 0x07FF) { 148 escape(sb, (char)(0xE0 | ((c >> 12) & 0x0F))); 149 escape(sb, (char)(0x80 | ((c >> 6) & 0x3F))); 150 escape(sb, (char)(0x80 | ((c >> 0) & 0x3F))); 151 } else { 152 escape(sb, (char)(0xC0 | ((c >> 6) & 0x1F))); 153 escape(sb, (char)(0x80 | ((c >> 0) & 0x3F))); 154 } 155 } 156 } 157 return sb.toString(); 158 } 159 160 /** 161 * Appends the URL escape sequence for the specified char to the 162 * specified StringBuffer. 163 */ escape(StringBuffer s, char c)164 private static void escape(StringBuffer s, char c) { 165 s.append('%'); 166 s.append(Character.forDigit((c >> 4) & 0xF, 16)); 167 s.append(Character.forDigit(c & 0xF, 16)); 168 } 169 } 170