Annotation of embedaddon/php/ext/mysqli/mysqli.c, revision 1.1.1.2

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:   | Authors: Georg Richter <georg@php.net>                               |
                     16:   |          Andrey Hristov <andrey@php.net>                             |
                     17:   |          Ulf Wendel <uw@php.net>                                     |
                     18:   +----------------------------------------------------------------------+
                     19: 
1.1.1.2 ! misho      20:   $Id$
1.1       misho      21: */
                     22: 
                     23: #ifdef HAVE_CONFIG_H
                     24: #include "config.h"
                     25: #endif
                     26: 
                     27: #include <signal.h>
                     28: 
                     29: #include "php.h"
                     30: #include "php_ini.h"
                     31: #include "ext/standard/info.h"
                     32: #include "ext/standard/php_string.h"
1.1.1.2 ! misho      33: #include "php_mysqli.h"
1.1       misho      34: #include "php_mysqli_structs.h"
                     35: #include "mysqli_priv.h"
                     36: #include "zend_exceptions.h"
1.1.1.2 ! misho      37: #include "zend_interfaces.h"
1.1       misho      38: 
                     39: ZEND_DECLARE_MODULE_GLOBALS(mysqli)
                     40: static PHP_GINIT_FUNCTION(mysqli);
                     41: 
                     42: #define MYSQLI_ADD_PROPERTIES(a,b) \
                     43: { \
                     44:        int i = 0; \
                     45:        while (b[i].pname != NULL) { \
                     46:                mysqli_add_property((a), (b)[i].pname, (b)[i].pname_length, \
                     47:                                                        (mysqli_read_t)(b)[i].r_func, (mysqli_write_t)(b)[i].w_func TSRMLS_CC); \
                     48:                i++; \
                     49:        }\
                     50: }
                     51: 
                     52: #define MYSQLI_ADD_PROPERTIES_INFO(a,b) \
                     53: { \
                     54:        int i = 0; \
                     55:        while (b[i].name != NULL) { \
                     56:                zend_declare_property_null((a), (b)[i].name, (b)[i].name_length, ZEND_ACC_PUBLIC TSRMLS_CC); \
                     57:                i++; \
                     58:        }\
                     59: }
                     60: 
                     61: 
                     62: 
                     63: static zend_object_handlers mysqli_object_handlers;
                     64: static HashTable classes;
                     65: static HashTable mysqli_driver_properties;
                     66: static HashTable mysqli_link_properties;
                     67: static HashTable mysqli_result_properties;
                     68: static HashTable mysqli_stmt_properties;
                     69: static HashTable mysqli_warning_properties;
                     70: 
                     71: zend_class_entry *mysqli_link_class_entry;
                     72: zend_class_entry *mysqli_stmt_class_entry;
                     73: zend_class_entry *mysqli_result_class_entry;
                     74: zend_class_entry *mysqli_driver_class_entry;
                     75: zend_class_entry *mysqli_warning_class_entry;
                     76: zend_class_entry *mysqli_exception_class_entry;
                     77: 
                     78: 
                     79: typedef int (*mysqli_read_t)(mysqli_object *obj, zval **retval TSRMLS_DC);
                     80: typedef int (*mysqli_write_t)(mysqli_object *obj, zval *newval TSRMLS_DC);
                     81: 
                     82: typedef struct _mysqli_prop_handler {
                     83:        char *name;
                     84:        size_t name_len;
                     85:        mysqli_read_t read_func;
                     86:        mysqli_write_t write_func;
                     87: } mysqli_prop_handler;
                     88: 
                     89: static int le_pmysqli;
                     90: 
                     91: 
                     92: /* Destructor for mysqli entries in free_links/used_links */
                     93: void php_mysqli_dtor_p_elements(void *data)
                     94: {
                     95:        MYSQL *mysql = (MYSQL *) data;
                     96:        TSRMLS_FETCH();
                     97:        mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT);
                     98: }
                     99: 
                    100: 
                    101: ZEND_RSRC_DTOR_FUNC(php_mysqli_dtor)
                    102: {
                    103:        if (rsrc->ptr) {
                    104:                mysqli_plist_entry *plist = (mysqli_plist_entry *) rsrc->ptr;
                    105:                zend_ptr_stack_clean(&plist->free_links, php_mysqli_dtor_p_elements, 0);
                    106:                zend_ptr_stack_destroy(&plist->free_links);
                    107:                free(plist);
                    108:        }
                    109: }
                    110: 
                    111: 
                    112: int php_le_pmysqli(void)
                    113: {
                    114:        return le_pmysqli;
                    115: }
                    116: 
                    117: #ifndef MYSQLI_USE_MYSQLND
                    118: /* {{{ php_free_stmt_bind_buffer */
                    119: void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type)
                    120: {
                    121:        unsigned int i;
                    122: 
                    123:        if (!bbuf.var_cnt) {
                    124:                return;
                    125:        }
                    126: 
                    127:        for (i=0; i < bbuf.var_cnt; i++) {
                    128: 
                    129:                /* free temporary bind buffer */
                    130:                if (type == FETCH_RESULT && bbuf.buf[i].val) {
                    131:                        efree(bbuf.buf[i].val);
                    132:                }
                    133: 
                    134:                if (bbuf.vars[i]) {
                    135:                        zval_ptr_dtor(&bbuf.vars[i]);
                    136:                }
                    137:        }
                    138: 
                    139:        if (bbuf.vars) {
                    140:                efree(bbuf.vars);
                    141:        }
                    142: 
                    143:        /*
                    144:          Don't free bbuf.is_null for FETCH_RESULT since we have allocated
                    145:          is_null and buf in one block so we free only buf, which is the beginning
                    146:          of the block. When FETCH_SIMPLE then buf wasn't allocated together with
                    147:          buf and we have to free it.
                    148:        */
                    149:        if (type == FETCH_RESULT) {
                    150:                efree(bbuf.buf);
                    151:        } else if (type == FETCH_SIMPLE){
                    152:                efree(bbuf.is_null);
                    153:        }
                    154: 
                    155:        bbuf.var_cnt = 0;
                    156: }
                    157: /* }}} */
                    158: #endif
                    159: 
                    160: /* {{{ php_clear_stmt_bind */
                    161: void php_clear_stmt_bind(MY_STMT *stmt TSRMLS_DC)
                    162: {
                    163:        if (stmt->stmt) {
                    164:                if (mysqli_stmt_close(stmt->stmt, TRUE)) {
                    165:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error occured while closing statement");
                    166:                        return;
                    167:                }
                    168:        }
                    169: 
                    170:        /*
                    171:          mysqlnd keeps track of the binding and has freed its
                    172:          structures in stmt_close() above
                    173:        */
                    174: #ifndef MYSQLI_USE_MYSQLND
                    175:        /* Clean param bind */
                    176:        php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
                    177:        /* Clean output bind */
                    178:        php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
                    179: #endif
                    180: 
                    181:        if (stmt->query) {
                    182:                efree(stmt->query);
                    183:        }
                    184:        efree(stmt);
                    185: }
                    186: /* }}} */
                    187: 
                    188: /* {{{ php_clear_mysql */
                    189: void php_clear_mysql(MY_MYSQL *mysql) {
                    190:        if (mysql->hash_key) {
                    191:                efree(mysql->hash_key);
                    192:                mysql->hash_key = NULL;
                    193:        }
                    194:        if (mysql->li_read) {
                    195:                zval_ptr_dtor(&(mysql->li_read));
                    196:                mysql->li_read = NULL;
                    197:        }
                    198: }
                    199: /* }}} */
                    200: 
                    201: /* {{{ mysqli_objects_free_storage
                    202:  */
                    203: static void mysqli_objects_free_storage(void *object TSRMLS_DC)
                    204: {
                    205:        zend_object *zo = (zend_object *)object;
                    206:        mysqli_object   *intern = (mysqli_object *)zo;
                    207:        MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr;
                    208: 
                    209:        my_efree(my_res);
                    210:        zend_object_std_dtor(&intern->zo TSRMLS_CC);
                    211:        efree(intern);
                    212: }
                    213: /* }}} */
                    214: 
                    215: /* mysqli_link_free_storage partly doubles the work of PHP_FUNCTION(mysqli_close) */
                    216: 
                    217: /* {{{ mysqli_link_free_storage
                    218:  */
                    219: static void mysqli_link_free_storage(void *object TSRMLS_DC)
                    220: {
                    221:        zend_object *zo = (zend_object *)object;
                    222:        mysqli_object   *intern = (mysqli_object *)zo;
                    223:        MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr;
                    224: 
                    225:        if (my_res && my_res->ptr) {
                    226:                MY_MYSQL *mysql = (MY_MYSQL *)my_res->ptr;
                    227:                if (mysql->mysql) {
                    228:                        php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, my_res->status TSRMLS_CC);
                    229:                }
                    230:                php_clear_mysql(mysql);
                    231:                efree(mysql);
                    232:                my_res->status = MYSQLI_STATUS_UNKNOWN;
                    233:        }
                    234:        mysqli_objects_free_storage(object TSRMLS_CC);
                    235: }
                    236: /* }}} */
                    237: 
                    238: /* {{{ mysql_driver_free_storage */
                    239: static void mysqli_driver_free_storage(void *object TSRMLS_DC)
                    240: {
                    241:        mysqli_objects_free_storage(object TSRMLS_CC);
                    242: }
                    243: /* }}} */
                    244: 
                    245: /* {{{ mysqli_stmt_free_storage
                    246:  */
                    247: static void mysqli_stmt_free_storage(void *object TSRMLS_DC)
                    248: {
                    249:        zend_object *zo = (zend_object *)object;
                    250:        mysqli_object   *intern = (mysqli_object *)zo;
                    251:        MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr;
                    252: 
                    253:        if (my_res && my_res->ptr) {
                    254:                MY_STMT *stmt = (MY_STMT *)my_res->ptr;
                    255:                php_clear_stmt_bind(stmt TSRMLS_CC);
                    256:        }
                    257:        mysqli_objects_free_storage(object TSRMLS_CC);
                    258: }
                    259: /* }}} */
                    260: 
                    261: /* {{{ mysqli_result_free_storage
                    262:  */
                    263: static void mysqli_result_free_storage(void *object TSRMLS_DC)
                    264: {
                    265:        zend_object *zo = (zend_object *)object;
                    266:        mysqli_object   *intern = (mysqli_object *)zo;
                    267:        MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr;
                    268: 
                    269:        if (my_res && my_res->ptr) {
                    270:                mysql_free_result(my_res->ptr);
                    271:        }
                    272:        mysqli_objects_free_storage(object TSRMLS_CC);
                    273: }
                    274: /* }}} */
                    275: 
                    276: /* {{{ mysqli_warning_free_storage
                    277:  */
                    278: static void mysqli_warning_free_storage(void *object TSRMLS_DC)
                    279: {
                    280:        zend_object *zo = (zend_object *)object;
                    281:        mysqli_object   *intern = (mysqli_object *)zo;
                    282:        MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr;
                    283: 
                    284:        if (my_res && my_res->ptr) {
                    285:                php_clear_warnings((MYSQLI_WARNING *)my_res->info);
                    286:                my_res->ptr = NULL;
                    287:        }
                    288:        mysqli_objects_free_storage(object TSRMLS_CC);
                    289: }
                    290: /* }}} */
                    291: 
                    292: /* {{{ mysqli_read_na */
                    293: static int mysqli_read_na(mysqli_object *obj, zval **retval TSRMLS_DC)
                    294: {
                    295:        *retval = NULL;
                    296:        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot read property");
                    297:        return FAILURE;
                    298: }
                    299: /* }}} */
                    300: 
                    301: /* {{{ mysqli_write_na */
                    302: static int mysqli_write_na(mysqli_object *obj, zval *newval TSRMLS_DC)
                    303: {
                    304:        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot write property");
                    305:        return FAILURE;
                    306: }
                    307: /* }}} */
                    308: 
                    309: #ifndef Z_ADDREF_P
                    310: /* PHP 5.2, old GC */
                    311: #define Z_ADDREF_P(pz)                         (++(pz)->refcount)
                    312: #define Z_REFCOUNT_P(pz)                       ((pz)->refcount)
                    313: #define Z_SET_REFCOUNT_P(pz, rc)       ((pz)->refcount = rc)
                    314: #endif
                    315: 
                    316: 
                    317: /* {{{ mysqli_read_property */
1.1.1.2 ! misho     318: zval *mysqli_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
1.1       misho     319: {
                    320:        zval tmp_member;
                    321:        zval *retval;
                    322:        mysqli_object *obj;
                    323:        mysqli_prop_handler *hnd;
                    324:        int ret;
                    325: 
                    326:        ret = FAILURE;
                    327:        obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC);
                    328: 
                    329:        if (member->type != IS_STRING) {
                    330:                tmp_member = *member;
                    331:                zval_copy_ctor(&tmp_member);
                    332:                convert_to_string(&tmp_member);
                    333:                member = &tmp_member;
                    334:        }
                    335: 
                    336:        if (obj->prop_handler != NULL) {
                    337:                ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
                    338:        }
                    339: 
                    340:        if (ret == SUCCESS) {
                    341:                ret = hnd->read_func(obj, &retval TSRMLS_CC);
                    342:                if (ret == SUCCESS) {
                    343:                        /* ensure we're creating a temporary variable */
                    344:                        Z_SET_REFCOUNT_P(retval, 0);
                    345:                } else {
                    346:                        retval = EG(uninitialized_zval_ptr);
                    347:                }
                    348:        } else {
                    349:                zend_object_handlers * std_hnd = zend_get_std_object_handlers();
1.1.1.2 ! misho     350:                retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
1.1       misho     351:        }
                    352: 
                    353:        if (member == &tmp_member) {
                    354:                zval_dtor(member);
                    355:        }
                    356:        return(retval);
                    357: }
                    358: /* }}} */
                    359: 
                    360: /* {{{ mysqli_write_property */
1.1.1.2 ! misho     361: void mysqli_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
1.1       misho     362: {
                    363:        zval tmp_member;
                    364:        mysqli_object *obj;
                    365:        mysqli_prop_handler *hnd;
                    366:        int ret;
                    367: 
                    368:        if (member->type != IS_STRING) {
                    369:                tmp_member = *member;
                    370:                zval_copy_ctor(&tmp_member);
                    371:                convert_to_string(&tmp_member);
                    372:                member = &tmp_member;
                    373:        }
                    374: 
                    375:        ret = FAILURE;
                    376:        obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC);
                    377: 
                    378:        if (obj->prop_handler != NULL) {
                    379:                ret = zend_hash_find((HashTable *)obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
                    380:        }
                    381:        if (ret == SUCCESS) {
                    382:                hnd->write_func(obj, value TSRMLS_CC);
                    383:                if (! PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) == 0) {
                    384:                        Z_ADDREF_P(value);
                    385:                        zval_ptr_dtor(&value);
                    386:                }
                    387:        } else {
                    388:                zend_object_handlers * std_hnd = zend_get_std_object_handlers();
1.1.1.2 ! misho     389:                std_hnd->write_property(object, member, value, key TSRMLS_CC);
1.1       misho     390:        }
                    391: 
                    392:        if (member == &tmp_member) {
                    393:                zval_dtor(member);
                    394:        }
                    395: }
                    396: /* }}} */
                    397: 
                    398: /* {{{ void mysqli_add_property(HashTable *h, char *pname, mysqli_read_t r_func, mysqli_write_t w_func TSRMLS_DC) */
                    399: void mysqli_add_property(HashTable *h, const char *pname, size_t pname_len, mysqli_read_t r_func, mysqli_write_t w_func TSRMLS_DC) {
                    400:        mysqli_prop_handler             p;
                    401: 
                    402:        p.name = (char*) pname;
                    403:        p.name_len = pname_len;
                    404:        p.read_func = (r_func) ? r_func : mysqli_read_na;
                    405:        p.write_func = (w_func) ? w_func : mysqli_write_na;
                    406:        zend_hash_add(h, pname, pname_len + 1, &p, sizeof(mysqli_prop_handler), NULL);
                    407: }
                    408: /* }}} */
                    409: 
1.1.1.2 ! misho     410: static int mysqli_object_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */
1.1       misho     411: {
                    412:        mysqli_object *obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC);
                    413:        mysqli_prop_handler     p;
                    414:        int ret = 0;
                    415: 
                    416:        if (zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&p) == SUCCESS) {
                    417:                switch (has_set_exists) {
                    418:                        case 2:
                    419:                                ret = 1;
                    420:                                break;
                    421:                        case 1: {
1.1.1.2 ! misho     422:                                zval *value = mysqli_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
1.1       misho     423:                                if (value != EG(uninitialized_zval_ptr)) {
                    424:                                        convert_to_boolean(value);
                    425:                                        ret = Z_BVAL_P(value)? 1:0;
                    426:                                        /* refcount is 0 */
                    427:                                        Z_ADDREF_P(value);
                    428:                                        zval_ptr_dtor(&value);
                    429:                                }
                    430:                                break;
                    431:                        }
                    432:                        case 0:{
1.1.1.2 ! misho     433:                                zval *value = mysqli_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
1.1       misho     434:                                if (value != EG(uninitialized_zval_ptr)) {
                    435:                                        ret = Z_TYPE_P(value) != IS_NULL? 1:0;
                    436:                                        /* refcount is 0 */
                    437:                                        Z_ADDREF_P(value);
                    438:                                        zval_ptr_dtor(&value);
                    439:                                }
                    440:                                break;
                    441:                        }
                    442:                        default:
                    443:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for has_set_exists");
                    444:                }
                    445:        } else {
                    446:                zend_object_handlers * std_hnd = zend_get_std_object_handlers();
1.1.1.2 ! misho     447:                ret = std_hnd->has_property(object, member, has_set_exists, key TSRMLS_CC);
1.1       misho     448:        }
                    449:        return ret;
                    450: } /* }}} */
                    451: 
                    452: 
                    453: #if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
                    454: HashTable * mysqli_object_get_debug_info(zval *object, int *is_temp TSRMLS_DC)
                    455: {
                    456:        mysqli_object *obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC);
                    457:        HashTable *retval, *props = obj->prop_handler;
                    458:        HashPosition pos;
                    459:        mysqli_prop_handler *entry;
                    460: 
                    461:        ALLOC_HASHTABLE(retval);
                    462:        ZEND_INIT_SYMTABLE_EX(retval, zend_hash_num_elements(props) + 1, 0);
                    463: 
                    464:        zend_hash_internal_pointer_reset_ex(props, &pos);
                    465:        while (zend_hash_get_current_data_ex(props, (void **)&entry, &pos) == SUCCESS) {
                    466:                zval member;
                    467:                zval *value;
                    468:                INIT_ZVAL(member);
                    469:                ZVAL_STRINGL(&member, entry->name, entry->name_len, 0);
1.1.1.2 ! misho     470:                value = mysqli_read_property(object, &member, BP_VAR_IS, 0 TSRMLS_CC);
1.1       misho     471:                if (value != EG(uninitialized_zval_ptr)) {
                    472:                        Z_ADDREF_P(value);
                    473:                        zend_hash_add(retval, entry->name, entry->name_len + 1, &value, sizeof(zval *), NULL);
                    474:                }
                    475:                zend_hash_move_forward_ex(props, &pos);
                    476:        }
                    477: 
                    478:        *is_temp = 1;
                    479:        return retval;
                    480: }
                    481: #endif
                    482: 
                    483: /* {{{ mysqli_objects_new
                    484:  */
                    485: PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_type TSRMLS_DC)
                    486: {
                    487:        zend_object_value retval;
                    488:        mysqli_object *intern;
                    489:        zend_class_entry *mysqli_base_class;
                    490:        zend_objects_free_object_storage_t free_storage;
                    491: 
                    492:        intern = emalloc(sizeof(mysqli_object));
                    493:        memset(intern, 0, sizeof(mysqli_object));
                    494:        intern->ptr = NULL;
                    495:        intern->prop_handler = NULL;
                    496: 
                    497:        mysqli_base_class = class_type;
                    498:        while (mysqli_base_class->type != ZEND_INTERNAL_CLASS &&
                    499:                   mysqli_base_class->parent != NULL) {
                    500:                mysqli_base_class = mysqli_base_class->parent;
                    501:        }
                    502:        zend_hash_find(&classes, mysqli_base_class->name, mysqli_base_class->name_length + 1,
                    503:                                        (void **) &intern->prop_handler);
                    504: 
                    505:        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
1.1.1.2 ! misho     506:        object_properties_init(&intern->zo, class_type);
1.1       misho     507: 
                    508:        /* link object */
                    509:        if (instanceof_function(class_type, mysqli_link_class_entry TSRMLS_CC)) {
                    510:                free_storage = mysqli_link_free_storage;
                    511:        } else if (instanceof_function(class_type, mysqli_driver_class_entry TSRMLS_CC)) { /* driver object */
                    512:                free_storage = mysqli_driver_free_storage;
                    513:        } else if (instanceof_function(class_type, mysqli_stmt_class_entry TSRMLS_CC)) { /* stmt object */
                    514:                free_storage = mysqli_stmt_free_storage;
                    515:        } else if (instanceof_function(class_type, mysqli_result_class_entry TSRMLS_CC)) { /* result object */
                    516:                free_storage = mysqli_result_free_storage;
                    517:        } else if (instanceof_function(class_type, mysqli_warning_class_entry TSRMLS_CC)) { /* warning object */
                    518:                free_storage = mysqli_warning_free_storage;
                    519:        } else {
                    520:                free_storage = mysqli_objects_free_storage;
                    521:        }
                    522: 
                    523:        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, free_storage, NULL TSRMLS_CC);
                    524:        retval.handlers = &mysqli_object_handlers;
                    525: 
                    526:        return retval;
                    527: }
                    528: /* }}} */
                    529: 
1.1.1.2 ! misho     530: #ifdef MYSQLI_USE_MYSQLND
        !           531: #include "ext/mysqlnd/mysqlnd_reverse_api.h"
        !           532: static MYSQLND *mysqli_convert_zv_to_mysqlnd(zval * zv TSRMLS_DC)
        !           533: {
        !           534:        if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) == mysqli_link_class_entry) {
        !           535:                MY_MYSQL * mysql;
        !           536:                MYSQLI_RESOURCE  * my_res;
        !           537:                mysqli_object * intern = (mysqli_object *)zend_object_store_get_object(zv TSRMLS_CC);
        !           538:                if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
        !           539:                        /* We know that we have a mysqli object, so this failure should be emitted */
        !           540:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %s", intern->zo.ce->name);
        !           541:                        return NULL;
        !           542:                }
        !           543:                mysql = (MY_MYSQL *)(my_res->ptr);
        !           544:                return mysql ? mysql->mysql : NULL;
        !           545:        }
        !           546:        return NULL;
        !           547: }
        !           548: 
        !           549: static MYSQLND_REVERSE_API mysqli_reverse_api = {
        !           550:        &mysqli_module_entry,
        !           551:        mysqli_convert_zv_to_mysqlnd
        !           552: };
        !           553: #endif
1.1       misho     554: 
                    555: /* {{{ PHP_INI_BEGIN
                    556: */
                    557: PHP_INI_BEGIN()
                    558:        STD_PHP_INI_ENTRY_EX("mysqli.max_links",                        "-1",   PHP_INI_SYSTEM,         OnUpdateLong,           max_links,                      zend_mysqli_globals,            mysqli_globals, display_link_numbers)
                    559:        STD_PHP_INI_ENTRY_EX("mysqli.max_persistent",           "-1",   PHP_INI_SYSTEM,         OnUpdateLong,           max_persistent,         zend_mysqli_globals,            mysqli_globals, display_link_numbers)
                    560:        STD_PHP_INI_BOOLEAN("mysqli.allow_persistent",          "1",    PHP_INI_SYSTEM,         OnUpdateLong,           allow_persistent,       zend_mysqli_globals,            mysqli_globals)
                    561:        STD_PHP_INI_ENTRY("mysqli.default_host",                        NULL,   PHP_INI_ALL,            OnUpdateString,         default_host,           zend_mysqli_globals,            mysqli_globals)
                    562:        STD_PHP_INI_ENTRY("mysqli.default_user",                        NULL,   PHP_INI_ALL,            OnUpdateString,         default_user,           zend_mysqli_globals,            mysqli_globals)
                    563:        STD_PHP_INI_ENTRY("mysqli.default_pw",                          NULL,   PHP_INI_ALL,            OnUpdateString,         default_pw,                     zend_mysqli_globals,            mysqli_globals)
                    564:        STD_PHP_INI_ENTRY("mysqli.default_port",                        "3306", PHP_INI_ALL,            OnUpdateLong,           default_port,           zend_mysqli_globals,            mysqli_globals)
                    565: #ifdef PHP_MYSQL_UNIX_SOCK_ADDR
                    566:        STD_PHP_INI_ENTRY("mysqli.default_socket",                      MYSQL_UNIX_ADDR,PHP_INI_ALL,OnUpdateStringUnempty,      default_socket, zend_mysqli_globals,            mysqli_globals)
                    567: #else
                    568:        STD_PHP_INI_ENTRY("mysqli.default_socket",                      NULL,   PHP_INI_ALL,            OnUpdateStringUnempty,  default_socket, zend_mysqli_globals,            mysqli_globals)
                    569: #endif
                    570:        STD_PHP_INI_BOOLEAN("mysqli.reconnect",                         "0",    PHP_INI_SYSTEM,         OnUpdateLong,           reconnect,                      zend_mysqli_globals,            mysqli_globals)
                    571:        STD_PHP_INI_BOOLEAN("mysqli.allow_local_infile",        "1",    PHP_INI_SYSTEM,         OnUpdateLong,           allow_local_infile,     zend_mysqli_globals,            mysqli_globals)
                    572: PHP_INI_END()
                    573: /* }}} */
                    574: 
                    575: 
                    576: /* {{{ PHP_GINIT_FUNCTION
                    577:  */
                    578: static PHP_GINIT_FUNCTION(mysqli)
                    579: {
                    580:        mysqli_globals->num_links = 0;
                    581:        mysqli_globals->num_active_persistent = 0;
                    582:        mysqli_globals->num_inactive_persistent = 0;
                    583:        mysqli_globals->max_links = -1;
                    584:        mysqli_globals->max_persistent = -1;
                    585:        mysqli_globals->allow_persistent = 1;
                    586:        mysqli_globals->default_port = 0;
                    587:        mysqli_globals->default_host = NULL;
                    588:        mysqli_globals->default_user = NULL;
                    589:        mysqli_globals->default_pw = NULL;
                    590:        mysqli_globals->default_socket = NULL;
                    591:        mysqli_globals->reconnect = 0;
                    592:        mysqli_globals->report_mode = 0;
                    593:        mysqli_globals->report_ht = 0;
                    594:        mysqli_globals->allow_local_infile = 1;
                    595: #ifdef HAVE_EMBEDDED_MYSQLI
                    596:        mysqli_globals->embedded = 1;
                    597: #else
                    598:        mysqli_globals->embedded = 0;
                    599: #endif
                    600: }
                    601: /* }}} */
                    602: 
                    603: /* {{{ PHP_MINIT_FUNCTION
                    604:  */
                    605: PHP_MINIT_FUNCTION(mysqli)
                    606: {
                    607:        zend_class_entry *ce,cex;
                    608:        zend_object_handlers *std_hnd = zend_get_std_object_handlers();
                    609: 
                    610:        REGISTER_INI_ENTRIES();
                    611: #ifndef MYSQLI_USE_MYSQLND
                    612: #if MYSQL_VERSION_ID >= 40000
                    613:        if (mysql_server_init(0, NULL, NULL)) {
                    614:                return FAILURE;
                    615:        }
                    616: #endif
                    617: #endif
                    618: 
                    619:        memcpy(&mysqli_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
                    620:        mysqli_object_handlers.clone_obj = NULL;
                    621:        mysqli_object_handlers.read_property = mysqli_read_property;
                    622:        mysqli_object_handlers.write_property = mysqli_write_property;
                    623:        mysqli_object_handlers.get_property_ptr_ptr = std_hnd->get_property_ptr_ptr;
                    624:        mysqli_object_handlers.has_property = mysqli_object_has_property;
                    625: #if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
                    626:        mysqli_object_handlers.get_debug_info = mysqli_object_get_debug_info;
                    627: #endif
                    628: 
                    629:        zend_hash_init(&classes, 0, NULL, NULL, 1);
                    630: 
                    631:        /* persistent connections */
                    632:        le_pmysqli = zend_register_list_destructors_ex(NULL, php_mysqli_dtor,
                    633:                "MySqli persistent connection", module_number);
                    634: 
                    635:        INIT_CLASS_ENTRY(cex, "mysqli_sql_exception", mysqli_exception_methods);
                    636: #ifdef HAVE_SPL
                    637:        mysqli_exception_class_entry = zend_register_internal_class_ex(&cex, spl_ce_RuntimeException, NULL TSRMLS_CC);
                    638: #else
                    639:        mysqli_exception_class_entry = zend_register_internal_class_ex(&cex, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
                    640: #endif
                    641:        mysqli_exception_class_entry->ce_flags |= ZEND_ACC_FINAL;
                    642:        zend_declare_property_long(mysqli_exception_class_entry, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC);
                    643:        zend_declare_property_string(mysqli_exception_class_entry, "sqlstate", sizeof("sqlstate")-1, "00000", ZEND_ACC_PROTECTED TSRMLS_CC);
                    644: 
                    645:        REGISTER_MYSQLI_CLASS_ENTRY("mysqli_driver", mysqli_driver_class_entry, mysqli_driver_methods);
                    646:        ce = mysqli_driver_class_entry;
                    647:        zend_hash_init(&mysqli_driver_properties, 0, NULL, NULL, 1);
                    648:        MYSQLI_ADD_PROPERTIES(&mysqli_driver_properties, mysqli_driver_property_entries);
                    649:        MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_driver_property_info_entries);
                    650:        zend_hash_add(&classes, ce->name, ce->name_length+1, &mysqli_driver_properties, sizeof(mysqli_driver_properties), NULL);
                    651:        ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
                    652: 
                    653:        REGISTER_MYSQLI_CLASS_ENTRY("mysqli", mysqli_link_class_entry, mysqli_link_methods);
                    654:        ce = mysqli_link_class_entry;
                    655:        zend_hash_init(&mysqli_link_properties, 0, NULL, NULL, 1);
                    656:        MYSQLI_ADD_PROPERTIES(&mysqli_link_properties, mysqli_link_property_entries);
                    657:        MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_link_property_info_entries);
                    658:        zend_hash_add(&classes, ce->name, ce->name_length+1, &mysqli_link_properties, sizeof(mysqli_link_properties), NULL);
                    659: 
                    660:        REGISTER_MYSQLI_CLASS_ENTRY("mysqli_warning", mysqli_warning_class_entry, mysqli_warning_methods);
                    661:        ce = mysqli_warning_class_entry;
                    662:        ce->ce_flags |= ZEND_ACC_FINAL_CLASS | ZEND_ACC_PROTECTED;
                    663:        zend_hash_init(&mysqli_warning_properties, 0, NULL, NULL, 1);
                    664:        MYSQLI_ADD_PROPERTIES(&mysqli_warning_properties, mysqli_warning_property_entries);
                    665:        MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_warning_property_info_entries);
                    666:        zend_hash_add(&classes, ce->name, ce->name_length+1, &mysqli_warning_properties, sizeof(mysqli_warning_properties), NULL);
                    667: 
                    668:        REGISTER_MYSQLI_CLASS_ENTRY("mysqli_result", mysqli_result_class_entry, mysqli_result_methods);
                    669:        ce = mysqli_result_class_entry;
                    670:        zend_hash_init(&mysqli_result_properties, 0, NULL, NULL, 1);
                    671:        MYSQLI_ADD_PROPERTIES(&mysqli_result_properties, mysqli_result_property_entries);
                    672:        MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_result_property_info_entries);
1.1.1.2 ! misho     673:        mysqli_result_class_entry->get_iterator = php_mysqli_result_get_iterator;
        !           674:        mysqli_result_class_entry->iterator_funcs.funcs = &php_mysqli_result_iterator_funcs;
        !           675:        zend_class_implements(mysqli_result_class_entry TSRMLS_CC, 1, zend_ce_traversable);
1.1       misho     676:        zend_hash_add(&classes, ce->name, ce->name_length+1, &mysqli_result_properties, sizeof(mysqli_result_properties), NULL);
                    677: 
                    678:        REGISTER_MYSQLI_CLASS_ENTRY("mysqli_stmt", mysqli_stmt_class_entry, mysqli_stmt_methods);
                    679:        ce = mysqli_stmt_class_entry;
                    680:        zend_hash_init(&mysqli_stmt_properties, 0, NULL, NULL, 1);
                    681:        MYSQLI_ADD_PROPERTIES(&mysqli_stmt_properties, mysqli_stmt_property_entries);
                    682:        MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_stmt_property_info_entries);
                    683:        zend_hash_add(&classes, ce->name, ce->name_length+1, &mysqli_stmt_properties, sizeof(mysqli_stmt_properties), NULL);
                    684: 
                    685:        /* mysqli_options */
                    686:        REGISTER_LONG_CONSTANT("MYSQLI_READ_DEFAULT_GROUP", MYSQL_READ_DEFAULT_GROUP, CONST_CS | CONST_PERSISTENT);
                    687:        REGISTER_LONG_CONSTANT("MYSQLI_READ_DEFAULT_FILE", MYSQL_READ_DEFAULT_FILE, CONST_CS | CONST_PERSISTENT);
                    688:        REGISTER_LONG_CONSTANT("MYSQLI_OPT_CONNECT_TIMEOUT", MYSQL_OPT_CONNECT_TIMEOUT, CONST_CS | CONST_PERSISTENT);
                    689:        REGISTER_LONG_CONSTANT("MYSQLI_OPT_LOCAL_INFILE", MYSQL_OPT_LOCAL_INFILE, CONST_CS | CONST_PERSISTENT);
                    690:        REGISTER_LONG_CONSTANT("MYSQLI_INIT_COMMAND", MYSQL_INIT_COMMAND, CONST_CS | CONST_PERSISTENT);
                    691: #if defined(MYSQLI_USE_MYSQLND)
                    692:        REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_CMD_BUFFER_SIZE", MYSQLND_OPT_NET_CMD_BUFFER_SIZE, CONST_CS | CONST_PERSISTENT);
                    693:        REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_READ_BUFFER_SIZE", MYSQLND_OPT_NET_READ_BUFFER_SIZE, CONST_CS | CONST_PERSISTENT);
                    694: #endif
                    695: #ifdef MYSQLND_STRING_TO_INT_CONVERSION
                    696:        REGISTER_LONG_CONSTANT("MYSQLI_OPT_INT_AND_FLOAT_NATIVE", MYSQLND_OPT_INT_AND_FLOAT_NATIVE, CONST_CS | CONST_PERSISTENT);
                    697: #endif
                    698: #if MYSQL_VERSION_ID > 50110 || defined(MYSQLI_USE_MYSQLND)
                    699:        REGISTER_LONG_CONSTANT("MYSQLI_OPT_SSL_VERIFY_SERVER_CERT", MYSQL_OPT_SSL_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
                    700: #endif
                    701: 
                    702:        /* mysqli_real_connect flags */
                    703:        REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL", CLIENT_SSL, CONST_CS | CONST_PERSISTENT);
                    704:        REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_COMPRESS",CLIENT_COMPRESS, CONST_CS | CONST_PERSISTENT);
                    705:        REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_INTERACTIVE", CLIENT_INTERACTIVE, CONST_CS | CONST_PERSISTENT);
                    706:        REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_IGNORE_SPACE", CLIENT_IGNORE_SPACE, CONST_CS | CONST_PERSISTENT);
                    707:        REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_NO_SCHEMA", CLIENT_NO_SCHEMA, CONST_CS | CONST_PERSISTENT);
                    708:        REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_FOUND_ROWS", CLIENT_FOUND_ROWS, CONST_CS | CONST_PERSISTENT);
                    709: 
                    710:        /* for mysqli_query */
                    711:        REGISTER_LONG_CONSTANT("MYSQLI_STORE_RESULT", MYSQLI_STORE_RESULT, CONST_CS | CONST_PERSISTENT);
                    712:        REGISTER_LONG_CONSTANT("MYSQLI_USE_RESULT", MYSQLI_USE_RESULT, CONST_CS | CONST_PERSISTENT);
                    713: #if defined (MYSQLI_USE_MYSQLND)
                    714:        REGISTER_LONG_CONSTANT("MYSQLI_ASYNC", MYSQLI_ASYNC, CONST_CS | CONST_PERSISTENT);
                    715: #endif
                    716: 
                    717:        /* for mysqli_fetch_assoc */
                    718:        REGISTER_LONG_CONSTANT("MYSQLI_ASSOC", MYSQLI_ASSOC, CONST_CS | CONST_PERSISTENT);
                    719:        REGISTER_LONG_CONSTANT("MYSQLI_NUM", MYSQLI_NUM, CONST_CS | CONST_PERSISTENT);
                    720:        REGISTER_LONG_CONSTANT("MYSQLI_BOTH", MYSQLI_BOTH, CONST_CS | CONST_PERSISTENT);
                    721: 
                    722:        /* for mysqli_stmt_set_attr */
                    723:        REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH", STMT_ATTR_UPDATE_MAX_LENGTH, CONST_CS | CONST_PERSISTENT);
                    724: 
                    725: #if MYSQL_VERSION_ID > 50003 || defined(MYSQLI_USE_MYSQLND)
                    726:        REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_CURSOR_TYPE", STMT_ATTR_CURSOR_TYPE, CONST_CS | CONST_PERSISTENT);
                    727:        REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_NO_CURSOR", CURSOR_TYPE_NO_CURSOR, CONST_CS | CONST_PERSISTENT);
                    728:        REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_READ_ONLY", CURSOR_TYPE_READ_ONLY, CONST_CS | CONST_PERSISTENT);
                    729:        REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_FOR_UPDATE", CURSOR_TYPE_FOR_UPDATE, CONST_CS | CONST_PERSISTENT);
                    730:        REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_SCROLLABLE", CURSOR_TYPE_SCROLLABLE, CONST_CS | CONST_PERSISTENT);
                    731: #endif
                    732: 
                    733: #if MYSQL_VERSION_ID > 50007 || defined(MYSQLI_USE_MYSQLND)
                    734:        REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_PREFETCH_ROWS", STMT_ATTR_PREFETCH_ROWS, CONST_CS | CONST_PERSISTENT);
                    735: #endif
                    736: 
                    737:        /* column information */
                    738:        REGISTER_LONG_CONSTANT("MYSQLI_NOT_NULL_FLAG", NOT_NULL_FLAG, CONST_CS | CONST_PERSISTENT);
                    739:        REGISTER_LONG_CONSTANT("MYSQLI_PRI_KEY_FLAG", PRI_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
                    740:        REGISTER_LONG_CONSTANT("MYSQLI_UNIQUE_KEY_FLAG", UNIQUE_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
                    741:        REGISTER_LONG_CONSTANT("MYSQLI_MULTIPLE_KEY_FLAG", MULTIPLE_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
                    742:        REGISTER_LONG_CONSTANT("MYSQLI_BLOB_FLAG", BLOB_FLAG, CONST_CS | CONST_PERSISTENT);
                    743:        REGISTER_LONG_CONSTANT("MYSQLI_UNSIGNED_FLAG", UNSIGNED_FLAG, CONST_CS | CONST_PERSISTENT);
                    744:        REGISTER_LONG_CONSTANT("MYSQLI_ZEROFILL_FLAG", ZEROFILL_FLAG, CONST_CS | CONST_PERSISTENT);
                    745:        REGISTER_LONG_CONSTANT("MYSQLI_AUTO_INCREMENT_FLAG", AUTO_INCREMENT_FLAG, CONST_CS | CONST_PERSISTENT);
                    746:        REGISTER_LONG_CONSTANT("MYSQLI_TIMESTAMP_FLAG", TIMESTAMP_FLAG, CONST_CS | CONST_PERSISTENT);
                    747:        REGISTER_LONG_CONSTANT("MYSQLI_SET_FLAG", SET_FLAG, CONST_CS | CONST_PERSISTENT);
                    748:        REGISTER_LONG_CONSTANT("MYSQLI_NUM_FLAG", NUM_FLAG, CONST_CS | CONST_PERSISTENT);
                    749:        REGISTER_LONG_CONSTANT("MYSQLI_PART_KEY_FLAG", PART_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
                    750:        REGISTER_LONG_CONSTANT("MYSQLI_GROUP_FLAG", GROUP_FLAG, CONST_CS | CONST_PERSISTENT);
                    751:        REGISTER_LONG_CONSTANT("MYSQLI_ENUM_FLAG", ENUM_FLAG, CONST_CS | CONST_PERSISTENT);
                    752:        REGISTER_LONG_CONSTANT("MYSQLI_BINARY_FLAG", BINARY_FLAG, CONST_CS | CONST_PERSISTENT);
                    753: #if MYSQL_VERSION_ID > 50001 || defined(MYSQLI_USE_MYSQLND)
                    754:        REGISTER_LONG_CONSTANT("MYSQLI_NO_DEFAULT_VALUE_FLAG", NO_DEFAULT_VALUE_FLAG, CONST_CS | CONST_PERSISTENT);
                    755: #endif
                    756: 
                    757: #if (MYSQL_VERSION_ID > 51122 && MYSQL_VERSION_ID < 60000) || (MYSQL_VERSION_ID > 60003) || defined(MYSQLI_USE_MYSQLND)
                    758:        REGISTER_LONG_CONSTANT("MYSQLI_ON_UPDATE_NOW_FLAG", ON_UPDATE_NOW_FLAG, CONST_CS | CONST_PERSISTENT);
                    759: #endif
                    760: 
                    761:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DECIMAL", FIELD_TYPE_DECIMAL, CONST_CS | CONST_PERSISTENT);
                    762:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TINY", FIELD_TYPE_TINY, CONST_CS | CONST_PERSISTENT);
                    763:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_SHORT", FIELD_TYPE_SHORT, CONST_CS | CONST_PERSISTENT);
                    764:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONG", FIELD_TYPE_LONG, CONST_CS | CONST_PERSISTENT);
                    765:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_FLOAT", FIELD_TYPE_FLOAT, CONST_CS | CONST_PERSISTENT);
                    766:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DOUBLE", FIELD_TYPE_DOUBLE, CONST_CS | CONST_PERSISTENT);
                    767:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NULL", FIELD_TYPE_NULL, CONST_CS | CONST_PERSISTENT);
                    768:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TIMESTAMP", FIELD_TYPE_TIMESTAMP, CONST_CS | CONST_PERSISTENT);
                    769:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONGLONG", FIELD_TYPE_LONGLONG, CONST_CS | CONST_PERSISTENT);
                    770:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_INT24", FIELD_TYPE_INT24, CONST_CS | CONST_PERSISTENT);
                    771:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DATE", FIELD_TYPE_DATE, CONST_CS | CONST_PERSISTENT);
                    772:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TIME", FIELD_TYPE_TIME, CONST_CS | CONST_PERSISTENT);
                    773:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DATETIME", FIELD_TYPE_DATETIME      , CONST_CS | CONST_PERSISTENT);
                    774:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_YEAR", FIELD_TYPE_YEAR, CONST_CS | CONST_PERSISTENT);
                    775:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NEWDATE", FIELD_TYPE_NEWDATE, CONST_CS | CONST_PERSISTENT);
                    776:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_ENUM", FIELD_TYPE_ENUM, CONST_CS | CONST_PERSISTENT);
                    777:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_SET", FIELD_TYPE_SET, CONST_CS | CONST_PERSISTENT);
                    778:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TINY_BLOB", FIELD_TYPE_TINY_BLOB, CONST_CS | CONST_PERSISTENT);
                    779:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_MEDIUM_BLOB", FIELD_TYPE_MEDIUM_BLOB, CONST_CS | CONST_PERSISTENT);
                    780:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONG_BLOB", FIELD_TYPE_LONG_BLOB, CONST_CS | CONST_PERSISTENT);
                    781:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_BLOB", FIELD_TYPE_BLOB, CONST_CS | CONST_PERSISTENT);
                    782:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_VAR_STRING", FIELD_TYPE_VAR_STRING, CONST_CS | CONST_PERSISTENT);
                    783:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_STRING", FIELD_TYPE_STRING, CONST_CS | CONST_PERSISTENT);
                    784:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_CHAR", FIELD_TYPE_CHAR, CONST_CS | CONST_PERSISTENT);
                    785:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_INTERVAL", FIELD_TYPE_INTERVAL, CONST_CS | CONST_PERSISTENT);
                    786:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_GEOMETRY", FIELD_TYPE_GEOMETRY, CONST_CS | CONST_PERSISTENT);
                    787: 
                    788: #if MYSQL_VERSION_ID > 50002 || defined(MYSQLI_USE_MYSQLND)
                    789:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NEWDECIMAL", FIELD_TYPE_NEWDECIMAL, CONST_CS | CONST_PERSISTENT);
                    790:        REGISTER_LONG_CONSTANT("MYSQLI_TYPE_BIT", FIELD_TYPE_BIT, CONST_CS | CONST_PERSISTENT);
                    791: #endif
                    792: 
                    793:        REGISTER_LONG_CONSTANT("MYSQLI_SET_CHARSET_NAME", MYSQL_SET_CHARSET_NAME, CONST_CS | CONST_PERSISTENT);
                    794:        REGISTER_LONG_CONSTANT("MYSQLI_SET_CHARSET_DIR", MYSQL_SET_CHARSET_DIR, CONST_CS | CONST_PERSISTENT);
                    795: 
                    796:        /* bind support */
                    797:        REGISTER_LONG_CONSTANT("MYSQLI_NO_DATA", MYSQL_NO_DATA, CONST_CS | CONST_PERSISTENT);
                    798: #ifdef MYSQL_DATA_TRUNCATED
                    799:        REGISTER_LONG_CONSTANT("MYSQLI_DATA_TRUNCATED", MYSQL_DATA_TRUNCATED, CONST_CS | CONST_PERSISTENT);
                    800: #endif
                    801: 
                    802:        /* reporting */
                    803:        REGISTER_LONG_CONSTANT("MYSQLI_REPORT_INDEX", MYSQLI_REPORT_INDEX, CONST_CS | CONST_PERSISTENT);
                    804:        REGISTER_LONG_CONSTANT("MYSQLI_REPORT_ERROR", MYSQLI_REPORT_ERROR, CONST_CS | CONST_PERSISTENT);
                    805:        REGISTER_LONG_CONSTANT("MYSQLI_REPORT_STRICT", MYSQLI_REPORT_STRICT, CONST_CS | CONST_PERSISTENT);
                    806:        REGISTER_LONG_CONSTANT("MYSQLI_REPORT_ALL", MYSQLI_REPORT_ALL, CONST_CS | CONST_PERSISTENT);
                    807:        REGISTER_LONG_CONSTANT("MYSQLI_REPORT_OFF", 0, CONST_CS | CONST_PERSISTENT);
                    808: 
                    809:        /* We use non-nested macros with expansion, as VC has problems */
                    810: #ifdef MYSQLI_USE_MYSQLND
                    811:        REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", MYSQLND_DBG_ENABLED, CONST_CS | CONST_PERSISTENT);
                    812: #else
1.1.1.2 ! misho     813: #ifdef DBUG_ON
1.1       misho     814:        REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 1, CONST_CS | CONST_PERSISTENT);
1.1.1.2 ! misho     815: #else
        !           816:        REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 0, CONST_CS | CONST_PERSISTENT);
1.1       misho     817: #endif
                    818: #endif
                    819: 
                    820:        REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED", SERVER_QUERY_NO_GOOD_INDEX_USED, CONST_CS | CONST_PERSISTENT);
                    821:        REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_NO_INDEX_USED", SERVER_QUERY_NO_INDEX_USED, CONST_CS | CONST_PERSISTENT);
                    822: #ifdef SERVER_QUERY_WAS_SLOW
                    823:        REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_WAS_SLOW", SERVER_QUERY_WAS_SLOW, CONST_CS | CONST_PERSISTENT);
                    824: #endif
                    825: #ifdef SERVER_PS_OUT_PARAMS
                    826:        REGISTER_LONG_CONSTANT("MYSQLI_SERVER_PS_OUT_PARAMS", SERVER_PS_OUT_PARAMS, CONST_CS | CONST_PERSISTENT);
                    827: #endif
                    828: 
                    829:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_GRANT",      REFRESH_GRANT, CONST_CS | CONST_PERSISTENT);
                    830:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_LOG",        REFRESH_LOG, CONST_CS | CONST_PERSISTENT);
                    831:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_TABLES",     REFRESH_TABLES, CONST_CS | CONST_PERSISTENT);
                    832:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_HOSTS",      REFRESH_HOSTS, CONST_CS | CONST_PERSISTENT);
                    833:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_STATUS",     REFRESH_STATUS, CONST_CS | CONST_PERSISTENT);
                    834:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_THREADS",    REFRESH_THREADS, CONST_CS | CONST_PERSISTENT);
                    835:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_SLAVE",      REFRESH_SLAVE, CONST_CS | CONST_PERSISTENT);
                    836:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_MASTER",     REFRESH_MASTER, CONST_CS | CONST_PERSISTENT);
                    837: #ifdef REFRESH_BACKUP_LOG
                    838:        REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_BACKUP_LOG", REFRESH_BACKUP_LOG, CONST_CS | CONST_PERSISTENT);
                    839: #endif
                    840: 
1.1.1.2 ! misho     841: 
        !           842: #ifdef MYSQLI_USE_MYSQLND
        !           843:        mysqlnd_reverse_api_register_api(&mysqli_reverse_api TSRMLS_CC);
        !           844: #endif
        !           845: 
1.1       misho     846:        return SUCCESS;
                    847: }
                    848: /* }}} */
                    849: 
                    850: /* {{{ PHP_MSHUTDOWN_FUNCTION
                    851:  */
                    852: PHP_MSHUTDOWN_FUNCTION(mysqli)
                    853: {
                    854: #ifndef MYSQLI_USE_MYSQLND
                    855: #if MYSQL_VERSION_ID >= 40000
                    856: #ifdef PHP_WIN32
                    857:        unsigned long client_ver = mysql_get_client_version();
                    858:        /*
                    859:          Can't call mysql_server_end() multiple times prior to 5.0.46 on Windows.
                    860:          PHP bug#41350 MySQL bug#25621
                    861:        */
                    862:        if ((client_ver >= 50046 && client_ver < 50100) || client_ver > 50122) {
                    863:                mysql_server_end();
                    864:        }
                    865: #else
                    866:        mysql_server_end();
                    867: #endif
                    868: #endif
                    869: #endif
                    870: 
                    871:        zend_hash_destroy(&mysqli_driver_properties);
                    872:        zend_hash_destroy(&mysqli_result_properties);
                    873:        zend_hash_destroy(&mysqli_stmt_properties);
                    874:        zend_hash_destroy(&mysqli_warning_properties);
                    875:        zend_hash_destroy(&mysqli_link_properties);
                    876:        zend_hash_destroy(&classes);
                    877: 
                    878:        UNREGISTER_INI_ENTRIES();
                    879:        return SUCCESS;
                    880: }
                    881: /* }}} */
                    882: 
                    883: /* {{{ PHP_RINIT_FUNCTION
                    884:  */
                    885: PHP_RINIT_FUNCTION(mysqli)
                    886: {
                    887: #if !defined(MYSQLI_USE_MYSQLND) && defined(ZTS) && MYSQL_VERSION_ID >= 40000
                    888:        if (mysql_thread_init()) {
                    889:                return FAILURE;
                    890:        }
                    891: #endif
                    892:        MyG(error_msg) = NULL;
                    893:        MyG(error_no) = 0;
                    894:        MyG(report_mode) = 0;
                    895: 
                    896:        return SUCCESS;
                    897: }
                    898: /* }}} */
                    899: 
                    900: #if defined(A0) && defined(MYSQLI_USE_MYSQLND)
                    901: static void php_mysqli_persistent_helper_for_every(void *p)
                    902: {
                    903:        TSRMLS_FETCH();
                    904:        mysqlnd_end_psession((MYSQLND *) p);
                    905: } /* }}} */
                    906: 
                    907: 
                    908: static int php_mysqli_persistent_helper_once(zend_rsrc_list_entry *le TSRMLS_DC)
                    909: {
                    910:        if (le->type == php_le_pmysqli()) {
                    911:                mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
                    912:                zend_ptr_stack_apply(&plist->free_links, php_mysqli_persistent_helper_for_every);
                    913:        }
                    914:        return ZEND_HASH_APPLY_KEEP;
                    915: } /* }}} */
                    916: #endif
                    917: 
                    918: 
                    919: /* {{{ PHP_RSHUTDOWN_FUNCTION
                    920:  */
                    921: PHP_RSHUTDOWN_FUNCTION(mysqli)
                    922: {
                    923:        /* check persistent connections, move used to free */
                    924: 
                    925: #if !defined(MYSQLI_USE_MYSQLND) && defined(ZTS) && MYSQL_VERSION_ID >= 40000
                    926:        mysql_thread_end();
                    927: #endif
                    928:        if (MyG(error_msg)) {
                    929:                efree(MyG(error_msg));
                    930:        }
                    931: #if defined(A0) && defined(MYSQLI_USE_MYSQLND)
                    932:        /* psession is being called when the connection is freed - explicitly or implicitly */
                    933:        zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysqli_persistent_helper_once TSRMLS_CC);
                    934: #endif
                    935:        return SUCCESS;
                    936: }
                    937: /* }}} */
                    938: 
                    939: 
                    940: /* {{{ PHP_MINFO_FUNCTION
                    941:  */
                    942: PHP_MINFO_FUNCTION(mysqli)
                    943: {
                    944:        char buf[32];
                    945: 
                    946:        php_info_print_table_start();
                    947:        php_info_print_table_header(2, "MysqlI Support", "enabled");
                    948:        php_info_print_table_row(2, "Client API library version", mysql_get_client_info());
                    949:        snprintf(buf, sizeof(buf), "%ld", MyG(num_active_persistent));
                    950:        php_info_print_table_row(2, "Active Persistent Links", buf);
                    951:        snprintf(buf, sizeof(buf), "%ld", MyG(num_inactive_persistent));
                    952:        php_info_print_table_row(2, "Inactive Persistent Links", buf);
                    953:        snprintf(buf, sizeof(buf), "%ld", MyG(num_links));
                    954:        php_info_print_table_row(2, "Active Links", buf);
                    955: #if !defined(MYSQLI_USE_MYSQLND)
                    956:        php_info_print_table_row(2, "Client API header version", MYSQL_SERVER_VERSION);
                    957:        php_info_print_table_row(2, "MYSQLI_SOCKET", MYSQL_UNIX_ADDR);
                    958: #endif
                    959:        php_info_print_table_end();
                    960: 
                    961:        DISPLAY_INI_ENTRIES();
                    962: }
                    963: /* }}} */
                    964: 
                    965: 
                    966: /* Dependancies */
                    967: static const  zend_module_dep mysqli_deps[] = {
                    968: #if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
                    969:        ZEND_MOD_REQUIRED("spl")
                    970: #endif
                    971: #if defined(MYSQLI_USE_MYSQLND)
                    972:        ZEND_MOD_REQUIRED("mysqlnd")
                    973: #endif
                    974:        ZEND_MOD_END
                    975: };
                    976: 
                    977: /* {{{ mysqli_module_entry
                    978:  */
                    979: zend_module_entry mysqli_module_entry = {
                    980: #if ZEND_MODULE_API_NO >= 20050922
                    981:        STANDARD_MODULE_HEADER_EX, NULL,
                    982:        mysqli_deps,
                    983: #elif ZEND_MODULE_API_NO >= 20010901
                    984:        STANDARD_MODULE_HEADER,
                    985: #endif
                    986:        "mysqli",
                    987:        mysqli_functions,
                    988:        PHP_MINIT(mysqli),
                    989:        PHP_MSHUTDOWN(mysqli),
                    990:        PHP_RINIT(mysqli),
                    991:        PHP_RSHUTDOWN(mysqli),
                    992:        PHP_MINFO(mysqli),
                    993:        "0.1", /* Replace with version number for your extension */
                    994:        PHP_MODULE_GLOBALS(mysqli),
                    995:        PHP_GINIT(mysqli),
                    996:        NULL,
                    997:        NULL,
                    998:        STANDARD_MODULE_PROPERTIES_EX
                    999: };
                   1000: /* }}} */
                   1001: 
                   1002: #ifdef COMPILE_DL_MYSQLI
                   1003: ZEND_GET_MODULE(mysqli)
                   1004: #endif
                   1005: 
                   1006: 
                   1007: /* {{{ mixed mysqli_stmt_construct()
                   1008: constructor for statement object.
                   1009: Parameters:
                   1010:   object -> mysqli_stmt_init
                   1011:   object, query -> mysqli_prepare
                   1012: */
                   1013: PHP_FUNCTION(mysqli_stmt_construct)
                   1014: {
                   1015:        MY_MYSQL                        *mysql;
                   1016:        zval                            *mysql_link;
                   1017:        MY_STMT                         *stmt;
                   1018:        MYSQLI_RESOURCE         *mysqli_resource;
                   1019:        char                            *statement;
                   1020:        int                                     statement_len;
                   1021: 
                   1022:        switch (ZEND_NUM_ARGS())
                   1023:        {
                   1024:                case 1:  /* mysql_stmt_init */
                   1025:                        if (zend_parse_parameters(1 TSRMLS_CC, "O", &mysql_link, mysqli_link_class_entry)==FAILURE) {
                   1026:                                return;
                   1027:                        }
                   1028:                        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                   1029: 
                   1030:                        stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
                   1031: 
                   1032:                        stmt->stmt = mysql_stmt_init(mysql->mysql);
                   1033:                break;
                   1034:                case 2:
                   1035:                        if (zend_parse_parameters(2 TSRMLS_CC, "Os", &mysql_link, mysqli_link_class_entry, &statement, &statement_len)==FAILURE) {
                   1036:                                return;
                   1037:                        }
                   1038:                        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                   1039: 
                   1040:                        stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
                   1041: 
                   1042:                        if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
                   1043:                                mysql_stmt_prepare(stmt->stmt, (char *)statement, statement_len);
                   1044:                        }
                   1045:                break;
                   1046:                default:
                   1047:                        WRONG_PARAM_COUNT;
                   1048:                break;
                   1049:        }
                   1050: 
                   1051:        if (!stmt->stmt) {
                   1052:                efree(stmt);
                   1053:                RETURN_FALSE;
                   1054:        }
                   1055: 
                   1056:        mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
                   1057:        mysqli_resource->ptr = (void *)stmt;
                   1058:        mysqli_resource->status = (ZEND_NUM_ARGS() == 1) ? MYSQLI_STATUS_INITIALIZED : MYSQLI_STATUS_VALID;
                   1059: 
                   1060:        ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
                   1061: }
                   1062: /* }}} */
                   1063: 
                   1064: /* {{{ mixed mysqli_result_construct()
                   1065: constructor for result object.
                   1066: Parameters:
                   1067:   object [, mode] -> mysqli_store/use_result
                   1068: */
                   1069: PHP_FUNCTION(mysqli_result_construct)
                   1070: {
                   1071:        MY_MYSQL                        *mysql;
                   1072:        MYSQL_RES                       *result = NULL;
                   1073:        zval                            *mysql_link;
                   1074:        MYSQLI_RESOURCE         *mysqli_resource;
                   1075:        long                            resmode = MYSQLI_STORE_RESULT;
                   1076: 
                   1077:        switch (ZEND_NUM_ARGS()) {
                   1078:                case 1:
                   1079:                        if (zend_parse_parameters(1 TSRMLS_CC, "O", &mysql_link, mysqli_link_class_entry)==FAILURE) {
                   1080:                                return;
                   1081:                        }
                   1082:                        break;
                   1083:                case 2:
                   1084:                        if (zend_parse_parameters(2 TSRMLS_CC, "Ol", &mysql_link, mysqli_link_class_entry, &resmode)==FAILURE) {
                   1085:                                return;
                   1086:                        }
                   1087:                        break;
                   1088:                default:
                   1089:                        WRONG_PARAM_COUNT;
                   1090:        }
                   1091: 
                   1092:        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                   1093: 
                   1094:        switch (resmode) {
                   1095:                case MYSQLI_STORE_RESULT:
                   1096:                        result = mysql_store_result(mysql->mysql);
                   1097:                        break;
                   1098:                case MYSQLI_USE_RESULT:
                   1099:                        result = mysql_use_result(mysql->mysql);
                   1100:                        break;
                   1101:                default:
                   1102:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
                   1103:        }
                   1104: 
                   1105:        if (!result) {
                   1106:                RETURN_FALSE;
                   1107:        }
                   1108: 
                   1109:        mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
                   1110:        mysqli_resource->ptr = (void *)result;
                   1111:        mysqli_resource->status = MYSQLI_STATUS_VALID;
                   1112: 
                   1113:        ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
                   1114: 
                   1115: }
                   1116: /* }}} */
                   1117: 
1.1.1.2 ! misho    1118: 
        !          1119: /* {{{ php_mysqli_fetch_into_hash_aux
1.1       misho    1120:  */
1.1.1.2 ! misho    1121: void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, long fetchtype TSRMLS_DC)
1.1       misho    1122: {
                   1123: #if !defined(MYSQLI_USE_MYSQLND)
1.1.1.2 ! misho    1124:        MYSQL_ROW row;
1.1       misho    1125:        unsigned int    i;
                   1126:        MYSQL_FIELD             *fields;
                   1127:        unsigned long   *field_len;
1.1.1.2 ! misho    1128:        
1.1       misho    1129:        if (!(row = mysql_fetch_row(result))) {
                   1130:                RETURN_NULL();
                   1131:        }
                   1132: 
                   1133:        if (fetchtype & MYSQLI_ASSOC) {
                   1134:                fields = mysql_fetch_fields(result);
                   1135:        }
                   1136: 
                   1137:        array_init(return_value);
                   1138:        field_len = mysql_fetch_lengths(result);
                   1139: 
                   1140:        for (i = 0; i < mysql_num_fields(result); i++) {
                   1141:                if (row[i]) {
                   1142:                        zval *res;
                   1143: 
                   1144:                        MAKE_STD_ZVAL(res);
                   1145: 
                   1146: #if MYSQL_VERSION_ID > 50002
                   1147:                        if (mysql_fetch_field_direct(result, i)->type == MYSQL_TYPE_BIT) {
                   1148:                                my_ulonglong llval;
                   1149:                                char tmp[22];
                   1150:                                switch (field_len[i]) {
                   1151:                                        case 8:llval = (my_ulonglong)  bit_uint8korr(row[i]);break;
                   1152:                                        case 7:llval = (my_ulonglong)  bit_uint7korr(row[i]);break;
                   1153:                                        case 6:llval = (my_ulonglong)  bit_uint6korr(row[i]);break;
                   1154:                                        case 5:llval = (my_ulonglong)  bit_uint5korr(row[i]);break;
                   1155:                                        case 4:llval = (my_ulonglong)  bit_uint4korr(row[i]);break;
                   1156:                                        case 3:llval = (my_ulonglong)  bit_uint3korr(row[i]);break;
                   1157:                                        case 2:llval = (my_ulonglong)  bit_uint2korr(row[i]);break;
                   1158:                                        case 1:llval = (my_ulonglong)  uint1korr(row[i]);break;
                   1159:                                }
                   1160:                                /* even though lval is declared as unsigned, the value
                   1161:                                 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
                   1162:                                 * use MYSQLI_LL_SPEC.
                   1163:                                 */
                   1164:                                snprintf(tmp, sizeof(tmp), (mysql_fetch_field_direct(result, i)->flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
                   1165:                                ZVAL_STRING(res, tmp, 1);
                   1166:                        } else
                   1167: #endif
                   1168:                        {
                   1169: 
1.1.1.2 ! misho    1170: #if PHP_API_VERSION < 20100412
1.1       misho    1171:                                /* check if we need magic quotes */
                   1172:                                if (PG(magic_quotes_runtime)) {
                   1173:                                        Z_TYPE_P(res) = IS_STRING;
                   1174:                                        Z_STRVAL_P(res) = php_addslashes(row[i], field_len[i], &Z_STRLEN_P(res), 0 TSRMLS_CC);
                   1175:                                } else {
1.1.1.2 ! misho    1176: #endif
1.1       misho    1177:                                        ZVAL_STRINGL(res, row[i], field_len[i], 1);
1.1.1.2 ! misho    1178: #if PHP_API_VERSION < 20100412
1.1       misho    1179:                                }
1.1.1.2 ! misho    1180: #endif
1.1       misho    1181:                        }
                   1182: 
                   1183:                        if (fetchtype & MYSQLI_NUM) {
                   1184:                                add_index_zval(return_value, i, res);
                   1185:                        }
                   1186:                        if (fetchtype & MYSQLI_ASSOC) {
                   1187:                                if (fetchtype & MYSQLI_NUM) {
                   1188:                                        Z_ADDREF_P(res);
                   1189:                                }
                   1190:                                add_assoc_zval(return_value, fields[i].name, res);
                   1191:                        }
                   1192:                } else {
                   1193:                        if (fetchtype & MYSQLI_NUM) {
                   1194:                                add_index_null(return_value, i);
                   1195:                        }
                   1196:                        if (fetchtype & MYSQLI_ASSOC) {
                   1197:                                add_assoc_null(return_value, fields[i].name);
                   1198:                        }
                   1199:                }
                   1200:        }
                   1201: #else
1.1.1.2 ! misho    1202:        mysqlnd_fetch_into(result, ((fetchtype & MYSQLI_NUM)? MYSQLND_FETCH_NUM:0) | ((fetchtype & MYSQLI_ASSOC)? MYSQLND_FETCH_ASSOC:0), return_value, MYSQLND_MYSQLI);
        !          1203: #endif
        !          1204: }
        !          1205: /* }}} */
        !          1206: 
        !          1207: 
        !          1208: /* {{{ php_mysqli_fetch_into_hash
        !          1209:  */
        !          1210: void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object)
        !          1211: {
        !          1212:        MYSQL_RES               *result;
        !          1213:        zval                    *mysql_result;
        !          1214:        long                    fetchtype;
        !          1215:        zval                    *ctor_params = NULL;
        !          1216:        zend_class_entry *ce = NULL;
        !          1217: 
        !          1218:        if (into_object) {
        !          1219:                char *class_name;
        !          1220:                int class_name_len;
        !          1221: 
        !          1222:                if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|sz", &mysql_result, mysqli_result_class_entry, &class_name, &class_name_len, &ctor_params) == FAILURE) {
        !          1223:                        return;
        !          1224:                }
        !          1225:                if (ZEND_NUM_ARGS() < (getThis() ? 1 : 2)) {
        !          1226:                        ce = zend_standard_class_def;
1.1       misho    1227:                } else {
1.1.1.2 ! misho    1228:                        ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
1.1       misho    1229:                }
1.1.1.2 ! misho    1230:                if (!ce) {
        !          1231:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name);
        !          1232:                        return;
        !          1233:                }
        !          1234:                fetchtype = MYSQLI_ASSOC;
1.1       misho    1235:        } else {
1.1.1.2 ! misho    1236:                if (override_flags) {
        !          1237:                        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
        !          1238:                                return;
        !          1239:                        }
        !          1240:                        fetchtype = override_flags;
        !          1241:                } else {
        !          1242:                        fetchtype = MYSQLI_BOTH;
        !          1243:                        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) {
        !          1244:                                return;
        !          1245:                        }
        !          1246:                }
1.1       misho    1247:        }
1.1.1.2 ! misho    1248:        MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1.1       misho    1249: 
1.1.1.2 ! misho    1250:        if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
        !          1251:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH");
        !          1252:                RETURN_FALSE;
        !          1253:        }
        !          1254: 
        !          1255:        php_mysqli_fetch_into_hash_aux(return_value, result, fetchtype TSRMLS_CC);
1.1       misho    1256: 
                   1257:        if (into_object && Z_TYPE_P(return_value) != IS_NULL) {
                   1258:                zval dataset = *return_value;
                   1259:                zend_fcall_info fci;
                   1260:                zend_fcall_info_cache fcc;
                   1261:                zval *retval_ptr;
                   1262: 
                   1263:                object_and_properties_init(return_value, ce, NULL);
                   1264:                zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
                   1265: 
                   1266:                if (ce->constructor) {
                   1267:                        fci.size = sizeof(fci);
                   1268:                        fci.function_table = &ce->function_table;
                   1269:                        fci.function_name = NULL;
                   1270:                        fci.symbol_table = NULL;
                   1271:                        fci.object_ptr = return_value;
                   1272:                        fci.retval_ptr_ptr = &retval_ptr;
                   1273:                        if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
                   1274:                                if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
                   1275:                                        HashTable *params_ht = Z_ARRVAL_P(ctor_params);
                   1276:                                        Bucket *p;
                   1277: 
                   1278:                                        fci.param_count = 0;
                   1279:                                        fci.params = safe_emalloc(sizeof(zval*), params_ht->nNumOfElements, 0);
                   1280:                                        p = params_ht->pListHead;
                   1281:                                        while (p != NULL) {
                   1282:                                                fci.params[fci.param_count++] = (zval**)p->pData;
                   1283:                                                p = p->pListNext;
                   1284:                                        }
                   1285:                                } else {
                   1286:                                        /* Two problems why we throw exceptions here: PHP is typeless
                   1287:                                         * and hence passing one argument that's not an array could be
                   1288:                                         * by mistake and the other way round is possible, too. The
                   1289:                                         * single value is an array. Also we'd have to make that one
                   1290:                                         * argument passed by reference.
                   1291:                                         */
                   1292:                                        zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Parameter ctor_params must be an array", 0 TSRMLS_CC);
                   1293:                                        return;
                   1294:                                }
                   1295:                        } else {
                   1296:                                fci.param_count = 0;
                   1297:                                fci.params = NULL;
                   1298:                        }
                   1299:                        fci.no_separation = 1;
                   1300: 
                   1301:                        fcc.initialized = 1;
                   1302:                        fcc.function_handler = ce->constructor;
                   1303:                        fcc.calling_scope = EG(scope);
                   1304:                        fcc.called_scope = Z_OBJCE_P(return_value);
                   1305:                        fcc.object_ptr = return_value;
                   1306: 
                   1307:                        if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
                   1308:                                zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
                   1309:                        } else {
                   1310:                                if (retval_ptr) {
                   1311:                                        zval_ptr_dtor(&retval_ptr);
                   1312:                                }
                   1313:                        }
                   1314:                        if (fci.params) {
                   1315:                                efree(fci.params);
                   1316:                        }
                   1317:                } else if (ctor_params) {
                   1318:                        zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name);
                   1319:                }
                   1320:        }
                   1321: }
                   1322: /* }}} */
                   1323: 
                   1324: 
                   1325: #if !defined(MYSQLI_USE_MYSQLND)
                   1326: 
                   1327: #define ALLOC_CALLBACK_ARGS(a, b, c)\
                   1328: if (c) {\
                   1329:        a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
                   1330:        for (i = b; i < c; i++) {\
                   1331:                a[i] = emalloc(sizeof(zval *));\
                   1332:                MAKE_STD_ZVAL(*a[i]);\
                   1333:        }\
                   1334: }
                   1335: 
                   1336: #define FREE_CALLBACK_ARGS(a, b, c)\
                   1337: if (a) {\
                   1338:        for (i=b; i < c; i++) {\
                   1339:                zval_ptr_dtor(a[i]);\
                   1340:                efree(a[i]);\
                   1341:        }\
                   1342:        efree(a);\
                   1343: }
                   1344: 
                   1345: #define LOCAL_INFILE_ERROR_MSG(source,dest)\
                   1346:        memset(source, 0, LOCAL_INFILE_ERROR_LEN);\
                   1347:        memcpy(source, dest, MIN(strlen(dest), LOCAL_INFILE_ERROR_LEN-1));\
                   1348:        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", dest);
                   1349: 
                   1350: 
                   1351: /* {{{ php_local_infile_init
                   1352:  */
                   1353: static int php_local_infile_init(void **ptr, const char *filename, void *userdata)
                   1354: {
                   1355:        mysqli_local_infile                     *data;
                   1356:        MY_MYSQL                                        *mysql;
                   1357:        php_stream_context                      *context = NULL;
                   1358: 
                   1359:        TSRMLS_FETCH();
                   1360: 
                   1361:        /* save pointer to MY_MYSQL structure (userdata) */
                   1362:        if (!(*ptr= data= ((mysqli_local_infile *)calloc(1, sizeof(mysqli_local_infile))))) {
                   1363:                return 1;
                   1364:        }
                   1365: 
                   1366:        if (!(mysql = (MY_MYSQL *)userdata)) {
                   1367:                LOCAL_INFILE_ERROR_MSG(data->error_msg, ER(CR_UNKNOWN_ERROR));
                   1368:                return 1;
                   1369:        }
                   1370: 
                   1371:        /* check open_basedir */
                   1372:        if (PG(open_basedir)) {
                   1373:                if (php_check_open_basedir_ex(filename, 0 TSRMLS_CC) == -1) {
                   1374:                        LOCAL_INFILE_ERROR_MSG(data->error_msg, "open_basedir restriction in effect. Unable to open file");
                   1375:                        return 1;
                   1376:                }
                   1377:        }
                   1378: 
                   1379:        mysql->li_stream = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context);
                   1380: 
                   1381:        if (mysql->li_stream == NULL) {
                   1382:                snprintf((char *)data->error_msg, sizeof(data->error_msg), "Can't find file '%-.64s'.", filename);
                   1383:                return 1;
                   1384:        }
                   1385: 
                   1386:        data->userdata = mysql;
                   1387: 
                   1388:        return 0;
                   1389: }
                   1390: /* }}} */
                   1391: 
                   1392: /* {{{ int php_local_infile_read */
                   1393: static int php_local_infile_read(void *ptr, char *buf, uint buf_len)
                   1394: {
                   1395:        mysqli_local_infile                     *data;
                   1396:        MY_MYSQL                                        *mysql;
                   1397:        zval                                            ***callback_args;
                   1398:        zval                                            *retval;
                   1399:        zval                                            *fp;
                   1400:        int                                                     argc = 4;
                   1401:        int                                                     i;
                   1402:        long                                            rc;
                   1403: 
                   1404:        TSRMLS_FETCH();
                   1405: 
                   1406:        data= (mysqli_local_infile *)ptr;
                   1407:        mysql = data->userdata;
                   1408: 
                   1409:        /* default processing */
                   1410:        if (!mysql->li_read) {
                   1411:                int count = (int)php_stream_read(mysql->li_stream, buf, buf_len);
                   1412: 
                   1413:                if (count < 0) {
                   1414:                        LOCAL_INFILE_ERROR_MSG(data->error_msg, ER(2));
                   1415:                }
                   1416: 
                   1417:                return count;
                   1418:        }
                   1419: 
                   1420:        ALLOC_CALLBACK_ARGS(callback_args, 1, argc);
                   1421: 
                   1422:        /* set parameters: filepointer, buffer, buffer_len, errormsg */
                   1423: 
                   1424:        MAKE_STD_ZVAL(fp);
                   1425:        php_stream_to_zval(mysql->li_stream, fp);
                   1426:        callback_args[0] = &fp;
                   1427:        ZVAL_STRING(*callback_args[1], "", 1);
                   1428:        ZVAL_LONG(*callback_args[2], buf_len);
                   1429:        ZVAL_STRING(*callback_args[3], "", 1);
                   1430: 
                   1431:        if (call_user_function_ex(EG(function_table),
                   1432:                                                NULL,
                   1433:                                                mysql->li_read,
                   1434:                                                &retval,
                   1435:                                                argc,
                   1436:                                                callback_args,
                   1437:                                                0,
                   1438:                                                NULL TSRMLS_CC) == SUCCESS) {
                   1439: 
                   1440:                rc = Z_LVAL_P(retval);
                   1441:                zval_ptr_dtor(&retval);
                   1442: 
                   1443:                if (rc > 0) {
                   1444:                        if (rc >= 0 && rc != Z_STRLEN_P(*callback_args[1])) {
                   1445:                                LOCAL_INFILE_ERROR_MSG(data->error_msg,
                   1446:                                                        "Mismatch between the return value of the callback and the content "
                   1447:                                                        "length of the buffer.");
                   1448:                                rc = -1;
                   1449:                        } else if (rc > buf_len) {
                   1450:                                /* check buffer overflow */
                   1451:                                LOCAL_INFILE_ERROR_MSG(data->error_msg, "Too much data returned");
                   1452:                                rc = -1;
                   1453:                        } else {
                   1454:                                memcpy(buf, Z_STRVAL_P(*callback_args[1]), MIN(rc, Z_STRLEN_P(*callback_args[1])));
                   1455:                        }
                   1456:                } else if (rc < 0) {
                   1457:                        LOCAL_INFILE_ERROR_MSG(data->error_msg, Z_STRVAL_P(*callback_args[3]));
                   1458:                }
                   1459:        } else {
                   1460:                LOCAL_INFILE_ERROR_MSG(data->error_msg, "Can't execute load data local init callback function");
                   1461:                rc = -1;
                   1462:        }
                   1463:        /*
                   1464:          If the (ab)user has closed the file handle we should
                   1465:          not try to use it anymore or even close it
                   1466:        */
                   1467:        if (!zend_rsrc_list_get_rsrc_type(Z_LVAL_P(fp) TSRMLS_CC)) {
                   1468:                LOCAL_INFILE_ERROR_MSG(data->error_msg, "File handle closed");
                   1469:                rc = -1;
                   1470:                /* Thus the end handler won't try to free already freed memory */
                   1471:                mysql->li_stream = NULL;
                   1472:        }
                   1473: 
                   1474:        FREE_CALLBACK_ARGS(callback_args, 1, argc);
                   1475:        efree(fp);
                   1476:        return rc;
                   1477: }
                   1478: /* }}} */
                   1479: 
                   1480: /* {{{ php_local_infile_error
                   1481:  */
                   1482: static int php_local_infile_error(void *ptr, char *error_msg, uint error_msg_len)
                   1483: {
                   1484:        mysqli_local_infile *data = (mysqli_local_infile *) ptr;
                   1485: 
                   1486:        if (data) {
                   1487:                strlcpy(error_msg, data->error_msg, error_msg_len);
                   1488:                return 2000;
                   1489:        }
                   1490:        strlcpy(error_msg, ER(CR_OUT_OF_MEMORY), error_msg_len);
                   1491:        return CR_OUT_OF_MEMORY;
                   1492: }
                   1493: /* }}} */
                   1494: 
                   1495: /* {{{ php_local_infile_end
                   1496:  */
                   1497: static void php_local_infile_end(void *ptr)
                   1498: {
                   1499:        mysqli_local_infile             *data;
                   1500:        MY_MYSQL                                *mysql;
                   1501: 
                   1502:        TSRMLS_FETCH();
                   1503: 
                   1504:        data= (mysqli_local_infile *)ptr;
                   1505: 
                   1506:        if (!data || !(mysql = data->userdata)) {
                   1507:                if (data) {
                   1508:                        free(data);
                   1509:                }
                   1510:                return;
                   1511:        }
                   1512: 
                   1513:        if (mysql->li_stream) {
                   1514:                php_stream_close(mysql->li_stream);
                   1515:        }
                   1516:        free(data);
                   1517:        return;
                   1518: }
                   1519: /* }}} */
                   1520: 
                   1521: 
                   1522: /* {{{ void php_set_local_infile_handler_default
                   1523: */
                   1524: void php_set_local_infile_handler_default(MY_MYSQL *mysql) {
                   1525:        /* register internal callback functions */
                   1526:        mysql_set_local_infile_handler(mysql->mysql, &php_local_infile_init, &php_local_infile_read,
                   1527:                                &php_local_infile_end, &php_local_infile_error, (void *)mysql);
                   1528:        if (mysql->li_read) {
                   1529:                zval_ptr_dtor(&mysql->li_read);
                   1530:                mysql->li_read = NULL;
                   1531:        }
                   1532: }
                   1533: /* }}} */
                   1534: #endif
                   1535: 
                   1536: /*
                   1537:  * Local variables:
                   1538:  * tab-width: 4
                   1539:  * c-basic-offset: 4
                   1540:  * End:
                   1541:  * vim600: noet sw=4 ts=4 fdm=marker
                   1542:  * vim<600: noet sw=4 ts=4
                   1543:  */

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