Mercurial Hosting > luan
diff src/org/eclipse/jetty/util/UrlEncoded.java @ 1068:9d357b9e4bcb
fix BufferUtil.newBuffer()
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 10 Nov 2016 00:23:05 -0700 |
parents | 8e9db0bbf4f9 |
children |
line wrap: on
line diff
--- a/src/org/eclipse/jetty/util/UrlEncoded.java Thu Nov 10 00:08:39 2016 -0700 +++ b/src/org/eclipse/jetty/util/UrlEncoded.java Thu Nov 10 00:23:05 2016 -0700 @@ -53,982 +53,982 @@ */ public class UrlEncoded extends MultiMap implements Cloneable { - private static final Logger LOG = LoggerFactory.getLogger(UrlEncoded.class); + private static final Logger LOG = LoggerFactory.getLogger(UrlEncoded.class); - public static final String ENCODING = System.getProperty("org.eclipse.jetty.util.UrlEncoding.charset",StringUtil.__UTF8); + public static final String ENCODING = System.getProperty("org.eclipse.jetty.util.UrlEncoding.charset",StringUtil.__UTF8); - /* ----------------------------------------------------------------- */ - public UrlEncoded(UrlEncoded url) - { - super(url); - } - - /* ----------------------------------------------------------------- */ - public UrlEncoded() - { - super(6); - } - - /* ----------------------------------------------------------------- */ - public UrlEncoded(String s) - { - super(6); - decode(s,ENCODING); - } - - /* ----------------------------------------------------------------- */ - public UrlEncoded(String s, String charset) - { - super(6); - decode(s,charset); - } - - /* ----------------------------------------------------------------- */ - public void decode(String query) - { - decodeTo(query,this,ENCODING,-1); - } - - /* ----------------------------------------------------------------- */ - public void decode(String query,String charset) - { - decodeTo(query,this,charset,-1); - } - - /* -------------------------------------------------------------- */ - /** Encode Hashtable with % encoding. - */ - public String encode() - { - return encode(ENCODING,false); - } - - /* -------------------------------------------------------------- */ - /** Encode Hashtable with % encoding. - */ - public String encode(String charset) - { - return encode(charset,false); - } - - /* -------------------------------------------------------------- */ - /** Encode Hashtable with % encoding. - * @param equalsForNullValue if True, then an '=' is always used, even - * for parameters without a value. e.g. "blah?a=&b=&c=". - */ - public synchronized String encode(String charset, boolean equalsForNullValue) - { - return encode(this,charset,equalsForNullValue); - } - - /* -------------------------------------------------------------- */ - /** Encode Hashtable with % encoding. - * @param equalsForNullValue if True, then an '=' is always used, even - * for parameters without a value. e.g. "blah?a=&b=&c=". - */ - public static String encode(MultiMap map, String charset, boolean equalsForNullValue) - { - if (charset==null) - charset=ENCODING; + /* ----------------------------------------------------------------- */ + public UrlEncoded(UrlEncoded url) + { + super(url); + } + + /* ----------------------------------------------------------------- */ + public UrlEncoded() + { + super(6); + } + + /* ----------------------------------------------------------------- */ + public UrlEncoded(String s) + { + super(6); + decode(s,ENCODING); + } + + /* ----------------------------------------------------------------- */ + public UrlEncoded(String s, String charset) + { + super(6); + decode(s,charset); + } + + /* ----------------------------------------------------------------- */ + public void decode(String query) + { + decodeTo(query,this,ENCODING,-1); + } + + /* ----------------------------------------------------------------- */ + public void decode(String query,String charset) + { + decodeTo(query,this,charset,-1); + } + + /* -------------------------------------------------------------- */ + /** Encode Hashtable with % encoding. + */ + public String encode() + { + return encode(ENCODING,false); + } + + /* -------------------------------------------------------------- */ + /** Encode Hashtable with % encoding. + */ + public String encode(String charset) + { + return encode(charset,false); + } + + /* -------------------------------------------------------------- */ + /** Encode Hashtable with % encoding. + * @param equalsForNullValue if True, then an '=' is always used, even + * for parameters without a value. e.g. "blah?a=&b=&c=". + */ + public synchronized String encode(String charset, boolean equalsForNullValue) + { + return encode(this,charset,equalsForNullValue); + } + + /* -------------------------------------------------------------- */ + /** Encode Hashtable with % encoding. + * @param equalsForNullValue if True, then an '=' is always used, even + * for parameters without a value. e.g. "blah?a=&b=&c=". + */ + public static String encode(MultiMap map, String charset, boolean equalsForNullValue) + { + if (charset==null) + charset=ENCODING; - StringBuilder result = new StringBuilder(128); + StringBuilder result = new StringBuilder(128); - Iterator iter = map.entrySet().iterator(); - while(iter.hasNext()) - { - Map.Entry entry = (Map.Entry)iter.next(); + Iterator iter = map.entrySet().iterator(); + while(iter.hasNext()) + { + Map.Entry entry = (Map.Entry)iter.next(); - String key = entry.getKey().toString(); - Object list = entry.getValue(); - int s=LazyList.size(list); + String key = entry.getKey().toString(); + Object list = entry.getValue(); + int s=LazyList.size(list); - if (s==0) - { - result.append(encodeString(key,charset)); - if(equalsForNullValue) - result.append('='); - } - else - { - for (int i=0;i<s;i++) - { - if (i>0) - result.append('&'); - Object val=LazyList.get(list,i); - result.append(encodeString(key,charset)); + if (s==0) + { + result.append(encodeString(key,charset)); + if(equalsForNullValue) + result.append('='); + } + else + { + for (int i=0;i<s;i++) + { + if (i>0) + result.append('&'); + Object val=LazyList.get(list,i); + result.append(encodeString(key,charset)); - if (val!=null) - { - String str=val.toString(); - if (str.length()>0) - { - result.append('='); - result.append(encodeString(str,charset)); - } - else if (equalsForNullValue) - result.append('='); - } - else if (equalsForNullValue) - result.append('='); - } - } - if (iter.hasNext()) - result.append('&'); - } - return result.toString(); - } + if (val!=null) + { + String str=val.toString(); + if (str.length()>0) + { + result.append('='); + result.append(encodeString(str,charset)); + } + else if (equalsForNullValue) + result.append('='); + } + else if (equalsForNullValue) + result.append('='); + } + } + if (iter.hasNext()) + result.append('&'); + } + return result.toString(); + } - /* -------------------------------------------------------------- */ - /** Decoded parameters to Map. - * @param content the string containing the encoded parameters - */ - public static void decodeTo(String content, MultiMap map, String charset) - { - decodeTo(content,map,charset,-1); - } - - /* -------------------------------------------------------------- */ - /** Decoded parameters to Map. - * @param content the string containing the encoded parameters - */ - public static void decodeTo(String content, MultiMap map, String charset, int maxKeys) - { - if (charset==null) - charset=ENCODING; + /* -------------------------------------------------------------- */ + /** Decoded parameters to Map. + * @param content the string containing the encoded parameters + */ + public static void decodeTo(String content, MultiMap map, String charset) + { + decodeTo(content,map,charset,-1); + } + + /* -------------------------------------------------------------- */ + /** Decoded parameters to Map. + * @param content the string containing the encoded parameters + */ + public static void decodeTo(String content, MultiMap map, String charset, int maxKeys) + { + if (charset==null) + charset=ENCODING; - synchronized(map) - { - String key = null; - String value = null; - int mark=-1; - boolean encoded=false; - for (int i=0;i<content.length();i++) - { - char c = content.charAt(i); - switch (c) - { - case '&': - int l=i-mark-1; - value = l==0?"": - (encoded?decodeString(content,mark+1,l,charset):content.substring(mark+1,i)); - mark=i; - encoded=false; - if (key != null) - { - map.add(key,value); - } - else if (value!=null&&value.length()>0) - { - map.add(value,""); - } - key = null; - value=null; - if (maxKeys>0 && map.size()>maxKeys) - throw new IllegalStateException("Form too many keys"); - break; - case '=': - if (key!=null) - break; - key = encoded?decodeString(content,mark+1,i-mark-1,charset):content.substring(mark+1,i); - mark=i; - encoded=false; - break; - case '+': - encoded=true; - break; - case '%': - encoded=true; - break; - } - } - - if (key != null) - { - int l=content.length()-mark-1; - value = l==0?"":(encoded?decodeString(content,mark+1,l,charset):content.substring(mark+1)); - map.add(key,value); - } - else if (mark<content.length()) - { - key = encoded - ?decodeString(content,mark+1,content.length()-mark-1,charset) - :content.substring(mark+1); - if (key != null && key.length() > 0) - { - map.add(key,""); - } - } - } - } + synchronized(map) + { + String key = null; + String value = null; + int mark=-1; + boolean encoded=false; + for (int i=0;i<content.length();i++) + { + char c = content.charAt(i); + switch (c) + { + case '&': + int l=i-mark-1; + value = l==0?"": + (encoded?decodeString(content,mark+1,l,charset):content.substring(mark+1,i)); + mark=i; + encoded=false; + if (key != null) + { + map.add(key,value); + } + else if (value!=null&&value.length()>0) + { + map.add(value,""); + } + key = null; + value=null; + if (maxKeys>0 && map.size()>maxKeys) + throw new IllegalStateException("Form too many keys"); + break; + case '=': + if (key!=null) + break; + key = encoded?decodeString(content,mark+1,i-mark-1,charset):content.substring(mark+1,i); + mark=i; + encoded=false; + break; + case '+': + encoded=true; + break; + case '%': + encoded=true; + break; + } + } + + if (key != null) + { + int l=content.length()-mark-1; + value = l==0?"":(encoded?decodeString(content,mark+1,l,charset):content.substring(mark+1)); + map.add(key,value); + } + else if (mark<content.length()) + { + key = encoded + ?decodeString(content,mark+1,content.length()-mark-1,charset) + :content.substring(mark+1); + if (key != null && key.length() > 0) + { + map.add(key,""); + } + } + } + } - /* -------------------------------------------------------------- */ - /** Decoded parameters to Map. - * @param raw the byte[] containing the encoded parameters - * @param offset the offset within raw to decode from - * @param length the length of the section to decode - * @param map the {@link MultiMap} to populate - */ - public static void decodeUtf8To(byte[] raw,int offset, int length, MultiMap map) - { - decodeUtf8To(raw,offset,length,map,new Utf8StringBuilder()); - } + /* -------------------------------------------------------------- */ + /** Decoded parameters to Map. + * @param raw the byte[] containing the encoded parameters + * @param offset the offset within raw to decode from + * @param length the length of the section to decode + * @param map the {@link MultiMap} to populate + */ + public static void decodeUtf8To(byte[] raw,int offset, int length, MultiMap map) + { + decodeUtf8To(raw,offset,length,map,new Utf8StringBuilder()); + } - /* -------------------------------------------------------------- */ - /** Decoded parameters to Map. - * @param raw the byte[] containing the encoded parameters - * @param offset the offset within raw to decode from - * @param length the length of the section to decode - * @param map the {@link MultiMap} to populate - * @param buffer the buffer to decode into - */ - public static void decodeUtf8To(byte[] raw,int offset, int length, MultiMap map,Utf8StringBuilder buffer) - { - synchronized(map) - { - String key = null; - String value = null; + /* -------------------------------------------------------------- */ + /** Decoded parameters to Map. + * @param raw the byte[] containing the encoded parameters + * @param offset the offset within raw to decode from + * @param length the length of the section to decode + * @param map the {@link MultiMap} to populate + * @param buffer the buffer to decode into + */ + public static void decodeUtf8To(byte[] raw,int offset, int length, MultiMap map,Utf8StringBuilder buffer) + { + synchronized(map) + { + String key = null; + String value = null; - // TODO cache of parameter names ??? - int end=offset+length; - for (int i=offset;i<end;i++) - { - byte b=raw[i]; - try - { - switch ((char)(0xff&b)) - { - case '&': - value = buffer.length()==0?"":buffer.toString(); - buffer.reset(); - if (key != null) - { - map.add(key,value); - } - else if (value!=null&&value.length()>0) - { - map.add(value,""); - } - key = null; - value=null; - break; + // TODO cache of parameter names ??? + int end=offset+length; + for (int i=offset;i<end;i++) + { + byte b=raw[i]; + try + { + switch ((char)(0xff&b)) + { + case '&': + value = buffer.length()==0?"":buffer.toString(); + buffer.reset(); + if (key != null) + { + map.add(key,value); + } + else if (value!=null&&value.length()>0) + { + map.add(value,""); + } + key = null; + value=null; + break; - case '=': - if (key!=null) - { - buffer.append(b); - break; - } - key = buffer.toString(); - buffer.reset(); - break; + case '=': + if (key!=null) + { + buffer.append(b); + break; + } + key = buffer.toString(); + buffer.reset(); + break; - case '+': - buffer.append((byte)' '); - break; + case '+': + buffer.append((byte)' '); + break; - case '%': - if (i+2<end) - { - if ('u'==raw[i+1]) - { - i++; - if (i+4<end) - buffer.getStringBuilder().append(Character.toChars((convertHexDigit(raw[++i])<<12) +(convertHexDigit(raw[++i])<<8) + (convertHexDigit(raw[++i])<<4) +convertHexDigit(raw[++i]))); - else - { - buffer.getStringBuilder().append(Utf8Appendable.REPLACEMENT); - i=end; - } - } - else - buffer.append((byte)((convertHexDigit(raw[++i])<<4) + convertHexDigit(raw[++i]))); - } - else - { - buffer.getStringBuilder().append(Utf8Appendable.REPLACEMENT); - i=end; - } - break; - - default: - buffer.append(b); - break; - } - } - catch(NotUtf8Exception e) - { - LOG.warn(e.toString()); - LOG.debug("",e); - } - } - - if (key != null) - { - value = buffer.length()==0?"":buffer.toReplacedString(); - buffer.reset(); - map.add(key,value); - } - else if (buffer.length()>0) - { - map.add(buffer.toReplacedString(),""); - } - } - } + case '%': + if (i+2<end) + { + if ('u'==raw[i+1]) + { + i++; + if (i+4<end) + buffer.getStringBuilder().append(Character.toChars((convertHexDigit(raw[++i])<<12) +(convertHexDigit(raw[++i])<<8) + (convertHexDigit(raw[++i])<<4) +convertHexDigit(raw[++i]))); + else + { + buffer.getStringBuilder().append(Utf8Appendable.REPLACEMENT); + i=end; + } + } + else + buffer.append((byte)((convertHexDigit(raw[++i])<<4) + convertHexDigit(raw[++i]))); + } + else + { + buffer.getStringBuilder().append(Utf8Appendable.REPLACEMENT); + i=end; + } + break; + + default: + buffer.append(b); + break; + } + } + catch(NotUtf8Exception e) + { + LOG.warn(e.toString()); + LOG.debug("",e); + } + } + + if (key != null) + { + value = buffer.length()==0?"":buffer.toReplacedString(); + buffer.reset(); + map.add(key,value); + } + else if (buffer.length()>0) + { + map.add(buffer.toReplacedString(),""); + } + } + } - /* -------------------------------------------------------------- */ - /** Decoded parameters to Map. - * @param in InputSteam to read - * @param map MultiMap to add parameters to - * @param maxLength maximum number of keys to read or -1 for no limit - */ - public static void decode88591To(InputStream in, MultiMap map, int maxLength, int maxKeys) - throws IOException - { - synchronized(map) - { - StringBuffer buffer = new StringBuffer(); - String key = null; - String value = null; - - int b; + /* -------------------------------------------------------------- */ + /** Decoded parameters to Map. + * @param in InputSteam to read + * @param map MultiMap to add parameters to + * @param maxLength maximum number of keys to read or -1 for no limit + */ + public static void decode88591To(InputStream in, MultiMap map, int maxLength, int maxKeys) + throws IOException + { + synchronized(map) + { + StringBuffer buffer = new StringBuffer(); + String key = null; + String value = null; + + int b; - // TODO cache of parameter names ??? - int totalLength=0; - while ((b=in.read())>=0) - { - switch ((char) b) - { - case '&': - value = buffer.length()==0?"":buffer.toString(); - buffer.setLength(0); - if (key != null) - { - map.add(key,value); - } - else if (value!=null&&value.length()>0) - { - map.add(value,""); - } - key = null; - value=null; - if (maxKeys>0 && map.size()>maxKeys) - throw new IllegalStateException("Form too many keys"); - break; - - case '=': - if (key!=null) - { - buffer.append((char)b); - break; - } - key = buffer.toString(); - buffer.setLength(0); - break; - - case '+': - buffer.append(' '); - break; - - case '%': - int code0=in.read(); - if ('u'==code0) - { - int code1=in.read(); - if (code1>=0) - { - int code2=in.read(); - if (code2>=0) - { - int code3=in.read(); - if (code3>=0) - buffer.append(Character.toChars((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3))); - } - } - } - else if (code0>=0) - { - int code1=in.read(); - if (code1>=0) - buffer.append((char)((convertHexDigit(code0)<<4)+convertHexDigit(code1))); - } - break; - - default: - buffer.append((char)b); - break; - } - if (maxLength>=0 && (++totalLength > maxLength)) - throw new IllegalStateException("Form too large"); - } - - if (key != null) - { - value = buffer.length()==0?"":buffer.toString(); - buffer.setLength(0); - map.add(key,value); - } - else if (buffer.length()>0) - { - map.add(buffer.toString(), ""); - } - } - } - - /* -------------------------------------------------------------- */ - /** Decoded parameters to Map. - * @param in InputSteam to read - * @param map MultiMap to add parameters to - * @param maxLength maximum number of keys to read or -1 for no limit - */ - public static void decodeUtf8To(InputStream in, MultiMap map, int maxLength, int maxKeys) - throws IOException - { - synchronized(map) - { - Utf8StringBuilder buffer = new Utf8StringBuilder(); - String key = null; - String value = null; - - int b; - - // TODO cache of parameter names ??? - int totalLength=0; - while ((b=in.read())>=0) - { - try - { - switch ((char) b) - { - case '&': - value = buffer.length()==0?"":buffer.toString(); - buffer.reset(); - if (key != null) - { - map.add(key,value); - } - else if (value!=null&&value.length()>0) - { - map.add(value,""); - } - key = null; - value=null; - if (maxKeys>0 && map.size()>maxKeys) - throw new IllegalStateException("Form too many keys"); - break; + // TODO cache of parameter names ??? + int totalLength=0; + while ((b=in.read())>=0) + { + switch ((char) b) + { + case '&': + value = buffer.length()==0?"":buffer.toString(); + buffer.setLength(0); + if (key != null) + { + map.add(key,value); + } + else if (value!=null&&value.length()>0) + { + map.add(value,""); + } + key = null; + value=null; + if (maxKeys>0 && map.size()>maxKeys) + throw new IllegalStateException("Form too many keys"); + break; + + case '=': + if (key!=null) + { + buffer.append((char)b); + break; + } + key = buffer.toString(); + buffer.setLength(0); + break; + + case '+': + buffer.append(' '); + break; + + case '%': + int code0=in.read(); + if ('u'==code0) + { + int code1=in.read(); + if (code1>=0) + { + int code2=in.read(); + if (code2>=0) + { + int code3=in.read(); + if (code3>=0) + buffer.append(Character.toChars((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3))); + } + } + } + else if (code0>=0) + { + int code1=in.read(); + if (code1>=0) + buffer.append((char)((convertHexDigit(code0)<<4)+convertHexDigit(code1))); + } + break; + + default: + buffer.append((char)b); + break; + } + if (maxLength>=0 && (++totalLength > maxLength)) + throw new IllegalStateException("Form too large"); + } + + if (key != null) + { + value = buffer.length()==0?"":buffer.toString(); + buffer.setLength(0); + map.add(key,value); + } + else if (buffer.length()>0) + { + map.add(buffer.toString(), ""); + } + } + } + + /* -------------------------------------------------------------- */ + /** Decoded parameters to Map. + * @param in InputSteam to read + * @param map MultiMap to add parameters to + * @param maxLength maximum number of keys to read or -1 for no limit + */ + public static void decodeUtf8To(InputStream in, MultiMap map, int maxLength, int maxKeys) + throws IOException + { + synchronized(map) + { + Utf8StringBuilder buffer = new Utf8StringBuilder(); + String key = null; + String value = null; + + int b; + + // TODO cache of parameter names ??? + int totalLength=0; + while ((b=in.read())>=0) + { + try + { + switch ((char) b) + { + case '&': + value = buffer.length()==0?"":buffer.toString(); + buffer.reset(); + if (key != null) + { + map.add(key,value); + } + else if (value!=null&&value.length()>0) + { + map.add(value,""); + } + key = null; + value=null; + if (maxKeys>0 && map.size()>maxKeys) + throw new IllegalStateException("Form too many keys"); + break; - case '=': - if (key!=null) - { - buffer.append((byte)b); - break; - } - key = buffer.toString(); - buffer.reset(); - break; + case '=': + if (key!=null) + { + buffer.append((byte)b); + break; + } + key = buffer.toString(); + buffer.reset(); + break; - case '+': - buffer.append((byte)' '); - break; + case '+': + buffer.append((byte)' '); + break; - case '%': - int code0=in.read(); - if ('u'==code0) - { - int code1=in.read(); - if (code1>=0) - { - int code2=in.read(); - if (code2>=0) - { - int code3=in.read(); - if (code3>=0) - buffer.getStringBuilder().append(Character.toChars((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3))); - } - } - } - else if (code0>=0) - { - int code1=in.read(); - if (code1>=0) - buffer.append((byte)((convertHexDigit(code0)<<4)+convertHexDigit(code1))); - } - break; - - default: - buffer.append((byte)b); - break; - } - } - catch(NotUtf8Exception e) - { - LOG.warn(e.toString()); - LOG.debug("",e); - } - if (maxLength>=0 && (++totalLength > maxLength)) - throw new IllegalStateException("Form too large"); - } - - if (key != null) - { - value = buffer.length()==0?"":buffer.toString(); - buffer.reset(); - map.add(key,value); - } - else if (buffer.length()>0) - { - map.add(buffer.toString(), ""); - } - } - } - - /* -------------------------------------------------------------- */ - public static void decodeUtf16To(InputStream in, MultiMap map, int maxLength, int maxKeys) throws IOException - { - InputStreamReader input = new InputStreamReader(in,StringUtil.__UTF16); - StringWriter buf = new StringWriter(8192); - IO.copy(input,buf,maxLength); - - decodeTo(buf.getBuffer().toString(),map,StringUtil.__UTF16,maxKeys); - } - - /* -------------------------------------------------------------- */ - /** Decoded parameters to Map. - * @param in the stream containing the encoded parameters - */ - public static void decodeTo(InputStream in, MultiMap map, String charset, int maxLength, int maxKeys) - throws IOException - { - //no charset present, use the configured default - if (charset==null) - { - charset=ENCODING; - } - - if (StringUtil.__UTF8.equalsIgnoreCase(charset)) - { - decodeUtf8To(in,map,maxLength,maxKeys); - return; - } - - if (StringUtil.__ISO_8859_1.equals(charset)) - { - decode88591To(in,map,maxLength,maxKeys); - return; - } + case '%': + int code0=in.read(); + if ('u'==code0) + { + int code1=in.read(); + if (code1>=0) + { + int code2=in.read(); + if (code2>=0) + { + int code3=in.read(); + if (code3>=0) + buffer.getStringBuilder().append(Character.toChars((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3))); + } + } + } + else if (code0>=0) + { + int code1=in.read(); + if (code1>=0) + buffer.append((byte)((convertHexDigit(code0)<<4)+convertHexDigit(code1))); + } + break; + + default: + buffer.append((byte)b); + break; + } + } + catch(NotUtf8Exception e) + { + LOG.warn(e.toString()); + LOG.debug("",e); + } + if (maxLength>=0 && (++totalLength > maxLength)) + throw new IllegalStateException("Form too large"); + } + + if (key != null) + { + value = buffer.length()==0?"":buffer.toString(); + buffer.reset(); + map.add(key,value); + } + else if (buffer.length()>0) + { + map.add(buffer.toString(), ""); + } + } + } + + /* -------------------------------------------------------------- */ + public static void decodeUtf16To(InputStream in, MultiMap map, int maxLength, int maxKeys) throws IOException + { + InputStreamReader input = new InputStreamReader(in,StringUtil.__UTF16); + StringWriter buf = new StringWriter(8192); + IO.copy(input,buf,maxLength); + + decodeTo(buf.getBuffer().toString(),map,StringUtil.__UTF16,maxKeys); + } + + /* -------------------------------------------------------------- */ + /** Decoded parameters to Map. + * @param in the stream containing the encoded parameters + */ + public static void decodeTo(InputStream in, MultiMap map, String charset, int maxLength, int maxKeys) + throws IOException + { + //no charset present, use the configured default + if (charset==null) + { + charset=ENCODING; + } + + if (StringUtil.__UTF8.equalsIgnoreCase(charset)) + { + decodeUtf8To(in,map,maxLength,maxKeys); + return; + } + + if (StringUtil.__ISO_8859_1.equals(charset)) + { + decode88591To(in,map,maxLength,maxKeys); + return; + } - if (StringUtil.__UTF16.equalsIgnoreCase(charset)) // Should be all 2 byte encodings - { - decodeUtf16To(in,map,maxLength,maxKeys); - return; - } - + if (StringUtil.__UTF16.equalsIgnoreCase(charset)) // Should be all 2 byte encodings + { + decodeUtf16To(in,map,maxLength,maxKeys); + return; + } + - synchronized(map) - { - String key = null; - String value = null; - - int c; - - int totalLength = 0; - ByteArrayOutputStream2 output = new ByteArrayOutputStream2(); - - int size=0; - - while ((c=in.read())>0) - { - switch ((char) c) - { - case '&': - size=output.size(); - value = size==0?"":output.toString(charset); - output.setCount(0); - if (key != null) - { - map.add(key,value); - } - else if (value!=null&&value.length()>0) - { - map.add(value,""); - } - key = null; - value=null; - if (maxKeys>0 && map.size()>maxKeys) - throw new IllegalStateException("Form too many keys"); - break; - case '=': - if (key!=null) - { - output.write(c); - break; - } - size=output.size(); - key = size==0?"":output.toString(charset); - output.setCount(0); - break; - case '+': - output.write(' '); - break; - case '%': - int code0=in.read(); - if ('u'==code0) - { - int code1=in.read(); - if (code1>=0) - { - int code2=in.read(); - if (code2>=0) - { - int code3=in.read(); - if (code3>=0) - output.write(new String(Character.toChars((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3))).getBytes(charset)); - } - } - - } - else if (code0>=0) - { - int code1=in.read(); - if (code1>=0) - output.write((convertHexDigit(code0)<<4)+convertHexDigit(code1)); - } - break; - default: - output.write(c); - break; - } - - totalLength++; - if (maxLength>=0 && totalLength > maxLength) - throw new IllegalStateException("Form too large"); - } + synchronized(map) + { + String key = null; + String value = null; + + int c; + + int totalLength = 0; + ByteArrayOutputStream2 output = new ByteArrayOutputStream2(); + + int size=0; + + while ((c=in.read())>0) + { + switch ((char) c) + { + case '&': + size=output.size(); + value = size==0?"":output.toString(charset); + output.setCount(0); + if (key != null) + { + map.add(key,value); + } + else if (value!=null&&value.length()>0) + { + map.add(value,""); + } + key = null; + value=null; + if (maxKeys>0 && map.size()>maxKeys) + throw new IllegalStateException("Form too many keys"); + break; + case '=': + if (key!=null) + { + output.write(c); + break; + } + size=output.size(); + key = size==0?"":output.toString(charset); + output.setCount(0); + break; + case '+': + output.write(' '); + break; + case '%': + int code0=in.read(); + if ('u'==code0) + { + int code1=in.read(); + if (code1>=0) + { + int code2=in.read(); + if (code2>=0) + { + int code3=in.read(); + if (code3>=0) + output.write(new String(Character.toChars((convertHexDigit(code0)<<12)+(convertHexDigit(code1)<<8)+(convertHexDigit(code2)<<4)+convertHexDigit(code3))).getBytes(charset)); + } + } + + } + else if (code0>=0) + { + int code1=in.read(); + if (code1>=0) + output.write((convertHexDigit(code0)<<4)+convertHexDigit(code1)); + } + break; + default: + output.write(c); + break; + } + + totalLength++; + if (maxLength>=0 && totalLength > maxLength) + throw new IllegalStateException("Form too large"); + } - size=output.size(); - if (key != null) - { - value = size==0?"":output.toString(charset); - output.setCount(0); - map.add(key,value); - } - else if (size>0) - map.add(output.toString(charset),""); - } - } - - /* -------------------------------------------------------------- */ - /** Decode String with % encoding. - * This method makes the assumption that the majority of calls - * will need no decoding. - */ - public static String decodeString(String encoded,int offset,int length,String charset) - { - if (charset==null || StringUtil.isUTF8(charset)) - { - Utf8StringBuffer buffer=null; + size=output.size(); + if (key != null) + { + value = size==0?"":output.toString(charset); + output.setCount(0); + map.add(key,value); + } + else if (size>0) + map.add(output.toString(charset),""); + } + } + + /* -------------------------------------------------------------- */ + /** Decode String with % encoding. + * This method makes the assumption that the majority of calls + * will need no decoding. + */ + public static String decodeString(String encoded,int offset,int length,String charset) + { + if (charset==null || StringUtil.isUTF8(charset)) + { + Utf8StringBuffer buffer=null; - for (int i=0;i<length;i++) - { - char c = encoded.charAt(offset+i); - if (c<0||c>0xff) - { - if (buffer==null) - { - buffer=new Utf8StringBuffer(length); - buffer.getStringBuffer().append(encoded,offset,offset+i+1); - } - else - buffer.getStringBuffer().append(c); - } - else if (c=='+') - { - if (buffer==null) - { - buffer=new Utf8StringBuffer(length); - buffer.getStringBuffer().append(encoded,offset,offset+i); - } - - buffer.getStringBuffer().append(' '); - } - else if (c=='%') - { - if (buffer==null) - { - buffer=new Utf8StringBuffer(length); - buffer.getStringBuffer().append(encoded,offset,offset+i); - } - - if ((i+2)<length) - { - try - { - if ('u'==encoded.charAt(offset+i+1)) - { - if((i+5)<length) - { - int o=offset+i+2; - i+=5; - String unicode = new String(Character.toChars(TypeUtil.parseInt(encoded,o,4,16))); - buffer.getStringBuffer().append(unicode); - } - else - { - i=length; - buffer.getStringBuffer().append(Utf8Appendable.REPLACEMENT); - } - } - else - { - int o=offset+i+1; - i+=2; - byte b=(byte)TypeUtil.parseInt(encoded,o,2,16); - buffer.append(b); - } - } - catch(NotUtf8Exception e) - { - LOG.warn(e.toString()); - LOG.debug("",e); - } - catch(NumberFormatException nfe) - { - LOG.debug("",nfe); - buffer.getStringBuffer().append(Utf8Appendable.REPLACEMENT); - } - } - else - { - buffer.getStringBuffer().append(Utf8Appendable.REPLACEMENT); - i=length; - } - } - else if (buffer!=null) - buffer.getStringBuffer().append(c); - } + for (int i=0;i<length;i++) + { + char c = encoded.charAt(offset+i); + if (c<0||c>0xff) + { + if (buffer==null) + { + buffer=new Utf8StringBuffer(length); + buffer.getStringBuffer().append(encoded,offset,offset+i+1); + } + else + buffer.getStringBuffer().append(c); + } + else if (c=='+') + { + if (buffer==null) + { + buffer=new Utf8StringBuffer(length); + buffer.getStringBuffer().append(encoded,offset,offset+i); + } + + buffer.getStringBuffer().append(' '); + } + else if (c=='%') + { + if (buffer==null) + { + buffer=new Utf8StringBuffer(length); + buffer.getStringBuffer().append(encoded,offset,offset+i); + } + + if ((i+2)<length) + { + try + { + if ('u'==encoded.charAt(offset+i+1)) + { + if((i+5)<length) + { + int o=offset+i+2; + i+=5; + String unicode = new String(Character.toChars(TypeUtil.parseInt(encoded,o,4,16))); + buffer.getStringBuffer().append(unicode); + } + else + { + i=length; + buffer.getStringBuffer().append(Utf8Appendable.REPLACEMENT); + } + } + else + { + int o=offset+i+1; + i+=2; + byte b=(byte)TypeUtil.parseInt(encoded,o,2,16); + buffer.append(b); + } + } + catch(NotUtf8Exception e) + { + LOG.warn(e.toString()); + LOG.debug("",e); + } + catch(NumberFormatException nfe) + { + LOG.debug("",nfe); + buffer.getStringBuffer().append(Utf8Appendable.REPLACEMENT); + } + } + else + { + buffer.getStringBuffer().append(Utf8Appendable.REPLACEMENT); + i=length; + } + } + else if (buffer!=null) + buffer.getStringBuffer().append(c); + } - if (buffer==null) - { - if (offset==0 && encoded.length()==length) - return encoded; - return encoded.substring(offset,offset+length); - } + if (buffer==null) + { + if (offset==0 && encoded.length()==length) + return encoded; + return encoded.substring(offset,offset+length); + } - return buffer.toReplacedString(); - } - else - { - StringBuffer buffer=null; + return buffer.toReplacedString(); + } + else + { + StringBuffer buffer=null; - try - { - for (int i=0;i<length;i++) - { - char c = encoded.charAt(offset+i); - if (c<0||c>0xff) - { - if (buffer==null) - { - buffer=new StringBuffer(length); - buffer.append(encoded,offset,offset+i+1); - } - else - buffer.append(c); - } - else if (c=='+') - { - if (buffer==null) - { - buffer=new StringBuffer(length); - buffer.append(encoded,offset,offset+i); - } - - buffer.append(' '); - } - else if (c=='%') - { - if (buffer==null) - { - buffer=new StringBuffer(length); - buffer.append(encoded,offset,offset+i); - } + try + { + for (int i=0;i<length;i++) + { + char c = encoded.charAt(offset+i); + if (c<0||c>0xff) + { + if (buffer==null) + { + buffer=new StringBuffer(length); + buffer.append(encoded,offset,offset+i+1); + } + else + buffer.append(c); + } + else if (c=='+') + { + if (buffer==null) + { + buffer=new StringBuffer(length); + buffer.append(encoded,offset,offset+i); + } + + buffer.append(' '); + } + else if (c=='%') + { + if (buffer==null) + { + buffer=new StringBuffer(length); + buffer.append(encoded,offset,offset+i); + } - byte[] ba=new byte[length]; - int n=0; - while(c>=0 && c<=0xff) - { - if (c=='%') - { - if(i+2<length) - { - try - { - if ('u'==encoded.charAt(offset+i+1)) - { - if (i+6<length) - { - int o=offset+i+2; - i+=6; - String unicode = new String(Character.toChars(TypeUtil.parseInt(encoded,o,4,16))); - byte[] reencoded = unicode.getBytes(charset); - System.arraycopy(reencoded,0,ba,n,reencoded.length); - n+=reencoded.length; - } - else - { - ba[n++] = (byte)'?'; - i=length; - } - } - else - { - int o=offset+i+1; - i+=3; - ba[n]=(byte)TypeUtil.parseInt(encoded,o,2,16); - n++; - } - } - catch(NumberFormatException nfe) - { - LOG.trace("",nfe); - ba[n++] = (byte)'?'; - } - } - else - { - ba[n++] = (byte)'?'; - i=length; - } - } - else if (c=='+') - { - ba[n++]=(byte)' '; - i++; - } - else - { - ba[n++]=(byte)c; - i++; - } - - if (i>=length) - break; - c = encoded.charAt(offset+i); - } + byte[] ba=new byte[length]; + int n=0; + while(c>=0 && c<=0xff) + { + if (c=='%') + { + if(i+2<length) + { + try + { + if ('u'==encoded.charAt(offset+i+1)) + { + if (i+6<length) + { + int o=offset+i+2; + i+=6; + String unicode = new String(Character.toChars(TypeUtil.parseInt(encoded,o,4,16))); + byte[] reencoded = unicode.getBytes(charset); + System.arraycopy(reencoded,0,ba,n,reencoded.length); + n+=reencoded.length; + } + else + { + ba[n++] = (byte)'?'; + i=length; + } + } + else + { + int o=offset+i+1; + i+=3; + ba[n]=(byte)TypeUtil.parseInt(encoded,o,2,16); + n++; + } + } + catch(NumberFormatException nfe) + { + LOG.trace("",nfe); + ba[n++] = (byte)'?'; + } + } + else + { + ba[n++] = (byte)'?'; + i=length; + } + } + else if (c=='+') + { + ba[n++]=(byte)' '; + i++; + } + else + { + ba[n++]=(byte)c; + i++; + } + + if (i>=length) + break; + c = encoded.charAt(offset+i); + } - i--; - buffer.append(new String(ba,0,n,charset)); + i--; + buffer.append(new String(ba,0,n,charset)); - } - else if (buffer!=null) - buffer.append(c); - } + } + else if (buffer!=null) + buffer.append(c); + } - if (buffer==null) - { - if (offset==0 && encoded.length()==length) - return encoded; - return encoded.substring(offset,offset+length); - } + if (buffer==null) + { + if (offset==0 && encoded.length()==length) + return encoded; + return encoded.substring(offset,offset+length); + } - return buffer.toString(); - } - catch (UnsupportedEncodingException e) - { - throw new RuntimeException(e); - } - } - - } - - /* ------------------------------------------------------------ */ - /** Perform URL encoding. - * @param string - * @return encoded string. - */ - public static String encodeString(String string) - { - return encodeString(string,ENCODING); - } - - /* ------------------------------------------------------------ */ - /** Perform URL encoding. - * @param string - * @return encoded string. - */ - public static String encodeString(String string,String charset) - { - if (charset==null) - charset=ENCODING; - byte[] bytes=null; - try - { - bytes=string.getBytes(charset); - } - catch(UnsupportedEncodingException e) - { - // LOG.warn(LogSupport.EXCEPTION,e); - bytes=string.getBytes(); - } - - int len=bytes.length; - byte[] encoded= new byte[bytes.length*3]; - int n=0; - boolean noEncode=true; - - for (int i=0;i<len;i++) - { - byte b = bytes[i]; - - if (b==' ') - { - noEncode=false; - encoded[n++]=(byte)'+'; - } - else if (b>='a' && b<='z' || - b>='A' && b<='Z' || - b>='0' && b<='9') - { - encoded[n++]=b; - } - else - { - noEncode=false; - encoded[n++]=(byte)'%'; - byte nibble= (byte) ((b&0xf0)>>4); - if (nibble>=10) - encoded[n++]=(byte)('A'+nibble-10); - else - encoded[n++]=(byte)('0'+nibble); - nibble= (byte) (b&0xf); - if (nibble>=10) - encoded[n++]=(byte)('A'+nibble-10); - else - encoded[n++]=(byte)('0'+nibble); - } - } + return buffer.toString(); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + + } + + /* ------------------------------------------------------------ */ + /** Perform URL encoding. + * @param string + * @return encoded string. + */ + public static String encodeString(String string) + { + return encodeString(string,ENCODING); + } + + /* ------------------------------------------------------------ */ + /** Perform URL encoding. + * @param string + * @return encoded string. + */ + public static String encodeString(String string,String charset) + { + if (charset==null) + charset=ENCODING; + byte[] bytes=null; + try + { + bytes=string.getBytes(charset); + } + catch(UnsupportedEncodingException e) + { + // LOG.warn(LogSupport.EXCEPTION,e); + bytes=string.getBytes(); + } + + int len=bytes.length; + byte[] encoded= new byte[bytes.length*3]; + int n=0; + boolean noEncode=true; + + for (int i=0;i<len;i++) + { + byte b = bytes[i]; + + if (b==' ') + { + noEncode=false; + encoded[n++]=(byte)'+'; + } + else if (b>='a' && b<='z' || + b>='A' && b<='Z' || + b>='0' && b<='9') + { + encoded[n++]=b; + } + else + { + noEncode=false; + encoded[n++]=(byte)'%'; + byte nibble= (byte) ((b&0xf0)>>4); + if (nibble>=10) + encoded[n++]=(byte)('A'+nibble-10); + else + encoded[n++]=(byte)('0'+nibble); + nibble= (byte) (b&0xf); + if (nibble>=10) + encoded[n++]=(byte)('A'+nibble-10); + else + encoded[n++]=(byte)('0'+nibble); + } + } - if (noEncode) - return string; - - try - { - return new String(encoded,0,n,charset); - } - catch(UnsupportedEncodingException e) - { - // LOG.warn(LogSupport.EXCEPTION,e); - return new String(encoded,0,n); - } - } + if (noEncode) + return string; + + try + { + return new String(encoded,0,n,charset); + } + catch(UnsupportedEncodingException e) + { + // LOG.warn(LogSupport.EXCEPTION,e); + return new String(encoded,0,n); + } + } - /* ------------------------------------------------------------ */ - /** - */ - @Override - public Object clone() - { - return new UrlEncoded(this); - } + /* ------------------------------------------------------------ */ + /** + */ + @Override + public Object clone() + { + return new UrlEncoded(this); + } }