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 @key randomness 28 */ 29 30 import java.util.BitSet; 31 import java.io.File; 32 import java.util.Random; 33 import sun.net.www.ParseUtil; 34 35 public class ParseUtil_4922813 { 36 public static void main(String[] argv) throws Exception { 37 38 int num = 400; 39 while (num-- >= 0) { 40 String source = getTestSource(); 41 String ec = sun.net.www.ParseUtil.encodePath(source); 42 String v117 = ParseUtil_V117.encodePath(source); 43 if (!ec.equals(v117)) { 44 throw new RuntimeException("Test Failed for : \n" 45 + " source =<" 46 + getUnicodeString(source) 47 + ">"); 48 } 49 50 } 51 } 52 53 static int maxCharCount = 200; 54 static int maxCodePoint = 0x10ffff; 55 static Random random; 56 static String getTestSource() { 57 if (random == null) { 58 long seed = System.currentTimeMillis(); 59 random = new Random(seed); 60 } 61 String source = ""; 62 int i = 0; 63 int count = random.nextInt(maxCharCount) + 1; 64 while (i < count) { 65 int codepoint = random.nextInt(127); 66 source = source + String.valueOf((char)codepoint); 67 68 codepoint = random.nextInt(0x7ff); 69 source = source + String.valueOf((char)codepoint); 70 71 codepoint = random.nextInt(maxCodePoint); 72 source = source + new String(Character.toChars(codepoint)); 73 74 i += 3; 75 } 76 return source; 77 } 78 79 static String getUnicodeString(String s){ 80 String unicodeString = ""; 81 for(int j=0; j< s.length(); j++){ 82 unicodeString += "0x"+ Integer.toString(s.charAt(j), 16); 83 } 84 return unicodeString; 85 } 86 } 87 class ParseUtil_V117 { 88 static BitSet encodedInPath; 89 static { 90 encodedInPath = new BitSet(256); 91 92 // Set the bits corresponding to characters that are encoded in the 93 // path component of a URI. 94 95 // These characters are reserved in the path segment as described in 96 // RFC2396 section 3.3. 97 encodedInPath.set('='); 98 encodedInPath.set(';'); 99 encodedInPath.set('?'); 100 encodedInPath.set('/'); 101 102 // These characters are defined as excluded in RFC2396 section 2.4.3 103 // and must be escaped if they occur in the data part of a URI. 104 encodedInPath.set('#'); 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 119 // US ASCII control characters 00-1F and 7F. 120 for (int i=0; i<32; i++) 121 encodedInPath.set(i); 122 encodedInPath.set(127); 123 } 124 /** 125 * Constructs an encoded version of the specified path string suitable 126 * for use in the construction of a URL. 127 * 128 * A path separator is replaced by a forward slash. The string is UTF8 129 * encoded. The % escape sequence is used for characters that are above 130 * 0x7F or those defined in RFC2396 as reserved or excluded in the path 131 * component of a URL. 132 */ 133 public static String encodePath(String path) { 134 StringBuffer sb = new StringBuffer(); 135 int n = path.length(); 136 for (int i=0; i<n; i++) { 137 char c = path.charAt(i); 138 if (c == File.separatorChar) 139 sb.append('/'); 140 else { 141 if (c <= 0x007F) { 142 if (encodedInPath.get(c)) 143 escape(sb, c); 144 else 145 sb.append(c); 146 } else if (c > 0x07FF) { 147 escape(sb, (char)(0xE0 | ((c >> 12) & 0x0F))); 148 escape(sb, (char)(0x80 | ((c >> 6) & 0x3F))); 149 escape(sb, (char)(0x80 | ((c >> 0) & 0x3F))); 150 } else { 151 escape(sb, (char)(0xC0 | ((c >> 6) & 0x1F))); 152 escape(sb, (char)(0x80 | ((c >> 0) & 0x3F))); 153 } 154 } 155 } 156 return sb.toString(); 157 } 158 159 /** 160 * Appends the URL escape sequence for the specified char to the 161 * specified StringBuffer. 162 */ 163 private static void escape(StringBuffer s, char c) { 164 s.append('%'); 165 s.append(Character.forDigit((c >> 4) & 0xF, 16)); 166 s.append(Character.forDigit(c & 0xF, 16)); 167 } 168 }