Back to index

php5  5.3.10
quot_print.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Kirill Maximov <kir@actimind.com>                            |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: quot_print.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include <stdlib.h>
00022 
00023 #ifdef HAVE_UNISTD_H
00024 #include <unistd.h>
00025 #endif
00026 #include <string.h>
00027 #include <errno.h>
00028 
00029 #include "php.h"
00030 #include "quot_print.h"
00031 
00032 #include <stdio.h>
00033 
00034 /*
00035 *  Converting HEX char to INT value
00036 */
00037 static char php_hex2int(int c) /* {{{ */
00038 {
00039        if (isdigit(c)) {
00040               return c - '0';
00041        }
00042        else if (c >= 'A' && c <= 'F') {
00043               return c - 'A' + 10;
00044        }
00045        else if (c >= 'a' && c <= 'f') {
00046               return c - 'a' + 10;
00047        }
00048        else {
00049               return -1;
00050        }
00051 }
00052 /* }}} */
00053 
00054 PHPAPI unsigned char *php_quot_print_decode(const unsigned char *str, size_t length, size_t *ret_length, int replace_us_by_ws) /* {{{ */
00055 {
00056        register unsigned int i;
00057        register unsigned const char *p1;
00058        register unsigned char *p2;
00059        register unsigned int h_nbl, l_nbl;
00060 
00061        size_t decoded_len, buf_size;
00062        unsigned char *retval;
00063 
00064        static unsigned int hexval_tbl[256] = {
00065               64, 64, 64, 64, 64, 64, 64, 64, 64, 32, 16, 64, 64, 16, 64, 64,
00066               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00067               32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00068                0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 64, 64, 64, 64, 64, 64,
00069               64, 10, 11, 12, 13, 14, 15, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00070               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00071               64, 10, 11, 12, 13, 14, 15, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00072               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00073               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00074               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00075               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00076               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00077               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00078               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00079               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00080               64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
00081        };
00082 
00083        if (replace_us_by_ws) {
00084               replace_us_by_ws = '_';
00085        }
00086 
00087        i = length, p1 = str; buf_size = length;
00088 
00089        while (i > 1 && *p1 != '\0') {
00090               if (*p1 == '=') {
00091                      buf_size -= 2;
00092                      p1++;
00093                      i--;
00094               }
00095               p1++;
00096               i--;
00097        }
00098 
00099        retval = emalloc(buf_size + 1);
00100        i = length; p1 = str; p2 = retval;
00101        decoded_len = 0;
00102 
00103        while (i > 0 && *p1 != '\0') {
00104               if (*p1 == '=') {
00105                      i--, p1++;
00106                      if (i == 0 || *p1 == '\0') {
00107                             break;
00108                      }
00109                      h_nbl = hexval_tbl[*p1];
00110                      if (h_nbl < 16) {
00111                             /* next char should be a hexadecimal digit */
00112                             if ((--i) == 0 || (l_nbl = hexval_tbl[*(++p1)]) >= 16) {
00113                                    efree(retval);
00114                                    return NULL;
00115                             }
00116                             *(p2++) = (h_nbl << 4) | l_nbl, decoded_len++;
00117                             i--, p1++;
00118                      } else if (h_nbl < 64) {
00119                             /* soft line break */
00120                             while (h_nbl == 32) {
00121                                    if (--i == 0 || (h_nbl = hexval_tbl[*(++p1)]) == 64) {
00122                                           efree(retval);
00123                                           return NULL;
00124                                    }
00125                             }
00126                             if (p1[0] == '\r' && i >= 2 && p1[1] == '\n') {
00127                                    i--, p1++;
00128                             }
00129                             i--, p1++;
00130                      } else {
00131                             efree(retval);
00132                             return NULL;
00133                      }
00134               } else {
00135                      *(p2++) = (replace_us_by_ws == *p1 ? '\x20': *p1);
00136                      i--, p1++, decoded_len++;
00137               }
00138        }
00139 
00140        *p2 = '\0';
00141        *ret_length = decoded_len;
00142        return retval;
00143 }
00144 /* }}} */
00145 
00146 #define PHP_QPRINT_MAXL 75
00147  
00148 PHPAPI unsigned char *php_quot_print_encode(const unsigned char *str, size_t length, size_t *ret_length) /* {{{ */
00149 {
00150        unsigned long lp = 0;
00151        unsigned char c, *ret, *d;
00152        char *hex = "0123456789ABCDEF";
00153 
00154        ret = safe_emalloc(1, 3 * length + 3 * (((3 * length)/PHP_QPRINT_MAXL) + 1), 0);
00155        d = ret;
00156 
00157        while (length--) {
00158               if (((c = *str++) == '\015') && (*str == '\012') && length > 0) {
00159                      *d++ = '\015';
00160                      *d++ = *str++;
00161                      length--;
00162                      lp = 0;
00163               } else {
00164                      if (iscntrl (c) || (c == 0x7f) || (c & 0x80) || (c == '=') || ((c == ' ') && (*str == '\015'))) {
00165                             if ((lp += 3) > PHP_QPRINT_MAXL) {
00166                                    *d++ = '=';
00167                                    *d++ = '\015';
00168                                    *d++ = '\012';
00169                                    lp = 3;
00170                             }
00171                             *d++ = '=';
00172                             *d++ = hex[c >> 4];
00173                             *d++ = hex[c & 0xf];
00174                      } else {
00175                             if ((++lp) > PHP_QPRINT_MAXL) {
00176                                    *d++ = '=';
00177                                    *d++ = '\015';
00178                                    *d++ = '\012';
00179                                    lp = 1;
00180                             }
00181                             *d++ = c;
00182                      }
00183               }
00184        }
00185        *d = '\0';
00186        *ret_length = d - ret;
00187 
00188        ret = erealloc(ret, *ret_length + 1);
00189        return ret;
00190 }
00191 /* }}} */
00192 
00193 /*
00194 *
00195 * Decoding  Quoted-printable string.
00196 *
00197 */
00198 /* {{{ proto string quoted_printable_decode(string str)
00199    Convert a quoted-printable string to an 8 bit string */
00200 PHP_FUNCTION(quoted_printable_decode)
00201 {
00202        char *arg1, *str_in, *str_out;
00203        int arg1_len, i = 0, j = 0, k;
00204 
00205        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg1, &arg1_len) == FAILURE) {
00206               return;
00207        }
00208     
00209        if (arg1_len == 0) {
00210               /* shortcut */
00211               RETURN_EMPTY_STRING();
00212        }
00213 
00214        str_in = arg1;
00215        str_out = emalloc(arg1_len + 1);
00216        while (str_in[i]) {
00217               switch (str_in[i]) {
00218               case '=':
00219                      if (str_in[i + 1] && str_in[i + 2] && 
00220                             isxdigit((int) str_in[i + 1]) && 
00221                             isxdigit((int) str_in[i + 2]))
00222                      {
00223                             str_out[j++] = (php_hex2int((int) str_in[i + 1]) << 4) 
00224                                           + php_hex2int((int) str_in[i + 2]);
00225                             i += 3;
00226                      } else  /* check for soft line break according to RFC 2045*/ {
00227                             k = 1;
00228                             while (str_in[i + k] && ((str_in[i + k] == 32) || (str_in[i + k] == 9))) {
00229                                    /* Possibly, skip spaces/tabs at the end of line */
00230                                    k++;
00231                             }
00232                             if (!str_in[i + k]) {
00233                                    /* End of line reached */
00234                                    i += k;
00235                             }
00236                             else if ((str_in[i + k] == 13) && (str_in[i + k + 1] == 10)) {
00237                                    /* CRLF */
00238                                    i += k + 2;
00239                             }
00240                             else if ((str_in[i + k] == 13) || (str_in[i + k] == 10)) {
00241                                    /* CR or LF */
00242                                    i += k + 1;
00243                             }
00244                             else {
00245                                    str_out[j++] = str_in[i++];
00246                             }
00247                      }
00248                      break;
00249               default:
00250                      str_out[j++] = str_in[i++];
00251               }
00252        }
00253        str_out[j] = '\0';
00254     
00255        RETVAL_STRINGL(str_out, j, 0);
00256 }
00257 /* }}} */
00258 
00259 /* {{{ proto string quoted_printable_encode(string str) */
00260 PHP_FUNCTION(quoted_printable_encode)
00261 {
00262        char *str, *new_str;
00263        int str_len;
00264        size_t new_str_len;
00265 
00266        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) != SUCCESS) {
00267               return;
00268        }
00269 
00270        if (!str_len) {
00271               RETURN_EMPTY_STRING();
00272        }
00273 
00274        new_str = (char *)php_quot_print_encode((unsigned char *)str, (size_t)str_len, &new_str_len);
00275        RETURN_STRINGL(new_str, new_str_len, 0);
00276 }
00277 /* }}} */
00278 
00279 /*
00280  * Local variables:
00281  * tab-width: 4
00282  * c-basic-offset: 4
00283  * End:
00284  * vim600: sw=4 ts=4 fdm=marker
00285  * vim<600: sw=4 ts=4
00286  */