1 2 3 /* 4 * The contents of this file are subject to the terms 5 * of the Common Development and Distribution License 6 * (the "License"). You may not use this file except 7 * in compliance with the License. 8 * 9 * You can obtain a copy of the license at 10 * glassfish/bootstrap/legal/CDDLv1.0.txt or 11 * https://glassfish.dev.java.net/public/CDDLv1.0.html. 12 * See the License for the specific language governing 13 * permissions and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL 16 * HEADER in each file and include the License file at 17 * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, 18 * add the following below this CDDL HEADER, with the 19 * fields enclosed by brackets "[]" replaced with your 20 * own identifying information: Portions Copyright [yyyy] 21 * [name of copyright owner] 22 * 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * 25 * Portions Copyright Apache Software Foundation. 26 */ 27 28 29 package javax.servlet.http; 30 31 import javax.servlet.ServletInputStream; 32 import java.util.Hashtable; 33 import java.util.ResourceBundle; 34 import java.util.StringTokenizer; 35 import java.io.IOException; 36 37 /** 38 * @deprecated As of Java(tm) Servlet API 2.3. 39 * These methods were only useful 40 * with the default encoding and have been moved 41 * to the request interfaces. 42 * 43 */ 44 45 46 public class HttpUtils { 47 48 private static final String LSTRING_FILE = 49 "javax.servlet.http.LocalStrings"; 50 private static ResourceBundle lStrings = 51 ResourceBundle.getBundle(LSTRING_FILE); 52 53 54 55 /** 56 * Constructs an empty <code>HttpUtils</code> object. 57 * 58 */ 59 60 public HttpUtils() {} 61 62 63 64 65 66 /** 67 * 68 * Parses a query string passed from the client to the 69 * server and builds a <code>HashTable</code> object 70 * with key-value pairs. 71 * The query string should be in the form of a string 72 * packaged by the GET or POST method, that is, it 73 * should have key-value pairs in the form <i>key=value</i>, 74 * with each pair separated from the next by a & character. 75 * 76 * <p>A key can appear more than once in the query string 77 * with different values. However, the key appears only once in 78 * the hashtable, with its value being 79 * an array of strings containing the multiple values sent 80 * by the query string. 81 * 82 * <p>The keys and values in the hashtable are stored in their 83 * decoded form, so 84 * any + characters are converted to spaces, and characters 85 * sent in hexadecimal notation (like <i>%xx</i>) are 86 * converted to ASCII characters. 87 * 88 * @param s a string containing the query to be parsed 89 * 90 * @return a <code>HashTable</code> object built 91 * from the parsed key-value pairs 92 * 93 * @exception IllegalArgumentException if the query string 94 * is invalid 95 * 96 */ 97 98 static public Hashtable parseQueryString(String s) { 99 100 String valArray[] = null; 101 102 if (s == null) { 103 throw new IllegalArgumentException(); 104 } 105 Hashtable ht = new Hashtable(); 106 StringBuffer sb = new StringBuffer(); 107 StringTokenizer st = new StringTokenizer(s, "&"); 108 while (st.hasMoreTokens()) { 109 String pair = (String)st.nextToken(); 110 int pos = pair.indexOf('='); 111 if (pos == -1) { 112 // XXX 113 // should give more detail about the illegal argument 114 throw new IllegalArgumentException(); 115 } 116 String key = parseName(pair.substring(0, pos), sb); 117 String val = parseName(pair.substring(pos+1, pair.length()), sb); 118 if (ht.containsKey(key)) { 119 String oldVals[] = (String []) ht.get(key); 120 valArray = new String[oldVals.length + 1]; 121 for (int i = 0; i < oldVals.length; i++) 122 valArray[i] = oldVals[i]; 123 valArray[oldVals.length] = val; 124 } else { 125 valArray = new String[1]; 126 valArray[0] = val; 127 } 128 ht.put(key, valArray); 129 } 130 return ht; 131 } 132 133 134 135 136 /** 137 * 138 * Parses data from an HTML form that the client sends to 139 * the server using the HTTP POST method and the 140 * <i>application/x-www-form-urlencoded</i> MIME type. 141 * 142 * <p>The data sent by the POST method contains key-value 143 * pairs. A key can appear more than once in the POST data 144 * with different values. However, the key appears only once in 145 * the hashtable, with its value being 146 * an array of strings containing the multiple values sent 147 * by the POST method. 148 * 149 * <p>The keys and values in the hashtable are stored in their 150 * decoded form, so 151 * any + characters are converted to spaces, and characters 152 * sent in hexadecimal notation (like <i>%xx</i>) are 153 * converted to ASCII characters. 154 * 155 * 156 * 157 * @param len an integer specifying the length, 158 * in characters, of the 159 * <code>ServletInputStream</code> 160 * object that is also passed to this 161 * method 162 * 163 * @param in the <code>ServletInputStream</code> 164 * object that contains the data sent 165 * from the client 166 * 167 * @return a <code>HashTable</code> object built 168 * from the parsed key-value pairs 169 * 170 * 171 * @exception IllegalArgumentException if the data 172 * sent by the POST method is invalid 173 * 174 */ 175 176 177 static public Hashtable parsePostData(int len, 178 ServletInputStream in) 179 { 180 // XXX 181 // should a length of 0 be an IllegalArgumentException 182 183 if (len <=0) 184 return new Hashtable(); // cheap hack to return an empty hash 185 186 if (in == null) { 187 throw new IllegalArgumentException(); 188 } 189 190 // 191 // Make sure we read the entire POSTed body. 192 // 193 byte[] postedBytes = new byte [len]; 194 try { 195 int offset = 0; 196 197 do { 198 int inputLen = in.read (postedBytes, offset, len - offset); 199 if (inputLen <= 0) { 200 String msg = lStrings.getString("err.io.short_read"); 201 throw new IllegalArgumentException (msg); 202 } 203 offset += inputLen; 204 } while ((len - offset) > 0); 205 206 } catch (IOException e) { 207 throw new IllegalArgumentException(e.getMessage()); 208 } 209 210 // XXX we shouldn't assume that the only kind of POST body 211 // is FORM data encoded using ASCII or ISO Latin/1 ... or 212 // that the body should always be treated as FORM data. 213 // 214 215 try { 216 String postedBody = new String(postedBytes, 0, len, "8859_1"); 217 return parseQueryString(postedBody); 218 } catch (java.io.UnsupportedEncodingException e) { 219 // XXX function should accept an encoding parameter & throw this 220 // exception. Otherwise throw something expected. 221 throw new IllegalArgumentException(e.getMessage()); 222 } 223 } 224 225 226 227 228 /* 229 * Parse a name in the query string. 230 */ 231 232 static private String parseName(String s, StringBuffer sb) { 233 sb.setLength(0); 234 for (int i = 0; i < s.length(); i++) { 235 char c = s.charAt(i); 236 switch (c) { 237 case '+': 238 sb.append(' '); 239 break; 240 case '%': 241 try { 242 sb.append((char) Integer.parseInt(s.substring(i+1, i+3), 243 16)); 244 i += 2; 245 } catch (NumberFormatException e) { 246 // XXX 247 // need to be more specific about illegal arg 248 throw new IllegalArgumentException(); 249 } catch (StringIndexOutOfBoundsException e) { 250 String rest = s.substring(i); 251 sb.append(rest); 252 if (rest.length()==2) 253 i++; 254 } 255 256 break; 257 default: 258 sb.append(c); 259 break; 260 } 261 } 262 return sb.toString(); 263 } 264 265 266 267 268 /** 269 * 270 * Reconstructs the URL the client used to make the request, 271 * using information in the <code>HttpServletRequest</code> object. 272 * The returned URL contains a protocol, server name, port 273 * number, and server path, but it does not include query 274 * string parameters. 275 * 276 * <p>Because this method returns a <code>StringBuffer</code>, 277 * not a string, you can modify the URL easily, for example, 278 * to append query parameters. 279 * 280 * <p>This method is useful for creating redirect messages 281 * and for reporting errors. 282 * 283 * @param req a <code>HttpServletRequest</code> object 284 * containing the client's request 285 * 286 * @return a <code>StringBuffer</code> object containing 287 * the reconstructed URL 288 * 289 */ 290 291 public static StringBuffer getRequestURL (HttpServletRequest req) { 292 StringBuffer url = new StringBuffer (); 293 String scheme = req.getScheme (); 294 int port = req.getServerPort (); 295 String urlPath = req.getRequestURI(); 296 297 //String servletPath = req.getServletPath (); 298 //String pathInfo = req.getPathInfo (); 299 300 url.append (scheme); // http, https 301 url.append ("://"); 302 url.append (req.getServerName ()); 303 if ((scheme.equals ("http") && port != 80) 304 || (scheme.equals ("https") && port != 443)) { 305 url.append (':'); 306 url.append (req.getServerPort ()); 307 } 308 //if (servletPath != null) 309 // url.append (servletPath); 310 //if (pathInfo != null) 311 // url.append (pathInfo); 312 url.append(urlPath); 313 return url; 314 } 315 } 316 317 318