Annotation of embedaddon/php/ext/mbstring/libmbfl/filters/mbfilter_utf7imap.c, revision 1.1.1.1

1.1       misho       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_utf7imap.h"
                     36: 
                     37: const mbfl_encoding mbfl_encoding_utf7imap = {
                     38:        mbfl_no_encoding_utf7imap,
                     39:        "UTF7-IMAP",
                     40:        NULL,
                     41:        NULL,
                     42:        NULL,
                     43:        MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
                     44: };
                     45: 
                     46: const struct mbfl_convert_vtbl vtbl_utf7imap_wchar = {
                     47:        mbfl_no_encoding_utf7imap,
                     48:        mbfl_no_encoding_wchar,
                     49:        mbfl_filt_conv_common_ctor,
                     50:        mbfl_filt_conv_common_dtor,
                     51:        mbfl_filt_conv_utf7imap_wchar,
                     52:        mbfl_filt_conv_common_flush };
                     53: 
                     54: const struct mbfl_convert_vtbl vtbl_wchar_utf7imap = {
                     55:        mbfl_no_encoding_wchar,
                     56:        mbfl_no_encoding_utf7imap,
                     57:        mbfl_filt_conv_common_ctor,
                     58:        mbfl_filt_conv_common_dtor,
                     59:        mbfl_filt_conv_wchar_utf7imap,
                     60:        mbfl_filt_conv_wchar_utf7imap_flush };
                     61: 
                     62: #define CK(statement)  do { if ((statement) < 0) return (-1); } while (0)
                     63: 
                     64: /*
                     65:  * UTF7-IMAP => wchar
                     66:  */
                     67: int mbfl_filt_conv_utf7imap_wchar(int c, mbfl_convert_filter *filter)
                     68: {
                     69:        int s, n;
                     70: 
                     71:        n = -1;
                     72:        if (filter->status != 0) {              /* Modified Base64 */
                     73:                if (c >= 0x41 && c <= 0x5a) {           /* A - Z */
                     74:                        n = c - 65;
                     75:                } else if (c >= 0x61 && c <= 0x7a) {    /* a - z */
                     76:                        n = c - 71;
                     77:                } else if (c >= 0x30 && c <= 0x39) {    /* 0 - 9 */
                     78:                        n = c + 4;
                     79:                } else if (c == 0x2b) {                 /* '+' */
                     80:                        n = 62;
                     81:                } else if (c == 0x2c) {                 /* ',' */
                     82:                        n = 63;
                     83:                }
                     84:                if (n < 0 || n > 63) {
                     85:                        if (c == 0x2d) {
                     86:                                if (filter->status == 1) {              /* "&-" -> "&" */
                     87:                                        CK((*filter->output_function)(0x26, filter->data));
                     88:                                }
                     89:                        } else if (c >= 0 && c < 0x80) {        /* ASCII exclude '-' */
                     90:                                CK((*filter->output_function)(c, filter->data));
                     91:                        } else {                /* illegal character */
                     92:                                s = c & MBFL_WCSGROUP_MASK;
                     93:                                s |= MBFL_WCSGROUP_THROUGH;
                     94:                                CK((*filter->output_function)(s, filter->data));
                     95:                        }
                     96:                        filter->cache = 0;
                     97:                        filter->status = 0;
                     98:                        return c;
                     99:                }
                    100:        }
                    101: 
                    102:        switch (filter->status) {
                    103:        /* directly encoded characters */
                    104:        case 0:
                    105:                if (c == 0x26) {        /* '&'  shift character */
                    106:                        filter->status++;
                    107:                } else if (c >= 0 && c < 0x80) {        /* ASCII */
                    108:                        CK((*filter->output_function)(c, filter->data));
                    109:                } else {                /* illegal character */
                    110:                        s = c & MBFL_WCSGROUP_MASK;
                    111:                        s |= MBFL_WCSGROUP_THROUGH;
                    112:                        CK((*filter->output_function)(s, filter->data));
                    113:                }
                    114:                break;
                    115: 
                    116:        /* decode Modified Base64 */
                    117:        case 1:
                    118:        case 2:
                    119:                filter->cache |= n << 10;
                    120:                filter->status = 3;
                    121:                break;
                    122:        case 3:
                    123:                filter->cache |= n << 4;
                    124:                filter->status = 4;
                    125:                break;
                    126:        case 4:
                    127:                s = ((n >> 2) & 0xf) | (filter->cache & 0xffff);
                    128:                n = (n & 0x3) << 14;
                    129:                filter->status = 5;
                    130:                if (s >= 0xd800 && s < 0xdc00) {
                    131:                        s = (((s & 0x3ff) << 16) + 0x400000) | n;
                    132:                        filter->cache = s;
                    133:                } else if (s >= 0xdc00 && s < 0xe000) {
                    134:                        s &= 0x3ff;
                    135:                        s |= (filter->cache & 0xfff0000) >> 6;
                    136:                        filter->cache = n;
                    137:                        if (s >= MBFL_WCSPLANE_SUPMIN && s < MBFL_WCSPLANE_SUPMAX) {
                    138:                                CK((*filter->output_function)(s, filter->data));
                    139:                        } else {                /* illegal character */
                    140:                                s &= MBFL_WCSGROUP_MASK;
                    141:                                s |= MBFL_WCSGROUP_THROUGH;
                    142:                                CK((*filter->output_function)(s, filter->data));
                    143:                        }
                    144:                } else {
                    145:                        filter->cache = n;
                    146:                        CK((*filter->output_function)(s, filter->data));
                    147:                }
                    148:                break;
                    149: 
                    150:        case 5:
                    151:                filter->cache |= n << 8;
                    152:                filter->status = 6;
                    153:                break;
                    154:        case 6:
                    155:                filter->cache |= n << 2;
                    156:                filter->status = 7;
                    157:                break;
                    158:        case 7:
                    159:                s = ((n >> 4) & 0x3) | (filter->cache & 0xffff);
                    160:                n = (n & 0xf) << 12;
                    161:                filter->status = 8;
                    162:                if (s >= 0xd800 && s < 0xdc00) {
                    163:                        s = (((s & 0x3ff) << 16) + 0x400000) | n;
                    164:                        filter->cache = s;
                    165:                } else if (s >= 0xdc00 && s < 0xe000) {
                    166:                        s &= 0x3ff;
                    167:                        s |= (filter->cache & 0xfff0000) >> 6;
                    168:                        filter->cache = n;
                    169:                        if (s >= MBFL_WCSPLANE_SUPMIN && s < MBFL_WCSPLANE_SUPMAX) {
                    170:                                CK((*filter->output_function)(s, filter->data));
                    171:                        } else {                /* illegal character */
                    172:                                s &= MBFL_WCSGROUP_MASK;
                    173:                                s |= MBFL_WCSGROUP_THROUGH;
                    174:                                CK((*filter->output_function)(s, filter->data));
                    175:                        }
                    176:                } else {
                    177:                        filter->cache = n;
                    178:                        CK((*filter->output_function)(s, filter->data));
                    179:                }
                    180:                break;
                    181: 
                    182:        case 8:
                    183:                filter->cache |= n << 6;
                    184:                filter->status = 9;
                    185:                break;
                    186:        case 9:
                    187:                s = n | (filter->cache & 0xffff);
                    188:                filter->status = 2;
                    189:                if (s >= 0xd800 && s < 0xdc00) {
                    190:                        s = (((s & 0x3ff) << 16) + 0x400000);
                    191:                        filter->cache = s;
                    192:                } else if (s >= 0xdc00 && s < 0xe000) {
                    193:                        s &= 0x3ff;
                    194:                        s |= (filter->cache & 0xfff0000) >> 6;
                    195:                        filter->cache = 0;
                    196:                        if (s >= MBFL_WCSPLANE_SUPMIN && s < MBFL_WCSPLANE_SUPMAX) {
                    197:                                CK((*filter->output_function)(s, filter->data));
                    198:                        } else {                /* illegal character */
                    199:                                s &= MBFL_WCSGROUP_MASK;
                    200:                                s |= MBFL_WCSGROUP_THROUGH;
                    201:                                CK((*filter->output_function)(s, filter->data));
                    202:                        }
                    203:                } else {
                    204:                        filter->cache = 0;
                    205:                        CK((*filter->output_function)(s, filter->data));
                    206:                }
                    207:                break;
                    208: 
                    209:        default:
                    210:                filter->status = 0;
                    211:                break;
                    212:        }
                    213: 
                    214:        return c;
                    215: }
                    216: 
                    217: static const unsigned char mbfl_utf7imap_base64_table[] =
                    218: {
                    219:  /* 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', */
                    220:    0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,
                    221:  /* 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', */
                    222:    0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,
                    223:  /* 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', */
                    224:    0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,
                    225:  /* 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', */
                    226:    0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,
                    227:  /* '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', ',', '\0' */
                    228:    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2b,0x2c,0x00
                    229: };
                    230: 
                    231: /*
                    232:  * wchar => UTF7-IMAP
                    233:  */
                    234: int mbfl_filt_conv_wchar_utf7imap(int c, mbfl_convert_filter *filter)
                    235: {
                    236:        int n, s;
                    237: 
                    238:        n = 0;
                    239:        if (c == 0x26) {
                    240:                n = 1;
                    241:        } else if ((c >= 0x20 && c <= 0x7e) || c == 0) {
                    242:                n = 2;
                    243:        } else if (c >= 0 && c < MBFL_WCSPLANE_UCS2MAX) {
                    244:                ;
                    245:        } else if (c >= MBFL_WCSPLANE_SUPMIN && c < MBFL_WCSPLANE_SUPMAX) {
                    246:                s = ((c >> 10) - 0x40) | 0xd800;
                    247:                CK((*filter->filter_function)(s, filter));
                    248:                s = (c & 0x3ff) | 0xdc00;
                    249:                CK((*filter->filter_function)(s, filter));
                    250:                return c;
                    251:        } else {
                    252:                if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
                    253:                        CK(mbfl_filt_conv_illegal_output(c, filter));
                    254:                }
                    255:                return c;
                    256:        }
                    257: 
                    258:        switch (filter->status) {
                    259:        case 0:
                    260:                if (n != 0) {   /* directly encode characters */
                    261:                        CK((*filter->output_function)(c, filter->data));
                    262:                        if (n == 1) {
                    263:                                CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    264:                        }
                    265:                } else {        /* Modified Base64 */
                    266:                        CK((*filter->output_function)(0x26, filter->data));             /* '&' */
                    267:                        filter->status = 1;
                    268:                        filter->cache = c;
                    269:                }
                    270:                break;
                    271: 
                    272:        /* encode Modified Base64 */
                    273:        case 1:
                    274:                s = filter->cache;
                    275:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s >> 10) & 0x3f], filter->data));
                    276:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s >> 4) & 0x3f], filter->data));
                    277:                if (n != 0) {
                    278:                        CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s << 2) & 0x3c], filter->data));
                    279:                        CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    280:                        CK((*filter->output_function)(c, filter->data));
                    281:                        if (n == 1) {
                    282:                                CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    283:                        }
                    284:                        filter->status = 0;
                    285:                } else {
                    286:                        filter->status = 2;
                    287:                        filter->cache = ((s & 0xf) << 16) | c;
                    288:                }
                    289:                break;
                    290: 
                    291:        case 2:
                    292:                s = filter->cache;
                    293:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s >> 14) & 0x3f], filter->data));
                    294:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s >> 8) & 0x3f], filter->data));
                    295:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s >> 2) & 0x3f], filter->data));
                    296:                if (n != 0) {
                    297:                        CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s << 4) & 0x30], filter->data));
                    298:                        CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    299:                        CK((*filter->output_function)(c, filter->data));
                    300:                        if (n == 1) {
                    301:                                CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    302:                        }
                    303:                        filter->status = 0;
                    304:                } else {
                    305:                        filter->status = 3;
                    306:                        filter->cache = ((s & 0x3) << 16) | c;
                    307:                }
                    308:                break;
                    309: 
                    310:        case 3:
                    311:                s = filter->cache;
                    312:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s >> 12) & 0x3f], filter->data));
                    313:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(s >> 6) & 0x3f], filter->data));
                    314:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[s & 0x3f], filter->data));
                    315:                if (n != 0) {
                    316:                        CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    317:                        CK((*filter->output_function)(c, filter->data));
                    318:                        if (n == 1) {
                    319:                                CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    320:                        }
                    321:                        filter->status = 0;
                    322:                } else {
                    323:                        filter->status = 1;
                    324:                        filter->cache = c;
                    325:                }
                    326:                break;
                    327: 
                    328:        default:
                    329:                filter->status = 0;
                    330:                break;
                    331:        }
                    332: 
                    333:        return c;
                    334: 
                    335: }
                    336: 
                    337: int mbfl_filt_conv_wchar_utf7imap_flush(mbfl_convert_filter *filter)
                    338: {
                    339:        int status, cache;
                    340: 
                    341:        status = filter->status;
                    342:        cache = filter->cache;
                    343:        filter->status = 0;
                    344:        filter->cache = 0;
                    345:        /* flush fragments */
                    346:        switch (status) {
                    347:        case 1:
                    348:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache >> 10) & 0x3f], filter->data));
                    349:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache >> 4) & 0x3f], filter->data));
                    350:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache << 2) & 0x3c], filter->data));
                    351:                CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    352:                break;
                    353: 
                    354:        case 2:
                    355:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache >> 14) & 0x3f], filter->data));
                    356:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache >> 8) & 0x3f], filter->data));
                    357:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache >> 2) & 0x3f], filter->data));
                    358:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache << 4) & 0x30], filter->data));
                    359:                CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    360:                break;
                    361: 
                    362:        case 3:
                    363:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache >> 12) & 0x3f], filter->data));
                    364:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[(cache >> 6) & 0x3f], filter->data));
                    365:                CK((*filter->output_function)(mbfl_utf7imap_base64_table[cache & 0x3f], filter->data));
                    366:                CK((*filter->output_function)(0x2d, filter->data));             /* '-' */
                    367:                break;
                    368:        }
                    369:        return 0;
                    370: }
                    371: 
                    372: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>