1 /*
2   +----------------------------------------------------------------------+
3   | Copyright (c) The PHP Group                                          |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 3.01 of the PHP license,      |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | http://www.php.net/license/3_01.txt                                  |
9   | If you did not receive a copy of the PHP license and are unable to   |
10   | obtain it through the world-wide-web, please send a note to          |
11   | license@php.net so we can mail you a copy immediately.               |
12   +----------------------------------------------------------------------+
13   | Authors: Georg Richter <georg@php.net>                               |
14   |          Andrey Hristov <andrey@php.net>                             |
15   |          Ulf Wendel <uw@php.net>                                     |
16   +----------------------------------------------------------------------+
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #include <signal.h>
24 
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "ext/standard/php_string.h"
29 #include "php_mysqli.h"
30 #include "php_mysqli_structs.h"
31 #include "mysqli_priv.h"
32 #include "zend_exceptions.h"
33 #include "ext/spl/spl_exceptions.h"
34 #include "zend_interfaces.h"
35 #include "mysqli_arginfo.h"
36 
37 ZEND_DECLARE_MODULE_GLOBALS(mysqli)
38 static PHP_GINIT_FUNCTION(mysqli);
39 
40 #define MYSQLI_ADD_PROPERTIES(a, b) \
41 { \
42 	int i = 0; \
43 	while (b[i].pname != NULL) { \
44 		mysqli_add_property((a), (b)[i].pname, (b)[i].pname_length, \
45 							(mysqli_read_t)(b)[i].r_func, (mysqli_write_t)(b)[i].w_func); \
46 		i++; \
47 	} \
48 }
49 
50 #define ERROR_ARG_POS(arg_num) (getThis() ? (arg_num-1) : (arg_num))
51 
52 static HashTable classes;
53 static zend_object_handlers mysqli_object_handlers;
54 static zend_object_handlers mysqli_object_driver_handlers;
55 static zend_object_handlers mysqli_object_link_handlers;
56 static zend_object_handlers mysqli_object_result_handlers;
57 static zend_object_handlers mysqli_object_stmt_handlers;
58 static zend_object_handlers mysqli_object_warning_handlers;
59 static HashTable mysqli_driver_properties;
60 static HashTable mysqli_link_properties;
61 static HashTable mysqli_result_properties;
62 static HashTable mysqli_stmt_properties;
63 static HashTable mysqli_warning_properties;
64 
65 zend_class_entry *mysqli_link_class_entry;
66 zend_class_entry *mysqli_stmt_class_entry;
67 zend_class_entry *mysqli_result_class_entry;
68 zend_class_entry *mysqli_driver_class_entry;
69 zend_class_entry *mysqli_warning_class_entry;
70 zend_class_entry *mysqli_exception_class_entry;
71 
72 
73 typedef int (*mysqli_read_t)(mysqli_object *obj, zval *rv, zend_bool quiet);
74 typedef int (*mysqli_write_t)(mysqli_object *obj, zval *newval);
75 
76 typedef struct _mysqli_prop_handler {
77 	zend_string *name;
78 	mysqli_read_t read_func;
79 	mysqli_write_t write_func;
80 } mysqli_prop_handler;
81 
82 static int le_pmysqli;
83 
free_prop_handler(zval * el)84 static void free_prop_handler(zval *el) {
85 	pefree(Z_PTR_P(el), 1);
86 }
87 
88 /* Destructor for mysqli entries in free_links/used_links */
php_mysqli_dtor_p_elements(void * data)89 void php_mysqli_dtor_p_elements(void *data)
90 {
91 	MYSQL *mysql = (MYSQL *)data;
92 	mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT);
93 }
94 
95 
ZEND_RSRC_DTOR_FUNC(php_mysqli_dtor)96 ZEND_RSRC_DTOR_FUNC(php_mysqli_dtor)
97 {
98 	if (res->ptr) {
99 		mysqli_plist_entry *plist = (mysqli_plist_entry *)res->ptr;
100 		zend_ptr_stack_clean(&plist->free_links, php_mysqli_dtor_p_elements, 0);
101 		zend_ptr_stack_destroy(&plist->free_links);
102 		free(plist);
103 	}
104 }
105 
106 
php_le_pmysqli(void)107 int php_le_pmysqli(void)
108 {
109 	return le_pmysqli;
110 }
111 
112 #ifndef MYSQLI_USE_MYSQLND
113 /* {{{ php_free_stmt_bind_buffer */
php_free_stmt_bind_buffer(BIND_BUFFER bbuf,int type)114 void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type)
115 {
116 	unsigned int i;
117 
118 	if (!bbuf.var_cnt) {
119 		return;
120 	}
121 
122 	for (i=0; i < bbuf.var_cnt; i++) {
123 
124 		/* free temporary bind buffer */
125 		if (type == FETCH_RESULT && bbuf.buf[i].val) {
126 			efree(bbuf.buf[i].val);
127 		}
128 
129 		zval_ptr_dtor(&bbuf.vars[i]);
130 	}
131 
132 	if (bbuf.vars) {
133 		efree(bbuf.vars);
134 	}
135 
136 	/*
137 	  Don't free bbuf.is_null for FETCH_RESULT since we have allocated
138 	  is_null and buf in one block so we free only buf, which is the beginning
139 	  of the block. When FETCH_SIMPLE then buf wasn't allocated together with
140 	  buf and we have to free it.
141 	*/
142 	if (type == FETCH_RESULT) {
143 		efree(bbuf.buf);
144 	} else if (type == FETCH_SIMPLE){
145 		efree(bbuf.is_null);
146 	}
147 
148 	bbuf.var_cnt = 0;
149 }
150 /* }}} */
151 #endif
152 
153 /* {{{ php_clear_stmt_bind */
php_clear_stmt_bind(MY_STMT * stmt)154 void php_clear_stmt_bind(MY_STMT *stmt)
155 {
156 	if (stmt->stmt) {
157 		if (mysqli_stmt_close(stmt->stmt, TRUE)) {
158 			php_error_docref(NULL, E_WARNING, "Error occurred while closing statement");
159 			return;
160 		}
161 	}
162 
163 	/*
164 	  mysqlnd keeps track of the binding and has freed its
165 	  structures in stmt_close() above
166 	*/
167 #ifndef MYSQLI_USE_MYSQLND
168 	/* Clean param bind */
169 	php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
170 	/* Clean output bind */
171 	php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
172 
173 	if (!Z_ISUNDEF(stmt->link_handle)) {
174 		zval_ptr_dtor(&stmt->link_handle);
175 	}
176 #endif
177 	if (stmt->query) {
178 		efree(stmt->query);
179 	}
180 	efree(stmt);
181 }
182 /* }}} */
183 
184 /* {{{ php_clear_mysql */
php_clear_mysql(MY_MYSQL * mysql)185 void php_clear_mysql(MY_MYSQL *mysql) {
186 	if (mysql->hash_key) {
187 		zend_string_release_ex(mysql->hash_key, 0);
188 		mysql->hash_key = NULL;
189 	}
190 	if (!Z_ISUNDEF(mysql->li_read)) {
191 		zval_ptr_dtor(&(mysql->li_read));
192 		ZVAL_UNDEF(&mysql->li_read);
193 	}
194 }
195 /* }}} */
196 
197 /* {{{ mysqli_objects_free_storage */
mysqli_objects_free_storage(zend_object * object)198 static void mysqli_objects_free_storage(zend_object	*object)
199 {
200 	mysqli_object 	*intern = php_mysqli_fetch_object(object);
201 	MYSQLI_RESOURCE	*my_res = (MYSQLI_RESOURCE *)intern->ptr;
202 
203 	if (my_res) {
204 		efree(my_res);
205 	}
206 	zend_object_std_dtor(&intern->zo);
207 }
208 /* }}} */
209 
210 /* mysqli_link_free_storage partly doubles the work of PHP_FUNCTION(mysqli_close) */
211 
212 /* {{{ mysqli_link_free_storage */
mysqli_link_free_storage(zend_object * object)213 static void mysqli_link_free_storage(zend_object *object)
214 {
215 	mysqli_object 	*intern = php_mysqli_fetch_object(object);
216 	MYSQLI_RESOURCE	*my_res = (MYSQLI_RESOURCE *)intern->ptr;
217 
218 	if (my_res && my_res->ptr) {
219 		MY_MYSQL *mysql = (MY_MYSQL *)my_res->ptr;
220 		if (mysql->mysql) {
221 			php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, my_res->status);
222 		}
223 		php_clear_mysql(mysql);
224 		efree(mysql);
225 		my_res->status = MYSQLI_STATUS_UNKNOWN;
226 	}
227 	mysqli_objects_free_storage(object);
228 }
229 /* }}} */
230 
231 /* {{{ mysql_driver_free_storage */
mysqli_driver_free_storage(zend_object * object)232 static void mysqli_driver_free_storage(zend_object *object)
233 {
234 	mysqli_objects_free_storage(object);
235 }
236 /* }}} */
237 
238 /* {{{ mysqli_stmt_free_storage */
mysqli_stmt_free_storage(zend_object * object)239 static void mysqli_stmt_free_storage(zend_object *object)
240 {
241 	mysqli_object 	*intern = php_mysqli_fetch_object(object);
242 	MYSQLI_RESOURCE	*my_res = (MYSQLI_RESOURCE *)intern->ptr;
243 
244 	if (my_res && my_res->ptr) {
245 		MY_STMT *stmt = (MY_STMT *)my_res->ptr;
246 		php_clear_stmt_bind(stmt);
247 	}
248 	mysqli_objects_free_storage(object);
249 }
250 /* }}} */
251 
252 /* {{{ mysqli_result_free_storage */
mysqli_result_free_storage(zend_object * object)253 static void mysqli_result_free_storage(zend_object *object)
254 {
255 	mysqli_object 	*intern = php_mysqli_fetch_object(object);
256 	MYSQLI_RESOURCE	*my_res = (MYSQLI_RESOURCE *)intern->ptr;
257 
258 	if (my_res && my_res->ptr) {
259 		mysql_free_result(my_res->ptr);
260 	}
261 	mysqli_objects_free_storage(object);
262 }
263 /* }}} */
264 
265 /* {{{ mysqli_warning_free_storage */
mysqli_warning_free_storage(zend_object * object)266 static void mysqli_warning_free_storage(zend_object *object)
267 {
268 	mysqli_object 	*intern = php_mysqli_fetch_object(object);
269 	MYSQLI_RESOURCE	*my_res = (MYSQLI_RESOURCE *)intern->ptr;
270 
271 	if (my_res && my_res->ptr) {
272 		php_clear_warnings((MYSQLI_WARNING *)my_res->info);
273 		my_res->ptr = NULL;
274 	}
275 	mysqli_objects_free_storage(object);
276 }
277 /* }}} */
278 
279 /* {{{ mysqli_read_na */
mysqli_read_na(mysqli_object * obj,zval * retval,zend_bool quiet)280 static int mysqli_read_na(mysqli_object *obj, zval *retval, zend_bool quiet)
281 {
282 	if (!quiet) {
283 		zend_throw_error(NULL, "Cannot read property");
284 	}
285 
286 	return FAILURE;
287 }
288 /* }}} */
289 
290 /* {{{ mysqli_write_na */
mysqli_write_na(mysqli_object * obj,zval * newval)291 static int mysqli_write_na(mysqli_object *obj, zval *newval)
292 {
293 	zend_throw_error(NULL, "Cannot write property");
294 
295 	return FAILURE;
296 }
297 /* }}} */
298 
299 /* {{{ mysqli_read_property */
mysqli_read_property(zend_object * object,zend_string * name,int type,void ** cache_slot,zval * rv)300 zval *mysqli_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
301 {
302 	zval *retval;
303 	mysqli_object *obj;
304 	mysqli_prop_handler *hnd = NULL;
305 
306 	obj = php_mysqli_fetch_object(object);
307 
308 	if (obj->prop_handler != NULL) {
309 		hnd = zend_hash_find_ptr(obj->prop_handler, name);
310 	}
311 
312 	if (hnd) {
313 		if (hnd->read_func(obj, rv, type == BP_VAR_IS) == SUCCESS) {
314 			retval = rv;
315 		} else {
316 			retval = &EG(uninitialized_zval);
317 		}
318 	} else {
319 		retval = zend_std_read_property(object, name, type, cache_slot, rv);
320 	}
321 
322 	return retval;
323 }
324 /* }}} */
325 
326 /* {{{ mysqli_write_property */
mysqli_write_property(zend_object * object,zend_string * name,zval * value,void ** cache_slot)327 zval *mysqli_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
328 {
329 	mysqli_object *obj;
330 	mysqli_prop_handler *hnd = NULL;
331 
332 	obj = php_mysqli_fetch_object(object);
333 
334 	if (obj->prop_handler != NULL) {
335 		hnd = zend_hash_find_ptr(obj->prop_handler, name);
336 	}
337 
338 	if (hnd) {
339 		hnd->write_func(obj, value);
340 	} else {
341 		value = zend_std_write_property(object, name, value, cache_slot);
342 	}
343 
344 	return value;
345 }
346 /* }}} */
347 
348 /* {{{ void mysqli_add_property(HashTable *h, char *pname, mysqli_read_t r_func, mysqli_write_t w_func) */
mysqli_add_property(HashTable * h,const char * pname,size_t pname_len,mysqli_read_t r_func,mysqli_write_t w_func)349 void mysqli_add_property(HashTable *h, const char *pname, size_t pname_len, mysqli_read_t r_func, mysqli_write_t w_func) {
350 	mysqli_prop_handler	p;
351 
352 	p.name = zend_string_init_interned(pname, pname_len, 1);
353 	p.read_func = (r_func) ? r_func : mysqli_read_na;
354 	p.write_func = (w_func) ? w_func : mysqli_write_na;
355 	zend_hash_add_mem(h, p.name, &p, sizeof(mysqli_prop_handler));
356 	zend_string_release_ex(p.name, 1);
357 }
358 /* }}} */
359 
mysqli_object_has_property(zend_object * object,zend_string * name,int has_set_exists,void ** cache_slot)360 static int mysqli_object_has_property(zend_object *object, zend_string *name, int has_set_exists, void **cache_slot) /* {{{ */
361 {
362 	mysqli_object *obj = php_mysqli_fetch_object(object);
363 	mysqli_prop_handler	*p;
364 	int ret = 0;
365 
366 	if ((p = zend_hash_find_ptr(obj->prop_handler, name)) != NULL) {
367 		switch (has_set_exists) {
368 			case ZEND_PROPERTY_EXISTS:
369 				ret = 1;
370 				break;
371 			case ZEND_PROPERTY_NOT_EMPTY: {
372 				zval rv;
373 				zval *value = mysqli_read_property(object, name, BP_VAR_IS, cache_slot, &rv);
374 				if (value != &EG(uninitialized_zval)) {
375 					convert_to_boolean(value);
376 					ret = Z_TYPE_P(value) == IS_TRUE ? 1 : 0;
377 				}
378 				break;
379 			}
380 			case ZEND_PROPERTY_ISSET: {
381 				zval rv;
382 				zval *value = mysqli_read_property(object, name, BP_VAR_IS, cache_slot, &rv);
383 				if (value != &EG(uninitialized_zval)) {
384 					ret = Z_TYPE_P(value) != IS_NULL? 1 : 0;
385 					zval_ptr_dtor(value);
386 				}
387 				break;
388 			}
389 			EMPTY_SWITCH_DEFAULT_CASE();
390 		}
391 	} else {
392 		ret = zend_std_has_property(object, name, has_set_exists, cache_slot);
393 	}
394 
395 	return ret;
396 } /* }}} */
397 
mysqli_object_get_debug_info(zend_object * object,int * is_temp)398 HashTable *mysqli_object_get_debug_info(zend_object *object, int *is_temp)
399 {
400 	mysqli_object *obj = php_mysqli_fetch_object(object);
401 	HashTable *retval, *props = obj->prop_handler;
402 	mysqli_prop_handler *entry;
403 
404 	retval = zend_new_array(zend_hash_num_elements(props) + 1);
405 
406 	ZEND_HASH_FOREACH_PTR(props, entry) {
407 		zval rv;
408 		zval *value;
409 
410 		value = mysqli_read_property(object, entry->name, BP_VAR_IS, 0, &rv);
411 		if (value != &EG(uninitialized_zval)) {
412 			zend_hash_add(retval, entry->name, value);
413 		}
414 	} ZEND_HASH_FOREACH_END();
415 
416 	*is_temp = 1;
417 	return retval;
418 }
419 
420 /* {{{ mysqli_objects_new */
mysqli_objects_new(zend_class_entry * class_type)421 PHP_MYSQLI_EXPORT(zend_object *) mysqli_objects_new(zend_class_entry *class_type)
422 {
423 	mysqli_object *intern;
424 	zend_class_entry *mysqli_base_class;
425 	zend_object_handlers *handlers;
426 
427 	intern = zend_object_alloc(sizeof(mysqli_object), class_type);
428 
429 	mysqli_base_class = class_type;
430 	while (mysqli_base_class->type != ZEND_INTERNAL_CLASS &&
431 		   mysqli_base_class->parent != NULL) {
432 		mysqli_base_class = mysqli_base_class->parent;
433 	}
434 	intern->prop_handler = zend_hash_find_ptr(&classes, mysqli_base_class->name);
435 
436 	zend_object_std_init(&intern->zo, class_type);
437 	object_properties_init(&intern->zo, class_type);
438 
439 	/* link object */
440 	if (instanceof_function(class_type, mysqli_link_class_entry)) {
441 		handlers = &mysqli_object_link_handlers;
442 	} else if (instanceof_function(class_type, mysqli_driver_class_entry)) { /* driver object */
443 		handlers = &mysqli_object_driver_handlers;
444 	} else if (instanceof_function(class_type, mysqli_stmt_class_entry)) { /* stmt object */
445 		handlers = &mysqli_object_stmt_handlers;
446 	} else if (instanceof_function(class_type, mysqli_result_class_entry)) { /* result object */
447 		handlers = &mysqli_object_result_handlers;
448 	} else if (instanceof_function(class_type, mysqli_warning_class_entry)) { /* warning object */
449 		handlers = &mysqli_object_warning_handlers;
450 	} else {
451 		handlers = &mysqli_object_handlers;
452 	}
453 
454 	intern->zo.handlers = handlers;
455 
456 	return &intern->zo;
457 }
458 /* }}} */
459 
460 #ifdef MYSQLI_USE_MYSQLND
461 #include "ext/mysqlnd/mysqlnd_reverse_api.h"
mysqli_convert_zv_to_mysqlnd(zval * zv)462 static MYSQLND *mysqli_convert_zv_to_mysqlnd(zval * zv)
463 {
464 	if (Z_TYPE_P(zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv), mysqli_link_class_entry)) {
465 		MY_MYSQL *mysql;
466 		MYSQLI_RESOURCE  *my_res;
467 		mysqli_object *intern = Z_MYSQLI_P(zv);
468 		if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
469 			/* We know that we have a mysqli object, so this failure should be emitted */
470 			zend_throw_error(NULL, "%s object is already closed", ZSTR_VAL(intern->zo.ce->name));
471 			return NULL;
472 		}
473 		mysql = (MY_MYSQL *)(my_res->ptr);
474 		return mysql ? mysql->mysql : NULL;
475 	}
476 	return NULL;
477 }
478 
479 static const MYSQLND_REVERSE_API mysqli_reverse_api = {
480 	&mysqli_module_entry,
481 	mysqli_convert_zv_to_mysqlnd
482 };
483 #endif
484 
485 /* {{{ PHP_INI_BEGIN */
486 PHP_INI_BEGIN()
487 	STD_PHP_INI_ENTRY_EX("mysqli.max_links",			"-1",	PHP_INI_SYSTEM,		OnUpdateLong,		max_links,			zend_mysqli_globals,		mysqli_globals, display_link_numbers)
488 	STD_PHP_INI_ENTRY_EX("mysqli.max_persistent",		"-1",	PHP_INI_SYSTEM,		OnUpdateLong,		max_persistent,		zend_mysqli_globals,		mysqli_globals,	display_link_numbers)
489 	STD_PHP_INI_BOOLEAN("mysqli.allow_persistent",		"1",	PHP_INI_SYSTEM,		OnUpdateLong,		allow_persistent,	zend_mysqli_globals,		mysqli_globals)
490 	STD_PHP_INI_BOOLEAN("mysqli.rollback_on_cached_plink",	"0",PHP_INI_SYSTEM,		OnUpdateBool,		rollback_on_cached_plink,	zend_mysqli_globals,		mysqli_globals)
491 	STD_PHP_INI_ENTRY("mysqli.default_host",			NULL,	PHP_INI_ALL,		OnUpdateString,		default_host,		zend_mysqli_globals,		mysqli_globals)
492 	STD_PHP_INI_ENTRY("mysqli.default_user",			NULL,	PHP_INI_ALL,		OnUpdateString,		default_user,		zend_mysqli_globals,		mysqli_globals)
493 	STD_PHP_INI_ENTRY("mysqli.default_pw",				NULL,	PHP_INI_ALL,		OnUpdateString,		default_pw,			zend_mysqli_globals,		mysqli_globals)
494 	STD_PHP_INI_ENTRY("mysqli.default_port",			"3306",	PHP_INI_ALL,		OnUpdateLong,		default_port,		zend_mysqli_globals,		mysqli_globals)
495 #ifdef PHP_MYSQL_UNIX_SOCK_ADDR
496 	STD_PHP_INI_ENTRY("mysqli.default_socket",			MYSQL_UNIX_ADDR,PHP_INI_ALL,OnUpdateStringUnempty,	default_socket,	zend_mysqli_globals,		mysqli_globals)
497 #else
498 	STD_PHP_INI_ENTRY("mysqli.default_socket",			NULL,	PHP_INI_ALL,		OnUpdateStringUnempty,	default_socket,	zend_mysqli_globals,		mysqli_globals)
499 #endif
500 	STD_PHP_INI_BOOLEAN("mysqli.reconnect",				"0",	PHP_INI_SYSTEM,		OnUpdateLong,		reconnect,			zend_mysqli_globals,		mysqli_globals)
501 	STD_PHP_INI_BOOLEAN("mysqli.allow_local_infile",	"0",	PHP_INI_SYSTEM,		OnUpdateLong,		allow_local_infile,	zend_mysqli_globals,		mysqli_globals)
PHP_INI_END()502 PHP_INI_END()
503 /* }}} */
504 
505 /* {{{ PHP_GINIT_FUNCTION */
506 static PHP_GINIT_FUNCTION(mysqli)
507 {
508 #if defined(COMPILE_DL_MYSQLI) && defined(ZTS)
509 	ZEND_TSRMLS_CACHE_UPDATE();
510 #endif
511 	mysqli_globals->num_links = 0;
512 	mysqli_globals->num_active_persistent = 0;
513 	mysqli_globals->num_inactive_persistent = 0;
514 	mysqli_globals->max_links = -1;
515 	mysqli_globals->max_persistent = -1;
516 	mysqli_globals->allow_persistent = 1;
517 	mysqli_globals->default_port = 0;
518 	mysqli_globals->default_host = NULL;
519 	mysqli_globals->default_user = NULL;
520 	mysqli_globals->default_pw = NULL;
521 	mysqli_globals->default_socket = NULL;
522 	mysqli_globals->reconnect = 0;
523 	mysqli_globals->report_mode = 0;
524 	mysqli_globals->report_ht = 0;
525 	mysqli_globals->allow_local_infile = 0;
526 	mysqli_globals->rollback_on_cached_plink = FALSE;
527 }
528 /* }}} */
529 
530 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(mysqli)531 PHP_MINIT_FUNCTION(mysqli)
532 {
533 	zend_class_entry *ce,cex;
534 
535 	REGISTER_INI_ENTRIES();
536 #ifndef MYSQLI_USE_MYSQLND
537 	if (mysql_server_init(0, NULL, NULL)) {
538 		return FAILURE;
539 	}
540 #endif
541 
542 	memcpy(&mysqli_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
543 	mysqli_object_handlers.offset = XtOffsetOf(mysqli_object, zo);
544 	mysqli_object_handlers.free_obj = mysqli_objects_free_storage;
545 	mysqli_object_handlers.clone_obj = NULL;
546 	mysqli_object_handlers.read_property = mysqli_read_property;
547 	mysqli_object_handlers.write_property = mysqli_write_property;
548 	mysqli_object_handlers.has_property = mysqli_object_has_property;
549 	mysqli_object_handlers.get_debug_info = mysqli_object_get_debug_info;
550 	memcpy(&mysqli_object_driver_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
551 	mysqli_object_driver_handlers.free_obj = mysqli_driver_free_storage;
552 	memcpy(&mysqli_object_link_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
553 	mysqli_object_link_handlers.free_obj = mysqli_link_free_storage;
554 	memcpy(&mysqli_object_result_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
555 	mysqli_object_result_handlers.free_obj = mysqli_result_free_storage;
556 	memcpy(&mysqli_object_stmt_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
557 	mysqli_object_stmt_handlers.free_obj = mysqli_stmt_free_storage;
558 	memcpy(&mysqli_object_warning_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
559 	mysqli_object_warning_handlers.free_obj = mysqli_warning_free_storage;
560 
561 	zend_hash_init(&classes, 0, NULL, NULL, 1);
562 
563 	/* persistent connections */
564 	le_pmysqli = zend_register_list_destructors_ex(NULL, php_mysqli_dtor,
565 		"MySqli persistent connection", module_number);
566 
567 	INIT_CLASS_ENTRY(cex, "mysqli_sql_exception", class_mysqli_sql_exception_methods);
568 	mysqli_exception_class_entry = zend_register_internal_class_ex(&cex, spl_ce_RuntimeException);
569 	mysqli_exception_class_entry->ce_flags |= ZEND_ACC_FINAL;
570 	zend_declare_property_long(mysqli_exception_class_entry, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED);
571 	zend_declare_property_string(mysqli_exception_class_entry, "sqlstate", sizeof("sqlstate")-1, "00000", ZEND_ACC_PROTECTED);
572 
573 	REGISTER_MYSQLI_CLASS_ENTRY("mysqli_driver", mysqli_driver_class_entry, class_mysqli_driver_methods);
574 	ce = mysqli_driver_class_entry;
575 	zend_hash_init(&mysqli_driver_properties, 0, NULL, free_prop_handler, 1);
576 	MYSQLI_ADD_PROPERTIES(&mysqli_driver_properties, mysqli_driver_property_entries);
577 	zend_declare_property_null(ce, "client_info", 		sizeof("client_info") - 1, ZEND_ACC_PUBLIC);
578 	zend_declare_property_null(ce, "client_version", 	sizeof("client_version") - 1, ZEND_ACC_PUBLIC);
579 	zend_declare_property_null(ce, "driver_version", 	sizeof("driver_version") - 1, ZEND_ACC_PUBLIC);
580 	zend_declare_property_null(ce, "reconnect",			sizeof("reconnect") - 1, ZEND_ACC_PUBLIC);
581 	zend_declare_property_null(ce, "report_mode", 		sizeof("report_mode") - 1, ZEND_ACC_PUBLIC);
582 	ce->ce_flags |= ZEND_ACC_FINAL;
583 	zend_hash_add_ptr(&classes, ce->name, &mysqli_driver_properties);
584 
585 	REGISTER_MYSQLI_CLASS_ENTRY("mysqli", mysqli_link_class_entry, class_mysqli_methods);
586 	ce = mysqli_link_class_entry;
587 	zend_hash_init(&mysqli_link_properties, 0, NULL, free_prop_handler, 1);
588 	MYSQLI_ADD_PROPERTIES(&mysqli_link_properties, mysqli_link_property_entries);
589 	zend_declare_property_null(ce, "affected_rows",		sizeof("affected_rows") - 1, ZEND_ACC_PUBLIC);
590 	zend_declare_property_null(ce, "client_info", 		sizeof("client_info") - 1, ZEND_ACC_PUBLIC);
591 	zend_declare_property_null(ce, "client_version", 	sizeof("client_version") - 1, ZEND_ACC_PUBLIC);
592 	zend_declare_property_null(ce, "connect_errno",		sizeof("connect_errno") - 1, ZEND_ACC_PUBLIC);
593 	zend_declare_property_null(ce, "connect_error",		sizeof("connect_error") - 1, ZEND_ACC_PUBLIC);
594 	zend_declare_property_null(ce, "errno",				sizeof("errno") - 1, ZEND_ACC_PUBLIC);
595 	zend_declare_property_null(ce, "error",				sizeof("error") - 1, ZEND_ACC_PUBLIC);
596 	zend_declare_property_null(ce, "error_list", 		sizeof("error_list") - 1, ZEND_ACC_PUBLIC);
597 	zend_declare_property_null(ce, "field_count", 		sizeof("field_count") - 1, ZEND_ACC_PUBLIC);
598 	zend_declare_property_null(ce, "host_info", 		sizeof("host_info") - 1, ZEND_ACC_PUBLIC);
599 	zend_declare_property_null(ce, "info", 				sizeof("info") - 1, ZEND_ACC_PUBLIC);
600 	zend_declare_property_null(ce, "insert_id",			sizeof("insert_id") - 1, ZEND_ACC_PUBLIC);
601 	zend_declare_property_null(ce, "server_info", 		sizeof("server_info") - 1, ZEND_ACC_PUBLIC);
602 	zend_declare_property_null(ce, "server_version", 	sizeof("server_version") - 1, ZEND_ACC_PUBLIC);
603 	zend_declare_property_null(ce, "sqlstate", 			sizeof("sqlstate") - 1, ZEND_ACC_PUBLIC);
604 	zend_declare_property_null(ce, "protocol_version", 	sizeof("protocol_version") - 1,  ZEND_ACC_PUBLIC);
605 	zend_declare_property_null(ce, "thread_id",			sizeof("thread_id") - 1, ZEND_ACC_PUBLIC);
606 	zend_declare_property_null(ce, "warning_count",		sizeof("warning_count") - 1, ZEND_ACC_PUBLIC);
607 	zend_hash_add_ptr(&classes, ce->name, &mysqli_link_properties);
608 
609 	REGISTER_MYSQLI_CLASS_ENTRY("mysqli_warning", mysqli_warning_class_entry, class_mysqli_warning_methods);
610 	ce = mysqli_warning_class_entry;
611 	ce->ce_flags |= ZEND_ACC_FINAL;
612 	zend_hash_init(&mysqli_warning_properties, 0, NULL, free_prop_handler, 1);
613 	MYSQLI_ADD_PROPERTIES(&mysqli_warning_properties, mysqli_warning_property_entries);
614 	zend_declare_property_null(ce, "message", 	sizeof("message") - 1, ZEND_ACC_PUBLIC);
615 	zend_declare_property_null(ce, "sqlstate", 	sizeof("sqlstate") - 1, ZEND_ACC_PUBLIC);
616 	zend_declare_property_null(ce, "errno",		sizeof("errno") - 1, ZEND_ACC_PUBLIC);
617 	zend_hash_add_ptr(&classes, ce->name, &mysqli_warning_properties);
618 
619 	REGISTER_MYSQLI_CLASS_ENTRY("mysqli_result", mysqli_result_class_entry, class_mysqli_result_methods);
620 	ce = mysqli_result_class_entry;
621 	zend_hash_init(&mysqli_result_properties, 0, NULL, free_prop_handler, 1);
622 	MYSQLI_ADD_PROPERTIES(&mysqli_result_properties, mysqli_result_property_entries);
623 	zend_declare_property_null(ce, "current_field",	sizeof("current_field") - 1,ZEND_ACC_PUBLIC);
624 	zend_declare_property_null(ce, "field_count",	sizeof("field_count") - 1, ZEND_ACC_PUBLIC);
625 	zend_declare_property_null(ce, "lengths",		sizeof("lengths") - 1, ZEND_ACC_PUBLIC);
626 	zend_declare_property_null(ce, "num_rows",		sizeof("num_rows") - 1, ZEND_ACC_PUBLIC);
627 	zend_declare_property_null(ce, "type",			sizeof("type") - 1, ZEND_ACC_PUBLIC);
628 	mysqli_result_class_entry->get_iterator = php_mysqli_result_get_iterator;
629 	zend_class_implements(mysqli_result_class_entry, 1, zend_ce_aggregate);
630 	zend_hash_add_ptr(&classes, ce->name, &mysqli_result_properties);
631 
632 	REGISTER_MYSQLI_CLASS_ENTRY("mysqli_stmt", mysqli_stmt_class_entry, class_mysqli_stmt_methods);
633 	ce = mysqli_stmt_class_entry;
634 	zend_hash_init(&mysqli_stmt_properties, 0, NULL, free_prop_handler, 1);
635 	MYSQLI_ADD_PROPERTIES(&mysqli_stmt_properties, mysqli_stmt_property_entries);
636 	zend_declare_property_null(ce, "affected_rows", sizeof("affected_rows") - 1, ZEND_ACC_PUBLIC);
637 	zend_declare_property_null(ce, "insert_id",		sizeof("insert_id") - 1, ZEND_ACC_PUBLIC);
638 	zend_declare_property_null(ce, "num_rows",		sizeof("num_rows") - 1, ZEND_ACC_PUBLIC);
639 	zend_declare_property_null(ce, "param_count",	sizeof("param_count") - 1, ZEND_ACC_PUBLIC);
640 	zend_declare_property_null(ce, "field_count",	sizeof("field_count") - 1, ZEND_ACC_PUBLIC);
641 	zend_declare_property_null(ce, "errno",			sizeof("errno") - 1, ZEND_ACC_PUBLIC);
642 	zend_declare_property_null(ce, "error",			sizeof("error") - 1, ZEND_ACC_PUBLIC);
643 	zend_declare_property_null(ce, "error_list",	sizeof("error_list") - 1, ZEND_ACC_PUBLIC);
644 	zend_declare_property_null(ce, "sqlstate",		sizeof("sqlstate") - 1, ZEND_ACC_PUBLIC);
645 	zend_declare_property_null(ce, "id",			sizeof("id") - 1, ZEND_ACC_PUBLIC);
646 	zend_hash_add_ptr(&classes, ce->name, &mysqli_stmt_properties);
647 
648 	/* mysqli_options */
649 	REGISTER_LONG_CONSTANT("MYSQLI_READ_DEFAULT_GROUP", MYSQL_READ_DEFAULT_GROUP, CONST_CS | CONST_PERSISTENT);
650 	REGISTER_LONG_CONSTANT("MYSQLI_READ_DEFAULT_FILE", MYSQL_READ_DEFAULT_FILE, CONST_CS | CONST_PERSISTENT);
651 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_CONNECT_TIMEOUT", MYSQL_OPT_CONNECT_TIMEOUT, CONST_CS | CONST_PERSISTENT);
652 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_LOCAL_INFILE", MYSQL_OPT_LOCAL_INFILE, CONST_CS | CONST_PERSISTENT);
653 	REGISTER_LONG_CONSTANT("MYSQLI_INIT_COMMAND", MYSQL_INIT_COMMAND, CONST_CS | CONST_PERSISTENT);
654 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_READ_TIMEOUT", MYSQL_OPT_READ_TIMEOUT, CONST_CS | CONST_PERSISTENT);
655 #ifdef MYSQLI_USE_MYSQLND
656 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_CMD_BUFFER_SIZE", MYSQLND_OPT_NET_CMD_BUFFER_SIZE, CONST_CS | CONST_PERSISTENT);
657 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_READ_BUFFER_SIZE", MYSQLND_OPT_NET_READ_BUFFER_SIZE, CONST_CS | CONST_PERSISTENT);
658 #endif
659 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
660 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_INT_AND_FLOAT_NATIVE", MYSQLND_OPT_INT_AND_FLOAT_NATIVE, CONST_CS | CONST_PERSISTENT);
661 #endif
662 #if MYSQL_VERSION_ID < 80000 || MYSQL_VERSION_ID >= 100000 || defined(MYSQLI_USE_MYSQLND)
663 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_SSL_VERIFY_SERVER_CERT", MYSQL_OPT_SSL_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
664 #endif
665 
666 #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
667 	REGISTER_LONG_CONSTANT("MYSQLI_SERVER_PUBLIC_KEY", MYSQL_SERVER_PUBLIC_KEY, CONST_CS | CONST_PERSISTENT);
668 #endif
669 
670 	/* mysqli_real_connect flags */
671 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL", CLIENT_SSL, CONST_CS | CONST_PERSISTENT);
672 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_COMPRESS",CLIENT_COMPRESS, CONST_CS | CONST_PERSISTENT);
673 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_INTERACTIVE", CLIENT_INTERACTIVE, CONST_CS | CONST_PERSISTENT);
674 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_IGNORE_SPACE", CLIENT_IGNORE_SPACE, CONST_CS | CONST_PERSISTENT);
675 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_NO_SCHEMA", CLIENT_NO_SCHEMA, CONST_CS | CONST_PERSISTENT);
676 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_FOUND_ROWS", CLIENT_FOUND_ROWS, CONST_CS | CONST_PERSISTENT);
677 #ifdef CLIENT_SSL_VERIFY_SERVER_CERT
678 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT", CLIENT_SSL_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
679 #ifdef MYSQLI_USE_MYSQLND
680 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT", CLIENT_SSL_DONT_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
681 #endif
682 #endif
683 #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
684 	REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS", CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS, CONST_CS | CONST_PERSISTENT);
685 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS", MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, CONST_CS | CONST_PERSISTENT);
686 #endif
687 
688 	/* for mysqli_query */
689 	REGISTER_LONG_CONSTANT("MYSQLI_STORE_RESULT", MYSQLI_STORE_RESULT, CONST_CS | CONST_PERSISTENT);
690 	REGISTER_LONG_CONSTANT("MYSQLI_USE_RESULT", MYSQLI_USE_RESULT, CONST_CS | CONST_PERSISTENT);
691 #if defined (MYSQLI_USE_MYSQLND)
692 	REGISTER_LONG_CONSTANT("MYSQLI_ASYNC", MYSQLI_ASYNC, CONST_CS | CONST_PERSISTENT);
693 	REGISTER_LONG_CONSTANT("MYSQLI_STORE_RESULT_COPY_DATA", MYSQLI_STORE_RESULT_COPY_DATA, CONST_CS | CONST_PERSISTENT);
694 #endif
695 
696 	/* for mysqli_fetch_assoc */
697 	REGISTER_LONG_CONSTANT("MYSQLI_ASSOC", MYSQLI_ASSOC, CONST_CS | CONST_PERSISTENT);
698 	REGISTER_LONG_CONSTANT("MYSQLI_NUM", MYSQLI_NUM, CONST_CS | CONST_PERSISTENT);
699 	REGISTER_LONG_CONSTANT("MYSQLI_BOTH", MYSQLI_BOTH, CONST_CS | CONST_PERSISTENT);
700 
701 	/* for mysqli_stmt_set_attr */
702 	REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH", STMT_ATTR_UPDATE_MAX_LENGTH, CONST_CS | CONST_PERSISTENT);
703 
704 	REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_CURSOR_TYPE", STMT_ATTR_CURSOR_TYPE, CONST_CS | CONST_PERSISTENT);
705 	REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_NO_CURSOR", CURSOR_TYPE_NO_CURSOR, CONST_CS | CONST_PERSISTENT);
706 	REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_READ_ONLY", CURSOR_TYPE_READ_ONLY, CONST_CS | CONST_PERSISTENT);
707 	REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_FOR_UPDATE", CURSOR_TYPE_FOR_UPDATE, CONST_CS | CONST_PERSISTENT);
708 	REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_SCROLLABLE", CURSOR_TYPE_SCROLLABLE, CONST_CS | CONST_PERSISTENT);
709 
710 	REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_PREFETCH_ROWS", STMT_ATTR_PREFETCH_ROWS, CONST_CS | CONST_PERSISTENT);
711 
712 	/* column information */
713 	REGISTER_LONG_CONSTANT("MYSQLI_NOT_NULL_FLAG", NOT_NULL_FLAG, CONST_CS | CONST_PERSISTENT);
714 	REGISTER_LONG_CONSTANT("MYSQLI_PRI_KEY_FLAG", PRI_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
715 	REGISTER_LONG_CONSTANT("MYSQLI_UNIQUE_KEY_FLAG", UNIQUE_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
716 	REGISTER_LONG_CONSTANT("MYSQLI_MULTIPLE_KEY_FLAG", MULTIPLE_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
717 	REGISTER_LONG_CONSTANT("MYSQLI_BLOB_FLAG", BLOB_FLAG, CONST_CS | CONST_PERSISTENT);
718 	REGISTER_LONG_CONSTANT("MYSQLI_UNSIGNED_FLAG", UNSIGNED_FLAG, CONST_CS | CONST_PERSISTENT);
719 	REGISTER_LONG_CONSTANT("MYSQLI_ZEROFILL_FLAG", ZEROFILL_FLAG, CONST_CS | CONST_PERSISTENT);
720 	REGISTER_LONG_CONSTANT("MYSQLI_AUTO_INCREMENT_FLAG", AUTO_INCREMENT_FLAG, CONST_CS | CONST_PERSISTENT);
721 	REGISTER_LONG_CONSTANT("MYSQLI_TIMESTAMP_FLAG", TIMESTAMP_FLAG, CONST_CS | CONST_PERSISTENT);
722 	REGISTER_LONG_CONSTANT("MYSQLI_SET_FLAG", SET_FLAG, CONST_CS | CONST_PERSISTENT);
723 	REGISTER_LONG_CONSTANT("MYSQLI_NUM_FLAG", NUM_FLAG, CONST_CS | CONST_PERSISTENT);
724 	REGISTER_LONG_CONSTANT("MYSQLI_PART_KEY_FLAG", PART_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
725 	REGISTER_LONG_CONSTANT("MYSQLI_GROUP_FLAG", GROUP_FLAG, CONST_CS | CONST_PERSISTENT);
726 	REGISTER_LONG_CONSTANT("MYSQLI_ENUM_FLAG", ENUM_FLAG, CONST_CS | CONST_PERSISTENT);
727 	REGISTER_LONG_CONSTANT("MYSQLI_BINARY_FLAG", BINARY_FLAG, CONST_CS | CONST_PERSISTENT);
728 	REGISTER_LONG_CONSTANT("MYSQLI_NO_DEFAULT_VALUE_FLAG", NO_DEFAULT_VALUE_FLAG, CONST_CS | CONST_PERSISTENT);
729 
730 #if MYSQL_VERSION_ID < 60000 || MYSQL_VERSION_ID > 60003 || defined(MYSQLI_USE_MYSQLND)
731 	REGISTER_LONG_CONSTANT("MYSQLI_ON_UPDATE_NOW_FLAG", ON_UPDATE_NOW_FLAG, CONST_CS | CONST_PERSISTENT);
732 #endif
733 
734 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DECIMAL", FIELD_TYPE_DECIMAL, CONST_CS | CONST_PERSISTENT);
735 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TINY", FIELD_TYPE_TINY, CONST_CS | CONST_PERSISTENT);
736 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_SHORT", FIELD_TYPE_SHORT, CONST_CS | CONST_PERSISTENT);
737 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONG", FIELD_TYPE_LONG, CONST_CS | CONST_PERSISTENT);
738 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_FLOAT", FIELD_TYPE_FLOAT, CONST_CS | CONST_PERSISTENT);
739 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DOUBLE", FIELD_TYPE_DOUBLE, CONST_CS | CONST_PERSISTENT);
740 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NULL", FIELD_TYPE_NULL, CONST_CS | CONST_PERSISTENT);
741 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TIMESTAMP", FIELD_TYPE_TIMESTAMP, CONST_CS | CONST_PERSISTENT);
742 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONGLONG", FIELD_TYPE_LONGLONG, CONST_CS | CONST_PERSISTENT);
743 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_INT24", FIELD_TYPE_INT24, CONST_CS | CONST_PERSISTENT);
744 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DATE", FIELD_TYPE_DATE, CONST_CS | CONST_PERSISTENT);
745 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TIME", FIELD_TYPE_TIME, CONST_CS | CONST_PERSISTENT);
746 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DATETIME", FIELD_TYPE_DATETIME	, CONST_CS | CONST_PERSISTENT);
747 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_YEAR", FIELD_TYPE_YEAR, CONST_CS | CONST_PERSISTENT);
748 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NEWDATE", FIELD_TYPE_NEWDATE, CONST_CS | CONST_PERSISTENT);
749 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_ENUM", FIELD_TYPE_ENUM, CONST_CS | CONST_PERSISTENT);
750 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_SET", FIELD_TYPE_SET, CONST_CS | CONST_PERSISTENT);
751 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TINY_BLOB", FIELD_TYPE_TINY_BLOB, CONST_CS | CONST_PERSISTENT);
752 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_MEDIUM_BLOB", FIELD_TYPE_MEDIUM_BLOB, CONST_CS | CONST_PERSISTENT);
753 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONG_BLOB", FIELD_TYPE_LONG_BLOB, CONST_CS | CONST_PERSISTENT);
754 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_BLOB", FIELD_TYPE_BLOB, CONST_CS | CONST_PERSISTENT);
755 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_VAR_STRING", FIELD_TYPE_VAR_STRING, CONST_CS | CONST_PERSISTENT);
756 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_STRING", FIELD_TYPE_STRING, CONST_CS | CONST_PERSISTENT);
757 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_CHAR", FIELD_TYPE_CHAR, CONST_CS | CONST_PERSISTENT);
758 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_INTERVAL", FIELD_TYPE_INTERVAL, CONST_CS | CONST_PERSISTENT);
759 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_GEOMETRY", FIELD_TYPE_GEOMETRY, CONST_CS | CONST_PERSISTENT);
760 #ifdef FIELD_TYPE_JSON
761 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_JSON", FIELD_TYPE_JSON, CONST_CS | CONST_PERSISTENT);
762 #endif
763 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NEWDECIMAL", FIELD_TYPE_NEWDECIMAL, CONST_CS | CONST_PERSISTENT);
764 	REGISTER_LONG_CONSTANT("MYSQLI_TYPE_BIT", FIELD_TYPE_BIT, CONST_CS | CONST_PERSISTENT);
765 
766 	REGISTER_LONG_CONSTANT("MYSQLI_SET_CHARSET_NAME", MYSQL_SET_CHARSET_NAME, CONST_CS | CONST_PERSISTENT);
767 	REGISTER_LONG_CONSTANT("MYSQLI_SET_CHARSET_DIR", MYSQL_SET_CHARSET_DIR, CONST_CS | CONST_PERSISTENT);
768 
769 	/* bind support */
770 	REGISTER_LONG_CONSTANT("MYSQLI_NO_DATA", MYSQL_NO_DATA, CONST_CS | CONST_PERSISTENT);
771 #ifdef MYSQL_DATA_TRUNCATED
772 	REGISTER_LONG_CONSTANT("MYSQLI_DATA_TRUNCATED", MYSQL_DATA_TRUNCATED, CONST_CS | CONST_PERSISTENT);
773 #endif
774 
775 	/* reporting */
776 	REGISTER_LONG_CONSTANT("MYSQLI_REPORT_INDEX", MYSQLI_REPORT_INDEX, CONST_CS | CONST_PERSISTENT);
777 	REGISTER_LONG_CONSTANT("MYSQLI_REPORT_ERROR", MYSQLI_REPORT_ERROR, CONST_CS | CONST_PERSISTENT);
778 	REGISTER_LONG_CONSTANT("MYSQLI_REPORT_STRICT", MYSQLI_REPORT_STRICT, CONST_CS | CONST_PERSISTENT);
779 	REGISTER_LONG_CONSTANT("MYSQLI_REPORT_ALL", MYSQLI_REPORT_ALL, CONST_CS | CONST_PERSISTENT);
780 	REGISTER_LONG_CONSTANT("MYSQLI_REPORT_OFF", 0, CONST_CS | CONST_PERSISTENT);
781 
782 	/* We use non-nested macros with expansion, as VC has problems */
783 #ifdef MYSQLI_USE_MYSQLND
784 	REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", MYSQLND_DBG_ENABLED, CONST_CS | CONST_PERSISTENT);
785 #else
786 #ifdef DBUG_ON
787 	REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 1, CONST_CS | CONST_PERSISTENT);
788 #else
789 	REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 0, CONST_CS | CONST_PERSISTENT);
790 #endif
791 #endif
792 
793 	REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED", SERVER_QUERY_NO_GOOD_INDEX_USED, CONST_CS | CONST_PERSISTENT);
794 	REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_NO_INDEX_USED", SERVER_QUERY_NO_INDEX_USED, CONST_CS | CONST_PERSISTENT);
795 #ifdef SERVER_QUERY_WAS_SLOW
796 	REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_WAS_SLOW", SERVER_QUERY_WAS_SLOW, CONST_CS | CONST_PERSISTENT);
797 #endif
798 #ifdef SERVER_PS_OUT_PARAMS
799 	REGISTER_LONG_CONSTANT("MYSQLI_SERVER_PS_OUT_PARAMS", SERVER_PS_OUT_PARAMS, CONST_CS | CONST_PERSISTENT);
800 #endif
801 
802 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_GRANT",      REFRESH_GRANT, CONST_CS | CONST_PERSISTENT);
803 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_LOG",        REFRESH_LOG, CONST_CS | CONST_PERSISTENT);
804 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_TABLES",     REFRESH_TABLES, CONST_CS | CONST_PERSISTENT);
805 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_HOSTS",      REFRESH_HOSTS, CONST_CS | CONST_PERSISTENT);
806 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_STATUS",     REFRESH_STATUS, CONST_CS | CONST_PERSISTENT);
807 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_THREADS",    REFRESH_THREADS, CONST_CS | CONST_PERSISTENT);
808 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_SLAVE",      REFRESH_SLAVE, CONST_CS | CONST_PERSISTENT);
809 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_MASTER",     REFRESH_MASTER, CONST_CS | CONST_PERSISTENT);
810 #ifdef REFRESH_BACKUP_LOG
811 	REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_BACKUP_LOG", REFRESH_BACKUP_LOG, CONST_CS | CONST_PERSISTENT);
812 #endif
813 
814 
815 	REGISTER_LONG_CONSTANT("MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT", TRANS_START_WITH_CONSISTENT_SNAPSHOT, CONST_CS | CONST_PERSISTENT);
816 	REGISTER_LONG_CONSTANT("MYSQLI_TRANS_START_READ_WRITE", TRANS_START_READ_WRITE, CONST_CS | CONST_PERSISTENT);
817 	REGISTER_LONG_CONSTANT("MYSQLI_TRANS_START_READ_ONLY", TRANS_START_READ_ONLY, CONST_CS | CONST_PERSISTENT);
818 
819 	REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_AND_CHAIN", TRANS_COR_AND_CHAIN, CONST_CS | CONST_PERSISTENT);
820 	REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_AND_NO_CHAIN", TRANS_COR_AND_NO_CHAIN, CONST_CS | CONST_PERSISTENT);
821 	REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_RELEASE", TRANS_COR_RELEASE, CONST_CS | CONST_PERSISTENT);
822 	REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_NO_RELEASE", TRANS_COR_NO_RELEASE, CONST_CS | CONST_PERSISTENT);
823 
824 
825 #ifdef MYSQLI_USE_MYSQLND
826 	mysqlnd_reverse_api_register_api(&mysqli_reverse_api);
827 #endif
828 
829 	return SUCCESS;
830 }
831 /* }}} */
832 
833 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(mysqli)834 PHP_MSHUTDOWN_FUNCTION(mysqli)
835 {
836 #ifndef MYSQLI_USE_MYSQLND
837 #ifdef PHP_WIN32
838 	zend_ulong client_ver = mysql_get_client_version();
839 	/*
840 	  Can't call mysql_server_end() multiple times prior to 5.0.46 on Windows.
841 	  PHP bug#41350 MySQL bug#25621
842 	*/
843 	if ((client_ver >= 50046 && client_ver < 50100) || client_ver > 50122) {
844 		mysql_server_end();
845 	}
846 #else
847 	mysql_server_end();
848 #endif
849 #endif
850 
851 	zend_hash_destroy(&mysqli_driver_properties);
852 	zend_hash_destroy(&mysqli_result_properties);
853 	zend_hash_destroy(&mysqli_stmt_properties);
854 	zend_hash_destroy(&mysqli_warning_properties);
855 	zend_hash_destroy(&mysqli_link_properties);
856 	zend_hash_destroy(&classes);
857 
858 	UNREGISTER_INI_ENTRIES();
859 	return SUCCESS;
860 }
861 /* }}} */
862 
863 /* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(mysqli)864 PHP_RINIT_FUNCTION(mysqli)
865 {
866 #if !defined(MYSQLI_USE_MYSQLND) && defined(ZTS)
867 	if (mysql_thread_init()) {
868 		return FAILURE;
869 	}
870 #endif
871 	MyG(error_msg) = NULL;
872 	MyG(error_no) = 0;
873 	MyG(report_mode) = 0;
874 
875 	return SUCCESS;
876 }
877 /* }}} */
878 
879 #if defined(A0) && defined(MYSQLI_USE_MYSQLND)
php_mysqli_persistent_helper_for_every(void * p)880 static void php_mysqli_persistent_helper_for_every(void *p)
881 {
882 	mysqlnd_end_psession((MYSQLND *) p);
883 } /* }}} */
884 
885 
php_mysqli_persistent_helper_once(zend_rsrc_list_entry * le)886 static int php_mysqli_persistent_helper_once(zend_rsrc_list_entry *le)
887 {
888 	if (le->type == php_le_pmysqli()) {
889 		mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
890 		zend_ptr_stack_apply(&plist->free_links, php_mysqli_persistent_helper_for_every);
891 	}
892 	return ZEND_HASH_APPLY_KEEP;
893 } /* }}} */
894 #endif
895 
896 
897 /* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(mysqli)898 PHP_RSHUTDOWN_FUNCTION(mysqli)
899 {
900 	/* check persistent connections, move used to free */
901 
902 #if !defined(MYSQLI_USE_MYSQLND) && defined(ZTS)
903 	mysql_thread_end();
904 #endif
905 	if (MyG(error_msg)) {
906 		efree(MyG(error_msg));
907 	}
908 #if defined(A0) && defined(MYSQLI_USE_MYSQLND)
909 	/* psession is being called when the connection is freed - explicitly or implicitly */
910 	zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysqli_persistent_helper_once);
911 #endif
912 	return SUCCESS;
913 }
914 /* }}} */
915 
916 
917 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(mysqli)918 PHP_MINFO_FUNCTION(mysqli)
919 {
920 	char buf[32];
921 
922 	php_info_print_table_start();
923 	php_info_print_table_header(2, "MysqlI Support", "enabled");
924 	php_info_print_table_row(2, "Client API library version", mysql_get_client_info());
925 	snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MyG(num_active_persistent));
926 	php_info_print_table_row(2, "Active Persistent Links", buf);
927 	snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MyG(num_inactive_persistent));
928 	php_info_print_table_row(2, "Inactive Persistent Links", buf);
929 	snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MyG(num_links));
930 	php_info_print_table_row(2, "Active Links", buf);
931 #ifndef MYSQLI_USE_MYSQLND
932 	php_info_print_table_row(2, "Client API header version", MYSQL_SERVER_VERSION);
933 	php_info_print_table_row(2, "MYSQLI_SOCKET", MYSQL_UNIX_ADDR);
934 #endif
935 	php_info_print_table_end();
936 
937 	DISPLAY_INI_ENTRIES();
938 }
939 /* }}} */
940 
941 
942 /* Dependencies */
943 static const  zend_module_dep mysqli_deps[] = {
944 	ZEND_MOD_REQUIRED("spl")
945 #ifdef MYSQLI_USE_MYSQLND
946 	ZEND_MOD_REQUIRED("mysqlnd")
947 #endif
948 	ZEND_MOD_END
949 };
950 
951 /* {{{ mysqli_module_entry */
952 zend_module_entry mysqli_module_entry = {
953 	STANDARD_MODULE_HEADER_EX, NULL,
954 	mysqli_deps,
955 	"mysqli",
956 	ext_functions,
957 	PHP_MINIT(mysqli),
958 	PHP_MSHUTDOWN(mysqli),
959 	PHP_RINIT(mysqli),
960 	PHP_RSHUTDOWN(mysqli),
961 	PHP_MINFO(mysqli),
962 	PHP_MYSQLI_VERSION,
963 	PHP_MODULE_GLOBALS(mysqli),
964 	PHP_GINIT(mysqli),
965 	NULL,
966 	NULL,
967 	STANDARD_MODULE_PROPERTIES_EX
968 };
969 /* }}} */
970 
971 #ifdef COMPILE_DL_MYSQLI
972 #ifdef ZTS
973 ZEND_TSRMLS_CACHE_DEFINE()
974 #endif
ZEND_GET_MODULE(mysqli)975 ZEND_GET_MODULE(mysqli)
976 #endif
977 
978 
979 PHP_METHOD(mysqli_stmt, __construct)
980 {
981 	MY_MYSQL			*mysql;
982 	zval				*mysql_link;
983 	MY_STMT				*stmt;
984 	MYSQLI_RESOURCE		*mysqli_resource;
985 	char				*statement = NULL;
986 	size_t					statement_len;
987 
988 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!", &mysql_link, mysqli_link_class_entry, &statement, &statement_len) == FAILURE) {
989 		RETURN_THROWS();
990 	}
991 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
992 
993 	stmt = (MY_STMT *) ecalloc(1, sizeof(MY_STMT));
994 
995 	if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
996 		efree(stmt);
997 		RETURN_FALSE;
998 	}
999 
1000 #ifndef MYSQLI_USE_MYSQLND
1001 	ZVAL_COPY(&stmt->link_handle, mysql_link);
1002 #endif
1003 
1004 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1005 	mysqli_resource->ptr = (void *)stmt;
1006 	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
1007 
1008 	MYSQLI_REGISTER_RESOURCE_EX(mysqli_resource, getThis());
1009 
1010 	if (statement) {
1011 		if(mysql_stmt_prepare(stmt->stmt, statement, statement_len)) {
1012 			MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1013 			RETURN_FALSE;
1014 		}
1015 		mysqli_resource->status = MYSQLI_STATUS_VALID;
1016 	}
1017 }
1018 
PHP_METHOD(mysqli_result,__construct)1019 PHP_METHOD(mysqli_result, __construct)
1020 {
1021 	MY_MYSQL			*mysql;
1022 	MYSQL_RES			*result = NULL;
1023 	zval				*mysql_link;
1024 	MYSQLI_RESOURCE		*mysqli_resource;
1025 	zend_long				resmode = MYSQLI_STORE_RESULT;
1026 
1027 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &mysql_link, mysqli_link_class_entry, &resmode) == FAILURE) {
1028 		RETURN_THROWS();
1029 	}
1030 
1031 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1032 
1033 	switch (resmode) {
1034 		case MYSQLI_STORE_RESULT:
1035 			result = mysql_store_result(mysql->mysql);
1036 			break;
1037 		case MYSQLI_USE_RESULT:
1038 			result = mysql_use_result(mysql->mysql);
1039 			break;
1040 		default:
1041 			zend_argument_value_error(2, "must be either MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT");
1042 			RETURN_THROWS();
1043 	}
1044 
1045 	if (!result) {
1046 		RETURN_FALSE;
1047 	}
1048 
1049 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1050 	mysqli_resource->ptr = (void *)result;
1051 	mysqli_resource->status = MYSQLI_STATUS_VALID;
1052 
1053 	MYSQLI_REGISTER_RESOURCE_EX(mysqli_resource, getThis());
1054 }
1055 
PHP_METHOD(mysqli_result,getIterator)1056 PHP_METHOD(mysqli_result, getIterator)
1057 {
1058 	if (zend_parse_parameters_none() == FAILURE) {
1059 		RETURN_THROWS();
1060 	}
1061 
1062 	zend_create_internal_iterator_zval(return_value, ZEND_THIS);
1063 }
1064 
1065 /* {{{ php_mysqli_fetch_into_hash_aux */
php_mysqli_fetch_into_hash_aux(zval * return_value,MYSQL_RES * result,zend_long fetchtype)1066 void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, zend_long fetchtype)
1067 {
1068 #ifndef MYSQLI_USE_MYSQLND
1069 	MYSQL_ROW row;
1070 	unsigned int	i, num_fields;
1071 	MYSQL_FIELD		*fields;
1072 	zend_ulong	*field_len;
1073 
1074 	if (!(row = mysql_fetch_row(result))) {
1075 		RETURN_NULL();
1076 	}
1077 
1078 	if (fetchtype & MYSQLI_ASSOC) {
1079 		fields = mysql_fetch_fields(result);
1080 	}
1081 
1082 	array_init(return_value);
1083 	field_len = mysql_fetch_lengths(result);
1084 	num_fields = mysql_num_fields(result);
1085 
1086 	for (i = 0; i < num_fields; i++) {
1087 		if (row[i]) {
1088 			zval res;
1089 
1090 			if (mysql_fetch_field_direct(result, i)->type == MYSQL_TYPE_BIT) {
1091 				my_ulonglong llval;
1092 				char tmp[22];
1093 				switch (field_len[i]) {
1094 					case 8:llval = (my_ulonglong)  bit_uint8korr(row[i]);break;
1095 					case 7:llval = (my_ulonglong)  bit_uint7korr(row[i]);break;
1096 					case 6:llval = (my_ulonglong)  bit_uint6korr(row[i]);break;
1097 					case 5:llval = (my_ulonglong)  bit_uint5korr(row[i]);break;
1098 					case 4:llval = (my_ulonglong)  bit_uint4korr(row[i]);break;
1099 					case 3:llval = (my_ulonglong)  bit_uint3korr(row[i]);break;
1100 					case 2:llval = (my_ulonglong)  bit_uint2korr(row[i]);break;
1101 					case 1:llval = (my_ulonglong)  uint1korr(row[i]);break;
1102 					EMPTY_SWITCH_DEFAULT_CASE()
1103 				}
1104 				/* even though lval is declared as unsigned, the value
1105 				 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
1106 				 * use MYSQLI_LL_SPEC.
1107 				 */
1108 				snprintf(tmp, sizeof(tmp), (mysql_fetch_field_direct(result, i)->flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1109 				ZVAL_STRING(&res, tmp);
1110 			} else {
1111 				ZVAL_STRINGL(&res, row[i], field_len[i]);
1112 			}
1113 
1114 			if (fetchtype & MYSQLI_NUM) {
1115 				add_index_zval(return_value, i, &res);
1116 			}
1117 			if (fetchtype & MYSQLI_ASSOC) {
1118 				if (fetchtype & MYSQLI_NUM && Z_REFCOUNTED(res)) {
1119 					Z_ADDREF(res);
1120 				}
1121 				add_assoc_zval(return_value, fields[i].name, &res);
1122 			}
1123 		} else {
1124 			if (fetchtype & MYSQLI_NUM) {
1125 				add_index_null(return_value, i);
1126 			}
1127 			if (fetchtype & MYSQLI_ASSOC) {
1128 				add_assoc_null(return_value, fields[i].name);
1129 			}
1130 		}
1131 	}
1132 #else
1133 	mysqlnd_fetch_into(result, ((fetchtype & MYSQLI_NUM)? MYSQLND_FETCH_NUM:0) | ((fetchtype & MYSQLI_ASSOC)? MYSQLND_FETCH_ASSOC:0), return_value, MYSQLND_MYSQLI);
1134 	/* TODO: We don't have access to the connection object at this point, so we use low-level
1135 	 * mysqlnd APIs to access the error information. We should try to pass through the connection
1136 	 * object instead. */
1137 	if (MyG(report_mode) & MYSQLI_REPORT_ERROR) {
1138 		MYSQLND_CONN_DATA *conn = result->conn;
1139 		unsigned error_no = conn->m->get_error_no(conn);
1140 		if (error_no) {
1141 			php_mysqli_report_error(
1142 				conn->m->get_sqlstate(conn), error_no, conn->m->get_error_str(conn));
1143 		}
1144 	}
1145 #endif
1146 }
1147 /* }}} */
1148 
1149 /* TODO Split this up */
1150 /* {{{ php_mysqli_fetch_into_hash */
php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS,int override_flags,int into_object)1151 void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object)
1152 {
1153 	MYSQL_RES		*result;
1154 	zval			*mysql_result;
1155 	zend_long			fetchtype;
1156 	zval			*ctor_params = NULL;
1157 	zend_class_entry *ce = NULL;
1158 
1159 	if (into_object) {
1160 		if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|Ca", &mysql_result, mysqli_result_class_entry, &ce, &ctor_params) == FAILURE) {
1161 			RETURN_THROWS();
1162 		}
1163 		if (ce == NULL) {
1164 			ce = zend_standard_class_def;
1165 		}
1166 		if (UNEXPECTED(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1167 			zend_throw_error(NULL, "Class %s cannot be instantiated", ZSTR_VAL(ce->name));
1168 			RETURN_THROWS();
1169 		}
1170 		fetchtype = MYSQLI_ASSOC;
1171 	} else {
1172 		if (override_flags) {
1173 			if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1174 				RETURN_THROWS();
1175 			}
1176 			fetchtype = override_flags;
1177 		} else {
1178 			fetchtype = MYSQLI_BOTH;
1179 			if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) {
1180 				RETURN_THROWS();
1181 			}
1182 		}
1183 	}
1184 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1185 
1186 	if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
1187 		zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_NUM, MYSQLI_ASSOC, or MYSQLI_BOTH");
1188 		RETURN_THROWS();
1189 	}
1190 
1191 	php_mysqli_fetch_into_hash_aux(return_value, result, fetchtype);
1192 
1193 	if (into_object && Z_TYPE_P(return_value) == IS_ARRAY) {
1194 		zval dataset, retval;
1195 		zend_fcall_info fci;
1196 		zend_fcall_info_cache fcc;
1197 
1198 		ZVAL_COPY_VALUE(&dataset, return_value);
1199 
1200 		object_init_ex(return_value, ce);
1201 		if (!ce->default_properties_count && !ce->__set) {
1202 			Z_OBJ_P(return_value)->properties = Z_ARR(dataset);
1203 		} else {
1204 			zend_merge_properties(return_value, Z_ARRVAL(dataset));
1205 			zval_ptr_dtor(&dataset);
1206 		}
1207 
1208 		if (ce->constructor) {
1209 			fci.size = sizeof(fci);
1210 			ZVAL_UNDEF(&fci.function_name);
1211 			fci.object = Z_OBJ_P(return_value);
1212 			fci.retval = &retval;
1213 			fci.params = NULL;
1214 			fci.param_count = 0;
1215 			fci.named_params = NULL;
1216 
1217 			if (ctor_params) {
1218 				if (zend_fcall_info_args(&fci, ctor_params) == FAILURE) {
1219 					ZEND_UNREACHABLE();
1220 				}
1221 			}
1222 
1223 			fcc.function_handler = ce->constructor;
1224 			fcc.called_scope = Z_OBJCE_P(return_value);
1225 			fcc.object = Z_OBJ_P(return_value);
1226 
1227 			if (zend_call_function(&fci, &fcc) == FAILURE) {
1228 				zend_throw_exception_ex(zend_ce_exception, 0, "Could not execute %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
1229 			} else {
1230 				zval_ptr_dtor(&retval);
1231 			}
1232 			zend_fcall_info_args_clear(&fci, 1);
1233 		} else if (ctor_params && zend_hash_num_elements(Z_ARRVAL_P(ctor_params)) > 0) {
1234 			zend_argument_error(zend_ce_exception, ERROR_ARG_POS(3),
1235 				"must be empty when the specified class (%s) does not have a constructor",
1236 				ZSTR_VAL(ce->name)
1237 			);
1238 		}
1239 	}
1240 }
1241 /* }}} */
1242