xref: /PHP-8.1/ext/mysqli/mysqli.c (revision 5b603709)
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