Back to index

php5  5.3.10
mbfilter_qprint.c
Go to the documentation of this file.
00001 /*
00002  * "streamable kanji code filter and converter"
00003  * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
00004  *
00005  * LICENSE NOTICES
00006  *
00007  * This file is part of "streamable kanji code filter and converter",
00008  * which is distributed under the terms of GNU Lesser General Public 
00009  * License (version 2) as published by the Free Software Foundation.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with "streamable kanji code filter and converter";
00018  * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
00019  * Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * The author of this file:
00022  *
00023  */
00024 /*
00025  * The source code included in this files was separated from mbfilter.c
00026  * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
00027  * 
00028  */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include "config.h"
00032 #endif
00033 
00034 #include "mbfilter.h"
00035 #include "mbfilter_qprint.h"
00036 #include "unicode_prop.h"
00037 
00038 static const char *mbfl_encoding_qprint_aliases[] = {"qprint", NULL};
00039 
00040 const mbfl_encoding mbfl_encoding_qprint = {
00041        mbfl_no_encoding_qprint,
00042        "Quoted-Printable",
00043        "Quoted-Printable",
00044        (const char *(*)[])&mbfl_encoding_qprint_aliases,
00045        NULL,
00046        MBFL_ENCTYPE_SBCS
00047 };
00048 
00049 const struct mbfl_convert_vtbl vtbl_8bit_qprint = {
00050        mbfl_no_encoding_8bit,
00051        mbfl_no_encoding_qprint,
00052        mbfl_filt_conv_common_ctor,
00053        mbfl_filt_conv_common_dtor,
00054        mbfl_filt_conv_qprintenc,
00055        mbfl_filt_conv_qprintenc_flush };
00056 
00057 const struct mbfl_convert_vtbl vtbl_qprint_8bit = {
00058        mbfl_no_encoding_qprint,
00059        mbfl_no_encoding_8bit,
00060        mbfl_filt_conv_common_ctor,
00061        mbfl_filt_conv_common_dtor,
00062        mbfl_filt_conv_qprintdec,
00063        mbfl_filt_conv_qprintdec_flush };
00064 
00065 
00066 #define CK(statement)       do { if ((statement) < 0) return (-1); } while (0)
00067 
00068 /*
00069  * any => Quoted-Printable
00070  */
00071 
00072 int mbfl_filt_conv_qprintenc(int c, mbfl_convert_filter *filter)
00073 {
00074        int s, n;
00075 
00076        switch (filter->status & 0xff) {
00077        case 0:
00078               filter->cache = c;
00079               filter->status++;
00080               break;
00081        default:
00082               s = filter->cache;
00083               filter->cache = c;
00084               n = (filter->status & 0xff00) >> 8;
00085 
00086               if (s == 0) {        /* null */
00087                      CK((*filter->output_function)(s, filter->data));
00088                      filter->status &= ~0xff00;
00089                      break;
00090               }
00091 
00092               if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
00093                      if (s == 0x0a || (s == 0x0d && c != 0x0a)) {     /* line feed */
00094                             CK((*filter->output_function)(0x0d, filter->data));            /* CR */
00095                             CK((*filter->output_function)(0x0a, filter->data));            /* LF */
00096                             filter->status &= ~0xff00;
00097                             break;
00098                      } else if (s == 0x0d) {
00099                             break;
00100                      }
00101               }
00102 
00103               if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0  && n >= 72) {       /* soft line feed */
00104                      CK((*filter->output_function)(0x3d, filter->data));            /* '=' */
00105                      CK((*filter->output_function)(0x0d, filter->data));            /* CR */
00106                      CK((*filter->output_function)(0x0a, filter->data));            /* LF */
00107                      filter->status &= ~0xff00;
00108               }
00109 
00110               if (s <= 0 || s >= 0x80 || s == 0x3d             /* not ASCII or '=' */
00111                  || ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) != 0 && 
00112                      (mbfl_charprop_table[s] & MBFL_CHP_MMHQENC) != 0)) {
00113                      /* hex-octet */
00114                      CK((*filter->output_function)(0x3d, filter->data));            /* '=' */
00115                      n = (s >> 4) & 0xf;
00116                      if (n < 10) {
00117                             n += 48;             /* '0' */
00118                      } else {
00119                             n += 55;             /* 'A' - 10 */
00120                      }
00121                      CK((*filter->output_function)(n, filter->data));
00122                      n = s & 0xf;
00123                      if (n < 10) {
00124                             n += 48;
00125                      } else {
00126                             n += 55;
00127                      }
00128                      CK((*filter->output_function)(n, filter->data));
00129                      if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
00130                             filter->status += 0x300;
00131                      }
00132               } else {
00133                      CK((*filter->output_function)(s, filter->data));
00134                      if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
00135                             filter->status += 0x100;
00136                      }
00137               }
00138               break;
00139        }
00140 
00141        return c;
00142 }
00143 
00144 int mbfl_filt_conv_qprintenc_flush(mbfl_convert_filter *filter)
00145 {
00146        /* flush filter cache */
00147        (*filter->filter_function)('\0', filter);
00148        filter->status &= ~0xffff;
00149        filter->cache = 0;
00150        return 0;
00151 }
00152 
00153 /*
00154  * Quoted-Printable => any
00155  */
00156 int mbfl_filt_conv_qprintdec(int c, mbfl_convert_filter *filter)
00157 {
00158        int n, m;
00159 
00160        static int hex2code_map[] = {
00161               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00162               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00163               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00164                0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
00165               -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00166               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00167               -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00168               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00169               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00170               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00171               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00172               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00173               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00174               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00175               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00176               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
00177        };
00178 
00179        switch (filter->status) {
00180        case 1:
00181               if (hex2code_map[c & 0xff] >= 0) {
00182                      filter->cache = c;
00183                      filter->status = 2;
00184               } else if (c == 0x0d) {     /* soft line feed */
00185                      filter->status = 3;
00186               } else if (c == 0x0a) {     /* soft line feed */
00187                      filter->status = 0;
00188               } else {
00189                      CK((*filter->output_function)(0x3d, filter->data));            /* '=' */
00190                      CK((*filter->output_function)(c, filter->data));
00191                      filter->status = 0;
00192               }
00193               break;
00194        case 2:
00195               m = hex2code_map[c & 0xff];
00196               if (m < 0) {
00197                      CK((*filter->output_function)(0x3d, filter->data));            /* '=' */
00198                      CK((*filter->output_function)(filter->cache, filter->data));
00199                      n = c;
00200               } else {
00201                      n = hex2code_map[filter->cache] << 4 | m;
00202               }
00203               CK((*filter->output_function)(n, filter->data));
00204               filter->status = 0;
00205               break;
00206        case 3:
00207               if (c != 0x0a) {            /* LF */
00208                      CK((*filter->output_function)(c, filter->data));
00209               }
00210               filter->status = 0;
00211               break;
00212        default:
00213               if (c == 0x3d) {            /* '=' */
00214                      filter->status = 1;
00215               } else {
00216                      CK((*filter->output_function)(c, filter->data));
00217               }
00218               break;
00219        }
00220 
00221        return c;
00222 }
00223 
00224 int mbfl_filt_conv_qprintdec_flush(mbfl_convert_filter *filter)
00225 {
00226        int status, cache;
00227 
00228        status = filter->status;
00229        cache = filter->cache;
00230        filter->status = 0;
00231        filter->cache = 0;
00232        /* flush fragments */
00233        if (status == 1) {
00234               CK((*filter->output_function)(0x3d, filter->data));            /* '=' */
00235        } else if (status == 2) {
00236               CK((*filter->output_function)(0x3d, filter->data));            /* '=' */
00237               CK((*filter->output_function)(cache, filter->data));
00238        }
00239 
00240        return 0;
00241 }
00242 
00243 
00244