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