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