QuotedPrintableCodec.java

00001 /*
00002  * Copyright 2001-2004 The Apache Software Foundation.
00003  * 
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  * 
00008  *      http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */ 
00016 
00017 package org.apache.commons.codec.net;
00018 
00019 import java.io.ByteArrayOutputStream;
00020 import java.io.UnsupportedEncodingException;
00021 import java.util.BitSet;
00022 import org.apache.commons.codec.BinaryDecoder;
00023 import org.apache.commons.codec.BinaryEncoder;
00024 import org.apache.commons.codec.DecoderException;
00025 import org.apache.commons.codec.EncoderException;
00026 import org.apache.commons.codec.StringDecoder;
00027 import org.apache.commons.codec.StringEncoder;
00028 
00059 public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, StringDecoder {
00063     private String charset = StringEncodings.UTF8;
00064 
00068     private static final BitSet PRINTABLE_CHARS = new BitSet(256);
00069 
00070     private static byte ESCAPE_CHAR = '=';
00071 
00072     private static byte TAB = 9;
00073 
00074     private static byte SPACE = 32;
00075     // Static initializer for printable chars collection
00076     static {
00077         // alpha characters
00078         for (int i = 33; i <= 60; i++) {
00079             PRINTABLE_CHARS.set(i);
00080         }
00081         for (int i = 62; i <= 126; i++) {
00082             PRINTABLE_CHARS.set(i);
00083         }
00084         PRINTABLE_CHARS.set(TAB);
00085         PRINTABLE_CHARS.set(SPACE);
00086     }
00087 
00091     public QuotedPrintableCodec() {
00092         super();
00093     }
00094 
00101     public QuotedPrintableCodec(String charset) {
00102         super();
00103         this.charset = charset;
00104     }
00105 
00114     private static final void encodeQuotedPrintable(int b, ByteArrayOutputStream buffer) {
00115         buffer.write(ESCAPE_CHAR);
00116         char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
00117         char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
00118         buffer.write(hex1);
00119         buffer.write(hex2);
00120     }
00121 
00136     public static final byte[] encodeQuotedPrintable(BitSet printable, byte[] bytes) {
00137         if (bytes == null) {
00138             return null;
00139         }
00140         if (printable == null) {
00141             printable = PRINTABLE_CHARS;
00142         }
00143         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
00144         for (int i = 0; i < bytes.length; i++) {
00145             int b = bytes[i];
00146             if (b < 0) {
00147                 b = 256 + b;
00148             }
00149             if (printable.get(b)) {
00150                 buffer.write(b);
00151             } else {
00152                 encodeQuotedPrintable(b, buffer);
00153             }
00154         }
00155         return buffer.toByteArray();
00156     }
00157 
00173     public static final byte[] decodeQuotedPrintable(byte[] bytes) throws DecoderException {
00174         if (bytes == null) {
00175             return null;
00176         }
00177         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
00178         for (int i = 0; i < bytes.length; i++) {
00179             int b = bytes[i];
00180             if (b == ESCAPE_CHAR) {
00181                 try {
00182                     int u = Character.digit((char) bytes[++i], 16);
00183                     int l = Character.digit((char) bytes[++i], 16);
00184                     if (u == -1 || l == -1) {
00185                         throw new DecoderException("Invalid quoted-printable encoding");
00186                     }
00187                     buffer.write((char) ((u << 4) + l));
00188                 } catch (ArrayIndexOutOfBoundsException e) {
00189                     throw new DecoderException("Invalid quoted-printable encoding");
00190                 }
00191             } else {
00192                 buffer.write(b);
00193             }
00194         }
00195         return buffer.toByteArray();
00196     }
00197 
00210     public byte[] encode(byte[] bytes) {
00211         return encodeQuotedPrintable(PRINTABLE_CHARS, bytes);
00212     }
00213 
00229     public byte[] decode(byte[] bytes) throws DecoderException {
00230         return decodeQuotedPrintable(bytes);
00231     }
00232 
00250     public String encode(String pString) throws EncoderException {
00251         if (pString == null) {
00252             return null;
00253         }
00254         try {
00255             return encode(pString, getDefaultCharset());
00256         } catch (UnsupportedEncodingException e) {
00257             throw new EncoderException(e.getMessage());
00258         }
00259     }
00260 
00275     public String decode(String pString, String charset) throws DecoderException, UnsupportedEncodingException {
00276         if (pString == null) {
00277             return null;
00278         }
00279         return new String(decode(pString.getBytes(StringEncodings.US_ASCII)), charset);
00280     }
00281 
00295     public String decode(String pString) throws DecoderException {
00296         if (pString == null) {
00297             return null;
00298         }
00299         try {
00300             return decode(pString, getDefaultCharset());
00301         } catch (UnsupportedEncodingException e) {
00302             throw new DecoderException(e.getMessage());
00303         }
00304     }
00305 
00316     public Object encode(Object pObject) throws EncoderException {
00317         if (pObject == null) {
00318             return null;
00319         } else if (pObject instanceof byte[]) {
00320             return encode((byte[]) pObject);
00321         } else if (pObject instanceof String) {
00322             return encode((String) pObject);
00323         } else {
00324             throw new EncoderException("Objects of type "
00325                 + pObject.getClass().getName()
00326                 + " cannot be quoted-printable encoded");
00327         }
00328     }
00329 
00341     public Object decode(Object pObject) throws DecoderException {
00342         if (pObject == null) {
00343             return null;
00344         } else if (pObject instanceof byte[]) {
00345             return decode((byte[]) pObject);
00346         } else if (pObject instanceof String) {
00347             return decode((String) pObject);
00348         } else {
00349             throw new DecoderException("Objects of type "
00350                 + pObject.getClass().getName()
00351                 + " cannot be quoted-printable decoded");
00352         }
00353     }
00354 
00360     public String getDefaultCharset() {
00361         return this.charset;
00362     }
00363 
00381     public String encode(String pString, String charset) throws UnsupportedEncodingException {
00382         if (pString == null) {
00383             return null;
00384         }
00385         return new String(encode(pString.getBytes(charset)), StringEncodings.US_ASCII);
00386     }
00387 }

Generated on Mon Dec 4 11:03:29 2006 for OpenMobileIS by  doxygen 1.5.1-p1