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 | https://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, 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,bool quiet)280 static int mysqli_read_na(mysqli_object *obj, zval *retval, bool quiet)
281 {
282 if (!quiet) {
283 zend_throw_error(NULL, "Cannot read property");
284 }
285
286 return FAILURE;
287 }
288 /* }}} */
289
290 /* {{{ mysqli_read_property */
mysqli_read_property(zend_object * object,zend_string * name,int type,void ** cache_slot,zval * rv)291 zval *mysqli_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
292 {
293 mysqli_object *obj = php_mysqli_fetch_object(object);
294 if (obj->prop_handler) {
295 mysqli_prop_handler *hnd = zend_hash_find_ptr(obj->prop_handler, name);
296 if (hnd) {
297 if (hnd->read_func(obj, rv, type == BP_VAR_IS) == SUCCESS) {
298 return rv;
299 } else {
300 return &EG(uninitialized_zval);
301 }
302 }
303 }
304
305 return zend_std_read_property(object, name, type, cache_slot, rv);
306 }
307 /* }}} */
308
309 /* {{{ mysqli_write_property */
mysqli_write_property(zend_object * object,zend_string * name,zval * value,void ** cache_slot)310 zval *mysqli_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
311 {
312 mysqli_object *obj = php_mysqli_fetch_object(object);
313 if (obj->prop_handler) {
314 const mysqli_prop_handler *hnd = zend_hash_find_ptr(obj->prop_handler, name);
315 if (hnd) {
316 if (!hnd->write_func) {
317 zend_throw_error(NULL, "Cannot write read-only property %s::$%s",
318 ZSTR_VAL(object->ce->name), ZSTR_VAL(name));
319 return &EG(error_zval);
320 }
321
322 zend_property_info *prop = zend_get_property_info(object->ce, name, /* silent */ true);
323 if (prop && ZEND_TYPE_IS_SET(prop->type)) {
324 zval tmp;
325 ZVAL_COPY(&tmp, value);
326 if (!zend_verify_property_type(prop, &tmp,
327 ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)))) {
328 zval_ptr_dtor(&tmp);
329 return &EG(error_zval);
330 }
331 hnd->write_func(obj, &tmp);
332 zval_ptr_dtor(&tmp);
333 } else {
334 hnd->write_func(obj, value);
335 }
336 return value;
337 }
338 }
339 return zend_std_write_property(object, name, value, cache_slot);
340 }
341 /* }}} */
342
343 /* {{{ 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)344 void mysqli_add_property(HashTable *h, const char *pname, size_t pname_len, mysqli_read_t r_func, mysqli_write_t w_func) {
345 mysqli_prop_handler p;
346
347 p.name = zend_string_init_interned(pname, pname_len, 1);
348 p.read_func = (r_func) ? r_func : mysqli_read_na;
349 p.write_func = w_func;
350 zend_hash_add_mem(h, p.name, &p, sizeof(mysqli_prop_handler));
351 zend_string_release_ex(p.name, 1);
352 }
353 /* }}} */
354
mysqli_object_has_property(zend_object * object,zend_string * name,int has_set_exists,void ** cache_slot)355 static int mysqli_object_has_property(zend_object *object, zend_string *name, int has_set_exists, void **cache_slot) /* {{{ */
356 {
357 mysqli_object *obj = php_mysqli_fetch_object(object);
358 mysqli_prop_handler *p;
359 int ret = 0;
360
361 if ((p = zend_hash_find_ptr(obj->prop_handler, name)) != NULL) {
362 switch (has_set_exists) {
363 case ZEND_PROPERTY_EXISTS:
364 ret = 1;
365 break;
366 case ZEND_PROPERTY_NOT_EMPTY: {
367 zval rv;
368 zval *value = mysqli_read_property(object, name, BP_VAR_IS, cache_slot, &rv);
369 if (value != &EG(uninitialized_zval)) {
370 convert_to_boolean(value);
371 ret = Z_TYPE_P(value) == IS_TRUE ? 1 : 0;
372 }
373 break;
374 }
375 case ZEND_PROPERTY_ISSET: {
376 zval rv;
377 zval *value = mysqli_read_property(object, name, BP_VAR_IS, cache_slot, &rv);
378 if (value != &EG(uninitialized_zval)) {
379 ret = Z_TYPE_P(value) != IS_NULL? 1 : 0;
380 zval_ptr_dtor(value);
381 }
382 break;
383 }
384 EMPTY_SWITCH_DEFAULT_CASE();
385 }
386 } else {
387 ret = zend_std_has_property(object, name, has_set_exists, cache_slot);
388 }
389
390 return ret;
391 } /* }}} */
392
mysqli_object_get_debug_info(zend_object * object,int * is_temp)393 HashTable *mysqli_object_get_debug_info(zend_object *object, int *is_temp)
394 {
395 mysqli_object *obj = php_mysqli_fetch_object(object);
396 HashTable *retval, *props = obj->prop_handler;
397 mysqli_prop_handler *entry;
398
399 retval = zend_new_array(zend_hash_num_elements(props) + 1);
400
401 ZEND_HASH_FOREACH_PTR(props, entry) {
402 zval rv;
403 zval *value;
404
405 value = mysqli_read_property(object, entry->name, BP_VAR_IS, 0, &rv);
406 if (value != &EG(uninitialized_zval)) {
407 zend_hash_add(retval, entry->name, value);
408 }
409 } ZEND_HASH_FOREACH_END();
410
411 *is_temp = 1;
412 return retval;
413 }
414
415 /* {{{ mysqli_objects_new */
mysqli_objects_new(zend_class_entry * class_type)416 PHP_MYSQLI_EXPORT(zend_object *) mysqli_objects_new(zend_class_entry *class_type)
417 {
418 mysqli_object *intern;
419 zend_class_entry *mysqli_base_class;
420 zend_object_handlers *handlers;
421
422 intern = zend_object_alloc(sizeof(mysqli_object), class_type);
423
424 mysqli_base_class = class_type;
425 while (mysqli_base_class->type != ZEND_INTERNAL_CLASS &&
426 mysqli_base_class->parent != NULL) {
427 mysqli_base_class = mysqli_base_class->parent;
428 }
429 intern->prop_handler = zend_hash_find_ptr(&classes, mysqli_base_class->name);
430
431 zend_object_std_init(&intern->zo, class_type);
432 object_properties_init(&intern->zo, class_type);
433
434 /* link object */
435 if (instanceof_function(class_type, mysqli_link_class_entry)) {
436 handlers = &mysqli_object_link_handlers;
437 } else if (instanceof_function(class_type, mysqli_driver_class_entry)) { /* driver object */
438 handlers = &mysqli_object_driver_handlers;
439 } else if (instanceof_function(class_type, mysqli_stmt_class_entry)) { /* stmt object */
440 handlers = &mysqli_object_stmt_handlers;
441 } else if (instanceof_function(class_type, mysqli_result_class_entry)) { /* result object */
442 handlers = &mysqli_object_result_handlers;
443 } else if (instanceof_function(class_type, mysqli_warning_class_entry)) { /* warning object */
444 handlers = &mysqli_object_warning_handlers;
445 } else {
446 handlers = &mysqli_object_handlers;
447 }
448
449 intern->zo.handlers = handlers;
450
451 return &intern->zo;
452 }
453 /* }}} */
454
455 #ifdef MYSQLI_USE_MYSQLND
456 #include "ext/mysqlnd/mysqlnd_reverse_api.h"
mysqli_convert_zv_to_mysqlnd(zval * zv)457 static MYSQLND *mysqli_convert_zv_to_mysqlnd(zval * zv)
458 {
459 if (Z_TYPE_P(zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv), mysqli_link_class_entry)) {
460 MY_MYSQL *mysql;
461 MYSQLI_RESOURCE *my_res;
462 mysqli_object *intern = Z_MYSQLI_P(zv);
463 if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
464 /* We know that we have a mysqli object, so this failure should be emitted */
465 zend_throw_error(NULL, "%s object is already closed", ZSTR_VAL(intern->zo.ce->name));
466 return NULL;
467 }
468 mysql = (MY_MYSQL *)(my_res->ptr);
469 return mysql ? mysql->mysql : NULL;
470 }
471 return NULL;
472 }
473
474 static const MYSQLND_REVERSE_API mysqli_reverse_api = {
475 &mysqli_module_entry,
476 mysqli_convert_zv_to_mysqlnd
477 };
478 #endif
479
480 /* {{{ PHP_INI_BEGIN */
481 PHP_INI_BEGIN()
482 STD_PHP_INI_ENTRY_EX("mysqli.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_mysqli_globals, mysqli_globals, display_link_numbers)
483 STD_PHP_INI_ENTRY_EX("mysqli.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_mysqli_globals, mysqli_globals, display_link_numbers)
484 STD_PHP_INI_BOOLEAN("mysqli.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_persistent, zend_mysqli_globals, mysqli_globals)
485 STD_PHP_INI_BOOLEAN("mysqli.rollback_on_cached_plink", "0",PHP_INI_SYSTEM, OnUpdateBool, rollback_on_cached_plink, zend_mysqli_globals, mysqli_globals)
486 STD_PHP_INI_ENTRY("mysqli.default_host", NULL, PHP_INI_ALL, OnUpdateString, default_host, zend_mysqli_globals, mysqli_globals)
487 STD_PHP_INI_ENTRY("mysqli.default_user", NULL, PHP_INI_ALL, OnUpdateString, default_user, zend_mysqli_globals, mysqli_globals)
488 STD_PHP_INI_ENTRY("mysqli.default_pw", NULL, PHP_INI_ALL, OnUpdateString, default_pw, zend_mysqli_globals, mysqli_globals)
489 STD_PHP_INI_ENTRY("mysqli.default_port", "3306", PHP_INI_ALL, OnUpdateLong, default_port, zend_mysqli_globals, mysqli_globals)
490 #ifdef PHP_MYSQL_UNIX_SOCK_ADDR
491 STD_PHP_INI_ENTRY("mysqli.default_socket", MYSQL_UNIX_ADDR,PHP_INI_ALL,OnUpdateStringUnempty, default_socket, zend_mysqli_globals, mysqli_globals)
492 #else
493 STD_PHP_INI_ENTRY("mysqli.default_socket", NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_socket, zend_mysqli_globals, mysqli_globals)
494 #endif
495 STD_PHP_INI_BOOLEAN("mysqli.reconnect", "0", PHP_INI_SYSTEM, OnUpdateLong, reconnect, zend_mysqli_globals, mysqli_globals)
496 STD_PHP_INI_BOOLEAN("mysqli.allow_local_infile", "0", PHP_INI_SYSTEM, OnUpdateLong, allow_local_infile, zend_mysqli_globals, mysqli_globals)
497 STD_PHP_INI_ENTRY("mysqli.local_infile_directory", NULL, PHP_INI_SYSTEM, OnUpdateString, local_infile_directory, zend_mysqli_globals, mysqli_globals)
PHP_INI_END()498 PHP_INI_END()
499 /* }}} */
500
501 /* {{{ PHP_GINIT_FUNCTION */
502 static PHP_GINIT_FUNCTION(mysqli)
503 {
504 #if defined(COMPILE_DL_MYSQLI) && defined(ZTS)
505 ZEND_TSRMLS_CACHE_UPDATE();
506 #endif
507 mysqli_globals->num_links = 0;
508 mysqli_globals->max_links = -1;
509 mysqli_globals->num_active_persistent = 0;
510 mysqli_globals->num_inactive_persistent = 0;
511 mysqli_globals->max_persistent = -1;
512 mysqli_globals->allow_persistent = 1;
513 mysqli_globals->default_port = 0;
514 mysqli_globals->default_host = NULL;
515 mysqli_globals->default_user = NULL;
516 mysqli_globals->default_pw = NULL;
517 mysqli_globals->default_socket = NULL;
518 mysqli_globals->reconnect = 0;
519 mysqli_globals->report_mode = MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT;;
520 mysqli_globals->allow_local_infile = 0;
521 mysqli_globals->local_infile_directory = NULL;
522 mysqli_globals->rollback_on_cached_plink = false;
523 }
524 /* }}} */
525
526 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(mysqli)527 PHP_MINIT_FUNCTION(mysqli)
528 {
529 REGISTER_INI_ENTRIES();
530 #ifndef MYSQLI_USE_MYSQLND
531 if (mysql_server_init(0, NULL, NULL)) {
532 return FAILURE;
533 }
534 #endif
535
536 memcpy(&mysqli_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
537 mysqli_object_handlers.offset = XtOffsetOf(mysqli_object, zo);
538 mysqli_object_handlers.free_obj = mysqli_objects_free_storage;
539 mysqli_object_handlers.clone_obj = NULL;
540 mysqli_object_handlers.read_property = mysqli_read_property;
541 mysqli_object_handlers.write_property = mysqli_write_property;
542 mysqli_object_handlers.has_property = mysqli_object_has_property;
543 mysqli_object_handlers.get_debug_info = mysqli_object_get_debug_info;
544 memcpy(&mysqli_object_driver_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
545 mysqli_object_driver_handlers.free_obj = mysqli_driver_free_storage;
546 memcpy(&mysqli_object_link_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
547 mysqli_object_link_handlers.free_obj = mysqli_link_free_storage;
548 memcpy(&mysqli_object_result_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
549 mysqli_object_result_handlers.free_obj = mysqli_result_free_storage;
550 memcpy(&mysqli_object_stmt_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
551 mysqli_object_stmt_handlers.free_obj = mysqli_stmt_free_storage;
552 memcpy(&mysqli_object_warning_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers));
553 mysqli_object_warning_handlers.free_obj = mysqli_warning_free_storage;
554
555 zend_hash_init(&classes, 0, NULL, NULL, 1);
556
557 /* persistent connections */
558 le_pmysqli = zend_register_list_destructors_ex(NULL, php_mysqli_dtor,
559 "MySqli persistent connection", module_number);
560
561 mysqli_exception_class_entry = register_class_mysqli_sql_exception(spl_ce_RuntimeException);
562
563 mysqli_driver_class_entry = register_class_mysqli_driver();
564 mysqli_driver_class_entry->create_object = mysqli_objects_new;
565 zend_hash_init(&mysqli_driver_properties, 0, NULL, free_prop_handler, 1);
566 MYSQLI_ADD_PROPERTIES(&mysqli_driver_properties, mysqli_driver_property_entries);
567 zend_hash_add_ptr(&classes, mysqli_driver_class_entry->name, &mysqli_driver_properties);
568
569 mysqli_link_class_entry = register_class_mysqli();
570 mysqli_link_class_entry->create_object = mysqli_objects_new;
571 zend_hash_init(&mysqli_link_properties, 0, NULL, free_prop_handler, 1);
572 MYSQLI_ADD_PROPERTIES(&mysqli_link_properties, mysqli_link_property_entries);
573 zend_hash_add_ptr(&classes, mysqli_link_class_entry->name, &mysqli_link_properties);
574
575 mysqli_warning_class_entry = register_class_mysqli_warning();
576 mysqli_warning_class_entry->create_object = mysqli_objects_new;
577 zend_hash_init(&mysqli_warning_properties, 0, NULL, free_prop_handler, 1);
578 MYSQLI_ADD_PROPERTIES(&mysqli_warning_properties, mysqli_warning_property_entries);
579 zend_hash_add_ptr(&classes, mysqli_warning_class_entry->name, &mysqli_warning_properties);
580
581 mysqli_result_class_entry = register_class_mysqli_result(zend_ce_aggregate);
582 mysqli_result_class_entry->create_object = mysqli_objects_new;
583 mysqli_result_class_entry->get_iterator = php_mysqli_result_get_iterator;
584 zend_hash_init(&mysqli_result_properties, 0, NULL, free_prop_handler, 1);
585 MYSQLI_ADD_PROPERTIES(&mysqli_result_properties, mysqli_result_property_entries);
586 zend_hash_add_ptr(&classes, mysqli_result_class_entry->name, &mysqli_result_properties);
587
588 mysqli_stmt_class_entry = register_class_mysqli_stmt();
589 mysqli_stmt_class_entry->create_object = mysqli_objects_new;
590 zend_hash_init(&mysqli_stmt_properties, 0, NULL, free_prop_handler, 1);
591 MYSQLI_ADD_PROPERTIES(&mysqli_stmt_properties, mysqli_stmt_property_entries);
592 zend_hash_add_ptr(&classes, mysqli_stmt_class_entry->name, &mysqli_stmt_properties);
593
594 /* mysqli_options */
595 REGISTER_LONG_CONSTANT("MYSQLI_READ_DEFAULT_GROUP", MYSQL_READ_DEFAULT_GROUP, CONST_CS | CONST_PERSISTENT);
596 REGISTER_LONG_CONSTANT("MYSQLI_READ_DEFAULT_FILE", MYSQL_READ_DEFAULT_FILE, CONST_CS | CONST_PERSISTENT);
597 REGISTER_LONG_CONSTANT("MYSQLI_OPT_CONNECT_TIMEOUT", MYSQL_OPT_CONNECT_TIMEOUT, CONST_CS | CONST_PERSISTENT);
598 REGISTER_LONG_CONSTANT("MYSQLI_OPT_LOCAL_INFILE", MYSQL_OPT_LOCAL_INFILE, CONST_CS | CONST_PERSISTENT);
599 #if (MYSQL_VERSION_ID >= 80021 && !defined(MARIADB_BASE_VERSION)) || defined(MYSQLI_USE_MYSQLND)
600 REGISTER_LONG_CONSTANT("MYSQLI_OPT_LOAD_DATA_LOCAL_DIR", MYSQL_OPT_LOAD_DATA_LOCAL_DIR, CONST_CS | CONST_PERSISTENT);
601 #endif
602 REGISTER_LONG_CONSTANT("MYSQLI_INIT_COMMAND", MYSQL_INIT_COMMAND, CONST_CS | CONST_PERSISTENT);
603 REGISTER_LONG_CONSTANT("MYSQLI_OPT_READ_TIMEOUT", MYSQL_OPT_READ_TIMEOUT, CONST_CS | CONST_PERSISTENT);
604 #ifdef MYSQLI_USE_MYSQLND
605 REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_CMD_BUFFER_SIZE", MYSQLND_OPT_NET_CMD_BUFFER_SIZE, CONST_CS | CONST_PERSISTENT);
606 REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_READ_BUFFER_SIZE", MYSQLND_OPT_NET_READ_BUFFER_SIZE, CONST_CS | CONST_PERSISTENT);
607 #endif
608 #ifdef MYSQLI_USE_MYSQLND
609 REGISTER_LONG_CONSTANT("MYSQLI_OPT_INT_AND_FLOAT_NATIVE", MYSQLND_OPT_INT_AND_FLOAT_NATIVE, CONST_CS | CONST_PERSISTENT);
610 #endif
611 #if MYSQL_VERSION_ID < 80000 || MYSQL_VERSION_ID >= 100000 || defined(MYSQLI_USE_MYSQLND)
612 REGISTER_LONG_CONSTANT("MYSQLI_OPT_SSL_VERIFY_SERVER_CERT", MYSQL_OPT_SSL_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
613 #endif
614
615 #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
616 REGISTER_LONG_CONSTANT("MYSQLI_SERVER_PUBLIC_KEY", MYSQL_SERVER_PUBLIC_KEY, CONST_CS | CONST_PERSISTENT);
617 #endif
618
619 /* mysqli_real_connect flags */
620 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL", CLIENT_SSL, CONST_CS | CONST_PERSISTENT);
621 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_COMPRESS",CLIENT_COMPRESS, CONST_CS | CONST_PERSISTENT);
622 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_INTERACTIVE", CLIENT_INTERACTIVE, CONST_CS | CONST_PERSISTENT);
623 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_IGNORE_SPACE", CLIENT_IGNORE_SPACE, CONST_CS | CONST_PERSISTENT);
624 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_NO_SCHEMA", CLIENT_NO_SCHEMA, CONST_CS | CONST_PERSISTENT);
625 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_FOUND_ROWS", CLIENT_FOUND_ROWS, CONST_CS | CONST_PERSISTENT);
626 #ifdef CLIENT_SSL_VERIFY_SERVER_CERT
627 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT", CLIENT_SSL_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
628 #ifdef MYSQLI_USE_MYSQLND
629 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT", CLIENT_SSL_DONT_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
630 #endif
631 #endif
632 #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
633 REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS", CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS, CONST_CS | CONST_PERSISTENT);
634 REGISTER_LONG_CONSTANT("MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS", MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, CONST_CS | CONST_PERSISTENT);
635 #endif
636
637 /* for mysqli_query */
638 REGISTER_LONG_CONSTANT("MYSQLI_STORE_RESULT", MYSQLI_STORE_RESULT, CONST_CS | CONST_PERSISTENT);
639 REGISTER_LONG_CONSTANT("MYSQLI_USE_RESULT", MYSQLI_USE_RESULT, CONST_CS | CONST_PERSISTENT);
640 #if defined (MYSQLI_USE_MYSQLND)
641 REGISTER_LONG_CONSTANT("MYSQLI_ASYNC", MYSQLI_ASYNC, CONST_CS | CONST_PERSISTENT);
642 REGISTER_LONG_CONSTANT("MYSQLI_STORE_RESULT_COPY_DATA", MYSQLI_STORE_RESULT_COPY_DATA, CONST_CS | CONST_PERSISTENT);
643 #endif
644
645 /* for mysqli_fetch_assoc */
646 REGISTER_LONG_CONSTANT("MYSQLI_ASSOC", MYSQLI_ASSOC, CONST_CS | CONST_PERSISTENT);
647 REGISTER_LONG_CONSTANT("MYSQLI_NUM", MYSQLI_NUM, CONST_CS | CONST_PERSISTENT);
648 REGISTER_LONG_CONSTANT("MYSQLI_BOTH", MYSQLI_BOTH, CONST_CS | CONST_PERSISTENT);
649
650 /* for mysqli_stmt_set_attr */
651 REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH", STMT_ATTR_UPDATE_MAX_LENGTH, CONST_CS | CONST_PERSISTENT);
652
653 REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_CURSOR_TYPE", STMT_ATTR_CURSOR_TYPE, CONST_CS | CONST_PERSISTENT);
654 REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_NO_CURSOR", CURSOR_TYPE_NO_CURSOR, CONST_CS | CONST_PERSISTENT);
655 REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_READ_ONLY", CURSOR_TYPE_READ_ONLY, CONST_CS | CONST_PERSISTENT);
656 REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_FOR_UPDATE", CURSOR_TYPE_FOR_UPDATE, CONST_CS | CONST_PERSISTENT);
657 REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_SCROLLABLE", CURSOR_TYPE_SCROLLABLE, CONST_CS | CONST_PERSISTENT);
658
659 REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_PREFETCH_ROWS", STMT_ATTR_PREFETCH_ROWS, CONST_CS | CONST_PERSISTENT);
660
661 /* column information */
662 REGISTER_LONG_CONSTANT("MYSQLI_NOT_NULL_FLAG", NOT_NULL_FLAG, CONST_CS | CONST_PERSISTENT);
663 REGISTER_LONG_CONSTANT("MYSQLI_PRI_KEY_FLAG", PRI_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
664 REGISTER_LONG_CONSTANT("MYSQLI_UNIQUE_KEY_FLAG", UNIQUE_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
665 REGISTER_LONG_CONSTANT("MYSQLI_MULTIPLE_KEY_FLAG", MULTIPLE_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
666 REGISTER_LONG_CONSTANT("MYSQLI_BLOB_FLAG", BLOB_FLAG, CONST_CS | CONST_PERSISTENT);
667 REGISTER_LONG_CONSTANT("MYSQLI_UNSIGNED_FLAG", UNSIGNED_FLAG, CONST_CS | CONST_PERSISTENT);
668 REGISTER_LONG_CONSTANT("MYSQLI_ZEROFILL_FLAG", ZEROFILL_FLAG, CONST_CS | CONST_PERSISTENT);
669 REGISTER_LONG_CONSTANT("MYSQLI_AUTO_INCREMENT_FLAG", AUTO_INCREMENT_FLAG, CONST_CS | CONST_PERSISTENT);
670 REGISTER_LONG_CONSTANT("MYSQLI_TIMESTAMP_FLAG", TIMESTAMP_FLAG, CONST_CS | CONST_PERSISTENT);
671 REGISTER_LONG_CONSTANT("MYSQLI_SET_FLAG", SET_FLAG, CONST_CS | CONST_PERSISTENT);
672 REGISTER_LONG_CONSTANT("MYSQLI_NUM_FLAG", NUM_FLAG, CONST_CS | CONST_PERSISTENT);
673 REGISTER_LONG_CONSTANT("MYSQLI_PART_KEY_FLAG", PART_KEY_FLAG, CONST_CS | CONST_PERSISTENT);
674 REGISTER_LONG_CONSTANT("MYSQLI_GROUP_FLAG", GROUP_FLAG, CONST_CS | CONST_PERSISTENT);
675 REGISTER_LONG_CONSTANT("MYSQLI_ENUM_FLAG", ENUM_FLAG, CONST_CS | CONST_PERSISTENT);
676 REGISTER_LONG_CONSTANT("MYSQLI_BINARY_FLAG", BINARY_FLAG, CONST_CS | CONST_PERSISTENT);
677 REGISTER_LONG_CONSTANT("MYSQLI_NO_DEFAULT_VALUE_FLAG", NO_DEFAULT_VALUE_FLAG, CONST_CS | CONST_PERSISTENT);
678
679 #if MYSQL_VERSION_ID < 60000 || MYSQL_VERSION_ID > 60003 || defined(MYSQLI_USE_MYSQLND)
680 REGISTER_LONG_CONSTANT("MYSQLI_ON_UPDATE_NOW_FLAG", ON_UPDATE_NOW_FLAG, CONST_CS | CONST_PERSISTENT);
681 #endif
682
683 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DECIMAL", FIELD_TYPE_DECIMAL, CONST_CS | CONST_PERSISTENT);
684 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TINY", FIELD_TYPE_TINY, CONST_CS | CONST_PERSISTENT);
685 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_SHORT", FIELD_TYPE_SHORT, CONST_CS | CONST_PERSISTENT);
686 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONG", FIELD_TYPE_LONG, CONST_CS | CONST_PERSISTENT);
687 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_FLOAT", FIELD_TYPE_FLOAT, CONST_CS | CONST_PERSISTENT);
688 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DOUBLE", FIELD_TYPE_DOUBLE, CONST_CS | CONST_PERSISTENT);
689 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NULL", FIELD_TYPE_NULL, CONST_CS | CONST_PERSISTENT);
690 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TIMESTAMP", FIELD_TYPE_TIMESTAMP, CONST_CS | CONST_PERSISTENT);
691 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONGLONG", FIELD_TYPE_LONGLONG, CONST_CS | CONST_PERSISTENT);
692 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_INT24", FIELD_TYPE_INT24, CONST_CS | CONST_PERSISTENT);
693 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DATE", FIELD_TYPE_DATE, CONST_CS | CONST_PERSISTENT);
694 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TIME", FIELD_TYPE_TIME, CONST_CS | CONST_PERSISTENT);
695 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_DATETIME", FIELD_TYPE_DATETIME , CONST_CS | CONST_PERSISTENT);
696 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_YEAR", FIELD_TYPE_YEAR, CONST_CS | CONST_PERSISTENT);
697 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NEWDATE", FIELD_TYPE_NEWDATE, CONST_CS | CONST_PERSISTENT);
698 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_ENUM", FIELD_TYPE_ENUM, CONST_CS | CONST_PERSISTENT);
699 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_SET", FIELD_TYPE_SET, CONST_CS | CONST_PERSISTENT);
700 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_TINY_BLOB", FIELD_TYPE_TINY_BLOB, CONST_CS | CONST_PERSISTENT);
701 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_MEDIUM_BLOB", FIELD_TYPE_MEDIUM_BLOB, CONST_CS | CONST_PERSISTENT);
702 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_LONG_BLOB", FIELD_TYPE_LONG_BLOB, CONST_CS | CONST_PERSISTENT);
703 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_BLOB", FIELD_TYPE_BLOB, CONST_CS | CONST_PERSISTENT);
704 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_VAR_STRING", FIELD_TYPE_VAR_STRING, CONST_CS | CONST_PERSISTENT);
705 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_STRING", FIELD_TYPE_STRING, CONST_CS | CONST_PERSISTENT);
706 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_CHAR", FIELD_TYPE_CHAR, CONST_CS | CONST_PERSISTENT);
707 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_INTERVAL", FIELD_TYPE_INTERVAL, CONST_CS | CONST_PERSISTENT);
708 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_GEOMETRY", FIELD_TYPE_GEOMETRY, CONST_CS | CONST_PERSISTENT);
709 #ifdef FIELD_TYPE_JSON
710 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_JSON", FIELD_TYPE_JSON, CONST_CS | CONST_PERSISTENT);
711 #endif
712 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_NEWDECIMAL", FIELD_TYPE_NEWDECIMAL, CONST_CS | CONST_PERSISTENT);
713 REGISTER_LONG_CONSTANT("MYSQLI_TYPE_BIT", FIELD_TYPE_BIT, CONST_CS | CONST_PERSISTENT);
714
715 REGISTER_LONG_CONSTANT("MYSQLI_SET_CHARSET_NAME", MYSQL_SET_CHARSET_NAME, CONST_CS | CONST_PERSISTENT);
716 REGISTER_LONG_CONSTANT("MYSQLI_SET_CHARSET_DIR", MYSQL_SET_CHARSET_DIR, CONST_CS | CONST_PERSISTENT);
717
718 /* bind support */
719 REGISTER_LONG_CONSTANT("MYSQLI_NO_DATA", MYSQL_NO_DATA, CONST_CS | CONST_PERSISTENT | CONST_DEPRECATED);
720 #ifdef MYSQL_DATA_TRUNCATED
721 REGISTER_LONG_CONSTANT("MYSQLI_DATA_TRUNCATED", MYSQL_DATA_TRUNCATED, CONST_CS | CONST_PERSISTENT | CONST_DEPRECATED);
722 #endif
723
724 /* reporting */
725 REGISTER_LONG_CONSTANT("MYSQLI_REPORT_INDEX", MYSQLI_REPORT_INDEX, CONST_CS | CONST_PERSISTENT);
726 REGISTER_LONG_CONSTANT("MYSQLI_REPORT_ERROR", MYSQLI_REPORT_ERROR, CONST_CS | CONST_PERSISTENT);
727 REGISTER_LONG_CONSTANT("MYSQLI_REPORT_STRICT", MYSQLI_REPORT_STRICT, CONST_CS | CONST_PERSISTENT);
728 REGISTER_LONG_CONSTANT("MYSQLI_REPORT_ALL", MYSQLI_REPORT_ALL, CONST_CS | CONST_PERSISTENT);
729 REGISTER_LONG_CONSTANT("MYSQLI_REPORT_OFF", 0, CONST_CS | CONST_PERSISTENT);
730
731 /* We use non-nested macros with expansion, as VC has problems */
732 #ifdef MYSQLI_USE_MYSQLND
733 REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", MYSQLND_DBG_ENABLED, CONST_CS | CONST_PERSISTENT);
734 #else
735 #ifdef DBUG_ON
736 REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 1, CONST_CS | CONST_PERSISTENT);
737 #else
738 REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 0, CONST_CS | CONST_PERSISTENT);
739 #endif
740 #endif
741
742 REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED", SERVER_QUERY_NO_GOOD_INDEX_USED, CONST_CS | CONST_PERSISTENT | CONST_DEPRECATED);
743 REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_NO_INDEX_USED", SERVER_QUERY_NO_INDEX_USED, CONST_CS | CONST_PERSISTENT | CONST_DEPRECATED);
744 #ifdef SERVER_QUERY_WAS_SLOW
745 REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_WAS_SLOW", SERVER_QUERY_WAS_SLOW, CONST_CS | CONST_PERSISTENT | CONST_DEPRECATED);
746 #endif
747 #ifdef SERVER_PS_OUT_PARAMS
748 REGISTER_LONG_CONSTANT("MYSQLI_SERVER_PS_OUT_PARAMS", SERVER_PS_OUT_PARAMS, CONST_CS | CONST_PERSISTENT | CONST_DEPRECATED);
749 #endif
750
751 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_GRANT", REFRESH_GRANT, CONST_CS | CONST_PERSISTENT);
752 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_LOG", REFRESH_LOG, CONST_CS | CONST_PERSISTENT);
753 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_TABLES", REFRESH_TABLES, CONST_CS | CONST_PERSISTENT);
754 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_HOSTS", REFRESH_HOSTS, CONST_CS | CONST_PERSISTENT);
755 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_STATUS", REFRESH_STATUS, CONST_CS | CONST_PERSISTENT);
756 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_THREADS", REFRESH_THREADS, CONST_CS | CONST_PERSISTENT);
757 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_REPLICA", REFRESH_SLAVE, CONST_CS | CONST_PERSISTENT);
758 /* temporarily for backward compatibility */
759 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_SLAVE", REFRESH_SLAVE, CONST_CS | CONST_PERSISTENT);
760 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_MASTER", REFRESH_MASTER, CONST_CS | CONST_PERSISTENT);
761 #ifdef REFRESH_BACKUP_LOG
762 REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_BACKUP_LOG", REFRESH_BACKUP_LOG, CONST_CS | CONST_PERSISTENT);
763 #endif
764
765
766 REGISTER_LONG_CONSTANT("MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT", TRANS_START_WITH_CONSISTENT_SNAPSHOT, CONST_CS | CONST_PERSISTENT);
767 REGISTER_LONG_CONSTANT("MYSQLI_TRANS_START_READ_WRITE", TRANS_START_READ_WRITE, CONST_CS | CONST_PERSISTENT);
768 REGISTER_LONG_CONSTANT("MYSQLI_TRANS_START_READ_ONLY", TRANS_START_READ_ONLY, CONST_CS | CONST_PERSISTENT);
769
770 REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_AND_CHAIN", TRANS_COR_AND_CHAIN, CONST_CS | CONST_PERSISTENT);
771 REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_AND_NO_CHAIN", TRANS_COR_AND_NO_CHAIN, CONST_CS | CONST_PERSISTENT);
772 REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_RELEASE", TRANS_COR_RELEASE, CONST_CS | CONST_PERSISTENT);
773 REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_NO_RELEASE", TRANS_COR_NO_RELEASE, CONST_CS | CONST_PERSISTENT);
774
775 #ifdef MARIADB_BASE_VERSION
776 REGISTER_BOOL_CONSTANT("MYSQLI_IS_MARIADB", 1, CONST_CS | CONST_PERSISTENT);
777 #else
778 REGISTER_BOOL_CONSTANT("MYSQLI_IS_MARIADB", 0, CONST_CS | CONST_PERSISTENT);
779 #endif
780
781
782 #ifdef MYSQLI_USE_MYSQLND
783 mysqlnd_reverse_api_register_api(&mysqli_reverse_api);
784 #endif
785
786 return SUCCESS;
787 }
788 /* }}} */
789
790 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(mysqli)791 PHP_MSHUTDOWN_FUNCTION(mysqli)
792 {
793 #ifndef MYSQLI_USE_MYSQLND
794 #ifdef PHP_WIN32
795 zend_ulong client_ver = mysql_get_client_version();
796 /*
797 Can't call mysql_server_end() multiple times prior to 5.0.46 on Windows.
798 PHP bug#41350 MySQL bug#25621
799 */
800 if ((client_ver >= 50046 && client_ver < 50100) || client_ver > 50122) {
801 mysql_server_end();
802 }
803 #else
804 mysql_server_end();
805 #endif
806 #endif
807
808 zend_hash_destroy(&mysqli_driver_properties);
809 zend_hash_destroy(&mysqli_result_properties);
810 zend_hash_destroy(&mysqli_stmt_properties);
811 zend_hash_destroy(&mysqli_warning_properties);
812 zend_hash_destroy(&mysqli_link_properties);
813 zend_hash_destroy(&classes);
814
815 UNREGISTER_INI_ENTRIES();
816 return SUCCESS;
817 }
818 /* }}} */
819
820 /* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(mysqli)821 PHP_RINIT_FUNCTION(mysqli)
822 {
823 #if !defined(MYSQLI_USE_MYSQLND) && defined(ZTS)
824 if (mysql_thread_init()) {
825 return FAILURE;
826 }
827 #endif
828 MyG(error_msg) = NULL;
829 MyG(error_no) = 0;
830 MyG(report_mode) = MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT;
831
832 return SUCCESS;
833 }
834 /* }}} */
835
836 #if defined(A0) && defined(MYSQLI_USE_MYSQLND)
php_mysqli_persistent_helper_for_every(void * p)837 static void php_mysqli_persistent_helper_for_every(void *p)
838 {
839 mysqlnd_end_psession((MYSQLND *) p);
840 } /* }}} */
841
842
php_mysqli_persistent_helper_once(zend_rsrc_list_entry * le)843 static int php_mysqli_persistent_helper_once(zend_rsrc_list_entry *le)
844 {
845 if (le->type == php_le_pmysqli()) {
846 mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
847 zend_ptr_stack_apply(&plist->free_links, php_mysqli_persistent_helper_for_every);
848 }
849 return ZEND_HASH_APPLY_KEEP;
850 } /* }}} */
851 #endif
852
853
854 /* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(mysqli)855 PHP_RSHUTDOWN_FUNCTION(mysqli)
856 {
857 /* check persistent connections, move used to free */
858
859 #if !defined(MYSQLI_USE_MYSQLND) && defined(ZTS)
860 mysql_thread_end();
861 #endif
862 if (MyG(error_msg)) {
863 efree(MyG(error_msg));
864 }
865 #if defined(A0) && defined(MYSQLI_USE_MYSQLND)
866 /* psession is being called when the connection is freed - explicitly or implicitly */
867 zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysqli_persistent_helper_once);
868 #endif
869 return SUCCESS;
870 }
871 /* }}} */
872
873
874 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(mysqli)875 PHP_MINFO_FUNCTION(mysqli)
876 {
877 char buf[32];
878
879 php_info_print_table_start();
880 php_info_print_table_header(2, "MysqlI Support", "enabled");
881 php_info_print_table_row(2, "Client API library version", mysql_get_client_info());
882 snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MyG(num_active_persistent));
883 php_info_print_table_row(2, "Active Persistent Links", buf);
884 snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MyG(num_inactive_persistent));
885 php_info_print_table_row(2, "Inactive Persistent Links", buf);
886 snprintf(buf, sizeof(buf), ZEND_LONG_FMT, MyG(num_links));
887 php_info_print_table_row(2, "Active Links", buf);
888 #ifndef MYSQLI_USE_MYSQLND
889 php_info_print_table_row(2, "Client API header version", MYSQL_SERVER_VERSION);
890 php_info_print_table_row(2, "MYSQLI_SOCKET", MYSQL_UNIX_ADDR);
891 #endif
892 php_info_print_table_end();
893
894 DISPLAY_INI_ENTRIES();
895 }
896 /* }}} */
897
898
899 /* Dependencies */
900 static const zend_module_dep mysqli_deps[] = {
901 ZEND_MOD_REQUIRED("spl")
902 #ifdef MYSQLI_USE_MYSQLND
903 ZEND_MOD_REQUIRED("mysqlnd")
904 #endif
905 ZEND_MOD_END
906 };
907
908 /* {{{ mysqli_module_entry */
909 zend_module_entry mysqli_module_entry = {
910 STANDARD_MODULE_HEADER_EX, NULL,
911 mysqli_deps,
912 "mysqli",
913 ext_functions,
914 PHP_MINIT(mysqli),
915 PHP_MSHUTDOWN(mysqli),
916 PHP_RINIT(mysqli),
917 PHP_RSHUTDOWN(mysqli),
918 PHP_MINFO(mysqli),
919 PHP_MYSQLI_VERSION,
920 PHP_MODULE_GLOBALS(mysqli),
921 PHP_GINIT(mysqli),
922 NULL,
923 NULL,
924 STANDARD_MODULE_PROPERTIES_EX
925 };
926 /* }}} */
927
928 #ifdef COMPILE_DL_MYSQLI
929 #ifdef ZTS
930 ZEND_TSRMLS_CACHE_DEFINE()
931 #endif
ZEND_GET_MODULE(mysqli)932 ZEND_GET_MODULE(mysqli)
933 #endif
934
935
936 PHP_METHOD(mysqli_stmt, __construct)
937 {
938 MY_MYSQL *mysql;
939 zval *mysql_link;
940 MY_STMT *stmt;
941 MYSQLI_RESOURCE *mysqli_resource;
942 char *statement = NULL;
943 size_t statement_len;
944
945 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!", &mysql_link, mysqli_link_class_entry, &statement, &statement_len) == FAILURE) {
946 RETURN_THROWS();
947 }
948 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
949
950 stmt = (MY_STMT *) ecalloc(1, sizeof(MY_STMT));
951
952 if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
953 efree(stmt);
954 RETURN_FALSE;
955 }
956
957 #ifndef MYSQLI_USE_MYSQLND
958 ZVAL_COPY(&stmt->link_handle, mysql_link);
959 #endif
960
961 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
962 mysqli_resource->ptr = (void *)stmt;
963 mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
964
965 MYSQLI_REGISTER_RESOURCE_EX(mysqli_resource, getThis());
966
967 if (statement) {
968 if(mysql_stmt_prepare(stmt->stmt, statement, statement_len)) {
969 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
970 RETURN_FALSE;
971 }
972 mysqli_resource->status = MYSQLI_STATUS_VALID;
973 }
974 }
975
PHP_METHOD(mysqli_result,__construct)976 PHP_METHOD(mysqli_result, __construct)
977 {
978 MY_MYSQL *mysql;
979 MYSQL_RES *result = NULL;
980 zval *mysql_link;
981 MYSQLI_RESOURCE *mysqli_resource;
982 zend_long resmode = MYSQLI_STORE_RESULT;
983
984 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &mysql_link, mysqli_link_class_entry, &resmode) == FAILURE) {
985 RETURN_THROWS();
986 }
987
988 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
989
990 switch (resmode) {
991 case MYSQLI_STORE_RESULT:
992 result = mysql_store_result(mysql->mysql);
993 break;
994 case MYSQLI_USE_RESULT:
995 result = mysql_use_result(mysql->mysql);
996 break;
997 default:
998 zend_argument_value_error(2, "must be either MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT");
999 RETURN_THROWS();
1000 }
1001
1002 if (!result) {
1003 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1004 RETURN_FALSE;
1005 }
1006
1007 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1008 mysqli_resource->ptr = (void *)result;
1009 mysqli_resource->status = MYSQLI_STATUS_VALID;
1010
1011 MYSQLI_REGISTER_RESOURCE_EX(mysqli_resource, getThis());
1012 }
1013
PHP_METHOD(mysqli_result,getIterator)1014 PHP_METHOD(mysqli_result, getIterator)
1015 {
1016 if (zend_parse_parameters_none() == FAILURE) {
1017 RETURN_THROWS();
1018 }
1019
1020 zend_create_internal_iterator_zval(return_value, ZEND_THIS);
1021 }
1022
1023 /* {{{ php_mysqli_fetch_into_hash_aux */
php_mysqli_fetch_into_hash_aux(zval * return_value,MYSQL_RES * result,zend_long fetchtype)1024 void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, zend_long fetchtype)
1025 {
1026 #ifndef MYSQLI_USE_MYSQLND
1027 MYSQL_ROW row;
1028 unsigned int i, num_fields;
1029 MYSQL_FIELD *fields;
1030 unsigned long *field_len;
1031
1032 if (!(row = mysql_fetch_row(result))) {
1033 RETURN_NULL();
1034 }
1035
1036 if (fetchtype & MYSQLI_ASSOC) {
1037 fields = mysql_fetch_fields(result);
1038 }
1039
1040 array_init(return_value);
1041 field_len = mysql_fetch_lengths(result);
1042 num_fields = mysql_num_fields(result);
1043
1044 for (i = 0; i < num_fields; i++) {
1045 if (row[i]) {
1046 zval res;
1047
1048 if (mysql_fetch_field_direct(result, i)->type == MYSQL_TYPE_BIT) {
1049 my_ulonglong llval;
1050 char tmp[22];
1051 switch (field_len[i]) {
1052 case 8:llval = (my_ulonglong) bit_uint8korr(row[i]);break;
1053 case 7:llval = (my_ulonglong) bit_uint7korr(row[i]);break;
1054 case 6:llval = (my_ulonglong) bit_uint6korr(row[i]);break;
1055 case 5:llval = (my_ulonglong) bit_uint5korr(row[i]);break;
1056 case 4:llval = (my_ulonglong) bit_uint4korr(row[i]);break;
1057 case 3:llval = (my_ulonglong) bit_uint3korr(row[i]);break;
1058 case 2:llval = (my_ulonglong) bit_uint2korr(row[i]);break;
1059 case 1:llval = (my_ulonglong) uint1korr(row[i]);break;
1060 EMPTY_SWITCH_DEFAULT_CASE()
1061 }
1062 /* even though lval is declared as unsigned, the value
1063 * may be negative. Therefore we cannot use MYSQLI_LLU_SPEC and must
1064 * use MYSQLI_LL_SPEC.
1065 */
1066 snprintf(tmp, sizeof(tmp), (mysql_fetch_field_direct(result, i)->flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1067 ZVAL_STRING(&res, tmp);
1068 } else {
1069 ZVAL_STRINGL(&res, row[i], field_len[i]);
1070 }
1071
1072 if (fetchtype & MYSQLI_NUM) {
1073 add_index_zval(return_value, i, &res);
1074 }
1075 if (fetchtype & MYSQLI_ASSOC) {
1076 if (fetchtype & MYSQLI_NUM && Z_REFCOUNTED(res)) {
1077 Z_ADDREF(res);
1078 }
1079 add_assoc_zval(return_value, fields[i].name, &res);
1080 }
1081 } else {
1082 if (fetchtype & MYSQLI_NUM) {
1083 add_index_null(return_value, i);
1084 }
1085 if (fetchtype & MYSQLI_ASSOC) {
1086 add_assoc_null(return_value, fields[i].name);
1087 }
1088 }
1089 }
1090 #else
1091 mysqlnd_fetch_into(result, ((fetchtype & MYSQLI_NUM)? MYSQLND_FETCH_NUM:0) | ((fetchtype & MYSQLI_ASSOC)? MYSQLND_FETCH_ASSOC:0), return_value);
1092 /* TODO: We don't have access to the connection object at this point, so we use low-level
1093 * mysqlnd APIs to access the error information. We should try to pass through the connection
1094 * object instead. */
1095 if (MyG(report_mode) & MYSQLI_REPORT_ERROR) {
1096 MYSQLND_CONN_DATA *conn = result->conn;
1097 unsigned error_no = conn->m->get_error_no(conn);
1098 if (error_no) {
1099 php_mysqli_report_error(
1100 conn->m->get_sqlstate(conn), error_no, conn->m->get_error_str(conn));
1101 }
1102 }
1103 #endif
1104 }
1105 /* }}} */
1106
1107 /* TODO Split this up */
1108 /* {{{ php_mysqli_fetch_into_hash */
php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS,int override_flags,int into_object)1109 void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object)
1110 {
1111 MYSQL_RES *result;
1112 zval *mysql_result;
1113 zend_long fetchtype;
1114 zval *ctor_params = NULL;
1115 zend_class_entry *ce = NULL;
1116
1117 if (into_object) {
1118 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|Ca", &mysql_result, mysqli_result_class_entry, &ce, &ctor_params) == FAILURE) {
1119 RETURN_THROWS();
1120 }
1121 if (ce == NULL) {
1122 ce = zend_standard_class_def;
1123 }
1124 if (UNEXPECTED(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1125 zend_throw_error(NULL, "Class %s cannot be instantiated", ZSTR_VAL(ce->name));
1126 RETURN_THROWS();
1127 }
1128 fetchtype = MYSQLI_ASSOC;
1129 } else {
1130 if (override_flags) {
1131 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1132 RETURN_THROWS();
1133 }
1134 fetchtype = override_flags;
1135 } else {
1136 fetchtype = MYSQLI_BOTH;
1137 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) {
1138 RETURN_THROWS();
1139 }
1140 }
1141 }
1142 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1143
1144 if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
1145 zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_NUM, MYSQLI_ASSOC, or MYSQLI_BOTH");
1146 RETURN_THROWS();
1147 }
1148
1149 php_mysqli_fetch_into_hash_aux(return_value, result, fetchtype);
1150
1151 if (into_object && Z_TYPE_P(return_value) == IS_ARRAY) {
1152 zval dataset, retval;
1153 zend_fcall_info fci;
1154 zend_fcall_info_cache fcc;
1155
1156 ZVAL_COPY_VALUE(&dataset, return_value);
1157
1158 object_init_ex(return_value, ce);
1159 HashTable *prop_table = zend_symtable_to_proptable(Z_ARR(dataset));
1160 zval_ptr_dtor(&dataset);
1161 if (!ce->default_properties_count && !ce->__set) {
1162 Z_OBJ_P(return_value)->properties = prop_table;
1163 } else {
1164 zend_merge_properties(return_value, prop_table);
1165 zend_array_release(prop_table);
1166 }
1167
1168 if (ce->constructor) {
1169 fci.size = sizeof(fci);
1170 ZVAL_UNDEF(&fci.function_name);
1171 fci.object = Z_OBJ_P(return_value);
1172 fci.retval = &retval;
1173 fci.params = NULL;
1174 fci.param_count = 0;
1175 fci.named_params = NULL;
1176
1177 if (ctor_params) {
1178 if (zend_fcall_info_args(&fci, ctor_params) == FAILURE) {
1179 ZEND_UNREACHABLE();
1180 }
1181 }
1182
1183 fcc.function_handler = ce->constructor;
1184 fcc.called_scope = Z_OBJCE_P(return_value);
1185 fcc.object = Z_OBJ_P(return_value);
1186
1187 if (zend_call_function(&fci, &fcc) == FAILURE) {
1188 zend_throw_exception_ex(zend_ce_exception, 0, "Could not execute %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
1189 } else {
1190 zval_ptr_dtor(&retval);
1191 }
1192 zend_fcall_info_args_clear(&fci, 1);
1193 } else if (ctor_params && zend_hash_num_elements(Z_ARRVAL_P(ctor_params)) > 0) {
1194 zend_argument_error(zend_ce_exception, ERROR_ARG_POS(3),
1195 "must be empty when the specified class (%s) does not have a constructor",
1196 ZSTR_VAL(ce->name)
1197 );
1198 }
1199 }
1200 }
1201 /* }}} */
1202