diff options
author | Andrey Hristov <andrey@php.net> | 2008-03-18 16:58:43 +0000 |
---|---|---|
committer | Andrey Hristov <andrey@php.net> | 2008-03-18 16:58:43 +0000 |
commit | e53f44b9bd98c11517f52b737ed220f4521c0871 (patch) | |
tree | 3fc6f8172a86c2aa9fadc47112ed4b01d6c688e4 /ext/mysqli/mysqli.c | |
parent | da591e8eca232ee7541bbb1dbf5c3be6f32ba284 (diff) | |
download | php-git-e53f44b9bd98c11517f52b737ed220f4521c0871.tar.gz |
MFB - Bug #44352 mysqli_connect_error() false negative for host errors
Diffstat (limited to 'ext/mysqli/mysqli.c')
-rw-r--r-- | ext/mysqli/mysqli.c | 224 |
1 files changed, 168 insertions, 56 deletions
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 871c6fb3de..8565f0a4ac 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -36,6 +36,27 @@ ZEND_DECLARE_MODULE_GLOBALS(mysqli) static PHP_GINIT_FUNCTION(mysqli); +#define MYSQLI_ADD_PROPERTIES(a,b) \ +{ \ + int i = 0; \ + while (b[i].pname != NULL) { \ + mysqli_add_property((a), (b)[i].pname, (b)[i].pname_length, \ + (mysqli_read_t)(b)[i].r_func, (mysqli_write_t)(b)[i].w_func TSRMLS_CC); \ + i++; \ + }\ +} + +#define MYSQLI_ADD_PROPERTIES_INFO(a,b) \ +{ \ + int i = 0; \ + while (b[i].name.s != NULL) { \ + zend_declare_property_null((a), (b)[i].name.s, (b)[i].name_length, ZEND_ACC_PUBLIC TSRMLS_CC); \ + i++; \ + }\ +} + + + static zend_object_handlers mysqli_object_handlers; static HashTable classes; static HashTable mysqli_driver_properties; @@ -61,6 +82,8 @@ typedef int (*mysqli_read_t)(mysqli_object *obj, zval **retval TSRMLS_DC); typedef int (*mysqli_write_t)(mysqli_object *obj, zval *newval TSRMLS_DC); typedef struct _mysqli_prop_handler { + char *name; + size_t name_len; mysqli_read_t read_func; mysqli_write_t write_func; } mysqli_prop_handler; @@ -68,7 +91,6 @@ typedef struct _mysqli_prop_handler { static int le_pmysqli; - /* Destructor for mysqli entries in free_links/used_links */ void php_mysqli_dtor_p_elements(void *data) { @@ -92,6 +114,7 @@ ZEND_RSRC_DTOR_FUNC(php_mysqli_dtor) } } + int php_le_pmysqli(void) { return le_pmysqli; @@ -116,7 +139,7 @@ void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type) if (bbuf.vars[i]) { zval_ptr_dtor(&bbuf.vars[i]); - } + } } if (bbuf.vars) { @@ -189,7 +212,7 @@ static void mysqli_objects_free_storage(void *object TSRMLS_DC) mysqli_object *intern = (mysqli_object *)zo; MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr; - my_efree(my_res); + my_efree(my_res); zend_object_std_dtor(&intern->zo TSRMLS_CC); efree(intern); } @@ -363,7 +386,7 @@ void mysqli_write_property(zval *object, zval *member, zval *value TSRMLS_DC) zend_object_handlers *std_hnd; int ret; - if (member->type != IS_STRING) { + if (member->type != IS_STRING) { tmp_member = *member; zval_copy_ctor(&tmp_member); convert_to_string(&tmp_member); @@ -393,14 +416,15 @@ void mysqli_write_property(zval *object, zval *member, zval *value TSRMLS_DC) } /* }}} */ -/* {{{ void mysqli_add_property(HashTable *h, char *pname, mysqli_read_t r_func, mysqli_write_t w_func TSRMLS_DC) */ -void mysqli_add_property(HashTable *h, char *pname, mysqli_read_t r_func, mysqli_write_t w_func TSRMLS_DC) { +/* {{{ 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) */ +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) { mysqli_prop_handler p; + p.name = (char*) pname; + p.name_len = pname_len; p.read_func = (r_func) ? r_func : mysqli_read_na; p.write_func = (w_func) ? w_func : mysqli_write_na; - - zend_hash_add(h, pname, strlen(pname) + 1, &p, sizeof(mysqli_prop_handler), NULL); + zend_ascii_hash_add(h, pname, pname_len + 1, &p, sizeof(mysqli_prop_handler), NULL); } /* }}} */ @@ -434,11 +458,95 @@ static union _zend_function *php_mysqli_constructor_get(zval *object TSRMLS_DC) } else if (obj->zo.ce == mysqli_warning_class_entry) { f.handler = ZEND_MN(mysqli_warning___construct); } - + return (union _zend_function*)&f; } } +static int mysqli_object_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC) /* {{{ */ +{ + mysqli_object *obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC); + mysqli_prop_handler p; + zval tmp_member; + int ret = 0; + + if (member->type != IS_STRING && member->type != IS_UNICODE) { + tmp_member = *member; + zval_copy_ctor(&tmp_member); + convert_to_text(&tmp_member); + member = &tmp_member; + } + + if (zend_ascii_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&p) == SUCCESS) { + switch (has_set_exists) { + case 2: + ret = 1; + break; + case 1: { + zval *value = mysqli_read_property(object, member, BP_VAR_IS TSRMLS_CC); + if (value != EG(uninitialized_zval_ptr)) { + convert_to_boolean(value); + ret = Z_BVAL_P(value)? 1:0; + /* refcount is 0 */ + Z_ADDREF_P(value); + zval_ptr_dtor(&value); + } + break; + } + case 0:{ + zval *value = mysqli_read_property(object, member, BP_VAR_IS TSRMLS_CC); + if (value != EG(uninitialized_zval_ptr)) { + ret = Z_TYPE_P(value) != IS_NULL? 1:0; + /* refcount is 0 */ + Z_ADDREF_P(value); + zval_ptr_dtor(&value); + } + break; + } + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for has_set_exists"); + } + } + if (member == &tmp_member) { + zval_dtor(member); + } + + return ret; +} /* }}} */ + + +HashTable * mysqli_object_get_debug_info(zval *object, int *is_temp TSRMLS_DC) +{ + mysqli_object *obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC); + HashTable *retval, *props = obj->prop_handler; + HashPosition pos; + mysqli_prop_handler *entry; + + ALLOC_HASHTABLE(retval); + ZEND_INIT_SYMTABLE_EX(retval, zend_hash_num_elements(props) + 1, 0); + + zend_hash_internal_pointer_reset_ex(props, &pos); + while (zend_hash_get_current_data_ex(props, (void **)&entry, &pos) == SUCCESS) { + zval member; + zval *value; + INIT_ZVAL(member); + ZVAL_ASCII_STRINGL(&member, entry->name, entry->name_len, 0); + value = mysqli_read_property(object, &member, BP_VAR_IS TSRMLS_CC); + if (value != EG(uninitialized_zval_ptr)) { + Z_ADDREF_P(value); + zend_ascii_hash_add(retval, entry->name, entry->name_len + 1, &value, sizeof(zval *), NULL); + } + zend_hash_move_forward_ex(props, &pos); + if (UG(unicode)) { + zval_dtor(&member); + } + } + + *is_temp = 1; + return retval; +} + + /* {{{ mysqli_objects_new */ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_type TSRMLS_DC) @@ -455,8 +563,8 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_ intern->prop_handler = NULL; mysqli_base_class = class_type; - while (mysqli_base_class->type != ZEND_INTERNAL_CLASS && mysqli_base_class->parent != NULL) - { + while (mysqli_base_class->type != ZEND_INTERNAL_CLASS && + mysqli_base_class->parent != NULL) { mysqli_base_class = mysqli_base_class->parent; } @@ -566,9 +674,9 @@ static PHP_GINIT_FUNCTION(mysqli) mysqli_globals->default_pw = NULL; mysqli_globals->default_socket = NULL; mysqli_globals->reconnect = 0; - mysqli_globals->allow_local_infile = 1; mysqli_globals->report_mode = 0; mysqli_globals->report_ht = 0; + mysqli_globals->allow_local_infile = 1; #ifdef HAVE_EMBEDDED_MYSQLI mysqli_globals->embedded = 1; #else @@ -589,7 +697,6 @@ PHP_MINIT_FUNCTION(mysqli) zend_object_handlers *std_hnd = zend_get_std_object_handlers(); REGISTER_INI_ENTRIES(); - #ifndef MYSQLI_USE_MYSQLND #if MYSQL_VERSION_ID >= 40000 if (mysql_server_init(0, NULL, NULL)) { @@ -607,6 +714,8 @@ PHP_MINIT_FUNCTION(mysqli) mysqli_object_handlers.write_property = mysqli_write_property; mysqli_object_handlers.get_property_ptr_ptr = std_hnd->get_property_ptr_ptr; mysqli_object_handlers.get_constructor = php_mysqli_constructor_get; + mysqli_object_handlers.has_property = mysqli_object_has_property; + mysqli_object_handlers.get_debug_info = mysqli_object_get_debug_info; zend_u_hash_init(&classes, 0, NULL, NULL, 1, 1); @@ -628,6 +737,7 @@ PHP_MINIT_FUNCTION(mysqli) ce = mysqli_driver_class_entry; zend_u_hash_init(&mysqli_driver_properties, 0, NULL, NULL, 1, 1); MYSQLI_ADD_PROPERTIES(&mysqli_driver_properties, mysqli_driver_property_entries); + MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_driver_property_info_entries); zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_driver_properties, sizeof(mysqli_driver_properties), NULL); ce->ce_flags |= ZEND_ACC_FINAL_CLASS; @@ -635,6 +745,7 @@ PHP_MINIT_FUNCTION(mysqli) ce = mysqli_link_class_entry; zend_u_hash_init(&mysqli_link_properties, 0, NULL, NULL, 1, 1); MYSQLI_ADD_PROPERTIES(&mysqli_link_properties, mysqli_link_property_entries); + MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_link_property_info_entries); zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_link_properties, sizeof(mysqli_link_properties), NULL); REGISTER_MYSQLI_CLASS_ENTRY("mysqli_warning", mysqli_warning_class_entry, mysqli_warning_methods); @@ -642,18 +753,21 @@ PHP_MINIT_FUNCTION(mysqli) ce->ce_flags |= ZEND_ACC_FINAL_CLASS | ZEND_ACC_PROTECTED; zend_u_hash_init(&mysqli_warning_properties, 0, NULL, NULL, 1, 1); MYSQLI_ADD_PROPERTIES(&mysqli_warning_properties, mysqli_warning_property_entries); + MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_warning_property_info_entries); zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_warning_properties, sizeof(mysqli_warning_properties), NULL); REGISTER_MYSQLI_CLASS_ENTRY("mysqli_result", mysqli_result_class_entry, mysqli_result_methods); ce = mysqli_result_class_entry; zend_u_hash_init(&mysqli_result_properties, 0, NULL, NULL, 1, 1); MYSQLI_ADD_PROPERTIES(&mysqli_result_properties, mysqli_result_property_entries); + MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_result_property_info_entries); zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_result_properties, sizeof(mysqli_result_properties), NULL); REGISTER_MYSQLI_CLASS_ENTRY("mysqli_stmt", mysqli_stmt_class_entry, mysqli_stmt_methods); ce = mysqli_stmt_class_entry; zend_u_hash_init(&mysqli_stmt_properties, 0, NULL, NULL, 1, 1); MYSQLI_ADD_PROPERTIES(&mysqli_stmt_properties, mysqli_stmt_property_entries); + MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_stmt_property_info_entries); zend_u_hash_add(&classes, ZEND_STR_TYPE, ce->name, ce->name_length+1, &mysqli_stmt_properties, sizeof(mysqli_stmt_properties), NULL); @@ -852,6 +966,8 @@ PHP_RINIT_FUNCTION(mysqli) */ PHP_RSHUTDOWN_FUNCTION(mysqli) { + /* check persistent connections, move used to free */ + #if !defined(MYSQLI_USE_MYSQLND) && defined(ZTS) && MYSQL_VERSION_ID >= 40000 mysql_thread_end(); #endif @@ -877,16 +993,16 @@ PHP_MINFO_FUNCTION(mysqli) php_info_print_table_start(); php_info_print_table_header(2, "MysqlI Support", "enabled"); php_info_print_table_row(2, "Client API library version", mysql_get_client_info()); -#if !defined(MYSQLI_USE_MYSQLND) - php_info_print_table_row(2, "Client API header version", MYSQL_SERVER_VERSION); - php_info_print_table_row(2, "MYSQLI_SOCKET", MYSQL_UNIX_ADDR); -#else snprintf(buf, sizeof(buf), "%ld", MyG(num_active_persistent)); php_info_print_table_row(2, "Active Persistent Links", buf); snprintf(buf, sizeof(buf), "%ld", MyG(num_inactive_persistent)); php_info_print_table_row(2, "Inactive Persistent Links", buf); snprintf(buf, sizeof(buf), "%ld", MyG(num_links)); php_info_print_table_row(2, "Active Links", buf); +#if !defined(MYSQLI_USE_MYSQLND) + php_info_print_table_row(2, "Client API header version", MYSQL_SERVER_VERSION); + php_info_print_table_row(2, "MYSQLI_SOCKET", MYSQL_UNIX_ADDR); +#else { zval values; @@ -912,12 +1028,12 @@ Parameters: object -> mysqli_stmt_init object, query -> mysqli_prepare */ -ZEND_FUNCTION(mysqli_stmt_construct) +PHP_FUNCTION(mysqli_stmt_construct) { MY_MYSQL *mysql; - zval *mysql_link; + zval *mysql_link; MY_STMT *stmt; - MYSQLI_RESOURCE *mysqli_resource; + MYSQLI_RESOURCE *mysqli_resource; char *statement; int statement_len; @@ -968,12 +1084,12 @@ constructor for result object. Parameters: object [, mode] -> mysqli_store/use_result */ -ZEND_FUNCTION(mysqli_result_construct) +PHP_FUNCTION(mysqli_result_construct) { MY_MYSQL *mysql; MYSQL_RES *result = NULL; zval *mysql_link; - MYSQLI_RESOURCE *mysqli_resource; + MYSQLI_RESOURCE *mysqli_resource; long resmode = MYSQLI_STORE_RESULT; switch (ZEND_NUM_ARGS()) { @@ -1018,6 +1134,7 @@ ZEND_FUNCTION(mysqli_result_construct) mysqli_resource->status = MYSQLI_STATUS_VALID; ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource; + } /* }}} */ @@ -1089,6 +1206,11 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags RETURN_NULL(); } + /* + It's needed to call fetch_fields because we need info whether + the field is binary. In 5_3 this is not needed as the latter + doesn't know about Unicode. + */ fields = mysql_fetch_fields(result); array_init(return_value); @@ -1215,21 +1337,9 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags } /* }}} */ -/* {{{ php_mysqli_set_error - */ -PHP_MYSQLI_API void php_mysqli_set_error(long mysql_errno, char *mysql_err TSRMLS_DC) -{ - MyG(error_no) = mysql_errno; - if (MyG(error_msg)) { - efree(MyG(error_msg)); - } - MyG(error_msg) = estrdup(mysql_err); -} -/* }}} */ #if !defined(MYSQLI_USE_MYSQLND) - #define ALLOC_CALLBACK_ARGS(a, b, c)\ if (c) {\ a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\ @@ -1249,27 +1359,14 @@ if (a) {\ } #define LOCAL_INFILE_ERROR_MSG(source,dest)\ -memset(source, 0, LOCAL_INFILE_ERROR_LEN);\ -memcpy(source, dest, MIN(strlen(dest), LOCAL_INFILE_ERROR_LEN-1));\ -php_error_docref(NULL TSRMLS_CC, E_WARNING, dest); - + memset(source, 0, LOCAL_INFILE_ERROR_LEN);\ + memcpy(source, dest, MIN(strlen(dest), LOCAL_INFILE_ERROR_LEN-1));\ + php_error_docref(NULL TSRMLS_CC, E_WARNING, dest); -/* {{{ void php_set_local_infile_handler_default -*/ -void php_set_local_infile_handler_default(MY_MYSQL *mysql) { - /* register internal callback functions */ - mysql_set_local_infile_handler(mysql->mysql, &php_local_infile_init, &php_local_infile_read, - &php_local_infile_end, &php_local_infile_error, (void *)mysql); - if (mysql->li_read) { - zval_ptr_dtor(&mysql->li_read); - mysql->li_read = NULL; - } -} -/* }}} */ /* {{{ php_local_infile_init */ -int php_local_infile_init(void **ptr, const char *filename, void *userdata) +static int php_local_infile_init(void **ptr, const char *filename, void *userdata) { mysqli_local_infile *data; MY_MYSQL *mysql; @@ -1309,7 +1406,7 @@ int php_local_infile_init(void **ptr, const char *filename, void *userdata) /* }}} */ /* {{{ int php_local_infile_read */ -int php_local_infile_read(void *ptr, char *buf, uint buf_len) +static int php_local_infile_read(void *ptr, char *buf, uint buf_len) { mysqli_local_infile *data; MY_MYSQL *mysql; @@ -1327,7 +1424,7 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len) /* default processing */ if (!mysql->li_read) { - int count= (int)php_stream_read(mysql->li_stream, buf, buf_len); + int count = (int)php_stream_read(mysql->li_stream, buf, buf_len); if (count < 0) { LOCAL_INFILE_ERROR_MSG(data->error_msg, ER(2)); @@ -1337,7 +1434,7 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len) } ALLOC_CALLBACK_ARGS(callback_args, 1, argc); - + /* set parameters: filepointer, buffer, buffer_len, errormsg */ MAKE_STD_ZVAL(fp); @@ -1398,7 +1495,7 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len) /* {{{ php_local_infile_error */ -int php_local_infile_error(void *ptr, char *error_msg, uint error_msg_len) +static int php_local_infile_error(void *ptr, char *error_msg, uint error_msg_len) { mysqli_local_infile *data = (mysqli_local_infile *) ptr; @@ -1413,7 +1510,7 @@ int php_local_infile_error(void *ptr, char *error_msg, uint error_msg_len) /* {{{ php_local_infile_end */ -void php_local_infile_end(void *ptr) +static void php_local_infile_end(void *ptr) { mysqli_local_infile *data; MY_MYSQL *mysql; @@ -1428,6 +1525,7 @@ void php_local_infile_end(void *ptr) } return; } + if (mysql->li_stream) { php_stream_close(mysql->li_stream); } @@ -1435,6 +1533,20 @@ void php_local_infile_end(void *ptr) return; } /* }}} */ + + +/* {{{ void php_set_local_infile_handler_default +*/ +void php_set_local_infile_handler_default(MY_MYSQL *mysql) { + /* register internal callback functions */ + mysql_set_local_infile_handler(mysql->mysql, &php_local_infile_init, &php_local_infile_read, + &php_local_infile_end, &php_local_infile_error, (void *)mysql); + if (mysql->li_read) { + zval_ptr_dtor(&mysql->li_read); + mysql->li_read = NULL; + } +} +/* }}} */ #endif /* |