001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.servlet.http;
019:
020: import javax.servlet.ServletInputStream;
021: import java.util.Hashtable;
022: import java.util.ResourceBundle;
023: import java.util.StringTokenizer;
024: import java.io.IOException;
025:
026: /**
027: * @deprecated As of Java(tm) Servlet API 2.3.
028: * These methods were only useful
029: * with the default encoding and have been moved
030: * to the request interfaces.
031: *
032: */
033:
034: public class HttpUtils {
035:
036: private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
037: private static ResourceBundle lStrings = ResourceBundle
038: .getBundle(LSTRING_FILE);
039:
040: /**
041: * Constructs an empty <code>HttpUtils</code> object.
042: *
043: */
044:
045: public HttpUtils() {
046: }
047:
048: /**
049: *
050: * Parses a query string passed from the client to the
051: * server and builds a <code>HashTable</code> object
052: * with key-value pairs.
053: * The query string should be in the form of a string
054: * packaged by the GET or POST method, that is, it
055: * should have key-value pairs in the form <i>key=value</i>,
056: * with each pair separated from the next by a & character.
057: *
058: * <p>A key can appear more than once in the query string
059: * with different values. However, the key appears only once in
060: * the hashtable, with its value being
061: * an array of strings containing the multiple values sent
062: * by the query string.
063: *
064: * <p>The keys and values in the hashtable are stored in their
065: * decoded form, so
066: * any + characters are converted to spaces, and characters
067: * sent in hexadecimal notation (like <i>%xx</i>) are
068: * converted to ASCII characters.
069: *
070: * @param s a string containing the query to be parsed
071: *
072: * @return a <code>HashTable</code> object built
073: * from the parsed key-value pairs
074: *
075: * @exception IllegalArgumentException if the query string
076: * is invalid
077: *
078: */
079:
080: static public Hashtable parseQueryString(String s) {
081:
082: String valArray[] = null;
083:
084: if (s == null) {
085: throw new IllegalArgumentException();
086: }
087: Hashtable ht = new Hashtable();
088: StringBuffer sb = new StringBuffer();
089: StringTokenizer st = new StringTokenizer(s, "&");
090: while (st.hasMoreTokens()) {
091: String pair = (String) st.nextToken();
092: int pos = pair.indexOf('=');
093: if (pos == -1) {
094: // XXX
095: // should give more detail about the illegal argument
096: throw new IllegalArgumentException();
097: }
098: String key = parseName(pair.substring(0, pos), sb);
099: String val = parseName(pair.substring(pos + 1, pair
100: .length()), sb);
101: if (ht.containsKey(key)) {
102: String oldVals[] = (String[]) ht.get(key);
103: valArray = new String[oldVals.length + 1];
104: for (int i = 0; i < oldVals.length; i++)
105: valArray[i] = oldVals[i];
106: valArray[oldVals.length] = val;
107: } else {
108: valArray = new String[1];
109: valArray[0] = val;
110: }
111: ht.put(key, valArray);
112: }
113: return ht;
114: }
115:
116: /**
117: *
118: * Parses data from an HTML form that the client sends to
119: * the server using the HTTP POST method and the
120: * <i>application/x-www-form-urlencoded</i> MIME type.
121: *
122: * <p>The data sent by the POST method contains key-value
123: * pairs. A key can appear more than once in the POST data
124: * with different values. However, the key appears only once in
125: * the hashtable, with its value being
126: * an array of strings containing the multiple values sent
127: * by the POST method.
128: *
129: * <p>The keys and values in the hashtable are stored in their
130: * decoded form, so
131: * any + characters are converted to spaces, and characters
132: * sent in hexadecimal notation (like <i>%xx</i>) are
133: * converted to ASCII characters.
134: *
135: *
136: *
137: * @param len an integer specifying the length,
138: * in characters, of the
139: * <code>ServletInputStream</code>
140: * object that is also passed to this
141: * method
142: *
143: * @param in the <code>ServletInputStream</code>
144: * object that contains the data sent
145: * from the client
146: *
147: * @return a <code>HashTable</code> object built
148: * from the parsed key-value pairs
149: *
150: *
151: * @exception IllegalArgumentException if the data
152: * sent by the POST method is invalid
153: *
154: */
155:
156: static public Hashtable parsePostData(int len, ServletInputStream in) {
157: // XXX
158: // should a length of 0 be an IllegalArgumentException
159:
160: if (len <= 0)
161: return new Hashtable(); // cheap hack to return an empty hash
162:
163: if (in == null) {
164: throw new IllegalArgumentException();
165: }
166:
167: //
168: // Make sure we read the entire POSTed body.
169: //
170: byte[] postedBytes = new byte[len];
171: try {
172: int offset = 0;
173:
174: do {
175: int inputLen = in.read(postedBytes, offset, len
176: - offset);
177: if (inputLen <= 0) {
178: String msg = lStrings
179: .getString("err.io.short_read");
180: throw new IllegalArgumentException(msg);
181: }
182: offset += inputLen;
183: } while ((len - offset) > 0);
184:
185: } catch (IOException e) {
186: throw new IllegalArgumentException(e.getMessage());
187: }
188:
189: // XXX we shouldn't assume that the only kind of POST body
190: // is FORM data encoded using ASCII or ISO Latin/1 ... or
191: // that the body should always be treated as FORM data.
192: //
193:
194: try {
195: String postedBody = new String(postedBytes, 0, len,
196: "8859_1");
197: return parseQueryString(postedBody);
198: } catch (java.io.UnsupportedEncodingException e) {
199: // XXX function should accept an encoding parameter & throw this
200: // exception. Otherwise throw something expected.
201: throw new IllegalArgumentException(e.getMessage());
202: }
203: }
204:
205: /*
206: * Parse a name in the query string.
207: */
208:
209: static private String parseName(String s, StringBuffer sb) {
210: sb.setLength(0);
211: for (int i = 0; i < s.length(); i++) {
212: char c = s.charAt(i);
213: switch (c) {
214: case '+':
215: sb.append(' ');
216: break;
217: case '%':
218: try {
219: sb.append((char) Integer.parseInt(s.substring(
220: i + 1, i + 3), 16));
221: i += 2;
222: } catch (NumberFormatException e) {
223: // XXX
224: // need to be more specific about illegal arg
225: throw new IllegalArgumentException();
226: } catch (StringIndexOutOfBoundsException e) {
227: String rest = s.substring(i);
228: sb.append(rest);
229: if (rest.length() == 2)
230: i++;
231: }
232:
233: break;
234: default:
235: sb.append(c);
236: break;
237: }
238: }
239: return sb.toString();
240: }
241:
242: /**
243: *
244: * Reconstructs the URL the client used to make the request,
245: * using information in the <code>HttpServletRequest</code> object.
246: * The returned URL contains a protocol, server name, port
247: * number, and server path, but it does not include query
248: * string parameters.
249: *
250: * <p>Because this method returns a <code>StringBuffer</code>,
251: * not a string, you can modify the URL easily, for example,
252: * to append query parameters.
253: *
254: * <p>This method is useful for creating redirect messages
255: * and for reporting errors.
256: *
257: * @param req a <code>HttpServletRequest</code> object
258: * containing the client's request
259: *
260: * @return a <code>StringBuffer</code> object containing
261: * the reconstructed URL
262: *
263: */
264:
265: public static StringBuffer getRequestURL(HttpServletRequest req) {
266: StringBuffer url = new StringBuffer();
267: String scheme = req.getScheme();
268: int port = req.getServerPort();
269: String urlPath = req.getRequestURI();
270:
271: //String servletPath = req.getServletPath ();
272: //String pathInfo = req.getPathInfo ();
273:
274: url.append(scheme); // http, https
275: url.append("://");
276: url.append(req.getServerName());
277: if ((scheme.equals("http") && port != 80)
278: || (scheme.equals("https") && port != 443)) {
279: url.append(':');
280: url.append(req.getServerPort());
281: }
282: //if (servletPath != null)
283: // url.append (servletPath);
284: //if (pathInfo != null)
285: // url.append (pathInfo);
286: url.append(urlPath);
287: return url;
288: }
289: }
|