• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.apache.commons.codec.net;
18 
19 import java.io.UnsupportedEncodingException;
20 import java.util.BitSet;
21 
22 import org.apache.commons.codec.DecoderException;
23 import org.apache.commons.codec.EncoderException;
24 import org.apache.commons.codec.StringDecoder;
25 import org.apache.commons.codec.StringEncoder;
26 
27 /**
28  * <p>
29  * Similar to the Quoted-Printable content-transfer-encoding defined in <a
30  * href="http://www.ietf.org/rfc/rfc1521.txt">RFC 1521</a> and designed to allow text containing mostly ASCII
31  * characters to be decipherable on an ASCII terminal without decoding.
32  * </p>
33  *
34  * <p>
35  * <a href="http://www.ietf.org/rfc/rfc1522.txt">RFC 1522</a> describes techniques to allow the encoding of non-ASCII
36  * text in various portions of a RFC 822 [2] message header, in a manner which is unlikely to confuse existing message
37  * handling software.
38  * </p>
39  *
40  * @see <a href="http://www.ietf.org/rfc/rfc1522.txt">MIME (Multipurpose Internet Mail Extensions) Part Two: Message
41  *          Header Extensions for Non-ASCII Text</a>
42  *
43  * @author Apache Software Foundation
44  * @since 1.3
45  * @version $Id: QCodec.java,v 1.6 2004/05/24 00:24:32 ggregory Exp $
46  *
47  * @deprecated Please use {@link java.net.URL#openConnection} instead.
48  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
49  *     for further details.
50  */
51 @Deprecated
52 public class QCodec extends RFC1522Codec implements StringEncoder, StringDecoder {
53     /**
54      * The default charset used for string decoding and encoding.
55      */
56     private String charset = StringEncodings.UTF8;
57 
58     /**
59      * BitSet of printable characters as defined in RFC 1522.
60      */
61     private static final BitSet PRINTABLE_CHARS = new BitSet(256);
62     // Static initializer for printable chars collection
63     static {
64         // alpha characters
65         PRINTABLE_CHARS.set(' ');
66         PRINTABLE_CHARS.set('!');
67         PRINTABLE_CHARS.set('"');
68         PRINTABLE_CHARS.set('#');
69         PRINTABLE_CHARS.set('$');
70         PRINTABLE_CHARS.set('%');
71         PRINTABLE_CHARS.set('&');
72         PRINTABLE_CHARS.set('\'');
73         PRINTABLE_CHARS.set('(');
74         PRINTABLE_CHARS.set(')');
75         PRINTABLE_CHARS.set('*');
76         PRINTABLE_CHARS.set('+');
77         PRINTABLE_CHARS.set(',');
78         PRINTABLE_CHARS.set('-');
79         PRINTABLE_CHARS.set('.');
80         PRINTABLE_CHARS.set('/');
81         for (int i = '0'; i <= '9'; i++) {
82             PRINTABLE_CHARS.set(i);
83         }
84         PRINTABLE_CHARS.set(':');
85         PRINTABLE_CHARS.set(';');
86         PRINTABLE_CHARS.set('<');
87         PRINTABLE_CHARS.set('>');
88         PRINTABLE_CHARS.set('@');
89         for (int i = 'A'; i <= 'Z'; i++) {
90             PRINTABLE_CHARS.set(i);
91         }
92         PRINTABLE_CHARS.set('[');
93         PRINTABLE_CHARS.set('\\');
94         PRINTABLE_CHARS.set(']');
95         PRINTABLE_CHARS.set('^');
96         PRINTABLE_CHARS.set('`');
97         for (int i = 'a'; i <= 'z'; i++) {
98             PRINTABLE_CHARS.set(i);
99         }
100         PRINTABLE_CHARS.set('{');
101         PRINTABLE_CHARS.set('|');
102         PRINTABLE_CHARS.set('}');
103         PRINTABLE_CHARS.set('~');
104     }
105 
106     private static byte BLANK = 32;
107 
108     private static byte UNDERSCORE = 95;
109 
110     private boolean encodeBlanks = false;
111 
112     /**
113      * Default constructor.
114      */
QCodec()115     public QCodec() {
116         super();
117     }
118 
119     /**
120      * Constructor which allows for the selection of a default charset
121      *
122      * @param charset
123      *                  the default string charset to use.
124      *
125      * @see <a href="http://java.sun.com/j2se/1.3/docs/api/java/lang/package-summary.html#charenc">JRE character
126      *          encoding names</a>
127      */
QCodec(final String charset)128     public QCodec(final String charset) {
129         super();
130         this.charset = charset;
131     }
132 
getEncoding()133     protected String getEncoding() {
134         return "Q";
135     }
136 
doEncoding(byte[] bytes)137     protected byte[] doEncoding(byte[] bytes) throws EncoderException {
138         if (bytes == null) {
139             return null;
140         }
141         byte[] data = QuotedPrintableCodec.encodeQuotedPrintable(PRINTABLE_CHARS, bytes);
142         if (this.encodeBlanks) {
143             for (int i = 0; i < data.length; i++) {
144                 if (data[i] == BLANK) {
145                     data[i] = UNDERSCORE;
146                 }
147             }
148         }
149         return data;
150     }
151 
doDecoding(byte[] bytes)152     protected byte[] doDecoding(byte[] bytes) throws DecoderException {
153         if (bytes == null) {
154             return null;
155         }
156         boolean hasUnderscores = false;
157         for (int i = 0; i < bytes.length; i++) {
158             if (bytes[i] == UNDERSCORE) {
159                 hasUnderscores = true;
160                 break;
161             }
162         }
163         if (hasUnderscores) {
164             byte[] tmp = new byte[bytes.length];
165             for (int i = 0; i < bytes.length; i++) {
166                 byte b = bytes[i];
167                 if (b != UNDERSCORE) {
168                     tmp[i] = b;
169                 } else {
170                     tmp[i] = BLANK;
171                 }
172             }
173             return QuotedPrintableCodec.decodeQuotedPrintable(tmp);
174         }
175         return QuotedPrintableCodec.decodeQuotedPrintable(bytes);
176     }
177 
178     /**
179      * Encodes a string into its quoted-printable form using the specified charset. Unsafe characters are escaped.
180      *
181      * @param pString
182      *                  string to convert to quoted-printable form
183      * @param charset
184      *                  the charset for pString
185      * @return quoted-printable string
186      *
187      * @throws EncoderException
188      *                  thrown if a failure condition is encountered during the encoding process.
189      */
encode(final String pString, final String charset)190     public String encode(final String pString, final String charset) throws EncoderException {
191         if (pString == null) {
192             return null;
193         }
194         try {
195             return encodeText(pString, charset);
196         } catch (UnsupportedEncodingException e) {
197             throw new EncoderException(e.getMessage());
198         }
199     }
200 
201     /**
202      * Encodes a string into its quoted-printable form using the default charset. Unsafe characters are escaped.
203      *
204      * @param pString
205      *                  string to convert to quoted-printable form
206      * @return quoted-printable string
207      *
208      * @throws EncoderException
209      *                  thrown if a failure condition is encountered during the encoding process.
210      */
encode(String pString)211     public String encode(String pString) throws EncoderException {
212         if (pString == null) {
213             return null;
214         }
215         return encode(pString, getDefaultCharset());
216     }
217 
218     /**
219      * Decodes a quoted-printable string into its original form. Escaped characters are converted back to their original
220      * representation.
221      *
222      * @param pString
223      *                  quoted-printable string to convert into its original form
224      *
225      * @return original string
226      *
227      * @throws DecoderException
228      *                  A decoder exception is thrown if a failure condition is encountered during the decode process.
229      */
decode(String pString)230     public String decode(String pString) throws DecoderException {
231         if (pString == null) {
232             return null;
233         }
234         try {
235             return decodeText(pString);
236         } catch (UnsupportedEncodingException e) {
237             throw new DecoderException(e.getMessage());
238         }
239     }
240 
241     /**
242      * Encodes an object into its quoted-printable form using the default charset. Unsafe characters are escaped.
243      *
244      * @param pObject
245      *                  object to convert to quoted-printable form
246      * @return quoted-printable object
247      *
248      * @throws EncoderException
249      *                  thrown if a failure condition is encountered during the encoding process.
250      */
encode(Object pObject)251     public Object encode(Object pObject) throws EncoderException {
252         if (pObject == null) {
253             return null;
254         } else if (pObject instanceof String) {
255             return encode((String) pObject);
256         } else {
257             throw new EncoderException("Objects of type "
258                 + pObject.getClass().getName()
259                 + " cannot be encoded using Q codec");
260         }
261     }
262 
263     /**
264      * Decodes a quoted-printable object into its original form. Escaped characters are converted back to their original
265      * representation.
266      *
267      * @param pObject
268      *                  quoted-printable object to convert into its original form
269      *
270      * @return original object
271      *
272      * @throws DecoderException
273      *                  A decoder exception is thrown if a failure condition is encountered during the decode process.
274      */
decode(Object pObject)275     public Object decode(Object pObject) throws DecoderException {
276         if (pObject == null) {
277             return null;
278         } else if (pObject instanceof String) {
279             return decode((String) pObject);
280         } else {
281             throw new DecoderException("Objects of type "
282                 + pObject.getClass().getName()
283                 + " cannot be decoded using Q codec");
284         }
285     }
286 
287     /**
288      * The default charset used for string decoding and encoding.
289      *
290      * @return the default string charset.
291      */
getDefaultCharset()292     public String getDefaultCharset() {
293         return this.charset;
294     }
295 
296     /**
297      * Tests if optional tranformation of SPACE characters is to be used
298      *
299      * @return <code>true</code> if SPACE characters are to be transformed, <code>false</code> otherwise
300      */
isEncodeBlanks()301     public boolean isEncodeBlanks() {
302         return this.encodeBlanks;
303     }
304 
305     /**
306      * Defines whether optional tranformation of SPACE characters is to be used
307      *
308      * @param b
309      *                  <code>true</code> if SPACE characters are to be transformed, <code>false</code> otherwise
310      */
setEncodeBlanks(boolean b)311     public void setEncodeBlanks(boolean b) {
312         this.encodeBlanks = b;
313     }
314 }
315