File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard / base64.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:57 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 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: Jim Winstead <jimw@php.net>                                  |
   16:    +----------------------------------------------------------------------+
   17:  */
   18: /* $Id: base64.c,v 1.1.1.4 2014/06/15 20:03:57 misho Exp $ */
   19: 
   20: #include <string.h>
   21: 
   22: #include "php.h"
   23: #include "base64.h"
   24: 
   25: /* {{{ base64 tables */
   26: static const char base64_table[] = {
   27: 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
   28: 	'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
   29: 	'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
   30: 	'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
   31: 	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
   32: };
   33: 
   34: static const char base64_pad = '=';
   35: 
   36: static const short base64_reverse_table[256] = {
   37: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -2, -1, -2, -2,
   38: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
   39: 	-1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
   40: 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
   41: 	-2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
   42: 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2,
   43: 	-2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
   44: 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
   45: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
   46: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
   47: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
   48: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
   49: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
   50: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
   51: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
   52: 	-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
   53: };
   54: /* }}} */
   55: 
   56: PHPAPI unsigned char *php_base64_encode(const unsigned char *str, int length, int *ret_length) /* {{{ */
   57: {
   58: 	const unsigned char *current = str;
   59: 	unsigned char *p;
   60: 	unsigned char *result;
   61: 
   62: 	if (length < 0) {
   63: 		if (ret_length != NULL) {
   64: 			*ret_length = 0;
   65: 		}
   66: 		return NULL;
   67: 	}
   68: 
   69: 	result = (unsigned char *) safe_emalloc((length + 2) / 3, 4 * sizeof(char), 1);
   70: 	p = result;
   71: 
   72: 	while (length > 2) { /* keep going until we have less than 24 bits */
   73: 		*p++ = base64_table[current[0] >> 2];
   74: 		*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
   75: 		*p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
   76: 		*p++ = base64_table[current[2] & 0x3f];
   77: 
   78: 		current += 3;
   79: 		length -= 3; /* we just handle 3 octets of data */
   80: 	}
   81: 
   82: 	/* now deal with the tail end of things */
   83: 	if (length != 0) {
   84: 		*p++ = base64_table[current[0] >> 2];
   85: 		if (length > 1) {
   86: 			*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
   87: 			*p++ = base64_table[(current[1] & 0x0f) << 2];
   88: 			*p++ = base64_pad;
   89: 		} else {
   90: 			*p++ = base64_table[(current[0] & 0x03) << 4];
   91: 			*p++ = base64_pad;
   92: 			*p++ = base64_pad;
   93: 		}
   94: 	}
   95: 	if (ret_length != NULL) {
   96: 		*ret_length = (int)(p - result);
   97: 	}
   98: 	*p = '\0';
   99: 	return result;
  100: }
  101: /* }}} */
  102: 
  103: /* {{{ */
  104: /* generate reverse table (do not set index 0 to 64)
  105: static unsigned short base64_reverse_table[256];
  106: #define rt base64_reverse_table
  107: void php_base64_init(void)
  108: {
  109: 	char *s = emalloc(10240), *sp;
  110: 	char *chp;
  111: 	short idx;
  112: 
  113: 	for(ch = 0; ch < 256; ch++) {
  114: 		chp = strchr(base64_table, ch);
  115: 		if(ch && chp) {
  116: 			idx = chp - base64_table;
  117: 			if (idx >= 64) idx = -1;
  118: 			rt[ch] = idx;
  119: 		} else {
  120: 			rt[ch] = -1;
  121: 		}
  122: 	}
  123: 	sp = s;
  124: 	sprintf(sp, "static const short base64_reverse_table[256] = {\n");
  125: 	for(ch =0; ch < 256;) {
  126: 		sp = s+strlen(s);
  127: 		sprintf(sp, "\t% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,% 3d,\n", rt[ch+0], rt[ch+1], rt[ch+2], rt[ch+3], rt[ch+4], rt[ch+5], rt[ch+6], rt[ch+7], rt[ch+8], rt[ch+9], rt[ch+10], rt[ch+11], rt[ch+12], rt[ch+13], rt[ch+14], rt[ch+15]);
  128: 		ch += 16;
  129: 	}
  130: 	sprintf(sp, "};");
  131: 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Reverse_table:\n%s", s);
  132: 	efree(s);
  133: }
  134: */
  135: /* }}} */
  136: 
  137: PHPAPI unsigned char *php_base64_decode(const unsigned char *str, int length, int *ret_length) /* {{{ */
  138: {
  139: 	return php_base64_decode_ex(str, length, ret_length, 0);
  140: }
  141: /* }}} */
  142: 
  143: PHPAPI unsigned char *php_base64_decode_ex(const unsigned char *str, int length, int *ret_length, zend_bool strict) /* {{{ */
  144: {
  145: 	const unsigned char *current = str;
  146: 	int ch, i = 0, j = 0, k;
  147: 	/* this sucks for threaded environments */
  148: 	unsigned char *result;
  149: 
  150: 	result = (unsigned char *)safe_emalloc(length, 1, 1);
  151: 
  152: 	/* run through the whole string, converting as we go */
  153: 	while ((ch = *current++) != '\0' && length-- > 0) {
  154: 		if (ch == base64_pad) {
  155: 			if (*current != '=' && ((i % 4) == 1 || (strict && length > 0))) {
  156: 				if ((i % 4) != 1) {
  157: 					while (isspace(*(++current))) {
  158: 						continue;
  159: 					}
  160: 					if (*current == '\0') {
  161: 						continue;
  162: 					}
  163: 				}
  164: 				efree(result);
  165: 				return NULL;
  166: 			}
  167: 			continue;
  168: 		}
  169: 
  170: 		ch = base64_reverse_table[ch];
  171: 		if ((!strict && ch < 0) || ch == -1) { /* a space or some other separator character, we simply skip over */
  172: 			continue;
  173: 		} else if (ch == -2) {
  174: 			efree(result);
  175: 			return NULL;
  176: 		}
  177: 
  178: 		switch(i % 4) {
  179: 		case 0:
  180: 			result[j] = ch << 2;
  181: 			break;
  182: 		case 1:
  183: 			result[j++] |= ch >> 4;
  184: 			result[j] = (ch & 0x0f) << 4;
  185: 			break;
  186: 		case 2:
  187: 			result[j++] |= ch >>2;
  188: 			result[j] = (ch & 0x03) << 6;
  189: 			break;
  190: 		case 3:
  191: 			result[j++] |= ch;
  192: 			break;
  193: 		}
  194: 		i++;
  195: 	}
  196: 
  197: 	k = j;
  198: 	/* mop things up if we ended on a boundary */
  199: 	if (ch == base64_pad) {
  200: 		switch(i % 4) {
  201: 		case 1:
  202: 			efree(result);
  203: 			return NULL;
  204: 		case 2:
  205: 			k++;
  206: 		case 3:
  207: 			result[k] = 0;
  208: 		}
  209: 	}
  210: 	if(ret_length) {
  211: 		*ret_length = j;
  212: 	}
  213: 	result[j] = '\0';
  214: 	return result;
  215: }
  216: /* }}} */
  217: 
  218: /* {{{ proto string base64_encode(string str)
  219:    Encodes string using MIME base64 algorithm */
  220: PHP_FUNCTION(base64_encode)
  221: {
  222: 	char *str;
  223: 	unsigned char *result;
  224: 	int str_len, ret_length;
  225: 
  226: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
  227: 		return;
  228: 	}
  229: 	result = php_base64_encode((unsigned char*)str, str_len, &ret_length);
  230: 	if (result != NULL) {
  231: 		RETVAL_STRINGL((char*)result, ret_length, 0);
  232: 	} else {
  233: 		RETURN_FALSE;
  234: 	}
  235: }
  236: /* }}} */
  237: 
  238: /* {{{ proto string base64_decode(string str[, bool strict])
  239:    Decodes string using MIME base64 algorithm */
  240: PHP_FUNCTION(base64_decode)
  241: {
  242: 	char *str;
  243: 	unsigned char *result;
  244: 	zend_bool strict = 0;
  245: 	int str_len, ret_length;
  246: 
  247: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &str, &str_len, &strict) == FAILURE) {
  248: 		return;
  249: 	}
  250: 	result = php_base64_decode_ex((unsigned char*)str, str_len, &ret_length, strict);
  251: 	if (result != NULL) {
  252: 		RETVAL_STRINGL((char*)result, ret_length, 0);
  253: 	} else {
  254: 		RETURN_FALSE;
  255: 	}
  256: }
  257: /* }}} */
  258: 
  259: /*
  260:  * Local variables:
  261:  * tab-width: 4
  262:  * c-basic-offset: 4
  263:  * End:
  264:  * vim600: sw=4 ts=4 fdm=marker
  265:  * vim<600: sw=4 ts=4
  266:  */

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