root/ext/mbstring/libmbfl/filters/mbfilter_qprint.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mbfl_filt_conv_qprintenc
  2. mbfl_filt_conv_qprintenc_flush
  3. mbfl_filt_conv_qprintdec
  4. mbfl_filt_conv_qprintdec_flush

   1 /*
   2  * "streamable kanji code filter and converter"
   3  * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
   4  *
   5  * LICENSE NOTICES
   6  *
   7  * This file is part of "streamable kanji code filter and converter",
   8  * which is distributed under the terms of GNU Lesser General Public
   9  * License (version 2) as published by the Free Software Foundation.
  10  *
  11  * This software is distributed in the hope that it will be useful,
  12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  * GNU Lesser General Public License for more details.
  15  *
  16  * You should have received a copy of the GNU Lesser General Public
  17  * License along with "streamable kanji code filter and converter";
  18  * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
  19  * Suite 330, Boston, MA  02111-1307  USA
  20  *
  21  * The author of this file:
  22  *
  23  */
  24 /*
  25  * The source code included in this files was separated from mbfilter.c
  26  * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
  27  *
  28  */
  29 
  30 #ifdef HAVE_CONFIG_H
  31 #include "config.h"
  32 #endif
  33 
  34 #include "mbfilter.h"
  35 #include "mbfilter_qprint.h"
  36 #include "unicode_prop.h"
  37 
  38 static const char *mbfl_encoding_qprint_aliases[] = {"qprint", NULL};
  39 
  40 const mbfl_encoding mbfl_encoding_qprint = {
  41         mbfl_no_encoding_qprint,
  42         "Quoted-Printable",
  43         "Quoted-Printable",
  44         (const char *(*)[])&mbfl_encoding_qprint_aliases,
  45         NULL,
  46         MBFL_ENCTYPE_ENC_STRM | MBFL_ENCTYPE_GL_UNSAFE
  47 };
  48 
  49 const struct mbfl_convert_vtbl vtbl_8bit_qprint = {
  50         mbfl_no_encoding_8bit,
  51         mbfl_no_encoding_qprint,
  52         mbfl_filt_conv_common_ctor,
  53         mbfl_filt_conv_common_dtor,
  54         mbfl_filt_conv_qprintenc,
  55         mbfl_filt_conv_qprintenc_flush };
  56 
  57 const struct mbfl_convert_vtbl vtbl_qprint_8bit = {
  58         mbfl_no_encoding_qprint,
  59         mbfl_no_encoding_8bit,
  60         mbfl_filt_conv_common_ctor,
  61         mbfl_filt_conv_common_dtor,
  62         mbfl_filt_conv_qprintdec,
  63         mbfl_filt_conv_qprintdec_flush };
  64 
  65 
  66 #define CK(statement)   do { if ((statement) < 0) return (-1); } while (0)
  67 
  68 /*
  69  * any => Quoted-Printable
  70  */
  71 
  72 int mbfl_filt_conv_qprintenc(int c, mbfl_convert_filter *filter)
  73 {
  74         int s, n;
  75 
  76         switch (filter->status & 0xff) {
  77         case 0:
  78                 filter->cache = c;
  79                 filter->status++;
  80                 break;
  81         default:
  82                 s = filter->cache;
  83                 filter->cache = c;
  84                 n = (filter->status & 0xff00) >> 8;
  85 
  86                 if (s == 0) {           /* null */
  87                         CK((*filter->output_function)(s, filter->data));
  88                         filter->status &= ~0xff00;
  89                         break;
  90                 }
  91 
  92                 if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
  93                         if (s == 0x0a || (s == 0x0d && c != 0x0a)) {    /* line feed */
  94                                 CK((*filter->output_function)(0x0d, filter->data));             /* CR */
  95                                 CK((*filter->output_function)(0x0a, filter->data));             /* LF */
  96                                 filter->status &= ~0xff00;
  97                                 break;
  98                         } else if (s == 0x0d) {
  99                                 break;
 100                         }
 101                 }
 102 
 103                 if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0  && n >= 72) {  /* soft line feed */
 104                         CK((*filter->output_function)(0x3d, filter->data));             /* '=' */
 105                         CK((*filter->output_function)(0x0d, filter->data));             /* CR */
 106                         CK((*filter->output_function)(0x0a, filter->data));             /* LF */
 107                         filter->status &= ~0xff00;
 108                 }
 109 
 110                 if (s <= 0 || s >= 0x80 || s == 0x3d            /* not ASCII or '=' */
 111                    || ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) != 0 &&
 112                        (mbfl_charprop_table[s] & MBFL_CHP_MMHQENC) != 0)) {
 113                         /* hex-octet */
 114                         CK((*filter->output_function)(0x3d, filter->data));             /* '=' */
 115                         n = (s >> 4) & 0xf;
 116                         if (n < 10) {
 117                                 n += 48;                /* '0' */
 118                         } else {
 119                                 n += 55;                /* 'A' - 10 */
 120                         }
 121                         CK((*filter->output_function)(n, filter->data));
 122                         n = s & 0xf;
 123                         if (n < 10) {
 124                                 n += 48;
 125                         } else {
 126                                 n += 55;
 127                         }
 128                         CK((*filter->output_function)(n, filter->data));
 129                         if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
 130                                 filter->status += 0x300;
 131                         }
 132                 } else {
 133                         CK((*filter->output_function)(s, filter->data));
 134                         if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
 135                                 filter->status += 0x100;
 136                         }
 137                 }
 138                 break;
 139         }
 140 
 141         return c;
 142 }
 143 
 144 int mbfl_filt_conv_qprintenc_flush(mbfl_convert_filter *filter)
 145 {
 146         /* flush filter cache */
 147         (*filter->filter_function)('\0', filter);
 148         filter->status &= ~0xffff;
 149         filter->cache = 0;
 150         return 0;
 151 }
 152 
 153 /*
 154  * Quoted-Printable => any
 155  */
 156 int mbfl_filt_conv_qprintdec(int c, mbfl_convert_filter *filter)
 157 {
 158         int n, m;
 159 
 160         static int hex2code_map[] = {
 161                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 162                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 163                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 164                  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
 165                 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 166                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 167                 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 168                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 169                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 170                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 171                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 172                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 173                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 174                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 175                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 176                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 177         };
 178 
 179         switch (filter->status) {
 180         case 1:
 181                 if (hex2code_map[c & 0xff] >= 0) {
 182                         filter->cache = c;
 183                         filter->status = 2;
 184                 } else if (c == 0x0d) { /* soft line feed */
 185                         filter->status = 3;
 186                 } else if (c == 0x0a) { /* soft line feed */
 187                         filter->status = 0;
 188                 } else {
 189                         CK((*filter->output_function)(0x3d, filter->data));             /* '=' */
 190                         CK((*filter->output_function)(c, filter->data));
 191                         filter->status = 0;
 192                 }
 193                 break;
 194         case 2:
 195                 m = hex2code_map[c & 0xff];
 196                 if (m < 0) {
 197                         CK((*filter->output_function)(0x3d, filter->data));             /* '=' */
 198                         CK((*filter->output_function)(filter->cache, filter->data));
 199                         n = c;
 200                 } else {
 201                         n = hex2code_map[filter->cache] << 4 | m;
 202                 }
 203                 CK((*filter->output_function)(n, filter->data));
 204                 filter->status = 0;
 205                 break;
 206         case 3:
 207                 if (c != 0x0a) {                /* LF */
 208                         CK((*filter->output_function)(c, filter->data));
 209                 }
 210                 filter->status = 0;
 211                 break;
 212         default:
 213                 if (c == 0x3d) {                /* '=' */
 214                         filter->status = 1;
 215                 } else {
 216                         CK((*filter->output_function)(c, filter->data));
 217                 }
 218                 break;
 219         }
 220 
 221         return c;
 222 }
 223 
 224 int mbfl_filt_conv_qprintdec_flush(mbfl_convert_filter *filter)
 225 {
 226         int status, cache;
 227 
 228         status = filter->status;
 229         cache = filter->cache;
 230         filter->status = 0;
 231         filter->cache = 0;
 232         /* flush fragments */
 233         if (status == 1) {
 234                 CK((*filter->output_function)(0x3d, filter->data));             /* '=' */
 235         } else if (status == 2) {
 236                 CK((*filter->output_function)(0x3d, filter->data));             /* '=' */
 237                 CK((*filter->output_function)(cache, filter->data));
 238         }
 239 
 240         return 0;
 241 }
 242 
 243 
 244 

/* [<][>][^][v][top][bottom][index][help] */