Return to quot_print.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard |
1.1 ! misho 1: /* ! 2: +----------------------------------------------------------------------+ ! 3: | PHP Version 5 | ! 4: +----------------------------------------------------------------------+ ! 5: | Copyright (c) 1997-2012 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: quot_print.c 321634 2012-01-01 13:15:04Z felipe $ */ ! 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(1, 3 * length + 3 * (((3 * length)/PHP_QPRINT_MAXL) + 1), 0); ! 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) { ! 166: *d++ = '='; ! 167: *d++ = '\015'; ! 168: *d++ = '\012'; ! 169: lp = 3; ! 170: } ! 171: *d++ = '='; ! 172: *d++ = hex[c >> 4]; ! 173: *d++ = hex[c & 0xf]; ! 174: } else { ! 175: if ((++lp) > PHP_QPRINT_MAXL) { ! 176: *d++ = '='; ! 177: *d++ = '\015'; ! 178: *d++ = '\012'; ! 179: lp = 1; ! 180: } ! 181: *d++ = c; ! 182: } ! 183: } ! 184: } ! 185: *d = '\0'; ! 186: *ret_length = d - ret; ! 187: ! 188: ret = erealloc(ret, *ret_length + 1); ! 189: return ret; ! 190: } ! 191: /* }}} */ ! 192: ! 193: /* ! 194: * ! 195: * Decoding Quoted-printable string. ! 196: * ! 197: */ ! 198: /* {{{ proto string quoted_printable_decode(string str) ! 199: Convert a quoted-printable string to an 8 bit string */ ! 200: PHP_FUNCTION(quoted_printable_decode) ! 201: { ! 202: char *arg1, *str_in, *str_out; ! 203: int arg1_len, i = 0, j = 0, k; ! 204: ! 205: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg1, &arg1_len) == FAILURE) { ! 206: return; ! 207: } ! 208: ! 209: if (arg1_len == 0) { ! 210: /* shortcut */ ! 211: RETURN_EMPTY_STRING(); ! 212: } ! 213: ! 214: str_in = arg1; ! 215: str_out = emalloc(arg1_len + 1); ! 216: while (str_in[i]) { ! 217: switch (str_in[i]) { ! 218: case '=': ! 219: if (str_in[i + 1] && str_in[i + 2] && ! 220: isxdigit((int) str_in[i + 1]) && ! 221: isxdigit((int) str_in[i + 2])) ! 222: { ! 223: str_out[j++] = (php_hex2int((int) str_in[i + 1]) << 4) ! 224: + php_hex2int((int) str_in[i + 2]); ! 225: i += 3; ! 226: } else /* check for soft line break according to RFC 2045*/ { ! 227: k = 1; ! 228: while (str_in[i + k] && ((str_in[i + k] == 32) || (str_in[i + k] == 9))) { ! 229: /* Possibly, skip spaces/tabs at the end of line */ ! 230: k++; ! 231: } ! 232: if (!str_in[i + k]) { ! 233: /* End of line reached */ ! 234: i += k; ! 235: } ! 236: else if ((str_in[i + k] == 13) && (str_in[i + k + 1] == 10)) { ! 237: /* CRLF */ ! 238: i += k + 2; ! 239: } ! 240: else if ((str_in[i + k] == 13) || (str_in[i + k] == 10)) { ! 241: /* CR or LF */ ! 242: i += k + 1; ! 243: } ! 244: else { ! 245: str_out[j++] = str_in[i++]; ! 246: } ! 247: } ! 248: break; ! 249: default: ! 250: str_out[j++] = str_in[i++]; ! 251: } ! 252: } ! 253: str_out[j] = '\0'; ! 254: ! 255: RETVAL_STRINGL(str_out, j, 0); ! 256: } ! 257: /* }}} */ ! 258: ! 259: /* {{{ proto string quoted_printable_encode(string str) */ ! 260: PHP_FUNCTION(quoted_printable_encode) ! 261: { ! 262: char *str, *new_str; ! 263: int str_len; ! 264: size_t new_str_len; ! 265: ! 266: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) != SUCCESS) { ! 267: return; ! 268: } ! 269: ! 270: if (!str_len) { ! 271: RETURN_EMPTY_STRING(); ! 272: } ! 273: ! 274: new_str = (char *)php_quot_print_encode((unsigned char *)str, (size_t)str_len, &new_str_len); ! 275: RETURN_STRINGL(new_str, new_str_len, 0); ! 276: } ! 277: /* }}} */ ! 278: ! 279: /* ! 280: * Local variables: ! 281: * tab-width: 4 ! 282: * c-basic-offset: 4 ! 283: * End: ! 284: * vim600: sw=4 ts=4 fdm=marker ! 285: * vim<600: sw=4 ts=4 ! 286: */