Annotation of embedaddon/php/ext/standard/quot_print.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:    | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Author: Kirill Maximov <kir@actimind.com>                            |
                     16:    +----------------------------------------------------------------------+
                     17:  */
                     18: 
1.1.1.2   misho      19: /* $Id$ */
1.1       misho      20: 
                     21: #include <stdlib.h>
                     22: 
                     23: #ifdef HAVE_UNISTD_H
                     24: #include <unistd.h>
                     25: #endif
                     26: #include <string.h>
                     27: #include <errno.h>
                     28: 
                     29: #include "php.h"
                     30: #include "quot_print.h"
                     31: 
                     32: #include <stdio.h>
                     33: 
                     34: /*
                     35: *  Converting HEX char to INT value
                     36: */
                     37: static char php_hex2int(int c) /* {{{ */
                     38: {
                     39:        if (isdigit(c)) {
                     40:                return c - '0';
                     41:        }
                     42:        else if (c >= 'A' && c <= 'F') {
                     43:                return c - 'A' + 10;
                     44:        }
                     45:        else if (c >= 'a' && c <= 'f') {
                     46:                return c - 'a' + 10;
                     47:        }
                     48:        else {
                     49:                return -1;
                     50:        }
                     51: }
                     52: /* }}} */
                     53: 
                     54: PHPAPI unsigned char *php_quot_print_decode(const unsigned char *str, size_t length, size_t *ret_length, int replace_us_by_ws) /* {{{ */
                     55: {
                     56:        register unsigned int i;
                     57:        register unsigned const char *p1;
                     58:        register unsigned char *p2;
                     59:        register unsigned int h_nbl, l_nbl;
                     60: 
                     61:        size_t decoded_len, buf_size;
                     62:        unsigned char *retval;
                     63: 
                     64:        static unsigned int hexval_tbl[256] = {
                     65:                64, 64, 64, 64, 64, 64, 64, 64, 64, 32, 16, 64, 64, 16, 64, 64,
                     66:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     67:                32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     68:                 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 64, 64, 64, 64, 64, 64,
                     69:                64, 10, 11, 12, 13, 14, 15, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     70:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     71:                64, 10, 11, 12, 13, 14, 15, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     72:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     73:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     74:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     75:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     76:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     77:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     78:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     79:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
                     80:                64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
                     81:        };
                     82: 
                     83:        if (replace_us_by_ws) {
                     84:                replace_us_by_ws = '_';
                     85:        }
                     86: 
                     87:        i = length, p1 = str; buf_size = length;
                     88: 
                     89:        while (i > 1 && *p1 != '\0') {
                     90:                if (*p1 == '=') {
                     91:                        buf_size -= 2;
                     92:                        p1++;
                     93:                        i--;
                     94:                }
                     95:                p1++;
                     96:                i--;
                     97:        }
                     98: 
                     99:        retval = emalloc(buf_size + 1);
                    100:        i = length; p1 = str; p2 = retval;
                    101:        decoded_len = 0;
                    102: 
                    103:        while (i > 0 && *p1 != '\0') {
                    104:                if (*p1 == '=') {
                    105:                        i--, p1++;
                    106:                        if (i == 0 || *p1 == '\0') {
                    107:                                break;
                    108:                        }
                    109:                        h_nbl = hexval_tbl[*p1];
                    110:                        if (h_nbl < 16) {
                    111:                                /* next char should be a hexadecimal digit */
                    112:                                if ((--i) == 0 || (l_nbl = hexval_tbl[*(++p1)]) >= 16) {
                    113:                                        efree(retval);
                    114:                                        return NULL;
                    115:                                }
                    116:                                *(p2++) = (h_nbl << 4) | l_nbl, decoded_len++;
                    117:                                i--, p1++;
                    118:                        } else if (h_nbl < 64) {
                    119:                                /* soft line break */
                    120:                                while (h_nbl == 32) {
                    121:                                        if (--i == 0 || (h_nbl = hexval_tbl[*(++p1)]) == 64) {
                    122:                                                efree(retval);
                    123:                                                return NULL;
                    124:                                        }
                    125:                                }
                    126:                                if (p1[0] == '\r' && i >= 2 && p1[1] == '\n') {
                    127:                                        i--, p1++;
                    128:                                }
                    129:                                i--, p1++;
                    130:                        } else {
                    131:                                efree(retval);
                    132:                                return NULL;
                    133:                        }
                    134:                } else {
                    135:                        *(p2++) = (replace_us_by_ws == *p1 ? '\x20': *p1);
                    136:                        i--, p1++, decoded_len++;
                    137:                }
                    138:        }
                    139: 
                    140:        *p2 = '\0';
                    141:        *ret_length = decoded_len;
                    142:        return retval;
                    143: }
                    144: /* }}} */
                    145: 
                    146: #define PHP_QPRINT_MAXL 75
                    147:  
                    148: PHPAPI unsigned char *php_quot_print_encode(const unsigned char *str, size_t length, size_t *ret_length) /* {{{ */
                    149: {
                    150:        unsigned long lp = 0;
                    151:        unsigned char c, *ret, *d;
                    152:        char *hex = "0123456789ABCDEF";
                    153: 
1.1.1.3 ! misho     154:        ret = safe_emalloc(3, length + (((3 * length)/(PHP_QPRINT_MAXL-9)) + 1), 1);
1.1       misho     155:        d = ret;
                    156: 
                    157:        while (length--) {
                    158:                if (((c = *str++) == '\015') && (*str == '\012') && length > 0) {
                    159:                        *d++ = '\015';
                    160:                        *d++ = *str++;
                    161:                        length--;
                    162:                        lp = 0;
                    163:                } else {
                    164:                        if (iscntrl (c) || (c == 0x7f) || (c & 0x80) || (c == '=') || ((c == ' ') && (*str == '\015'))) {
1.1.1.3 ! misho     165:                                if ((((lp+= 3) > PHP_QPRINT_MAXL) && (c <= 0x7f)) 
        !           166:             || ((c > 0x7f) && (c <= 0xdf) && ((lp + 3) > PHP_QPRINT_MAXL)) 
        !           167:             || ((c > 0xdf) && (c <= 0xef) && ((lp + 6) > PHP_QPRINT_MAXL)) 
        !           168:             || ((c > 0xef) && (c <= 0xf4) && ((lp + 9) > PHP_QPRINT_MAXL))) {
1.1       misho     169:                                        *d++ = '=';
                    170:                                        *d++ = '\015';
                    171:                                        *d++ = '\012';
                    172:                                        lp = 3;
                    173:                                }
                    174:                                *d++ = '=';
                    175:                                *d++ = hex[c >> 4];
                    176:                                *d++ = hex[c & 0xf];
                    177:                        } else {
                    178:                                if ((++lp) > PHP_QPRINT_MAXL) {
                    179:                                        *d++ = '=';
                    180:                                        *d++ = '\015';
                    181:                                        *d++ = '\012';
                    182:                                        lp = 1;
                    183:                                }
                    184:                                *d++ = c;
                    185:                        }
                    186:                }
                    187:        }
                    188:        *d = '\0';
                    189:        *ret_length = d - ret;
                    190: 
                    191:        ret = erealloc(ret, *ret_length + 1);
                    192:        return ret;
                    193: }
                    194: /* }}} */
                    195: 
                    196: /*
                    197: *
                    198: * Decoding  Quoted-printable string.
                    199: *
                    200: */
                    201: /* {{{ proto string quoted_printable_decode(string str)
                    202:    Convert a quoted-printable string to an 8 bit string */
                    203: PHP_FUNCTION(quoted_printable_decode)
                    204: {
                    205:        char *arg1, *str_in, *str_out;
                    206:        int arg1_len, i = 0, j = 0, k;
                    207: 
                    208:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg1, &arg1_len) == FAILURE) {
                    209:                return;
                    210:        }
                    211:     
                    212:        if (arg1_len == 0) {
                    213:                /* shortcut */
                    214:                RETURN_EMPTY_STRING();
                    215:        }
                    216: 
                    217:        str_in = arg1;
                    218:        str_out = emalloc(arg1_len + 1);
                    219:        while (str_in[i]) {
                    220:                switch (str_in[i]) {
                    221:                case '=':
                    222:                        if (str_in[i + 1] && str_in[i + 2] && 
                    223:                                isxdigit((int) str_in[i + 1]) && 
                    224:                                isxdigit((int) str_in[i + 2]))
                    225:                        {
                    226:                                str_out[j++] = (php_hex2int((int) str_in[i + 1]) << 4) 
                    227:                                                + php_hex2int((int) str_in[i + 2]);
                    228:                                i += 3;
                    229:                        } else  /* check for soft line break according to RFC 2045*/ {
                    230:                                k = 1;
                    231:                                while (str_in[i + k] && ((str_in[i + k] == 32) || (str_in[i + k] == 9))) {
                    232:                                        /* Possibly, skip spaces/tabs at the end of line */
                    233:                                        k++;
                    234:                                }
                    235:                                if (!str_in[i + k]) {
                    236:                                        /* End of line reached */
                    237:                                        i += k;
                    238:                                }
                    239:                                else if ((str_in[i + k] == 13) && (str_in[i + k + 1] == 10)) {
                    240:                                        /* CRLF */
                    241:                                        i += k + 2;
                    242:                                }
                    243:                                else if ((str_in[i + k] == 13) || (str_in[i + k] == 10)) {
                    244:                                        /* CR or LF */
                    245:                                        i += k + 1;
                    246:                                }
                    247:                                else {
                    248:                                        str_out[j++] = str_in[i++];
                    249:                                }
                    250:                        }
                    251:                        break;
                    252:                default:
                    253:                        str_out[j++] = str_in[i++];
                    254:                }
                    255:        }
                    256:        str_out[j] = '\0';
                    257:     
                    258:        RETVAL_STRINGL(str_out, j, 0);
                    259: }
                    260: /* }}} */
                    261: 
                    262: /* {{{ proto string quoted_printable_encode(string str) */
                    263: PHP_FUNCTION(quoted_printable_encode)
                    264: {
                    265:        char *str, *new_str;
                    266:        int str_len;
                    267:        size_t new_str_len;
                    268: 
                    269:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) != SUCCESS) {
                    270:                return;
                    271:        }
                    272: 
                    273:        if (!str_len) {
                    274:                RETURN_EMPTY_STRING();
                    275:        }
                    276: 
                    277:        new_str = (char *)php_quot_print_encode((unsigned char *)str, (size_t)str_len, &new_str_len);
                    278:        RETURN_STRINGL(new_str, new_str_len, 0);
                    279: }
                    280: /* }}} */
                    281: 
                    282: /*
                    283:  * Local variables:
                    284:  * tab-width: 4
                    285:  * c-basic-offset: 4
                    286:  * End:
                    287:  * vim600: sw=4 ts=4 fdm=marker
                    288:  * vim<600: sw=4 ts=4
                    289:  */

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