Annotation of embedaddon/php/ext/mysqli/mysqli_nonapi.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
                      5:   | Copyright (c) 1997-2012 The PHP Group                                |
                      6:   +----------------------------------------------------------------------+
                      7:   | This source file is subject to version 3.01 of the PHP license,      |
                      8:   | that is bundled with this package in the file LICENSE, and is        |
                      9:   | available through the world-wide-web at the following url:           |
                     10:   | http://www.php.net/license/3_01.txt                                  |
                     11:   | If you did not receive a copy of the PHP license and are unable to   |
                     12:   | obtain it through the world-wide-web, please send a note to          |
                     13:   | license@php.net so we can mail you a copy immediately.               |
                     14:   +----------------------------------------------------------------------+
                     15:   | Authors: Georg Richter <georg@php.net>                               |
                     16:   |          Andrey Hristov <andrey@php.net>                             |
                     17:   |          Ulf Wendel <uw@php.net>                                     |
                     18:   +----------------------------------------------------------------------+
                     19: 
                     20:   $Id: mysqli_nonapi.c 321634 2012-01-01 13:15:04Z felipe $
                     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 "php_mysqli_structs.h"
                     33: #include "mysqli_priv.h"
                     34: 
                     35: #define SAFE_STR(a) ((a)?a:"")
                     36: 
                     37: #ifndef zend_parse_parameters_none
                     38: #define zend_parse_parameters_none()   \
                     39:         zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
                     40: #endif
                     41: 
                     42: /* {{{ php_mysqli_set_error
                     43:  */
                     44: static void php_mysqli_set_error(long mysql_errno, char *mysql_err TSRMLS_DC)
                     45: {
                     46:        MyG(error_no) = mysql_errno;
                     47:        if (MyG(error_msg)) {
                     48:                efree(MyG(error_msg));
                     49:        }
                     50:        if(mysql_err && *mysql_err) {
                     51:                MyG(error_msg) = estrdup(mysql_err);
                     52:        } else {
                     53:                MyG(error_msg) = NULL;
                     54:        }
                     55: }
                     56: /* }}} */
                     57: 
                     58: 
                     59: void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_connect, zend_bool in_ctor)
                     60: {
                     61:        MY_MYSQL                        *mysql = NULL;
                     62:        MYSQLI_RESOURCE         *mysqli_resource = NULL;
                     63:        zval                            *object = getThis();
                     64:        char                            *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL;
                     65:        int                                     hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0;
                     66:        zend_bool                       persistent = FALSE;
                     67:        long                            port = 0, flags = 0;
                     68:        uint                            hash_len;
                     69:        char                            *hash_key = NULL;
                     70:        zend_bool                       new_connection = FALSE;
                     71:        zend_rsrc_list_entry    *le;
                     72:        mysqli_plist_entry *plist = NULL;
                     73:        zend_bool                       self_alloced = 0;
                     74: 
                     75: 
                     76: #if !defined(MYSQL_USE_MYSQLND)
                     77:        if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) {
                     78:                php_error_docref(NULL TSRMLS_CC, E_WARNING,
                     79:                                                "Headers and client library minor version mismatch. Headers:%d Library:%ld",
                     80:                                                MYSQL_VERSION_ID, mysql_get_client_version());
                     81:        }
                     82: #endif
                     83: 
                     84:        if (getThis() && !ZEND_NUM_ARGS() && in_ctor) {
                     85:                php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU);
                     86:                return;
                     87:        }
                     88:        hostname = username = dbname = passwd = socket = NULL;
                     89: 
                     90:        if (!is_real_connect) {
                     91:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ssssls", &hostname, &hostname_len, &username, &username_len,
                     92:                                                                        &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len) == FAILURE) {
                     93:                        return;
                     94:                }
                     95: 
                     96:                if (object && instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {
                     97:                        mysqli_resource = ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr;
                     98:                        if (mysqli_resource && mysqli_resource->ptr) {
                     99:                                mysql = (MY_MYSQL*) mysqli_resource->ptr;
                    100:                        }
                    101:                }
                    102:                if (!mysql) {
                    103:                        mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
                    104:                        self_alloced = 1;
                    105:                }
                    106:                flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */
                    107:        } else {
                    108:                /* We have flags too */
                    109:                if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|sssslsl", &object, mysqli_link_class_entry,
                    110:                                                                                &hostname, &hostname_len, &username, &username_len, &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len,
                    111:                                                                                &flags) == FAILURE) {
                    112:                        return;
                    113:                }
                    114: 
                    115:                mysqli_resource = ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr;
                    116:                MYSQLI_FETCH_RESOURCE_CONN(mysql, &object, MYSQLI_STATUS_INITIALIZED);
                    117: 
                    118:                /* set some required options */
                    119:                flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */
                    120:                /* remove some insecure options */
                    121:                flags &= ~CLIENT_MULTI_STATEMENTS;   /* don't allow multi_queries via connect parameter */
                    122:                if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
                    123:                        flags &= ~CLIENT_LOCAL_FILES;
                    124:                }
                    125:        }
                    126: 
                    127:        if (!socket_len || !socket) {
                    128:                socket = MyG(default_socket);
                    129:        }
                    130:        if (!port){
                    131:                port = MyG(default_port);
                    132:        }
                    133:        if (!passwd) {
                    134:                passwd = MyG(default_pw);
                    135:                passwd_len = strlen(SAFE_STR(passwd));
                    136:        }
                    137:        if (!username){
                    138:                username = MyG(default_user);
                    139:        }
                    140:        if (!hostname || !hostname_len) {
                    141:                hostname = MyG(default_host);
                    142:        }
                    143: 
                    144:        if (mysql->mysql && mysqli_resource &&
                    145:                (mysqli_resource->status > MYSQLI_STATUS_INITIALIZED))
                    146:        {
                    147:                /* already connected, we should close the connection */
                    148:                php_mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT, mysqli_resource->status TSRMLS_CC);
                    149:        }
                    150: 
                    151:        if (strlen(SAFE_STR(hostname)) > 2 && !strncasecmp(hostname, "p:", 2)) {
                    152:                hostname += 2;
                    153:                if (!MyG(allow_persistent)) {
                    154:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Persistent connections are disabled. Downgrading to normal");
                    155:                } else {
                    156:                        mysql->persistent = persistent = TRUE;
                    157: 
                    158:                        hash_len = spprintf(&hash_key, 0, "mysqli_%s_%s%ld%s%s%s", SAFE_STR(hostname), SAFE_STR(socket),
                    159:                                                                port, SAFE_STR(username), SAFE_STR(dbname),
                    160:                                                                SAFE_STR(passwd));
                    161: 
                    162:                        mysql->hash_key = hash_key;
                    163: 
                    164:                        /* check if we can reuse exisiting connection ... */
                    165:                        if (zend_hash_find(&EG(persistent_list), hash_key, hash_len + 1, (void **)&le) == SUCCESS) {
                    166:                                if (Z_TYPE_P(le) == php_le_pmysqli()) {
                    167:                                        plist = (mysqli_plist_entry *) le->ptr;
                    168: 
                    169:                                        do {
                    170:                                                if (zend_ptr_stack_num_elements(&plist->free_links)) {
                    171:                                                        mysql->mysql = zend_ptr_stack_pop(&plist->free_links);
                    172: 
                    173:                                                        MyG(num_inactive_persistent)--;
                    174:                                                        /* reset variables */
                    175: 
                    176: #ifndef MYSQLI_NO_CHANGE_USER_ON_PCONNECT
                    177:                                                        if (!mysqli_change_user_silent(mysql->mysql, username, passwd, dbname)) {
                    178: #else
                    179:                                                        if (!mysql_ping(mysql->mysql)) {
                    180: #endif
                    181: #ifdef MYSQLI_USE_MYSQLND
                    182:                                                                mysqlnd_restart_psession(mysql->mysql);
                    183: #endif
                    184:                                                                MyG(num_active_persistent)++;
                    185:                                                                goto end;
                    186:                                                        } else {
                    187:                                                                mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT);
                    188:                                                                mysql->mysql = NULL;
                    189:                                                        }
                    190:                                                }
                    191:                                        } while (0);
                    192:                                }
                    193:                        } else {
                    194:                                zend_rsrc_list_entry le;
                    195:                                le.type = php_le_pmysqli();
                    196:                                le.ptr = plist = calloc(1, sizeof(mysqli_plist_entry));
                    197: 
                    198:                                zend_ptr_stack_init_ex(&plist->free_links, 1);
                    199:                                zend_hash_update(&EG(persistent_list), hash_key, hash_len + 1, (void *)&le, sizeof(le), NULL);
                    200:                        }
                    201:                }
                    202:        }
                    203:        if (MyG(max_links) != -1 && MyG(num_links) >= MyG(max_links)) {
                    204:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MyG(num_links));
                    205:                goto err;
                    206:        }
                    207: 
                    208:        if (persistent && MyG(max_persistent) != -1 &&
                    209:                (MyG(num_active_persistent) + MyG(num_inactive_persistent))>= MyG(max_persistent))
                    210:        {
                    211:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)",
                    212:                                                                MyG(num_active_persistent) + MyG(num_inactive_persistent));
                    213:                goto err;
                    214:        }
                    215:        if (!mysql->mysql) {
                    216: #if !defined(MYSQLI_USE_MYSQLND)
                    217:                if (!(mysql->mysql = mysql_init(NULL))) {
                    218: #else
                    219:                if (!(mysql->mysql = mysqlnd_init(persistent))) {
                    220: #endif
                    221:                        goto err;
                    222:                }
                    223:                new_connection = TRUE;
                    224:        }
                    225: 
                    226: #ifdef HAVE_EMBEDDED_MYSQLI
                    227:        if (hostname_len) {
                    228:                unsigned int external=1;
                    229:                mysql_options(mysql->mysql, MYSQL_OPT_USE_REMOTE_CONNECTION, (char *)&external);
                    230:        } else {
                    231:                mysql_options(mysql->mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, 0);
                    232:        }
                    233: #endif
                    234: 
                    235: #if !defined(MYSQLI_USE_MYSQLND)
                    236:        /* BC for prior to bug fix #53425 */
                    237:        flags |= CLIENT_MULTI_RESULTS;
                    238: 
                    239:        if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, flags) == NULL)
                    240: #else
                    241:        if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
                    242:                                                port, socket, flags TSRMLS_CC) == NULL)
                    243: #endif
                    244:        {
                    245:                /* Save error messages - for mysqli_connect_error() & mysqli_connect_errno() */
                    246:                php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql) TSRMLS_CC);
                    247:                php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
                    248:                                                                                "%s", mysql_error(mysql->mysql));
                    249:                if (!is_real_connect) {
                    250:                        /* free mysql structure */
                    251:                        mysqli_close(mysql->mysql, MYSQLI_CLOSE_DISCONNECTED);
                    252:                        mysql->mysql = NULL;
                    253:                }
                    254:                goto err;
                    255:        }
                    256: 
                    257:        /* clear error */
                    258:        php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql) TSRMLS_CC);
                    259: 
                    260: #if !defined(MYSQLI_USE_MYSQLND)
                    261:        mysql->mysql->reconnect = MyG(reconnect);
                    262: 
                    263:        /* set our own local_infile handler */
                    264:        php_set_local_infile_handler_default(mysql);
                    265: #endif
                    266: 
                    267:        mysql_options(mysql->mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&MyG(allow_local_infile));
                    268: 
                    269: end:
                    270:        if (!mysqli_resource) {
                    271:                mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
                    272:                mysqli_resource->ptr = (void *)mysql;
                    273:        }
                    274:        mysqli_resource->status = MYSQLI_STATUS_VALID;
                    275: 
                    276:        /* store persistent connection */
                    277:        if (persistent && (new_connection || is_real_connect)) {
                    278:                MyG(num_active_persistent)++;
                    279:        }
                    280: 
                    281:        MyG(num_links)++;
                    282: 
                    283:        mysql->multi_query = 0;
                    284: 
                    285:        if (!object || !instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {
                    286:                MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
                    287:        } else {
                    288:                ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr = mysqli_resource;
                    289:        }
                    290:        if (!is_real_connect) {
                    291:                return;
                    292:        } else {
                    293:                RETURN_TRUE;
                    294:        }
                    295: 
                    296: err:
                    297:        if (mysql->hash_key) {
                    298:                efree(mysql->hash_key);
                    299:                mysql->hash_key = NULL;
                    300:                mysql->persistent = FALSE;
                    301:        }
                    302:        if (!is_real_connect && self_alloced) {
                    303:                efree(mysql);
                    304:        }
                    305:        RETVAL_FALSE;
                    306: }
                    307: 
                    308: 
                    309: /* {{{ proto object mysqli_connect([string hostname [,string username [,string passwd [,string dbname [,int port [,string socket]]]]]])
                    310:    Open a connection to a mysql server */
                    311: PHP_FUNCTION(mysqli_connect)
                    312: {
                    313:        mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE, FALSE);
                    314: }
                    315: /* }}} */
                    316: 
                    317: 
                    318: /* {{{ proto object mysqli_link_construct()
                    319:   */
                    320: PHP_FUNCTION(mysqli_link_construct)
                    321: {
                    322:        mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE, TRUE);
                    323: }
                    324: /* }}} */
                    325: 
                    326: 
                    327: /* {{{ proto int mysqli_connect_errno(void)
                    328:    Returns the numerical value of the error message from last connect command */
                    329: PHP_FUNCTION(mysqli_connect_errno)
                    330: {
                    331:        RETURN_LONG(MyG(error_no));
                    332: }
                    333: /* }}} */
                    334: 
                    335: /* {{{ proto string mysqli_connect_error(void)
                    336:    Returns the text of the error message from previous MySQL operation */
                    337: PHP_FUNCTION(mysqli_connect_error)
                    338: {
                    339:        if (MyG(error_msg)) {
                    340:                RETURN_STRING(MyG(error_msg),1);
                    341:        } else {
                    342:                RETURN_NULL();
                    343:        }
                    344: }
                    345: /* }}} */
                    346: 
                    347: 
                    348: /* {{{ proto mixed mysqli_fetch_array (object result [,int resulttype])
                    349:    Fetch a result row as an associative array, a numeric array, or both */
                    350: PHP_FUNCTION(mysqli_fetch_array)
                    351: {
                    352:        php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
                    353: }
                    354: /* }}} */
                    355: 
                    356: /* {{{ proto mixed mysqli_fetch_assoc (object result)
                    357:    Fetch a result row as an associative array */
                    358: PHP_FUNCTION(mysqli_fetch_assoc)
                    359: {
                    360:        php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 0);
                    361: }
                    362: /* }}} */
                    363: 
                    364: 
                    365: /* {{{ proto mixed mysqli_fetch_all (object result [,int resulttype])
                    366:    Fetches all result rows as an associative array, a numeric array, or both */
                    367: #if defined(MYSQLI_USE_MYSQLND)
                    368: PHP_FUNCTION(mysqli_fetch_all)
                    369: {
                    370:        MYSQL_RES       *result;
                    371:        zval            *mysql_result;
                    372:        long            mode = MYSQLND_FETCH_NUM;
                    373: 
                    374:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &mode) == FAILURE) {
                    375:                return;
                    376:        }
                    377:        MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
                    378: 
                    379:        if (!mode || (mode & ~MYSQLND_FETCH_BOTH)) {
                    380:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Mode can be only MYSQLI_FETCH_NUM, "
                    381:                                 "MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH");
                    382:                RETURN_FALSE;
                    383:        }
                    384: 
                    385:        mysqlnd_fetch_all(result, mode, return_value);
                    386: }
                    387: /* }}} */
                    388: 
                    389: 
                    390: /* {{{ proto array mysqli_cache_stats(void) U
                    391:    Returns statistics about the zval cache */
                    392: PHP_FUNCTION(mysqli_get_cache_stats)
                    393: {
                    394:        if (zend_parse_parameters_none() == FAILURE) {
                    395:                return;
                    396:        }
                    397:        array_init(return_value);
                    398: }
                    399: /* }}} */
                    400: 
                    401: 
                    402: /* {{{ proto array mysqli_get_client_stats(void)
                    403:    Returns statistics about the zval cache */
                    404: PHP_FUNCTION(mysqli_get_client_stats)
                    405: {
                    406:        if (zend_parse_parameters_none() == FAILURE) {
                    407:                return;
                    408:        }
                    409:        mysqlnd_get_client_stats(return_value);
                    410: }
                    411: /* }}} */
                    412: 
                    413: 
                    414: /* {{{ proto array mysqli_get_connection_stats(void)
                    415:    Returns statistics about the zval cache */
                    416: PHP_FUNCTION(mysqli_get_connection_stats)
                    417: {
                    418:        MY_MYSQL        *mysql;
                    419:        zval            *mysql_link;
                    420: 
                    421:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
                    422:                                                                         &mysql_link, mysqli_link_class_entry) == FAILURE) {
                    423:                return;
                    424:        }
                    425:        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                    426: 
                    427:        mysqlnd_get_connection_stats(mysql->mysql, return_value);
                    428: }
                    429: #endif
                    430: /* }}} */
                    431: 
                    432: 
                    433: /* {{{ proto mixed mysqli_fetch_object (object result [, string class_name [, NULL|array ctor_params]])
                    434:    Fetch a result row as an object */
                    435: PHP_FUNCTION(mysqli_fetch_object)
                    436: {
                    437:        php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 1);
                    438: }
                    439: /* }}} */
                    440: 
                    441: /* {{{ proto bool mysqli_multi_query(object link, string query)
                    442:    allows to execute multiple queries  */
                    443: PHP_FUNCTION(mysqli_multi_query)
                    444: {
                    445:        MY_MYSQL        *mysql;
                    446:        zval            *mysql_link;
                    447:        char            *query = NULL;
                    448:        int             query_len;
                    449: 
                    450:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
                    451:                return;
                    452:        }
                    453:        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                    454: 
                    455:        MYSQLI_ENABLE_MQ;
                    456:        if (mysql_real_query(mysql->mysql, query, query_len)) {
                    457: #ifndef MYSQLI_USE_MYSQLND
                    458:                char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1];
                    459:                unsigned int s_errno;
                    460:                /* we have to save error information, cause
                    461:                MYSQLI_DISABLE_MQ will reset error information */
                    462:                strcpy(s_error, mysql_error(mysql->mysql));
                    463:                strcpy(s_sqlstate, mysql_sqlstate(mysql->mysql));
                    464:                s_errno = mysql_errno(mysql->mysql);
                    465: #else
                    466:                MYSQLND_ERROR_INFO error_info = mysql->mysql->error_info;
                    467: #endif
                    468:                MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
                    469:                MYSQLI_DISABLE_MQ;
                    470: 
                    471: #ifndef MYSQLI_USE_MYSQLND
                    472:                /* restore error information */
                    473:                strcpy(mysql->mysql->net.last_error, s_error);
                    474:                strcpy(mysql->mysql->net.sqlstate, s_sqlstate);
                    475:                mysql->mysql->net.last_errno = s_errno;
                    476: #else
                    477:                mysql->mysql->error_info = error_info;
                    478: #endif
                    479:                RETURN_FALSE;
                    480:        }
                    481:        RETURN_TRUE;
                    482: }
                    483: /* }}} */
                    484: 
                    485: /* {{{ proto mixed mysqli_query(object link, string query [,int resultmode]) */
                    486: PHP_FUNCTION(mysqli_query)
                    487: {
                    488:        MY_MYSQL                        *mysql;
                    489:        zval                            *mysql_link;
                    490:        MYSQLI_RESOURCE         *mysqli_resource;
                    491:        MYSQL_RES                       *result;
                    492:        char                            *query = NULL;
                    493:        int                             query_len;
                    494:        long                            resultmode = MYSQLI_STORE_RESULT;
                    495: 
                    496:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", &mysql_link, mysqli_link_class_entry, &query, &query_len, &resultmode) == FAILURE) {
                    497:                return;
                    498:        }
                    499: 
                    500:        if (!query_len) {
                    501:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query");
                    502:                RETURN_FALSE;
                    503:        }
                    504:        if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT) {
                    505:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
                    506:                RETURN_FALSE;
                    507:        }
                    508: 
                    509:        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                    510: 
                    511:        MYSQLI_DISABLE_MQ;
                    512: 
                    513: 
                    514: #ifdef MYSQLI_USE_MYSQLND
                    515:        if (resultmode & MYSQLI_ASYNC) {
                    516:                if (mysqli_async_query(mysql->mysql, query, query_len)) {
                    517:                        MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
                    518:                        RETURN_FALSE;
                    519:                }
                    520:                mysql->async_result_fetch_type = resultmode & ~MYSQLI_ASYNC;
                    521:                RETURN_TRUE;
                    522:        }
                    523: #endif
                    524: 
                    525:        if (mysql_real_query(mysql->mysql, query, query_len)) {
                    526:                MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
                    527:                RETURN_FALSE;
                    528:        }
                    529: 
                    530:        if (!mysql_field_count(mysql->mysql)) {
                    531:                /* no result set - not a SELECT */
                    532:                if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
                    533:                        php_mysqli_report_index(query, mysqli_server_status(mysql->mysql) TSRMLS_CC);
                    534:                }
                    535:                RETURN_TRUE;
                    536:        }
                    537: 
                    538:        switch (resultmode) {
                    539:                case MYSQLI_STORE_RESULT:
                    540:                        result = mysql_store_result(mysql->mysql);
                    541:                        break;
                    542:                case MYSQLI_USE_RESULT:
                    543:                        result = mysql_use_result(mysql->mysql);
                    544:                        break;
                    545:        }
                    546:        if (!result) {
                    547:                php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
                    548:                                                                                "%s", mysql_error(mysql->mysql));
                    549:                RETURN_FALSE;
                    550:        }
                    551: 
                    552:        if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
                    553:                php_mysqli_report_index(query, mysqli_server_status(mysql->mysql) TSRMLS_CC);
                    554:        }
                    555: 
                    556:        mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
                    557:        mysqli_resource->ptr = (void *)result;
                    558:        mysqli_resource->status = MYSQLI_STATUS_VALID;
                    559:        MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
                    560: }
                    561: /* }}} */
                    562: 
                    563: 
                    564: #if defined(MYSQLI_USE_MYSQLND)
                    565: #include "php_network.h"
                    566: /* {{{ mysqlnd_zval_array_to_mysqlnd_array functions */
                    567: static int mysqlnd_zval_array_to_mysqlnd_array(zval *in_array, MYSQLND ***out_array TSRMLS_DC)
                    568: {
                    569:        zval **elem;
                    570:        int i = 0, current = 0;
                    571: 
                    572:        if (Z_TYPE_P(in_array) != IS_ARRAY) {
                    573:                return 0;
                    574:        }
                    575:        *out_array = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(in_array)) + 1, sizeof(MYSQLND *));
                    576:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(in_array));
                    577:                 zend_hash_get_current_data(Z_ARRVAL_P(in_array), (void **) &elem) == SUCCESS;
                    578:                 zend_hash_move_forward(Z_ARRVAL_P(in_array))) {
                    579:                i++;
                    580:                if (Z_TYPE_PP(elem) != IS_OBJECT ||
                    581:                        !instanceof_function(Z_OBJCE_PP(elem), mysqli_link_class_entry TSRMLS_CC)) {
                    582:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter %d not a mysqli object", i);
                    583:                } else {
                    584:                        MY_MYSQL *mysql;
                    585:                        MYSQLI_RESOURCE *my_res;
                    586:                        mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC);
                    587:                        if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
                    588:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%d] Couldn't fetch %s", i, intern->zo.ce->name);
                    589:                                continue;
                    590:                        }
                    591:                        mysql = (MY_MYSQL*) my_res->ptr;
                    592:                        if (MYSQLI_STATUS_VALID && my_res->status < MYSQLI_STATUS_VALID) {
                    593:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object %d or resource %s", i, intern->zo.ce->name);
                    594:                                continue;
                    595:                        }
                    596:                        (*out_array)[current++] = mysql->mysql;
                    597:                }
                    598:        }
                    599:        return 0;
                    600: }
                    601: /* }}} */
                    602: 
                    603: 
                    604: /* {{{ mysqlnd_zval_array_from_mysqlnd_array */
                    605: static int mysqlnd_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *out_array TSRMLS_DC)
                    606: {
                    607:        MYSQLND **p = in_array;
                    608:        HashTable *new_hash;
                    609:        zval **elem, **dest_elem;
                    610:        int ret = 0;
                    611: 
                    612:        ALLOC_HASHTABLE(new_hash);
                    613:        zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(out_array)), NULL, ZVAL_PTR_DTOR, 0);
                    614: 
                    615:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(out_array));
                    616:                 zend_hash_get_current_data(Z_ARRVAL_P(out_array), (void **) &elem) == SUCCESS;
                    617:                 zend_hash_move_forward(Z_ARRVAL_P(out_array)))
                    618:        {
                    619:                if (Z_TYPE_PP(elem) != IS_OBJECT || !instanceof_function(Z_OBJCE_PP(elem), mysqli_link_class_entry TSRMLS_CC)) {
                    620:                        continue;
                    621:                }
                    622:                {
                    623:                        MY_MYSQL *mysql;
                    624:                        mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC);
                    625:                        mysql = (MY_MYSQL *) ((MYSQLI_RESOURCE *)intern->ptr)->ptr;
                    626:                        if (mysql->mysql == *p) {
                    627:                                zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
                    628:                                if (dest_elem) {
                    629:                                        zval_add_ref(dest_elem);
                    630:                                }
                    631:                                ret++;
                    632:                                p++;
                    633:                        }
                    634:                }
                    635:        }
                    636: 
                    637:        /* destroy old array and add new one */
                    638:        zend_hash_destroy(Z_ARRVAL_P(out_array));
                    639:        efree(Z_ARRVAL_P(out_array));
                    640: 
                    641:        zend_hash_internal_pointer_reset(new_hash);
                    642:        Z_ARRVAL_P(out_array) = new_hash;
                    643: 
                    644:        return 0;
                    645: }
                    646: /* }}} */
                    647: 
                    648: 
                    649: /* {{{ mysqlnd_dont_poll_zval_array_from_mysqlnd_array */
                    650: static int mysqlnd_dont_poll_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *in_zval_array, zval *out_array TSRMLS_DC)
                    651: {
                    652:        MYSQLND **p = in_array;
                    653:        HashTable *new_hash;
                    654:        zval **elem, **dest_elem;
                    655:        int ret = 0;
                    656: 
                    657:        ALLOC_HASHTABLE(new_hash);
                    658:        zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(in_zval_array)), NULL, ZVAL_PTR_DTOR, 0);
                    659:        if (in_array) {
                    660:                for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(in_zval_array));
                    661:                         zend_hash_get_current_data(Z_ARRVAL_P(in_zval_array), (void **) &elem) == SUCCESS;
                    662:                         zend_hash_move_forward(Z_ARRVAL_P(in_zval_array)))
                    663:                {
                    664:                        MY_MYSQL *mysql;
                    665:                        mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC);
                    666:                        mysql = (MY_MYSQL *) ((MYSQLI_RESOURCE *)intern->ptr)->ptr;
                    667:                        if (mysql->mysql == *p) {
                    668:                                zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
                    669:                                if (dest_elem) {
                    670:                                        zval_add_ref(dest_elem);
                    671:                                }
                    672:                                ret++;
                    673:                                p++;
                    674:                        }
                    675:                }
                    676:        }
                    677: 
                    678:        /* destroy old array and add new one */
                    679:        zend_hash_destroy(Z_ARRVAL_P(out_array));
                    680:        efree(Z_ARRVAL_P(out_array));
                    681: 
                    682:        zend_hash_internal_pointer_reset(new_hash);
                    683:        Z_ARRVAL_P(out_array) = new_hash;
                    684: 
                    685:        return 0;
                    686: }
                    687: /* }}} */
                    688: 
                    689: 
                    690: /* {{{ proto int mysqli_poll(array read, array write, array error, long sec [, long usec]) U
                    691:    Poll connections */
                    692: PHP_FUNCTION(mysqli_poll)
                    693: {
                    694:        zval                    *r_array, *e_array, *dont_poll_array;
                    695:        MYSQLND                 **new_r_array = NULL, **new_e_array = NULL, **new_dont_poll_array = NULL;
                    696:        long                    sec = 0, usec = 0;
                    697:        enum_func_status ret;
                    698:        uint                    desc_num;
                    699: 
                    700:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!al|l", &r_array, &e_array, &dont_poll_array, &sec, &usec) == FAILURE) {
                    701:                return;
                    702:        }
                    703:        if (sec < 0 || usec < 0) {
                    704:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Negative values passed for sec and/or usec");
                    705:                RETURN_FALSE;
                    706:        }
                    707: 
                    708:        if (r_array != NULL) {
                    709:                mysqlnd_zval_array_to_mysqlnd_array(r_array, &new_r_array TSRMLS_CC);
                    710:        }
                    711:        if (e_array != NULL) {
                    712:                mysqlnd_zval_array_to_mysqlnd_array(e_array, &new_e_array TSRMLS_CC);
                    713:        }
                    714: 
                    715:        ret = mysqlnd_poll(new_r_array, new_e_array, &new_dont_poll_array, sec, usec, &desc_num);
                    716: 
                    717:        mysqlnd_dont_poll_zval_array_from_mysqlnd_array(r_array != NULL ? new_dont_poll_array:NULL, r_array, dont_poll_array TSRMLS_CC);
                    718: 
                    719:        if (r_array != NULL) {
                    720:                mysqlnd_zval_array_from_mysqlnd_array(new_r_array, r_array TSRMLS_CC);
                    721:        }
                    722:        if (e_array != NULL) {
                    723:                mysqlnd_zval_array_from_mysqlnd_array(new_e_array, e_array TSRMLS_CC);
                    724:        }
                    725: 
                    726:        if (new_dont_poll_array) {
                    727:                efree(new_dont_poll_array);
                    728:        }
                    729:        if (new_r_array) {
                    730:                efree(new_r_array);
                    731:        }
                    732:        if (new_e_array) {
                    733:                efree(new_e_array);
                    734:        }
                    735:        if (ret == PASS) {
                    736:                RETURN_LONG(desc_num);
                    737:        } else {
                    738:                RETURN_FALSE;
                    739:        }
                    740: }
                    741: /* }}} */
                    742: 
                    743: 
                    744: /* {{{ proto int mysqli_reap_async_query(object link) U
                    745:    Poll connections */
                    746: PHP_FUNCTION(mysqli_reap_async_query)
                    747: {
                    748:        MY_MYSQL                *mysql;
                    749:        zval                    *mysql_link;
                    750:        MYSQLI_RESOURCE         *mysqli_resource;
                    751:        MYSQL_RES                       *result;
                    752: 
                    753:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
                    754:                return;
                    755:        }
                    756: 
                    757:        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                    758: 
                    759:        if (FAIL == mysqlnd_reap_async_query(mysql->mysql)) {
                    760:                RETURN_FALSE;
                    761:        }
                    762: 
                    763:        if (!mysql_field_count(mysql->mysql)) {
                    764:                /* no result set - not a SELECT */
                    765:                if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
                    766: /*                     php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC); */
                    767:                }
                    768:                RETURN_TRUE;
                    769:        }
                    770: 
                    771:        switch (mysql->async_result_fetch_type) {
                    772:                case MYSQLI_STORE_RESULT:
                    773:                        result = mysql_store_result(mysql->mysql);
                    774:                        break;
                    775:                case MYSQLI_USE_RESULT:
                    776:                        result = mysql_use_result(mysql->mysql);
                    777:                        break;
                    778:        }
                    779: 
                    780:        if (!result) {
                    781:                php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
                    782:                                                                                "%s", mysql_error(mysql->mysql));
                    783:                RETURN_FALSE;
                    784:        }
                    785: 
                    786:        if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
                    787: /*             php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC); */
                    788:        }
                    789: 
                    790:        mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
                    791:        mysqli_resource->ptr = (void *)result;
                    792:        mysqli_resource->status = MYSQLI_STATUS_VALID;
                    793:        MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
                    794: }
                    795: /* }}} */
                    796: 
                    797: 
                    798: /* {{{ proto object mysqli_stmt_get_result(object link) U
                    799:    Buffer result set on client */
                    800: PHP_FUNCTION(mysqli_stmt_get_result)
                    801: {
                    802:        MYSQL_RES               *result;
                    803:        MYSQLI_RESOURCE *mysqli_resource;
                    804:        MY_STMT                 *stmt;
                    805:        zval                    *mysql_stmt;
                    806: 
                    807:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
                    808:                return;
                    809:        }
                    810:        MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
                    811: 
                    812:        if (!(result = mysqlnd_stmt_get_result(stmt->stmt))) {
                    813:                MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
                    814:                RETURN_FALSE;
                    815:        }
                    816: 
                    817:        mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
                    818:        mysqli_resource->ptr = (void *)result;
                    819:        mysqli_resource->status = MYSQLI_STATUS_VALID;
                    820:        MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
                    821: }
                    822: /* }}} */
                    823: #endif
                    824: 
                    825: 
                    826: /* {{{ proto object mysqli_get_warnings(object link) */
                    827: PHP_FUNCTION(mysqli_get_warnings)
                    828: {
                    829:        MY_MYSQL                        *mysql;
                    830:        zval                            *mysql_link;
                    831:        MYSQLI_RESOURCE         *mysqli_resource;
                    832:        MYSQLI_WARNING          *w;
                    833: 
                    834:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
                    835:                return;
                    836:        }
                    837:        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                    838: 
                    839:        if (mysql_warning_count(mysql->mysql)) {
                    840:                w = php_get_warnings(mysql->mysql TSRMLS_CC);
                    841:        } else {
                    842:                RETURN_FALSE;
                    843:        }
                    844:        mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
                    845:        mysqli_resource->ptr = mysqli_resource->info = (void *)w;
                    846:        mysqli_resource->status = MYSQLI_STATUS_VALID;
                    847:        MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
                    848: }
                    849: /* }}} */
                    850: 
                    851: /* {{{ proto object mysqli_stmt_get_warnings(object link) */
                    852: PHP_FUNCTION(mysqli_stmt_get_warnings)
                    853: {
                    854:        MY_STMT                         *stmt;
                    855:        zval                            *stmt_link;
                    856:        MYSQLI_RESOURCE         *mysqli_resource;
                    857:        MYSQLI_WARNING          *w;
                    858: 
                    859:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &stmt_link, mysqli_stmt_class_entry) == FAILURE) {
                    860:                return;
                    861:        }
                    862:        MYSQLI_FETCH_RESOURCE_STMT(stmt, &stmt_link, MYSQLI_STATUS_VALID);
                    863: 
                    864:        if (mysqli_stmt_warning_count(stmt->stmt)) {
                    865:                w = php_get_warnings(mysqli_stmt_get_connection(stmt->stmt) TSRMLS_CC);
                    866:        } else {
                    867:                RETURN_FALSE;
                    868:        }
                    869:        mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
                    870:        mysqli_resource->ptr = mysqli_resource->info = (void *)w;
                    871:        mysqli_resource->status = MYSQLI_STATUS_VALID;
                    872:        MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
                    873: }
                    874: /* }}} */
                    875: 
                    876: #ifdef HAVE_MYSQLI_SET_CHARSET
                    877: /* {{{ proto bool mysqli_set_charset(object link, string csname)
                    878:    sets client character set */
                    879: PHP_FUNCTION(mysqli_set_charset)
                    880: {
                    881:        MY_MYSQL        *mysql;
                    882:        zval            *mysql_link;
                    883:        char            *cs_name;
                    884:        int                     csname_len;
                    885: 
                    886:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &csname_len) == FAILURE) {
                    887:                return;
                    888:        }
                    889:        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                    890: 
                    891:        if (mysql_set_character_set(mysql->mysql, cs_name)) {
                    892:                RETURN_FALSE;
                    893:        }
                    894:        RETURN_TRUE;
                    895: }
                    896: /* }}} */
                    897: #endif
                    898: 
                    899: #ifdef HAVE_MYSQLI_GET_CHARSET
                    900: /* {{{ proto object mysqli_get_charset(object link) U
                    901:    returns a character set object */
                    902: PHP_FUNCTION(mysqli_get_charset)
                    903: {
                    904:        MY_MYSQL                                *mysql;
                    905:        zval                                    *mysql_link;
                    906:        const char                              *name = NULL, *collation = NULL, *dir = NULL, *comment = NULL;
                    907:        uint                                    minlength, maxlength, number, state;
                    908: #if !defined(MYSQLI_USE_MYSQLND)
                    909:        MY_CHARSET_INFO                 cs;
                    910: #else
                    911:        const MYSQLND_CHARSET   *cs;
                    912: #endif
                    913: 
                    914:        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
                    915:                return;
                    916:        }
                    917:        MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
                    918: 
                    919: 
                    920: #if !defined(MYSQLI_USE_MYSQLND)
                    921:        mysql_get_character_set_info(mysql->mysql, &cs);
                    922:        name = (char *)cs.csname;
                    923:        collation = (char *)cs.name;
                    924:        dir = (char *)cs.dir;
                    925:        minlength = cs.mbminlen;
                    926:        maxlength = cs.mbmaxlen;
                    927:        number = cs.number;
                    928:        state = cs.state;
                    929:        comment = cs.comment;
                    930: #else
                    931:        cs = mysql->mysql->charset;
                    932:        if (!cs) {
                    933:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The connection has no charset associated");
                    934:                RETURN_NULL();
                    935:        }
                    936:        name = cs->name;
                    937:        collation = cs->collation;
                    938:        minlength = cs->char_minlen;
                    939:        maxlength = cs->char_maxlen;
                    940:        number = cs->nr;
                    941:        comment = cs->comment;
                    942:        state = 1;      /* all charsets are compiled in */
                    943: #endif
                    944:        object_init(return_value);
                    945: 
                    946:        add_property_string(return_value, "charset", (name) ? (char *)name : "", 1);
                    947:        add_property_string(return_value, "collation",(collation) ? (char *)collation : "", 1);
                    948:        add_property_string(return_value, "dir", (dir) ? (char *)dir : "", 1);
                    949:        add_property_long(return_value, "min_length", minlength);
                    950:        add_property_long(return_value, "max_length", maxlength);
                    951:        add_property_long(return_value, "number", number);
                    952:        add_property_long(return_value, "state", state);
                    953:        add_property_string(return_value, "comment", (comment) ? (char *)comment : "", 1);
                    954: }
                    955: /* }}} */
                    956: #endif
                    957: 
                    958: /*
                    959:  * Local variables:
                    960:  * tab-width: 4
                    961:  * c-basic-offset: 4
                    962:  * End:
                    963:  * vim600: noet sw=4 ts=4 fdm=marker
                    964:  * vim<600: noet sw=4 ts=4
                    965:  */

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