Annotation of embedaddon/php/ext/pdo/pdo.c, revision 1.1
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: Wez Furlong <wez@php.net> |
! 16: | Marcus Boerger <helly@php.net> |
! 17: | Sterling Hughes <sterling@php.net> |
! 18: +----------------------------------------------------------------------+
! 19: */
! 20:
! 21: /* $Id: pdo.c 321634 2012-01-01 13:15:04Z felipe $ */
! 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: 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>