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 java.net;
019:
020: import java.io.UnsupportedEncodingException;
021: import java.nio.ByteBuffer;
022: import java.nio.CharBuffer;
023: import java.nio.charset.Charset;
024: import java.nio.charset.IllegalCharsetNameException;
025: import java.nio.charset.UnsupportedCharsetException;
026:
027: import org.apache.harmony.luni.util.Msg;
028:
029: /**
030: * This class is used to decode a string which is encoded in the
031: * <code>application/x-www-form-urlencoded</code> MIME content type.
032: */
033: public class URLDecoder {
034:
035: static Charset defaultCharset;
036:
037: /**
038: * Decodes the string argument which is assumed to be encoded in the
039: * <code>x-www-form-urlencoded</code> MIME content type.
040: * <p>
041: * '+' will be converted to space, '%' and two following hex digit
042: * characters are converted to the equivalent byte value. All other
043: * characters are passed through unmodified.
044: * <p>
045: * e.g. "A+B+C %24%25" -> "A B C $%"
046: *
047: * @param s
048: * java.lang.String The encoded string.
049: * @return java.lang.String The decoded version.
050: *
051: * @deprecated use URLDecoder#decode(String, String) instead
052: */
053: @Deprecated
054: public static String decode(String s) {
055:
056: if (defaultCharset == null) {
057: try {
058: defaultCharset = Charset.forName(System
059: .getProperty("file.encoding")); //$NON-NLS-1$
060: } catch (IllegalCharsetNameException e) {
061: // Ignored
062: } catch (UnsupportedCharsetException e) {
063: // Ignored
064: }
065:
066: if (defaultCharset == null) {
067: defaultCharset = Charset.forName("ISO-8859-1"); //$NON-NLS-1$
068: }
069: }
070: return decode(s, defaultCharset);
071: }
072:
073: /**
074: * Decodes the string argument which is assumed to be encoded in the
075: * <code>x-www-form-urlencoded</code> MIME content type using the
076: * specified encoding scheme.
077: * <p>
078: * '+' will be converted to space, '%' and two following hex digit
079: * characters are converted to the equivalent byte value. All other
080: * characters are passed through unmodified.
081: *
082: * <p>
083: * e.g. "A+B+C %24%25" -> "A B C $%"
084: *
085: * @param s
086: * java.lang.String The encoded string.
087: * @param enc
088: * java.lang.String The encoding scheme to use
089: * @return java.lang.String The decoded version.
090: */
091: public static String decode(String s, String enc)
092: throws UnsupportedEncodingException {
093:
094: if (enc == null) {
095: throw new NullPointerException();
096: }
097:
098: // If the given encoding is an empty string throw an exception.
099: if (enc.length() == 0) {
100: throw new UnsupportedEncodingException(
101: // K00a5=Invalid parameter - {0}
102: Msg.getString("K00a5", "enc")); //$NON-NLS-1$ //$NON-NLS-2$
103: }
104:
105: if (s.indexOf('%') == -1) {
106: if (s.indexOf('+') == -1)
107: return s;
108: char str[] = s.toCharArray();
109: for (int i = 0; i < str.length; i++) {
110: if (str[i] == '+')
111: str[i] = ' ';
112: }
113: return new String(str);
114: }
115:
116: Charset charset = null;
117: try {
118: charset = Charset.forName(enc);
119: } catch (IllegalCharsetNameException e) {
120: throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
121: enc).initCause(e));
122: } catch (UnsupportedCharsetException e) {
123: throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
124: enc).initCause(e));
125: }
126:
127: return decode(s, charset);
128: }
129:
130: private static String decode(String s, Charset charset) {
131:
132: char str_buf[] = new char[s.length()];
133: byte buf[] = new byte[s.length() / 3];
134: int buf_len = 0;
135:
136: for (int i = 0; i < s.length();) {
137: char c = s.charAt(i);
138: if (c == '+') {
139: str_buf[buf_len] = ' ';
140: } else if (c == '%') {
141:
142: int len = 0;
143: do {
144: if (i + 2 >= s.length()) {
145: throw new IllegalArgumentException(
146: // K01fe=Incomplete % sequence at\: {0}
147: Msg.getString("K01fe", i)); //$NON-NLS-1$
148: }
149: int d1 = Character.digit(s.charAt(i + 1), 16);
150: int d2 = Character.digit(s.charAt(i + 2), 16);
151: if (d1 == -1 || d2 == -1) {
152: throw new IllegalArgumentException(
153: // K01ff=Invalid % sequence ({0}) at\: {1}
154: Msg.getString("K01ff", //$NON-NLS-1$
155: s.substring(i, i + 3), String
156: .valueOf(i)));
157: }
158: buf[len++] = (byte) ((d1 << 4) + d2);
159: i += 3;
160: } while (i < s.length() && s.charAt(i) == '%');
161:
162: CharBuffer cb = charset.decode(ByteBuffer.wrap(buf, 0,
163: len));
164: len = cb.length();
165: System.arraycopy(cb.array(), 0, str_buf, buf_len, len);
166: buf_len += len;
167: continue;
168: } else {
169: str_buf[buf_len] = c;
170: }
171: i++;
172: buf_len++;
173: }
174: return new String(str_buf, 0, buf_len);
175: }
176: }
|