package cn.org.rapid_framework.web.util; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.StringTokenizer; /** * @author badqiu */ @SuppressWarnings("unchecked") public class HttpUtils { public HttpUtils() { } /** * * Parses a query string passed from the client to the server and builds a * <code>HashTable</code> object with key-value pairs. The query string * should be in the form of a string packaged by the GET or POST method, * that is, it should have key-value pairs in the form <i>key=value</i>, * with each pair separated from the next by a & character. * * <p> * A key can appear more than once in the query string with different * values. However, the key appears only once in the hashtable, with its * value being an array of strings containing the multiple values sent by * the query string. * * <p> * When the keys and values are moved into the hashtable, any + characters * are converted to spaces, and characters sent in hexadecimal notation * (like <i>%xx</i>) are converted to ASCII characters. * * @param s * a string containing the query to be parsed * * @return a <code>HashTable</code> object built from the parsed key-value * pairs * * @exception IllegalArgumentException * if the query string is invalid * */ static public Hashtable parseQueryString(String s) { String valArray[] = null; if (s == null) { throw new IllegalArgumentException("queryString must not null"); } Hashtable ht = new Hashtable(); StringBuffer sb = new StringBuffer(); StringTokenizer st = new StringTokenizer(s, "&"); while (st.hasMoreTokens()) { String pair = (String) st.nextToken(); if(pair.trim().length() == 0) continue; int pos = pair.indexOf('='); if (pos == -1) { throw new IllegalArgumentException("cannot parse queryString:"+s); } String key = parseName(pair.substring(0, pos), sb); String val = parseName(pair.substring(pos + 1, pair.length()), sb); if (ht.containsKey(key)) { String oldVals[] = (String[]) ht.get(key); valArray = new String[oldVals.length + 1]; for (int i = 0; i < oldVals.length; i++) valArray[i] = oldVals[i]; valArray[oldVals.length] = val; } else { valArray = new String[1]; valArray[0] = val; } ht.put(key, valArray); } return fixValueArray2SingleStringObject(ht); } private static Hashtable fixValueArray2SingleStringObject(Hashtable ht) { Hashtable result = new Hashtable(); for(Iterator it = ht.entrySet().iterator();it.hasNext();) { Map.Entry entry = (Map.Entry)it.next(); String[] valueArray = (String[])entry.getValue(); if(valueArray == null) result.put(entry.getKey(), valueArray); else result.put(entry.getKey(),valueArray.length == 1 ? valueArray[0] : valueArray); } return result; } static private String parseName(String s, StringBuffer sb) { sb.setLength(0); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); switch (c) { case '+': sb.append(' '); break; case '%': try { sb.append((char) Integer.parseInt( s.substring(i + 1, i + 3), 16)); i += 2; } catch (NumberFormatException e) { // need to be more specific about illegal arg throw new IllegalArgumentException(); } catch (StringIndexOutOfBoundsException e) { String rest = s.substring(i); sb.append(rest); if (rest.length() == 2) i++; } break; default: sb.append(c); break; } } return sb.toString(); } }