Home | History | Annotate | Download | only in net
      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      */
    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      */
    128     public QCodec(final String charset) {
    129         super();
    130         this.charset = charset;
    131     }
    132 
    133     protected String getEncoding() {
    134         return "Q";
    135     }
    136 
    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 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    311     public void setEncodeBlanks(boolean b) {
    312         this.encodeBlanks = b;
    313     }
    314 }
    315