summaryrefslogtreecommitdiff
path: root/ext/mysqli/mysqli.c
diff options
context:
space:
mode:
authorAndrey Hristov <andrey@php.net>2008-03-18 16:58:43 +0000
committerAndrey Hristov <andrey@php.net>2008-03-18 16:58:43 +0000
commite53f44b9bd98c11517f52b737ed220f4521c0871 (patch)
tree3fc6f8172a86c2aa9fadc47112ed4b01d6c688e4 /ext/mysqli/mysqli.c
parentda591e8eca232ee7541bbb1dbf5c3be6f32ba284 (diff)
downloadphp-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.c224
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
/*