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 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1047 RETURN_FALSE;
1048 }
1049
1050 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1051 mysqli_resource->ptr = (void *)result;
1052 mysqli_resource->status = MYSQLI_STATUS_VALID;
1053
1054 MYSQLI_REGISTER_RESOURCE_EX(mysqli_resource, getThis());
1055 }
1056
PHP_METHOD(mysqli_result,getIterator)1057 PHP_METHOD(mysqli_result, getIterator)
1058 {
1059 if (zend_parse_parameters_none() == FAILURE) {
1060 RETURN_THROWS();
1061 }
1062
1063 zend_create_internal_iterator_zval(return_value, ZEND_THIS);
1064 }
1065
1066 /* {{{ php_mysqli_fetch_into_hash_aux */
php_mysqli_fetch_into_hash_aux(zval * return_value,MYSQL_RES * result,zend_long fetchtype)1067 void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, zend_long fetchtype)
1068 {
1069 #ifndef MYSQLI_USE_MYSQLND
1070 MYSQL_ROW row;
1071 unsigned int i, num_fields;
1072 MYSQL_FIELD *fields;
1073 zend_ulong *field_len;
1074
1075 if (!(row = mysql_fetch_row(result))) {
1076 RETURN_NULL();
1077 }
1078
1079 if (fetchtype & MYSQLI_ASSOC) {
1080 fields = mysql_fetch_fields(result);
1081 }
1082
1083 array_init(return_value);
1084 field_len = mysql_fetch_lengths(result);
1085 num_fields = mysql_num_fields(result);
1086
1087 for (i = 0; i < num_fields; i++) {
1088 if (row[i]) {
1089 zval res;
1090
1091 if (mysql_fetch_field_direct(result, i)->type == MYSQL_TYPE_BIT) {
1092 my_ulonglong llval;
1093 char tmp[22];
1094 switch (field_len[i]) {
1095 case 8:llval = (my_ulonglong) bit_uint8korr(row[i]);break;
1096 case 7:llval = (my_ulonglong) bit_uint7korr(row[i]);break;
1097 case 6:llval = (my_ulonglong) bit_uint6korr(row[i]);break;
1098 case 5:llval = (my_ulonglong) bit_uint5korr(row[i]);break;
1099 case 4:llval = (my_ulonglong) bit_uint4korr(row[i]);break;
1100 case 3:llval = (my_ulonglong) bit_uint3korr(row[i]);break;
1101 case 2:llval = (my_ulonglong) bit_uint2korr(row[i]);break;
1102 case 1:llval = (my_ulonglong) uint1korr(row[i]);break;
1103 EMPTY_SWITCH_DEFAULT_CASE()
1104 }
1105 /* even though lval is declared as unsigned, the value
1106 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
1107 * use MYSQLI_LL_SPEC.
1108 */
1109 snprintf(tmp, sizeof(tmp), (mysql_fetch_field_direct(result, i)->flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1110 ZVAL_STRING(&res, tmp);
1111 } else {
1112 ZVAL_STRINGL(&res, row[i], field_len[i]);
1113 }
1114
1115 if (fetchtype & MYSQLI_NUM) {
1116 add_index_zval(return_value, i, &res);
1117 }
1118 if (fetchtype & MYSQLI_ASSOC) {
1119 if (fetchtype & MYSQLI_NUM && Z_REFCOUNTED(res)) {
1120 Z_ADDREF(res);
1121 }
1122 add_assoc_zval(return_value, fields[i].name, &res);
1123 }
1124 } else {
1125 if (fetchtype & MYSQLI_NUM) {
1126 add_index_null(return_value, i);
1127 }
1128 if (fetchtype & MYSQLI_ASSOC) {
1129 add_assoc_null(return_value, fields[i].name);
1130 }
1131 }
1132 }
1133 #else
1134 mysqlnd_fetch_into(result, ((fetchtype & MYSQLI_NUM)? MYSQLND_FETCH_NUM:0) | ((fetchtype & MYSQLI_ASSOC)? MYSQLND_FETCH_ASSOC:0), return_value, MYSQLND_MYSQLI);
1135 /* TODO: We don't have access to the connection object at this point, so we use low-level
1136 * mysqlnd APIs to access the error information. We should try to pass through the connection
1137 * object instead. */
1138 if (MyG(report_mode) & MYSQLI_REPORT_ERROR) {
1139 MYSQLND_CONN_DATA *conn = result->conn;
1140 unsigned error_no = conn->m->get_error_no(conn);
1141 if (error_no) {
1142 php_mysqli_report_error(
1143 conn->m->get_sqlstate(conn), error_no, conn->m->get_error_str(conn));
1144 }
1145 }
1146 #endif
1147 }
1148 /* }}} */
1149
1150 /* TODO Split this up */
1151 /* {{{ php_mysqli_fetch_into_hash */
php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS,int override_flags,int into_object)1152 void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object)
1153 {
1154 MYSQL_RES *result;
1155 zval *mysql_result;
1156 zend_long fetchtype;
1157 zval *ctor_params = NULL;
1158 zend_class_entry *ce = NULL;
1159
1160 if (into_object) {
1161 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|Ca", &mysql_result, mysqli_result_class_entry, &ce, &ctor_params) == FAILURE) {
1162 RETURN_THROWS();
1163 }
1164 if (ce == NULL) {
1165 ce = zend_standard_class_def;
1166 }
1167 if (UNEXPECTED(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1168 zend_throw_error(NULL, "Class %s cannot be instantiated", ZSTR_VAL(ce->name));
1169 RETURN_THROWS();
1170 }
1171 fetchtype = MYSQLI_ASSOC;
1172 } else {
1173 if (override_flags) {
1174 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1175 RETURN_THROWS();
1176 }
1177 fetchtype = override_flags;
1178 } else {
1179 fetchtype = MYSQLI_BOTH;
1180 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) {
1181 RETURN_THROWS();
1182 }
1183 }
1184 }
1185 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1186
1187 if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
1188 zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_NUM, MYSQLI_ASSOC, or MYSQLI_BOTH");
1189 RETURN_THROWS();
1190 }
1191
1192 php_mysqli_fetch_into_hash_aux(return_value, result, fetchtype);
1193
1194 if (into_object && Z_TYPE_P(return_value) == IS_ARRAY) {
1195 zval dataset, retval;
1196 zend_fcall_info fci;
1197 zend_fcall_info_cache fcc;
1198
1199 ZVAL_COPY_VALUE(&dataset, return_value);
1200
1201 object_init_ex(return_value, ce);
1202 HashTable *prop_table = zend_symtable_to_proptable(Z_ARR(dataset));
1203 zval_ptr_dtor(&dataset);
1204 if (!ce->default_properties_count && !ce->__set) {
1205 Z_OBJ_P(return_value)->properties = prop_table;
1206 } else {
1207 zend_merge_properties(return_value, prop_table);
1208 zend_array_release(prop_table);
1209 }
1210
1211 if (ce->constructor) {
1212 fci.size = sizeof(fci);
1213 ZVAL_UNDEF(&fci.function_name);
1214 fci.object = Z_OBJ_P(return_value);
1215 fci.retval = &retval;
1216 fci.params = NULL;
1217 fci.param_count = 0;
1218 fci.named_params = NULL;
1219
1220 if (ctor_params) {
1221 if (zend_fcall_info_args(&fci, ctor_params) == FAILURE) {
1222 ZEND_UNREACHABLE();
1223 }
1224 }
1225
1226 fcc.function_handler = ce->constructor;
1227 fcc.called_scope = Z_OBJCE_P(return_value);
1228 fcc.object = Z_OBJ_P(return_value);
1229
1230 if (zend_call_function(&fci, &fcc) == FAILURE) {
1231 zend_throw_exception_ex(zend_ce_exception, 0, "Could not execute %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
1232 } else {
1233 zval_ptr_dtor(&retval);
1234 }
1235 zend_fcall_info_args_clear(&fci, 1);
1236 } else if (ctor_params && zend_hash_num_elements(Z_ARRVAL_P(ctor_params)) > 0) {
1237 zend_argument_error(zend_ce_exception, ERROR_ARG_POS(3),
1238 "must be empty when the specified class (%s) does not have a constructor",
1239 ZSTR_VAL(ce->name)
1240 );
1241 }
1242 }
1243 }
1244 /* }}} */
1245