root/ext/standard/quot_print.c

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

DEFINITIONS

This source file includes following definitions.
  1. php_hex2int
  2. php_quot_print_decode
  3. php_quot_print_encode
  4. PHP_FUNCTION
  5. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   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 
  19 /* $Id$ */
  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 
 154         ret = safe_emalloc(3, length + (((3 * length)/(PHP_QPRINT_MAXL-9)) + 1), 1);
 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'))) {
 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))) {
 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  */

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