File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / pdo / pdo.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:51 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: Wez Furlong <wez@php.net>                                    |
   16:   |         Marcus Boerger <helly@php.net>                               |
   17:   |         Sterling Hughes <sterling@php.net>                           |
   18:   +----------------------------------------------------------------------+
   19: */
   20: 
   21: /* $Id: pdo.c,v 1.1.1.4 2014/06/15 20:03:51 misho Exp $ */
   22: 
   23: #ifdef HAVE_CONFIG_H
   24: #include "config.h"
   25: #endif
   26: 
   27: #include <ctype.h>
   28: #include "php.h"
   29: #include "php_ini.h"
   30: #include "ext/standard/info.h"
   31: #include "php_pdo.h"
   32: #include "php_pdo_driver.h"
   33: #include "php_pdo_int.h"
   34: #include "zend_exceptions.h"
   35: 
   36: static zend_class_entry *spl_ce_RuntimeException;
   37: 
   38: ZEND_DECLARE_MODULE_GLOBALS(pdo)
   39: static PHP_GINIT_FUNCTION(pdo);
   40: 
   41: /* True global resources - no need for thread safety here */
   42: 
   43: /* the registry of PDO drivers */
   44: HashTable pdo_driver_hash;
   45: 
   46: /* we use persistent resources for the driver connection stuff */
   47: static int le_ppdo;
   48: 
   49: int php_pdo_list_entry(void)
   50: {
   51: 	return le_ppdo;
   52: }
   53: 
   54: /* for exceptional circumstances */
   55: zend_class_entry *pdo_exception_ce;
   56: 
   57: PDO_API zend_class_entry *php_pdo_get_dbh_ce(void)
   58: {
   59: 	return pdo_dbh_ce;
   60: }
   61: 
   62: PDO_API zend_class_entry *php_pdo_get_exception(void)
   63: {
   64: 	return pdo_exception_ce;
   65: }
   66: 
   67: PDO_API char *php_pdo_str_tolower_dup(const char *src, int len)
   68: {
   69: 	char *dest = emalloc(len + 1);
   70: 	zend_str_tolower_copy(dest, src, len);
   71: 	return dest;
   72: }
   73: 
   74: PDO_API zend_class_entry *php_pdo_get_exception_base(int root TSRMLS_DC)
   75: {
   76: #if can_handle_soft_dependency_on_SPL && defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
   77: 	if (!root) {
   78: 		if (!spl_ce_RuntimeException) {
   79: 			zend_class_entry **pce;
   80: 
   81: 			if (zend_hash_find(CG(class_table), "runtimeexception", sizeof("RuntimeException"), (void **) &pce) == SUCCESS) {
   82: 				spl_ce_RuntimeException = *pce;
   83: 				return *pce;
   84: 			}
   85: 		} else {
   86: 			return spl_ce_RuntimeException;
   87: 		}
   88: 	}
   89: #endif
   90: #if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2)
   91: 	return zend_exception_get_default();
   92: #else
   93: 	return zend_exception_get_default(TSRMLS_C);
   94: #endif
   95: }
   96: 
   97: zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce;
   98: 
   99: /* {{{ proto array pdo_drivers()
  100:  Return array of available PDO drivers */
  101: PHP_FUNCTION(pdo_drivers)
  102: {
  103: 	HashPosition pos;
  104: 	pdo_driver_t **pdriver;
  105: 
  106: 	if (zend_parse_parameters_none() == FAILURE) {
  107: 		return;
  108: 	}
  109: 	
  110: 	array_init(return_value);
  111: 
  112: 	zend_hash_internal_pointer_reset_ex(&pdo_driver_hash, &pos);
  113: 	while (SUCCESS == zend_hash_get_current_data_ex(&pdo_driver_hash, (void**)&pdriver, &pos)) {
  114: 		add_next_index_stringl(return_value, (char*)(*pdriver)->driver_name, (*pdriver)->driver_name_len, 1);
  115: 		zend_hash_move_forward_ex(&pdo_driver_hash, &pos);
  116: 	}
  117: }
  118: /* }}} */
  119: 
  120: /* {{{ arginfo */
  121: ZEND_BEGIN_ARG_INFO(arginfo_pdo_drivers, 0)
  122: ZEND_END_ARG_INFO()
  123: /* }}} */
  124: 
  125: /* {{{ pdo_functions[] */
  126: const zend_function_entry pdo_functions[] = {
  127: 	PHP_FE(pdo_drivers,             arginfo_pdo_drivers)
  128: 	PHP_FE_END
  129: };
  130: /* }}} */
  131: 
  132: /* {{{ pdo_functions[] */
  133: #if ZEND_MODULE_API_NO >= 20050922
  134: static const zend_module_dep pdo_deps[] = {
  135: #ifdef HAVE_SPL
  136: 	ZEND_MOD_REQUIRED("spl")
  137: #endif
  138: 	ZEND_MOD_END
  139: };
  140: #endif
  141: /* }}} */
  142: 
  143: /* {{{ pdo_module_entry */
  144: zend_module_entry pdo_module_entry = {
  145: #if ZEND_MODULE_API_NO >= 20050922
  146: 	STANDARD_MODULE_HEADER_EX, NULL,
  147: 	pdo_deps,
  148: #else
  149: 	STANDARD_MODULE_HEADER,
  150: #endif
  151: 	"PDO",
  152: 	pdo_functions,
  153: 	PHP_MINIT(pdo),
  154: 	PHP_MSHUTDOWN(pdo),
  155: 	NULL,
  156: 	NULL,
  157: 	PHP_MINFO(pdo),
  158: 	"1.0.4dev",
  159: 	PHP_MODULE_GLOBALS(pdo),
  160: 	PHP_GINIT(pdo),
  161: 	NULL,
  162: 	NULL,
  163: 	STANDARD_MODULE_PROPERTIES_EX
  164: };
  165: /* }}} */
  166: 
  167: /* TODO: visit persistent handles: for each persistent statement handle,
  168:  * remove bound parameter associations */
  169: 
  170: #ifdef COMPILE_DL_PDO
  171: ZEND_GET_MODULE(pdo)
  172: #endif
  173: 
  174: /* {{{ PHP_GINIT_FUNCTION */
  175: static PHP_GINIT_FUNCTION(pdo)
  176: {
  177: 	pdo_globals->global_value = 0;
  178: }
  179: /* }}} */
  180: 
  181: PDO_API int php_pdo_register_driver(pdo_driver_t *driver)
  182: {
  183: 	if (driver->api_version != PDO_DRIVER_API) {
  184: 		zend_error(E_ERROR, "PDO: driver %s requires PDO API version %ld; this is PDO version %d",
  185: 			driver->driver_name, driver->api_version, PDO_DRIVER_API);
  186: 		return FAILURE;
  187: 	}
  188: 	if (!zend_hash_exists(&module_registry, "pdo", sizeof("pdo"))) {
  189: 		zend_error(E_ERROR, "You MUST load PDO before loading any PDO drivers");
  190: 		return FAILURE;	/* NOTREACHED */
  191: 	}
  192: 
  193: 	return zend_hash_add(&pdo_driver_hash, (char*)driver->driver_name, driver->driver_name_len,
  194: 			(void**)&driver, sizeof(pdo_driver_t *), NULL);
  195: }
  196: 
  197: PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver)
  198: {
  199: 	if (!zend_hash_exists(&module_registry, "pdo", sizeof("pdo"))) {
  200: 		return;
  201: 	}
  202: 
  203: 	zend_hash_del(&pdo_driver_hash, (char*)driver->driver_name, driver->driver_name_len);
  204: }
  205: 
  206: pdo_driver_t *pdo_find_driver(const char *name, int namelen)
  207: {
  208: 	pdo_driver_t **driver = NULL;
  209: 	
  210: 	zend_hash_find(&pdo_driver_hash, (char*)name, namelen, (void**)&driver);
  211: 
  212: 	return driver ? *driver : NULL;
  213: }
  214: 
  215: PDO_API int php_pdo_parse_data_source(const char *data_source,
  216: 		unsigned long data_source_len, struct pdo_data_src_parser *parsed,
  217: 		int nparams)
  218: {
  219: 	int i, j;
  220: 	int valstart = -1;
  221: 	int semi = -1;
  222: 	int optstart = 0;
  223: 	int nlen;
  224: 	int n_matches = 0;
  225: 	int n_semicolumns = 0;
  226: 
  227: 	i = 0;
  228: 	while (i < data_source_len) {
  229: 		/* looking for NAME= */
  230: 
  231: 		if (data_source[i] == '\0') {
  232: 			break;
  233: 		}
  234: 
  235: 		if (data_source[i] != '=') {
  236: 			++i;
  237: 			continue;
  238: 		}
  239: 
  240: 		valstart = ++i;
  241: 
  242: 		/* now we're looking for VALUE; or just VALUE<NUL> */
  243: 		semi = -1;
  244: 		n_semicolumns = 0;
  245: 		while (i < data_source_len) {
  246: 			if (data_source[i] == '\0') {
  247: 				semi = i++;
  248: 				break;
  249: 			}
  250: 			if (data_source[i] == ';') {
  251: 				if ((i + 1 >= data_source_len) || data_source[i+1] != ';') {
  252: 					semi = i++;
  253: 					break;
  254: 				} else {
  255: 					n_semicolumns++; 
  256: 					i += 2;
  257: 					continue;
  258: 				}
  259: 			}
  260: 			++i;
  261: 		}
  262: 
  263: 		if (semi == -1) {
  264: 			semi = i;
  265: 		}
  266: 
  267: 		/* find the entry in the array */
  268: 		nlen = valstart - optstart - 1;
  269: 		for (j = 0; j < nparams; j++) {
  270: 			if (0 == strncmp(data_source + optstart, parsed[j].optname, nlen) && parsed[j].optname[nlen] == '\0') {
  271: 				/* got a match */
  272: 				if (parsed[j].freeme) {
  273: 					efree(parsed[j].optval);
  274: 				}
  275: 
  276: 				if (n_semicolumns == 0) {
  277: 					parsed[j].optval = estrndup(data_source + valstart, semi - valstart - n_semicolumns);
  278: 				} else {
  279: 					int vlen = semi - valstart;
  280: 					const char *orig_val = data_source + valstart;
  281: 					char *new_val  = (char *) emalloc(vlen - n_semicolumns + 1);
  282: 				
  283: 					parsed[j].optval = new_val;
  284: 
  285: 					while (vlen && *orig_val) {
  286: 						*new_val = *orig_val;
  287: 						new_val++;
  288: 
  289: 						if (*orig_val == ';') {
  290: 							orig_val+=2; 
  291: 							vlen-=2;
  292: 						} else {
  293: 							orig_val++;
  294: 							vlen--;
  295: 						}
  296: 					}
  297: 					*new_val = '\0';
  298: 				}
  299: 
  300: 				parsed[j].freeme = 1;
  301: 				++n_matches;
  302: 				break;
  303: 			}
  304: 		}
  305: 
  306: 		while (i < data_source_len && isspace(data_source[i])) {
  307: 			i++;
  308: 		}
  309: 
  310: 		optstart = i;
  311: 	}
  312: 
  313: 	return n_matches;
  314: }
  315: 
  316: static const char digit_vec[] = "0123456789";
  317: PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC)
  318: {
  319: 	char buffer[65];
  320: 	char outbuf[65] = "";
  321: 	register char *p;
  322: 	long long_val;
  323: 	char *dst = outbuf;
  324: 
  325: 	if (i64 < 0) {
  326: 		i64 = -i64;
  327: 		*dst++ = '-';
  328: 	}
  329: 
  330: 	if (i64 == 0) {
  331: 		*dst++ = '0';
  332: 		*dst++ = '\0';
  333: 		return estrdup(outbuf);
  334: 	}
  335: 
  336: 	p = &buffer[sizeof(buffer)-1];
  337: 	*p = '\0';
  338: 
  339: 	while ((pdo_uint64_t)i64 > (pdo_uint64_t)LONG_MAX) {
  340: 		pdo_uint64_t quo = (pdo_uint64_t)i64 / (unsigned int)10;
  341: 		unsigned int rem = (unsigned int)(i64 - quo*10U);
  342: 		*--p = digit_vec[rem];
  343: 		i64 = (pdo_int64_t)quo;
  344: 	}
  345: 	long_val = (long)i64;
  346: 	while (long_val != 0) {
  347: 		long quo = long_val / 10;
  348: 		*--p = digit_vec[(unsigned int)(long_val - quo * 10)];
  349: 		long_val = quo;
  350: 	}
  351: 	while ((*dst++ = *p++) != 0)
  352: 		;
  353: 	*dst = '\0';
  354: 	return estrdup(outbuf);
  355: }
  356: 
  357: /* {{{ PHP_MINIT_FUNCTION */
  358: PHP_MINIT_FUNCTION(pdo)
  359: {
  360: 	zend_class_entry ce;
  361: 
  362: 	spl_ce_RuntimeException = NULL;
  363: 
  364: 	if (FAILURE == pdo_sqlstate_init_error_table()) {
  365: 		return FAILURE;
  366: 	}
  367: 
  368: 	zend_hash_init(&pdo_driver_hash, 0, NULL, NULL, 1);
  369: 
  370: 	le_ppdo = zend_register_list_destructors_ex(NULL, php_pdo_pdbh_dtor,
  371: 		"PDO persistent database", module_number);
  372: 
  373: 	INIT_CLASS_ENTRY(ce, "PDOException", NULL);
  374: 
  375:  	pdo_exception_ce = zend_register_internal_class_ex(&ce, php_pdo_get_exception_base(0 TSRMLS_CC), NULL TSRMLS_CC);
  376: 
  377: 	zend_declare_property_null(pdo_exception_ce, "errorInfo", sizeof("errorInfo")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
  378: 
  379: 	pdo_dbh_init(TSRMLS_C);
  380: 	pdo_stmt_init(TSRMLS_C);
  381: 
  382: 	return SUCCESS;
  383: }
  384: /* }}} */
  385: 
  386: /* {{{ PHP_MSHUTDOWN_FUNCTION */
  387: PHP_MSHUTDOWN_FUNCTION(pdo)
  388: {
  389: 	zend_hash_destroy(&pdo_driver_hash);
  390: 	pdo_sqlstate_fini_error_table();
  391: 	return SUCCESS;
  392: }
  393: /* }}} */
  394: 
  395: /* {{{ PHP_MINFO_FUNCTION */
  396: PHP_MINFO_FUNCTION(pdo)
  397: {
  398: 	HashPosition pos;
  399: 	char *drivers = NULL, *ldrivers = estrdup("");
  400: 	pdo_driver_t **pdriver;
  401: 	
  402: 	php_info_print_table_start();
  403: 	php_info_print_table_header(2, "PDO support", "enabled");
  404: 
  405: 	zend_hash_internal_pointer_reset_ex(&pdo_driver_hash, &pos);
  406: 	while (SUCCESS == zend_hash_get_current_data_ex(&pdo_driver_hash, (void**)&pdriver, &pos)) {
  407: 		spprintf(&drivers, 0, "%s, %s", ldrivers, (*pdriver)->driver_name);
  408: 		zend_hash_move_forward_ex(&pdo_driver_hash, &pos);
  409: 		efree(ldrivers);
  410: 		ldrivers = drivers;
  411: 	}
  412: 	
  413: 	php_info_print_table_row(2, "PDO drivers", drivers ? drivers+2 : "");
  414: 
  415: 	if (drivers) {
  416: 		efree(drivers);
  417: 	} else {
  418: 		efree(ldrivers);
  419: 	}
  420: 
  421: 	php_info_print_table_end();
  422: 
  423: }
  424: /* }}} */
  425: 
  426: /*
  427:  * Local variables:
  428:  * tab-width: 4
  429:  * c-basic-offset: 4
  430:  * End:
  431:  * vim600: noet sw=4 ts=4 fdm=marker
  432:  * vim<600: noet sw=4 ts=4
  433:  */

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