Annotation of embedaddon/php/ext/pdo/pdo.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:   | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       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: 
1.1.1.2   misho      21: /* $Id$ */
1.1       misho      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;
1.1.1.2   misho     280:                                        const char *orig_val = data_source + valstart;
1.1       misho     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>