View Javadoc

    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 &amp; 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