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