1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) The PHP Group                                          |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Georg Richter <georg@php.net>                               |
16   |          Andrey Hristov <andrey@php.net>                             |
17   |          Ulf Wendel <uw@php.net>                                     |
18   +----------------------------------------------------------------------+
19 */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <signal.h>
26 
27 #include "php.h"
28 #include "php_ini.h"
29 #include "php_globals.h"
30 #include "ext/standard/info.h"
31 #include "zend_smart_str.h"
32 #include "php_mysqli_structs.h"
33 #include "mysqli_priv.h"
34 #include "ext/mysqlnd/mysql_float_to_double.h"
35 
36 
37 #if !defined(MYSQLI_USE_MYSQLND)
38 /* {{{ mysqli_tx_cor_options_to_string */
mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str * str, const uint32_t mode)39 static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str * str, const uint32_t mode)
40 {
41 	if (mode & TRANS_COR_AND_CHAIN && !(mode & TRANS_COR_AND_NO_CHAIN)) {
42 		if (str->s && ZSTR_LEN(str->s)) {
43 			smart_str_appendl(str, " ", sizeof(" ") - 1);
44 		}
45 		smart_str_appendl(str, "AND CHAIN", sizeof("AND CHAIN") - 1);
46 	} else if (mode & TRANS_COR_AND_NO_CHAIN && !(mode & TRANS_COR_AND_CHAIN)) {
47 		if (str->s && ZSTR_LEN(str->s)) {
48 			smart_str_appendl(str, " ", sizeof(" ") - 1);
49 		}
50 		smart_str_appendl(str, "AND NO CHAIN", sizeof("AND NO CHAIN") - 1);
51 	}
52 
53 	if (mode & TRANS_COR_RELEASE && !(mode & TRANS_COR_NO_RELEASE)) {
54 		if (str->s && ZSTR_LEN(str->s)) {
55 			smart_str_appendl(str, " ", sizeof(" ") - 1);
56 		}
57 		smart_str_appendl(str, "RELEASE", sizeof("RELEASE") - 1);
58 	} else if (mode & TRANS_COR_NO_RELEASE && !(mode & TRANS_COR_RELEASE)) {
59 		if (str->s && ZSTR_LEN(str->s)) {
60 			smart_str_appendl(str, " ", sizeof(" ") - 1);
61 		}
62 		smart_str_appendl(str, "NO RELEASE", sizeof("NO RELEASE") - 1);
63 	}
64 	smart_str_0(str);
65 }
66 /* }}} */
67 
68 /* {{{ mysqlnd_escape_string_for_tx_name_in_comment */
69 char *
mysqli_escape_string_for_tx_name_in_comment(const char * const name)70 mysqli_escape_string_for_tx_name_in_comment(const char * const name)
71 {
72 	char * ret = NULL;
73 	if (name) {
74 		zend_bool warned = FALSE;
75 		const char * p_orig = name;
76 		char * p_copy;
77 		p_copy = ret = emalloc(strlen(name) + 1 + 2 + 2 + 1); /* space, open, close, NullS */
78 		*p_copy++ = ' ';
79 		*p_copy++ = '/';
80 		*p_copy++ = '*';
81 		while (1) {
82 			register char v = *p_orig;
83 			if (v == 0) {
84 				break;
85 			}
86 			if ((v >= '0' && v <= '9') ||
87 				(v >= 'a' && v <= 'z') ||
88 				(v >= 'A' && v <= 'Z') ||
89 				v == '-' ||
90 				v == '_' ||
91 				v == ' ' ||
92 				v == '=')
93 			{
94 				*p_copy++ = v;
95 			} else if (warned == FALSE) {
96 				php_error_docref(NULL, E_WARNING, "Transaction name truncated. Must be only [0-9A-Za-z\\-_=]+");
97 				warned = TRUE;
98 			}
99 			++p_orig;
100 		}
101 		*p_copy++ = '*';
102 		*p_copy++ = '/';
103 		*p_copy++ = 0;
104 	}
105 	return ret;
106 }
107 /* }}} */
108 
109 /* {{{ mysqli_commit_or_rollback_libmysql */
mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const uint32_t mode, const char * const name)110 static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const uint32_t mode, const char * const name)
111 {
112 	int ret;
113 	smart_str tmp_str = {0};
114 	mysqli_tx_cor_options_to_string(conn, &tmp_str, mode);
115 	smart_str_0(&tmp_str);
116 
117 	{
118 		char *query;
119 		char *name_esc = mysqli_escape_string_for_tx_name_in_comment(name);
120 		size_t query_len;
121 
122 		query_len = spprintf(&query, 0,
123 				(commit? "COMMIT%s %s":"ROLLBACK%s %s"), name_esc? name_esc:"", tmp_str.s? ZSTR_VAL(tmp_str.s):"");
124 		smart_str_free(&tmp_str);
125 		if (name_esc) {
126 			efree(name_esc);
127 			name_esc = NULL;
128 		}
129 
130 		ret = mysql_real_query(conn, query, query_len);
131 		efree(query);
132 	}
133 	return ret;
134 }
135 /* }}} */
136 #endif
137 
138 /* {{{ proto mixed mysqli_affected_rows(object link)
139    Get number of affected rows in previous MySQL operation */
PHP_FUNCTIONnull140 PHP_FUNCTION(mysqli_affected_rows)
141 {
142 	MY_MYSQL 		*mysql;
143 	zval  			*mysql_link;
144 	my_ulonglong	rc;
145 
146 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
147 		return;
148 	}
149 
150 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
151 
152 	rc = mysql_affected_rows(mysql->mysql);
153 	if (rc == (my_ulonglong) -1) {
154 		RETURN_LONG(-1);
155 	}
156 	MYSQLI_RETURN_LONG_INT(rc);
157 }
158 /* }}} */
159 
160 /* {{{ proto bool mysqli_autocommit(object link, bool mode)
161    Turn auto commit on or of */
PHP_FUNCTIONnull162 PHP_FUNCTION(mysqli_autocommit)
163 {
164 	MY_MYSQL	*mysql;
165 	zval		*mysql_link;
166 	zend_bool	automode;
167 
168 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ob", &mysql_link, mysqli_link_class_entry, &automode) == FAILURE) {
169 		return;
170 	}
171 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
172 
173 	if (mysql_autocommit(mysql->mysql, (my_bool)automode)) {
174 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
175 		RETURN_FALSE;
176 	}
177 	RETURN_TRUE;
178 }
179 /* }}} */
180 
181 /* {{{ mysqli_stmt_bind_param_do_bind */
182 #ifndef MYSQLI_USE_MYSQLND
183 static
mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars, zval *args, unsigned int start, const char * const types)184 int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars,
185 								   zval *args, unsigned int start, const char * const types)
186 {
187 	int				i, ofs;
188 	MYSQL_BIND		*bind;
189 	unsigned long	rc;
190 
191 	/* prevent leak if variables are already bound */
192 	if (stmt->param.var_cnt) {
193 		php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
194 	}
195 
196 	stmt->param.is_null = ecalloc(num_vars, sizeof(char));
197 	bind = (MYSQL_BIND *) ecalloc(num_vars, sizeof(MYSQL_BIND));
198 
199 	ofs = 0;
200 	for (i = start; i < argc; i++) {
201 		zval *param;
202 		if (Z_ISREF(args[i])) {
203 			param = Z_REFVAL(args[i]);
204 		} else {
205 			param = &args[i];
206 		}
207 		/* set specified type */
208 		switch (types[ofs]) {
209 			case 'd': /* Double */
210 				bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
211 				bind[ofs].buffer = &Z_DVAL_P(param);
212 				bind[ofs].is_null = &stmt->param.is_null[ofs];
213 				break;
214 
215 			case 'i': /* Integer */
216 #if SIZEOF_ZEND_LONG==8
217 				bind[ofs].buffer_type = MYSQL_TYPE_LONGLONG;
218 #elif SIZEOF_ZEND_LONG==4
219 				bind[ofs].buffer_type = MYSQL_TYPE_LONG;
220 #endif
221 				bind[ofs].buffer = &Z_LVAL_P(param);
222 				bind[ofs].is_null = &stmt->param.is_null[ofs];
223 				break;
224 
225 			case 'b': /* Blob (send data) */
226 				bind[ofs].buffer_type = MYSQL_TYPE_LONG_BLOB;
227 				/* don't initialize is_null and length to 0 because we use ecalloc */
228 				break;
229 
230 			case 's': /* string */
231 				bind[ofs].buffer_type = MYSQL_TYPE_VAR_STRING;
232 				/* don't initialize buffer and buffer_length because we use ecalloc */
233 				bind[ofs].is_null = &stmt->param.is_null[ofs];
234 				break;
235 
236 			default:
237 				php_error_docref(NULL, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[ofs], i+1);
238 				rc = 1;
239 				goto end_1;
240 		}
241 		ofs++;
242 	}
243 	rc = mysql_stmt_bind_param(stmt->stmt, bind);
244 
245 end_1:
246 	if (rc) {
247 		efree(stmt->param.is_null);
248 	} else {
249 		stmt->param.var_cnt = num_vars;
250 		stmt->param.vars = safe_emalloc(num_vars, sizeof(zval), 0);
251 		for (i = 0; i < num_vars; i++) {
252 			if (bind[i].buffer_type != MYSQL_TYPE_LONG_BLOB) {
253 				ZVAL_COPY(&stmt->param.vars[i], &args[i+start]);
254 			} else {
255 				ZVAL_UNDEF(&stmt->param.vars[i]);
256 			}
257 		}
258 	}
259 	efree(bind);
260 
261 	return rc;
262 }
263 #else
264 static
mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars, zval *args, unsigned int start, const char * const types)265 int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars,
266 								   zval *args, unsigned int start, const char * const types)
267 {
268 	unsigned int i;
269 	MYSQLND_PARAM_BIND	*params;
270 	enum_func_status	ret = FAIL;
271 
272 	/* If no params -> skip binding and return directly */
273 	if (argc == start) {
274 		return PASS;
275 	}
276 	params = mysqlnd_stmt_alloc_param_bind(stmt->stmt);
277 	if (!params) {
278 		goto end;
279 	}
280 	for (i = 0; i < (argc - start); i++) {
281 		zend_uchar type;
282 		switch (types[i]) {
283 			case 'd': /* Double */
284 				type = MYSQL_TYPE_DOUBLE;
285 				break;
286 			case 'i': /* Integer */
287 #if SIZEOF_ZEND_LONG==8
288 				type = MYSQL_TYPE_LONGLONG;
289 #elif SIZEOF_ZEND_LONG==4
290 				type = MYSQL_TYPE_LONG;
291 #endif
292 				break;
293 			case 'b': /* Blob (send data) */
294 				type = MYSQL_TYPE_LONG_BLOB;
295 				break;
296 			case 's': /* string */
297 				type = MYSQL_TYPE_VAR_STRING;
298 				break;
299 			default:
300 				/* We count parameters from 1 */
301 				php_error_docref(NULL, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[i], i + start + 1);
302 				ret = FAIL;
303 				mysqlnd_stmt_free_param_bind(stmt->stmt, params);
304 				goto end;
305 		}
306 		ZVAL_COPY_VALUE(&params[i].zv, &args[i + start]);
307 		params[i].type = type;
308 	}
309 	ret = mysqlnd_stmt_bind_param(stmt->stmt, params);
310 
311 end:
312 	return ret;
313 }
314 #endif
315 /* }}} */
316 
317 /* {{{ proto bool mysqli_stmt_bind_param(object stmt, string types, mixed variable [,mixed ...])
318    Bind variables to a prepared statement as parameters */
PHP_FUNCTIONnull319 PHP_FUNCTION(mysqli_stmt_bind_param)
320 {
321 	zval			*args;
322 	int				argc = ZEND_NUM_ARGS();
323 	int				num_vars;
324 	int				start = 2;
325 	MY_STMT			*stmt;
326 	zval			*mysql_stmt;
327 	char			*types;
328 	size_t			types_len;
329 	zend_ulong	rc;
330 
331 	/* calculate and check number of parameters */
332 	if (argc < 2) {
333 		/* there has to be at least one pair */
334 		WRONG_PARAM_COUNT;
335 	}
336 
337 	if (zend_parse_method_parameters((getThis()) ? 1:2, getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry,
338 									&types, &types_len) == FAILURE) {
339 		return;
340 	}
341 
342 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
343 
344 	num_vars = argc - 1;
345 	if (getThis()) {
346 		start = 1;
347 	} else {
348 		/* ignore handle parameter in procedural interface*/
349 		--num_vars;
350 	}
351 	if (!types_len) {
352 		php_error_docref(NULL, E_WARNING, "Invalid type or no types specified");
353 		RETURN_FALSE;
354 	}
355 
356 	if (types_len != (size_t)(argc - start)) {
357 		/* number of bind variables doesn't match number of elements in type definition string */
358 		php_error_docref(NULL, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables");
359 		RETURN_FALSE;
360 	}
361 
362 	if (types_len != mysql_stmt_param_count(stmt->stmt)) {
363 		php_error_docref(NULL, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement");
364 		RETURN_FALSE;
365 	}
366 
367 	args = safe_emalloc(argc, sizeof(zval), 0);
368 
369 	if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
370 		zend_wrong_param_count();
371 		rc = 1;
372 	} else {
373 		rc = mysqli_stmt_bind_param_do_bind(stmt, argc, num_vars, args, start, types);
374 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
375 	}
376 
377 	efree(args);
378 
379 	RETURN_BOOL(!rc);
380 }
381 /* }}} */
382 
383 /* {{{ mysqli_stmt_bind_result_do_bind */
384 #ifndef MYSQLI_USE_MYSQLND
385 /* TODO:
386    do_alloca, free_alloca
387 */
388 static int
mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)389 mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)
390 {
391 	MYSQL_BIND	*bind;
392 	int			i, ofs;
393 	int			var_cnt = argc;
394 	zend_long		col_type;
395 	zend_ulong		rc;
396 
397 	/* prevent leak if variables are already bound */
398 	if (stmt->result.var_cnt) {
399 		php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
400 	}
401 
402 	bind = (MYSQL_BIND *)ecalloc(var_cnt, sizeof(MYSQL_BIND));
403 	{
404 		int size;
405 		char *p = emalloc(size= var_cnt * (sizeof(char) + sizeof(VAR_BUFFER)));
406 		stmt->result.buf = (VAR_BUFFER *) p;
407 		stmt->result.is_null = p + var_cnt * sizeof(VAR_BUFFER);
408 		memset(p, 0, size);
409 	}
410 
411 	for (i = 0; i < var_cnt; i++) {
412 		ofs = i;
413 		col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING;
414 
415 		switch (col_type) {
416 			case MYSQL_TYPE_FLOAT:
417 				stmt->result.buf[ofs].type = IS_DOUBLE;
418 				stmt->result.buf[ofs].buflen = sizeof(float);
419 
420 				stmt->result.buf[ofs].val = (char *)emalloc(sizeof(float));
421 				bind[ofs].buffer_type = MYSQL_TYPE_FLOAT;
422 				bind[ofs].buffer = stmt->result.buf[ofs].val;
423 				bind[ofs].is_null = &stmt->result.is_null[ofs];
424 				break;
425 
426 			case MYSQL_TYPE_DOUBLE:
427 				stmt->result.buf[ofs].type = IS_DOUBLE;
428 				stmt->result.buf[ofs].buflen = sizeof(double);
429 
430 				/* allocate buffer for double */
431 				stmt->result.buf[ofs].val = (char *)emalloc(sizeof(double));
432 				bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
433 				bind[ofs].buffer = stmt->result.buf[ofs].val;
434 				bind[ofs].is_null = &stmt->result.is_null[ofs];
435 				break;
436 
437 			case MYSQL_TYPE_NULL:
438 				stmt->result.buf[ofs].type = IS_NULL;
439 				/*
440 				  don't initialize to 0 :
441 				  1. stmt->result.buf[ofs].buflen
442 				  2. bind[ofs].buffer
443 				  3. bind[ofs].buffer_length
444 				  because memory was allocated with ecalloc
445 				*/
446 				bind[ofs].buffer_type = MYSQL_TYPE_NULL;
447 				bind[ofs].is_null = &stmt->result.is_null[ofs];
448 				break;
449 
450 			case MYSQL_TYPE_SHORT:
451 			case MYSQL_TYPE_TINY:
452 			case MYSQL_TYPE_LONG:
453 			case MYSQL_TYPE_INT24:
454 			case MYSQL_TYPE_YEAR:
455 				stmt->result.buf[ofs].type = IS_LONG;
456 				/* don't set stmt->result.buf[ofs].buflen to 0, we used ecalloc */
457 				stmt->result.buf[ofs].val = (char *)emalloc(sizeof(int));
458 				bind[ofs].buffer_type = MYSQL_TYPE_LONG;
459 				bind[ofs].buffer = stmt->result.buf[ofs].val;
460 				bind[ofs].is_null = &stmt->result.is_null[ofs];
461 				bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
462 				break;
463 
464 			case MYSQL_TYPE_LONGLONG:
465 #if MYSQL_VERSION_ID > 50002 || defined(MYSQLI_USE_MYSQLND)
466 			case MYSQL_TYPE_BIT:
467 #endif
468 				stmt->result.buf[ofs].type = IS_STRING;
469 				stmt->result.buf[ofs].buflen = sizeof(my_ulonglong);
470 				stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
471 				bind[ofs].buffer_type = col_type;
472 				bind[ofs].buffer = stmt->result.buf[ofs].val;
473 				bind[ofs].is_null = &stmt->result.is_null[ofs];
474 				bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
475 				bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
476 				bind[ofs].length = &stmt->result.buf[ofs].output_len;
477 				break;
478 
479 			case MYSQL_TYPE_DATE:
480 			case MYSQL_TYPE_TIME:
481 			case MYSQL_TYPE_DATETIME:
482 			case MYSQL_TYPE_NEWDATE:
483 			case MYSQL_TYPE_VAR_STRING:
484 			case MYSQL_TYPE_STRING:
485 			case MYSQL_TYPE_TINY_BLOB:
486 			case MYSQL_TYPE_BLOB:
487 			case MYSQL_TYPE_MEDIUM_BLOB:
488 			case MYSQL_TYPE_LONG_BLOB:
489 			case MYSQL_TYPE_TIMESTAMP:
490 			case MYSQL_TYPE_DECIMAL:
491 			case MYSQL_TYPE_GEOMETRY:
492 #ifdef FIELD_TYPE_NEWDECIMAL
493 			case MYSQL_TYPE_NEWDECIMAL:
494 #endif
495 			{
496 #if MYSQL_VERSION_ID >= 50107
497 				/* Changed to my_bool in MySQL 5.1. See MySQL Bug #16144 */
498 				my_bool tmp;
499 #else
500 				zend_ulong tmp = 0;
501 #endif
502 				stmt->result.buf[ofs].type = IS_STRING;
503 				/*
504 					If the user has called $stmt->store_result() then we have asked
505 					max_length to be updated. this is done only for BLOBS because we don't want to allocate
506 					big chunkgs of memory 2^16 or 2^24
507 				*/
508 				if (stmt->stmt->fields[ofs].max_length == 0 &&
509 					!mysql_stmt_attr_get(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp) && !tmp)
510 				{
511 					/*
512 					  Allocate directly 256 because it's easier to allocate a bit more
513 					  than update max length even for text columns. Try SELECT UNION SELECT UNION with
514 					  different lengths and you will see that we get different lengths in stmt->stmt->fields[ofs].length
515 					  The just take 256 and saves us from realloc-ing.
516 					*/
517 					stmt->result.buf[ofs].buflen =
518 						(stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256;
519 
520 				} else {
521 					/*
522 						the user has called store_result(). if he does not there is no way to determine the
523 						libmysql does not allow us to allocate 0 bytes for a buffer so we try 1
524 					*/
525 					if (!(stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length))
526 						++stmt->result.buf[ofs].buflen;
527 				}
528 				stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
529 				bind[ofs].buffer_type = MYSQL_TYPE_STRING;
530 				bind[ofs].buffer = stmt->result.buf[ofs].val;
531 				bind[ofs].is_null = &stmt->result.is_null[ofs];
532 				bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
533 				bind[ofs].length = &stmt->result.buf[ofs].output_len;
534 				break;
535 			}
536 			default:
537 				php_error_docref(NULL, E_WARNING, "Server returned unknown type %ld. Probably your client library is incompatible with the server version you use!", col_type);
538 				break;
539 		}
540 	}
541 
542 	rc = mysql_stmt_bind_result(stmt->stmt, bind);
543 	MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
544 
545 	if (rc) {
546 		/* don't close the statement or subsequent usage (for example ->execute()) will lead to crash */
547 		for (i=0; i < var_cnt ; i++) {
548 			if (stmt->result.buf[i].val) {
549 				efree(stmt->result.buf[i].val);
550 			}
551 		}
552 		/* Don't free stmt->result.is_null because is_null & buf are one block of memory  */
553 		efree(stmt->result.buf);
554 	} else {
555 		stmt->result.var_cnt = var_cnt;
556 		stmt->result.vars = safe_emalloc((var_cnt), sizeof(zval), 0);
557 		for (i = 0; i < var_cnt; i++) {
558 			ZVAL_COPY(&stmt->result.vars[i], &args[i]);
559 		}
560 	}
561 	efree(bind);
562 
563 	return rc;
564 }
565 #else
566 static int
mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)567 mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)
568 {
569 	unsigned int i;
570 	MYSQLND_RESULT_BIND *params = mysqlnd_stmt_alloc_result_bind(stmt->stmt);
571 	if (params) {
572 		for (i = 0; i < argc; i++) {
573 			ZVAL_COPY_VALUE(&params[i].zv, &args[i]);
574 		}
575 		return mysqlnd_stmt_bind_result(stmt->stmt, params);
576 	}
577 	return FAIL;
578 }
579 #endif
580 /* }}} */
581 
582 /* {{{ proto bool mysqli_stmt_bind_result(object stmt, mixed var [,mixed ...])
583    Bind variables to a prepared statement for result storage */
PHP_FUNCTIONnull584 PHP_FUNCTION(mysqli_stmt_bind_result)
585 {
586 	zval		*args;
587 	int			argc;
588 	zend_ulong		rc;
589 	MY_STMT		*stmt;
590 	zval		*mysql_stmt;
591 
592 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O+", &mysql_stmt, mysqli_stmt_class_entry, &args, &argc) == FAILURE) {
593 		return;
594 	}
595 
596 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
597 
598 	if ((uint32_t)argc != mysql_stmt_field_count(stmt->stmt)) {
599 		php_error_docref(NULL, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statement");
600 		RETURN_FALSE;
601 	}
602 
603 	rc = mysqli_stmt_bind_result_do_bind(stmt, args, argc);
604 	RETURN_BOOL(!rc);
605 }
606 /* }}} */
607 
608 /* {{{ proto bool mysqli_change_user(object link, string user, string password, string database)
609    Change logged-in user of the active connection */
PHP_FUNCTIONnull610 PHP_FUNCTION(mysqli_change_user)
611 {
612 	MY_MYSQL	*mysql;
613 	zval		*mysql_link = NULL;
614 	char		*user, *password, *dbname;
615 	size_t			user_len, password_len, dbname_len;
616 	zend_ulong		rc;
617 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
618 	MY_CHARSET_INFO old_charset;
619 #endif
620 
621 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Osss!", &mysql_link, mysqli_link_class_entry, &user, &user_len, &password, &password_len, &dbname, &dbname_len) == FAILURE) {
622 		return;
623 	}
624 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
625 
626 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
627 	mysql_get_character_set_info(mysql->mysql, &old_charset);
628 #endif
629 
630 #if defined(MYSQLI_USE_MYSQLND)
631 	rc = mysqlnd_change_user_ex(mysql->mysql, user, password, dbname, FALSE, (size_t) password_len);
632 #else
633 	rc = mysql_change_user(mysql->mysql, user, password, dbname);
634 #endif
635 	MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
636 
637 	if (rc) {
638 		RETURN_FALSE;
639 	}
640 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
641 	if (mysql_get_server_version(mysql->mysql) < 50123L) {
642 		/*
643 		  Request the current charset, or it will be reset to the system one.
644 		  5.0 doesn't support it. Support added in 5.1.23 by fixing the following bug :
645 		  Bug #30472 libmysql doesn't reset charset, insert_id after succ. mysql_change_user() call
646 		*/
647 		rc = mysql_set_character_set(mysql->mysql, old_charset.csname);
648 	}
649 #endif
650 
651 	RETURN_TRUE;
652 }
653 /* }}} */
654 
655 /* {{{ proto string mysqli_character_set_name(object link)
656    Returns the name of the character set used for this connection */
PHP_FUNCTIONnull657 PHP_FUNCTION(mysqli_character_set_name)
658 {
659 	MY_MYSQL	*mysql;
660 	zval		*mysql_link;
661 	const char	*cs_name;
662 
663 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
664 		return;
665 	}
666 
667 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
668 	cs_name = mysql_character_set_name(mysql->mysql);
669 	if (cs_name) {
670 		RETURN_STRING(cs_name);
671 	}
672 }
673 /* }}} */
674 
675 /* {{{ php_mysqli_close */
php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status)676 void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status)
677 {
678 	if (resource_status > MYSQLI_STATUS_INITIALIZED) {
679 		MyG(num_links)--;
680 	}
681 
682 	if (!mysql->persistent) {
683 		mysqli_close(mysql->mysql, close_type);
684 	} else {
685 		zend_resource *le;
686 		if ((le = zend_hash_find_ptr(&EG(persistent_list), mysql->hash_key)) != NULL) {
687 			if (le->type == php_le_pmysqli()) {
688 				mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
689 #if defined(MYSQLI_USE_MYSQLND)
690 				mysqlnd_end_psession(mysql->mysql);
691 #endif
692 
693 				if (MyG(rollback_on_cached_plink) &&
694 #if !defined(MYSQLI_USE_MYSQLND)
695 					mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, TRANS_COR_NO_OPT, NULL))
696 #else
697 					FAIL == mysqlnd_rollback(mysql->mysql, TRANS_COR_NO_OPT, NULL))
698 #endif
699 				{
700 					mysqli_close(mysql->mysql, close_type);
701 				} else {
702 					zend_ptr_stack_push(&plist->free_links, mysql->mysql);
703 					MyG(num_inactive_persistent)++;
704 				}
705 				MyG(num_active_persistent)--;
706 			}
707 		}
708 		mysql->persistent = FALSE;
709 	}
710 	mysql->mysql = NULL;
711 
712 	php_clear_mysql(mysql);
713 }
714 /* }}} */
715 
716 /* {{{ proto bool mysqli_close(object link)
717    Close connection */
PHP_FUNCTIONnull718 PHP_FUNCTION(mysqli_close)
719 {
720 	zval		*mysql_link;
721 	MY_MYSQL	*mysql;
722 
723 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
724 		return;
725 	}
726 
727 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
728 
729 	php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, ((MYSQLI_RESOURCE *)(Z_MYSQLI_P(mysql_link))->ptr)->status);
730 	((MYSQLI_RESOURCE *)(Z_MYSQLI_P(mysql_link))->ptr)->status = MYSQLI_STATUS_UNKNOWN;
731 
732 	MYSQLI_CLEAR_RESOURCE(mysql_link);
733 	efree(mysql);
734 	RETURN_TRUE;
735 }
736 /* }}} */
737 
738 /* {{{ proto bool mysqli_commit(object link[, int flags [, string name ]])
739    Commit outstanding actions and close transaction */
PHP_FUNCTIONnull740 PHP_FUNCTION(mysqli_commit)
741 {
742 	MY_MYSQL	*mysql;
743 	zval		*mysql_link;
744 	zend_long		flags = TRANS_COR_NO_OPT;
745 	char *		name = NULL;
746 	size_t			name_len = 0;
747 
748 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
749 		return;
750 	}
751 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
752 
753 #if !defined(MYSQLI_USE_MYSQLND)
754 	if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name)) {
755 #else
756 	if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) {
757 #endif
758 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
759 		RETURN_FALSE;
760 	}
761 	RETURN_TRUE;
762 }
763 /* }}} */
764 
765 /* {{{ proto bool mysqli_data_seek(object result, int offset)
766    Move internal result pointer */
767 PHP_FUNCTION(mysqli_data_seek)
768 {
769 	MYSQL_RES	*result;
770 	zval		*mysql_result;
771 	zend_long		offset;
772 
773 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
774 		return;
775 	}
776 
777 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
778 
779 	if (mysqli_result_is_unbuffered(result)) {
780 		php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
781 		RETURN_FALSE;
782 	}
783 
784 	if (offset < 0 || (uint64_t)offset >= mysql_num_rows(result)) {
785 		RETURN_FALSE;
786 	}
787 
788 	mysql_data_seek(result, offset);
789 	RETURN_TRUE;
790 }
791 /* }}} */
792 
793 /* {{{ proto void mysqli_debug(string debug)
794 */
795 PHP_FUNCTION(mysqli_debug)
796 {
797 	char	*debug;
798 	size_t		debug_len;
799 
800 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &debug, &debug_len) == FAILURE) {
801 		return;
802 	}
803 
804 	mysql_debug(debug);
805 	RETURN_TRUE;
806 }
807 /* }}} */
808 
809 /* {{{ proto bool mysqli_dump_debug_info(object link)
810 */
811 PHP_FUNCTION(mysqli_dump_debug_info)
812 {
813 	MY_MYSQL	*mysql;
814 	zval		*mysql_link;
815 
816 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
817 		return;
818 	}
819 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
820 
821 	RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql))
822 }
823 /* }}} */
824 
825 /* {{{ proto int mysqli_errno(object link)
826    Returns the numerical value of the error message from previous MySQL operation */
827 PHP_FUNCTION(mysqli_errno)
828 {
829 	MY_MYSQL	*mysql;
830 	zval		*mysql_link;
831 
832 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
833 		return;
834 	}
835 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
836 	RETURN_LONG(mysql_errno(mysql->mysql));
837 }
838 /* }}} */
839 
840 /* {{{ proto string mysqli_error(object link)
841    Returns the text of the error message from previous MySQL operation */
842 PHP_FUNCTION(mysqli_error)
843 {
844 	MY_MYSQL	*mysql;
845 	zval		*mysql_link;
846 	const char	*err;
847 
848 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
849 		return;
850 	}
851 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
852 	err = mysql_error(mysql->mysql);
853 	if (err) {
854 		RETURN_STRING(err);
855 	}
856 }
857 /* }}} */
858 
859 /* {{{ proto bool mysqli_stmt_execute(object stmt)
860    Execute a prepared statement */
861 PHP_FUNCTION(mysqli_stmt_execute)
862 {
863 	MY_STMT		*stmt;
864 	zval		*mysql_stmt;
865 #ifndef MYSQLI_USE_MYSQLND
866 	unsigned int	i;
867 #endif
868 
869 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
870 		return;
871 	}
872 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
873 
874 #ifndef MYSQLI_USE_MYSQLND
875 	if (stmt->param.var_cnt) {
876 		int j;
877 		for (i = 0; i < stmt->param.var_cnt; i++) {
878 			if (!Z_ISREF(stmt->param.vars[i])) {
879 				continue;
880 			}
881 			for (j = i + 1; j < stmt->param.var_cnt; j++) {
882 				/* Oops, someone binding the same variable - clone */
883 				if (Z_ISREF(stmt->param.vars[j]) &&
884 					   	Z_REFVAL(stmt->param.vars[j]) == Z_REFVAL(stmt->param.vars[i])) {
885 					/*SEPARATE_ZVAL(&stmt->param.vars[j]);*/
886 					Z_DELREF_P(&stmt->param.vars[j]);
887 					ZVAL_COPY(&stmt->param.vars[j], Z_REFVAL(stmt->param.vars[j]));
888 					break;
889 				}
890 			}
891 		}
892 	}
893 	for (i = 0; i < stmt->param.var_cnt; i++) {
894 		if (!Z_ISUNDEF(stmt->param.vars[i])) {
895 			zval *param;
896 			if (Z_ISREF(stmt->param.vars[i])) {
897 				param = Z_REFVAL(stmt->param.vars[i]);
898 			} else {
899 				param = &stmt->param.vars[i];
900 			}
901 			if (!(stmt->param.is_null[i] = (Z_ISNULL_P(param)))) {
902 				switch (stmt->stmt->params[i].buffer_type) {
903 					case MYSQL_TYPE_VAR_STRING:
904 						if (!try_convert_to_string(param)) {
905 							return;
906 						}
907 
908 						stmt->stmt->params[i].buffer = Z_STRVAL_P(param);
909 						stmt->stmt->params[i].buffer_length = Z_STRLEN_P(param);
910 						break;
911 					case MYSQL_TYPE_DOUBLE:
912 						convert_to_double_ex(param);
913 						stmt->stmt->params[i].buffer = &Z_DVAL_P(param);
914 						break;
915 					case MYSQL_TYPE_LONGLONG:
916 					case MYSQL_TYPE_LONG:
917 						convert_to_long_ex(param);
918 						stmt->stmt->params[i].buffer = &Z_LVAL_P(param);
919 						break;
920 					default:
921 						break;
922 				}
923 			}
924 		}
925 	}
926 #endif
927 
928 	if (mysql_stmt_execute(stmt->stmt)) {
929 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
930 		RETVAL_FALSE;
931 	} else {
932 		RETVAL_TRUE;
933 	}
934 
935 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
936 		php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt));
937 	}
938 }
939 /* }}} */
940 
941 #ifndef MYSQLI_USE_MYSQLND
942 /* {{{ void mysqli_stmt_fetch_libmysql
943    Fetch results from a prepared statement into the bound variables */
944 void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
945 {
946 	MY_STMT		*stmt;
947 	zval			*mysql_stmt;
948 	unsigned int	i;
949 	zend_ulong			ret;
950 	unsigned int	uval;
951 	my_ulonglong	llval;
952 
953 
954 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
955 		return;
956 	}
957 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
958 
959 	/* reset buffers */
960 	for (i = 0; i < stmt->result.var_cnt; i++) {
961 		if (stmt->result.buf[i].type == IS_STRING) {
962 			memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen);
963 		}
964 	}
965 	ret = mysql_stmt_fetch(stmt->stmt);
966 #ifdef MYSQL_DATA_TRUNCATED
967 	if (!ret || ret == MYSQL_DATA_TRUNCATED) {
968 #else
969 	if (!ret) {
970 #endif
971 		for (i = 0; i < stmt->result.var_cnt; i++) {
972 			zval *result;
973 			/* it must be a reference, isn't it? */
974 			if (Z_ISREF(stmt->result.vars[i])) {
975 				result = &stmt->result.vars[i];
976 			} else {
977 				continue; // but be safe ...
978 			}
979 			/* Even if the string is of length zero there is one byte alloced so efree() in all cases */
980 			if (!stmt->result.is_null[i]) {
981 				switch (stmt->result.buf[i].type) {
982 					case IS_LONG:
983 						if ((stmt->stmt->fields[i].type == MYSQL_TYPE_LONG)
984 						    && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG))
985 						{
986 							/* unsigned int (11) */
987 							uval= *(unsigned int *) stmt->result.buf[i].val;
988 #if SIZEOF_ZEND_LONG==4
989 							if (uval > INT_MAX) {
990 								char *tmp, *p;
991 								int j = 10;
992 								tmp = emalloc(11);
993 								p= &tmp[9];
994 								do {
995 									*p-- = (uval % 10) + 48;
996 									uval = uval / 10;
997 								} while (--j > 0);
998 								tmp[10]= '\0';
999 								/* unsigned int > INT_MAX is 10 digits - ALWAYS */
1000 								ZEND_TRY_ASSIGN_REF_STRINGL(result, tmp, 10);
1001 								efree(tmp);
1002 								break;
1003 							}
1004 #endif
1005 						}
1006 						if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) {
1007 							ZEND_TRY_ASSIGN_REF_LONG(result, *(unsigned int *)stmt->result.buf[i].val);
1008 						} else {
1009 							ZEND_TRY_ASSIGN_REF_LONG(result, *(int *)stmt->result.buf[i].val);
1010 						}
1011 						break;
1012 					case IS_DOUBLE:
1013 					{
1014 						double dval;
1015 						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_FLOAT) {
1016 #ifndef NOT_FIXED_DEC
1017 # define NOT_FIXED_DEC 31
1018 #endif
1019 							dval = mysql_float_to_double(*(float *)stmt->result.buf[i].val,
1020 										(stmt->stmt->fields[i].decimals >= NOT_FIXED_DEC) ? -1 :
1021 										stmt->stmt->fields[i].decimals);
1022 						} else {
1023 							dval = *((double *)stmt->result.buf[i].val);
1024 						}
1025 
1026 						ZEND_TRY_ASSIGN_REF_DOUBLE(result, dval);
1027 						break;
1028 					}
1029 					case IS_STRING:
1030 						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
1031 #if MYSQL_VERSION_ID > 50002
1032 						 || stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT
1033 #endif
1034 						 ) {
1035 							my_bool uns = (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0;
1036 #if MYSQL_VERSION_ID > 50002
1037 							if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) {
1038 								switch (stmt->result.buf[i].output_len) {
1039 									case 8:llval = (my_ulonglong)  bit_uint8korr(stmt->result.buf[i].val);break;
1040 									case 7:llval = (my_ulonglong)  bit_uint7korr(stmt->result.buf[i].val);break;
1041 									case 6:llval = (my_ulonglong)  bit_uint6korr(stmt->result.buf[i].val);break;
1042 									case 5:llval = (my_ulonglong)  bit_uint5korr(stmt->result.buf[i].val);break;
1043 									case 4:llval = (my_ulonglong)  bit_uint4korr(stmt->result.buf[i].val);break;
1044 									case 3:llval = (my_ulonglong)  bit_uint3korr(stmt->result.buf[i].val);break;
1045 									case 2:llval = (my_ulonglong)  bit_uint2korr(stmt->result.buf[i].val);break;
1046 									case 1:llval = (my_ulonglong)  uint1korr(stmt->result.buf[i].val);break;
1047 								}
1048 							} else
1049 #endif
1050 							{
1051 								llval= *(my_ulonglong *) stmt->result.buf[i].val;
1052 							}
1053 #if SIZEOF_ZEND_LONG==8
1054 							if (uns && llval > 9223372036854775807L) {
1055 #elif SIZEOF_ZEND_LONG==4
1056 							if ((uns && llval > L64(2147483647)) ||
1057 								(!uns && (( L64(2147483647) < (my_longlong) llval) ||
1058 								(L64(-2147483648) > (my_longlong) llval))))
1059 							{
1060 #endif
1061 								char tmp[22];
1062 								/* even though lval is declared as unsigned, the value
1063 								 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
1064 								 * use MYSQLI_LL_SPEC.
1065 								 */
1066 								snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1067 								ZEND_TRY_ASSIGN_REF_STRING(result, tmp);
1068 							} else {
1069 								ZEND_TRY_ASSIGN_REF_LONG(result, llval);
1070 							}
1071 						} else {
1072 #if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002
1073 							if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) {
1074 								/* result was truncated */
1075 								ZEND_TRY_ASSIGN_REF_STRINGL(result, stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length);
1076 							} else {
1077 #else
1078 							{
1079 #endif
1080 								ZEND_TRY_ASSIGN_REF_STRINGL(result, stmt->result.buf[i].val, stmt->result.buf[i].output_len);
1081 							}
1082 						}
1083 						break;
1084 					default:
1085 						break;
1086 				}
1087 			} else {
1088 				ZEND_TRY_ASSIGN_REF_NULL(result);
1089 			}
1090 		}
1091 	} else {
1092 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1093 	}
1094 
1095 	switch (ret) {
1096 		case 0:
1097 #ifdef MYSQL_DATA_TRUNCATED
1098 		/* according to SQL standard truncation (e.g. loss of precision is
1099 		   not an error) - for detecting possible truncation you have to
1100 		   check mysqli_stmt_warning
1101 		*/
1102 		case MYSQL_DATA_TRUNCATED:
1103 #endif
1104 			RETURN_TRUE;
1105 		break;
1106 		case 1:
1107 			RETURN_FALSE;
1108 		break;
1109 		default:
1110 			RETURN_NULL();
1111 		break;
1112 	}
1113 }
1114 /* }}} */
1115 #else
1116 /* {{{ mixed mysqli_stmt_fetch_mysqlnd */
1117 void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)
1118 {
1119 	MY_STMT		*stmt;
1120 	zval		*mysql_stmt;
1121 	zend_bool	fetched_anything;
1122 
1123 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1124 		return;
1125 	}
1126 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1127 
1128 	if (FAIL == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) {
1129 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1130 		RETURN_BOOL(FALSE);
1131 	} else if (fetched_anything == TRUE) {
1132 		RETURN_BOOL(TRUE);
1133 	} else {
1134 		RETURN_NULL();
1135 	}
1136 }
1137 #endif
1138 /* }}} */
1139 
1140 /* {{{ proto mixed mysqli_stmt_fetch(object stmt)
1141    Fetch results from a prepared statement into the bound variables */
1142 PHP_FUNCTION(mysqli_stmt_fetch)
1143 {
1144 #if !defined(MYSQLI_USE_MYSQLND)
1145 	mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1146 #else
1147 	mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1148 #endif
1149 }
1150 /* }}} */
1151 
1152 /* {{{  php_add_field_properties */
1153 static void php_add_field_properties(zval *value, const MYSQL_FIELD *field)
1154 {
1155 #ifdef MYSQLI_USE_MYSQLND
1156 	add_property_str(value, "name", zend_string_copy(field->sname));
1157 #else
1158 	add_property_stringl(value, "name",(field->name ? field->name : ""), field->name_length);
1159 #endif
1160 
1161 	add_property_stringl(value, "orgname", (field->org_name ? field->org_name : ""), field->org_name_length);
1162 	add_property_stringl(value, "table", (field->table ? field->table : ""), field->table_length);
1163 	add_property_stringl(value, "orgtable", (field->org_table ? field->org_table : ""), field->org_table_length);
1164 	add_property_stringl(value, "def", (field->def ? field->def : ""), field->def_length);
1165 	add_property_stringl(value, "db", (field->db ? field->db : ""), field->db_length);
1166 
1167 	/* FIXME: manually set the catalog to "def" due to bug in
1168 	 * libmysqlclient which does not initialize field->catalog
1169 	 * and in addition, the catalog is always be "def"
1170 	 */
1171 	add_property_string(value, "catalog", "def");
1172 
1173 	add_property_long(value, "max_length", field->max_length);
1174 	add_property_long(value, "length", field->length);
1175 	add_property_long(value, "charsetnr", field->charsetnr);
1176 	add_property_long(value, "flags", field->flags);
1177 	add_property_long(value, "type", field->type);
1178 	add_property_long(value, "decimals", field->decimals);
1179 }
1180 /* }}} */
1181 
1182 /* {{{ proto mixed mysqli_fetch_field(object result)
1183    Get column information from a result and return as an object */
1184 PHP_FUNCTION(mysqli_fetch_field)
1185 {
1186 	MYSQL_RES	*result;
1187 	zval		*mysql_result;
1188 	const MYSQL_FIELD	*field;
1189 
1190 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1191 		return;
1192 	}
1193 
1194 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1195 
1196 	if (!(field = mysql_fetch_field(result))) {
1197 		RETURN_FALSE;
1198 	}
1199 
1200 	object_init(return_value);
1201 	php_add_field_properties(return_value, field);
1202 }
1203 /* }}} */
1204 
1205 /* {{{ proto mixed mysqli_fetch_fields(object result)
1206    Return array of objects containing field meta-data */
1207 PHP_FUNCTION(mysqli_fetch_fields)
1208 {
1209 	MYSQL_RES	*result;
1210 	zval		*mysql_result;
1211 	zval		obj;
1212 
1213 	unsigned int i, num_fields;
1214 
1215 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1216 		return;
1217 	}
1218 
1219 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1220 
1221 	array_init(return_value);
1222 	num_fields = mysql_num_fields(result);
1223 
1224 	for (i = 0; i < num_fields; i++) {
1225 		const MYSQL_FIELD *field = mysql_fetch_field_direct(result, i);
1226 
1227 		object_init(&obj);
1228 
1229 		php_add_field_properties(&obj, field);
1230 		add_index_zval(return_value, i, &obj);
1231 	}
1232 }
1233 /* }}} */
1234 
1235 /* {{{ proto mixed mysqli_fetch_field_direct(object result, int offset)
1236    Fetch meta-data for a single field */
1237 PHP_FUNCTION(mysqli_fetch_field_direct)
1238 {
1239 	MYSQL_RES	*result;
1240 	zval		*mysql_result;
1241 	const MYSQL_FIELD	*field;
1242 	zend_long		offset;
1243 
1244 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
1245 		return;
1246 	}
1247 
1248 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1249 
1250 	if (offset < 0 || offset >= (zend_long) mysql_num_fields(result)) {
1251 		php_error_docref(NULL, E_WARNING, "Field offset is invalid for resultset");
1252 		RETURN_FALSE;
1253 	}
1254 
1255 	if (!(field = mysql_fetch_field_direct(result,offset))) {
1256 		RETURN_FALSE;
1257 	}
1258 
1259 	object_init(return_value);
1260 	php_add_field_properties(return_value, field);
1261 }
1262 /* }}} */
1263 
1264 /* {{{ proto mixed mysqli_fetch_lengths(object result)
1265    Get the length of each output in a result */
1266 PHP_FUNCTION(mysqli_fetch_lengths)
1267 {
1268 	MYSQL_RES		*result;
1269 	zval			*mysql_result;
1270 	unsigned int	i, num_fields;
1271 #if defined(MYSQLI_USE_MYSQLND)
1272 	const size_t	*ret;
1273 #else
1274 	const zend_ulong *ret;
1275 #endif
1276 
1277 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1278 		return;
1279 	}
1280 
1281 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1282 
1283 	if (!(ret = mysql_fetch_lengths(result))) {
1284 		RETURN_FALSE;
1285 	}
1286 
1287 	array_init(return_value);
1288 	num_fields = mysql_num_fields(result);
1289 
1290 	for (i = 0; i < num_fields; i++) {
1291 		add_index_long(return_value, i, ret[i]);
1292 	}
1293 }
1294 /* }}} */
1295 
1296 /* {{{ proto array mysqli_fetch_row(object result)
1297    Get a result row as an enumerated array */
1298 PHP_FUNCTION(mysqli_fetch_row)
1299 {
1300 	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM, 0);
1301 }
1302 /* }}} */
1303 
1304 /* {{{ proto int mysqli_field_count(object link)
1305    Fetch the number of fields returned by the last query for the given link
1306 */
1307 PHP_FUNCTION(mysqli_field_count)
1308 {
1309 	MY_MYSQL	*mysql;
1310 	zval		*mysql_link;
1311 
1312 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1313 		return;
1314 	}
1315 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1316 
1317 	RETURN_LONG(mysql_field_count(mysql->mysql));
1318 }
1319 /* }}} */
1320 
1321 /* {{{ proto int mysqli_field_seek(object result, int fieldnr)
1322    Set result pointer to a specified field offset
1323 */
1324 PHP_FUNCTION(mysqli_field_seek)
1325 {
1326 	MYSQL_RES		*result;
1327 	zval			*mysql_result;
1328 	zend_long	fieldnr;
1329 
1330 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) {
1331 		return;
1332 	}
1333 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1334 
1335 	if (fieldnr < 0 || (uint32_t)fieldnr >= mysql_num_fields(result)) {
1336 		php_error_docref(NULL, E_WARNING, "Invalid field offset");
1337 		RETURN_FALSE;
1338 	}
1339 
1340 	mysql_field_seek(result, fieldnr);
1341 	RETURN_TRUE;
1342 }
1343 /* }}} */
1344 
1345 /* {{{ proto int mysqli_field_tell(object result)
1346    Get current field offset of result pointer */
1347 PHP_FUNCTION(mysqli_field_tell)
1348 {
1349 	MYSQL_RES	*result;
1350 	zval		*mysql_result;
1351 
1352 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1353 		return;
1354 	}
1355 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1356 
1357 	RETURN_LONG(mysql_field_tell(result));
1358 }
1359 /* }}} */
1360 
1361 /* {{{ proto void mysqli_free_result(object result)
1362    Free query result memory for the given result handle */
1363 PHP_FUNCTION(mysqli_free_result)
1364 {
1365 	MYSQL_RES	*result;
1366 	zval		*mysql_result;
1367 
1368 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1369 		return;
1370 	}
1371 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1372 
1373 	mysqli_free_result(result, FALSE);
1374 	MYSQLI_CLEAR_RESOURCE(mysql_result);
1375 }
1376 /* }}} */
1377 
1378 /* {{{ proto string mysqli_get_client_info(void)
1379    Get MySQL client info */
1380 PHP_FUNCTION(mysqli_get_client_info)
1381 {
1382 	const char * info = mysql_get_client_info();
1383 	if (info) {
1384 		RETURN_STRING(info);
1385 	}
1386 }
1387 /* }}} */
1388 
1389 /* {{{ proto int mysqli_get_client_version(void)
1390    Get MySQL client info */
1391 PHP_FUNCTION(mysqli_get_client_version)
1392 {
1393 	RETURN_LONG((zend_long)mysql_get_client_version());
1394 }
1395 /* }}} */
1396 
1397 /* {{{ proto string mysqli_get_host_info(object link)
1398    Get MySQL host info */
1399 PHP_FUNCTION(mysqli_get_host_info)
1400 {
1401 	MY_MYSQL	*mysql;
1402 	zval		*mysql_link = NULL;
1403 
1404 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1405 		return;
1406 	}
1407 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1408 #if !defined(MYSQLI_USE_MYSQLND)
1409 	RETURN_STRING((mysql->mysql->host_info) ? mysql->mysql->host_info : "");
1410 #else
1411 	RETURN_STRING((mysql->mysql->data->host_info) ? mysql->mysql->data->host_info : "");
1412 #endif
1413 }
1414 /* }}} */
1415 
1416 /* {{{ proto int mysqli_get_proto_info(object link)
1417    Get MySQL protocol information */
1418 PHP_FUNCTION(mysqli_get_proto_info)
1419 {
1420 	MY_MYSQL	*mysql;
1421 	zval		*mysql_link = NULL;
1422 
1423 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1424 		return;
1425 	}
1426 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1427 	RETURN_LONG(mysql_get_proto_info(mysql->mysql));
1428 }
1429 /* }}} */
1430 
1431 /* {{{ proto string mysqli_get_server_info(object link)
1432    Get MySQL server info */
1433 PHP_FUNCTION(mysqli_get_server_info)
1434 {
1435 	MY_MYSQL	*mysql;
1436 	zval		*mysql_link = NULL;
1437 	const char	*info;
1438 
1439 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1440 		return;
1441 	}
1442 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1443 
1444 	info = mysql_get_server_info(mysql->mysql);
1445 	if (info) {
1446 		RETURN_STRING(info);
1447 	}
1448 }
1449 /* }}} */
1450 
1451 /* {{{ proto int mysqli_get_server_version(object link)
1452    Return the MySQL version for the server referenced by the given link */
1453 PHP_FUNCTION(mysqli_get_server_version)
1454 {
1455 	MY_MYSQL	*mysql;
1456 	zval		*mysql_link = NULL;
1457 
1458 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1459 		return;
1460 	}
1461 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1462 
1463 	RETURN_LONG(mysql_get_server_version(mysql->mysql));
1464 }
1465 /* }}} */
1466 
1467 /* {{{ proto string mysqli_info(object link)
1468    Get information about the most recent query */
1469 PHP_FUNCTION(mysqli_info)
1470 {
1471 	MY_MYSQL	*mysql;
1472 	zval		*mysql_link = NULL;
1473 	const char	*info;
1474 
1475 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1476 		return;
1477 	}
1478 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1479 
1480 	info = mysql_info(mysql->mysql);
1481 	if (info) {
1482 		RETURN_STRING(info);
1483 	}
1484 }
1485 /* }}} */
1486 
1487 /* {{{ php_mysqli_init() */
1488 void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_method)
1489 {
1490 	MYSQLI_RESOURCE *mysqli_resource;
1491 	MY_MYSQL *mysql;
1492 
1493 	if (is_method && (Z_MYSQLI_P(getThis()))->ptr) {
1494 		return;
1495 	}
1496 
1497 	mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL));
1498 
1499 #if !defined(MYSQLI_USE_MYSQLND)
1500 	if (!(mysql->mysql = mysql_init(NULL)))
1501 #else
1502 	/*
1503 	  We create always persistent, as if the user want to connecto
1504 	  to p:somehost, we can't convert the handle then
1505 	*/
1506 	if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, TRUE)))
1507 #endif
1508 	{
1509 		efree(mysql);
1510 		RETURN_FALSE;
1511 	}
1512 
1513 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1514 	mysqli_resource->ptr = (void *)mysql;
1515 	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
1516 
1517 	if (!is_method) {
1518 		MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
1519 	} else {
1520 		(Z_MYSQLI_P(getThis()))->ptr = mysqli_resource;
1521 	}
1522 }
1523 /* }}} */
1524 
1525 /* {{{ proto resource mysqli_init(void)
1526    Initialize mysqli and return a resource for use with mysql_real_connect */
1527 PHP_FUNCTION(mysqli_init)
1528 {
1529 	php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE);
1530 }
1531 /* }}} */
1532 
1533 /* {{{ proto resource mysqli::init(void)
1534    Initialize mysqli and return a resource for use with mysql_real_connect */
1535 PHP_FUNCTION(mysqli_init_method)
1536 {
1537 	php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE);
1538 }
1539 /* }}} */
1540 
1541 /* {{{ proto mixed mysqli_insert_id(object link)
1542    Get the ID generated from the previous INSERT operation */
1543 PHP_FUNCTION(mysqli_insert_id)
1544 {
1545 	MY_MYSQL		*mysql;
1546 	my_ulonglong	rc;
1547 	zval			*mysql_link;
1548 
1549 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1550 		return;
1551 	}
1552 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1553 	rc = mysql_insert_id(mysql->mysql);
1554 	MYSQLI_RETURN_LONG_INT(rc)
1555 }
1556 /* }}} */
1557 
1558 /* {{{ proto bool mysqli_kill(object link, int processid)
1559    Kill a mysql process on the server */
1560 PHP_FUNCTION(mysqli_kill)
1561 {
1562 	MY_MYSQL	*mysql;
1563 	zval		*mysql_link;
1564 	zend_long		processid;
1565 
1566 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) {
1567 		return;
1568 	}
1569 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1570 
1571 	if (processid <= 0) {
1572 		php_error_docref(NULL, E_WARNING, "processid should have positive value");
1573 		RETURN_FALSE;
1574 	}
1575 
1576 	if (mysql_kill(mysql->mysql, processid)) {
1577 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1578 		RETURN_FALSE;
1579 	}
1580 	RETURN_TRUE;
1581 }
1582 /* }}} */
1583 
1584 /* {{{ proto bool mysqli_more_results(object link)
1585    check if there any more query results from a multi query */
1586 PHP_FUNCTION(mysqli_more_results)
1587 {
1588 	MY_MYSQL	*mysql;
1589 	zval		*mysql_link;
1590 
1591 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1592 		return;
1593 	}
1594 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1595 
1596 	RETURN_BOOL(mysql_more_results(mysql->mysql));
1597 }
1598 /* }}} */
1599 
1600 /* {{{ proto bool mysqli_next_result(object link)
1601    read next result from multi_query */
1602 PHP_FUNCTION(mysqli_next_result) {
1603 	MY_MYSQL	*mysql;
1604 	zval		*mysql_link;
1605 
1606 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1607 		return;
1608 	}
1609 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1610 
1611 	RETURN_BOOL(!mysql_next_result(mysql->mysql));
1612 }
1613 /* }}} */
1614 
1615 #if defined(HAVE_STMT_NEXT_RESULT) && defined(MYSQLI_USE_MYSQLND)
1616 /* {{{ proto bool mysqli_stmt_more_results(object link)
1617    check if there any more query results from a multi query */
1618 PHP_FUNCTION(mysqli_stmt_more_results)
1619 {
1620 	MY_STMT		*stmt;
1621 	zval		*mysql_stmt;
1622 
1623 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1624 		return;
1625 	}
1626 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1627 
1628 	RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1629 }
1630 /* }}} */
1631 
1632 /* {{{ proto bool mysqli_stmt_next_result(object link)
1633    read next result from multi_query */
1634 PHP_FUNCTION(mysqli_stmt_next_result) {
1635 	MY_STMT		*stmt;
1636 	zval		*mysql_stmt;
1637 
1638 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1639 		return;
1640 	}
1641 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1642 
1643 	RETURN_BOOL(!mysql_stmt_next_result(stmt->stmt));
1644 }
1645 /* }}} */
1646 #endif
1647 
1648 /* {{{ proto int mysqli_num_fields(object result)
1649    Get number of fields in result */
1650 PHP_FUNCTION(mysqli_num_fields)
1651 {
1652 	MYSQL_RES	*result;
1653 	zval		*mysql_result;
1654 
1655 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1656 		return;
1657 	}
1658 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1659 
1660 	RETURN_LONG(mysql_num_fields(result));
1661 }
1662 /* }}} */
1663 
1664 /* {{{ proto mixed mysqli_num_rows(object result)
1665    Get number of rows in result */
1666 PHP_FUNCTION(mysqli_num_rows)
1667 {
1668 	MYSQL_RES	*result;
1669 	zval		*mysql_result;
1670 
1671 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1672 		return;
1673 	}
1674 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1675 
1676 	if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) {
1677 		php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
1678 		RETURN_LONG(0);
1679 	}
1680 
1681 	MYSQLI_RETURN_LONG_INT(mysql_num_rows(result));
1682 }
1683 /* }}} */
1684 
1685 /* {{{ mysqli_options_get_option_zval_type */
1686 static int mysqli_options_get_option_zval_type(int option)
1687 {
1688 	switch (option) {
1689 #ifdef MYSQLI_USE_MYSQLND
1690 		case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
1691 		case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
1692 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
1693 		case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
1694 #endif
1695 #endif /* MYSQLI_USE_MYSQLND */
1696 		case MYSQL_OPT_CONNECT_TIMEOUT:
1697 #ifdef MYSQL_REPORT_DATA_TRUNCATION
1698 		case MYSQL_REPORT_DATA_TRUNCATION:
1699 #endif
1700 		case MYSQL_OPT_LOCAL_INFILE:
1701 		case MYSQL_OPT_NAMED_PIPE:
1702 #ifdef MYSQL_OPT_PROTOCOL
1703                 case MYSQL_OPT_PROTOCOL:
1704 #endif /* MySQL 4.1.0 */
1705 		case MYSQL_OPT_READ_TIMEOUT:
1706 		case MYSQL_OPT_WRITE_TIMEOUT:
1707 #ifdef MYSQL_OPT_GUESS_CONNECTION /* removed in MySQL-8.0 */
1708 		case MYSQL_OPT_GUESS_CONNECTION:
1709 		case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
1710 		case MYSQL_OPT_USE_REMOTE_CONNECTION:
1711 		case MYSQL_SECURE_AUTH:
1712 #endif
1713 #ifdef MYSQL_OPT_RECONNECT
1714 		case MYSQL_OPT_RECONNECT:
1715 #endif /* MySQL 5.0.13 */
1716 #ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
1717 		case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
1718 #endif /* MySQL 5.0.23 */
1719 #ifdef MYSQL_OPT_COMPRESS
1720 		case MYSQL_OPT_COMPRESS:
1721 #endif /* mysqlnd @ PHP 5.3.2 */
1722 #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
1723 		case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
1724 #endif
1725 			return IS_LONG;
1726 
1727 #ifdef MYSQL_SHARED_MEMORY_BASE_NAME
1728 		case MYSQL_SHARED_MEMORY_BASE_NAME:
1729 #endif /* MySQL 4.1.0 */
1730 #ifdef MYSQL_SET_CLIENT_IP
1731 		case MYSQL_SET_CLIENT_IP:
1732 #endif /* MySQL 4.1.1 */
1733 		case MYSQL_READ_DEFAULT_FILE:
1734 		case MYSQL_READ_DEFAULT_GROUP:
1735 		case MYSQL_INIT_COMMAND:
1736 		case MYSQL_SET_CHARSET_NAME:
1737 		case MYSQL_SET_CHARSET_DIR:
1738 #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
1739 		case MYSQL_SERVER_PUBLIC_KEY:
1740 #endif
1741 			return IS_STRING;
1742 
1743 		default:
1744 			return IS_NULL;
1745 	}
1746 }
1747 /* }}} */
1748 
1749 /* {{{ proto bool mysqli_options(object link, int flags, mixed values)
1750    Set options */
1751 PHP_FUNCTION(mysqli_options)
1752 {
1753 	MY_MYSQL		*mysql;
1754 	zval			*mysql_link = NULL;
1755 	zval			*mysql_value;
1756 	zend_long			mysql_option;
1757 	unsigned int	l_value;
1758 	zend_long			ret;
1759 	int				expected_type;
1760 
1761 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
1762 		return;
1763 	}
1764 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
1765 
1766 #if !defined(MYSQLI_USE_MYSQLND)
1767 	if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
1768 		if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
1769 			RETURN_FALSE;
1770 		}
1771 	}
1772 #endif
1773 	expected_type = mysqli_options_get_option_zval_type(mysql_option);
1774 	if (expected_type != Z_TYPE_P(mysql_value)) {
1775 		switch (expected_type) {
1776 			case IS_STRING:
1777 				if (!try_convert_to_string(mysql_value)) {
1778 					return;
1779 				}
1780 				break;
1781 			case IS_LONG:
1782 				convert_to_long_ex(mysql_value);
1783 				break;
1784 			default:
1785 				break;
1786 		}
1787 	}
1788 	switch (expected_type) {
1789 		case IS_STRING:
1790 			ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value));
1791 			break;
1792 		case IS_LONG:
1793 			l_value = Z_LVAL_P(mysql_value);
1794 			ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
1795 			break;
1796 		default:
1797 			ret = 1;
1798 			break;
1799 	}
1800 
1801 	RETURN_BOOL(!ret);
1802 }
1803 /* }}} */
1804 
1805 /* {{{ proto bool mysqli_ping(object link)
1806    Ping a server connection or reconnect if there is no connection */
1807 PHP_FUNCTION(mysqli_ping)
1808 {
1809 	MY_MYSQL	*mysql;
1810 	zval		*mysql_link;
1811 	zend_long		rc;
1812 
1813 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1814 		return;
1815 	}
1816 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1817 	rc = mysql_ping(mysql->mysql);
1818 	MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1819 
1820 	RETURN_BOOL(!rc);
1821 }
1822 /* }}} */
1823 
1824 /* {{{ proto mixed mysqli_prepare(object link, string query)
1825    Prepare a SQL statement for execution */
1826 PHP_FUNCTION(mysqli_prepare)
1827 {
1828 	MY_MYSQL		*mysql;
1829 	MY_STMT			*stmt;
1830 	char			*query = NULL;
1831 	size_t				query_len;
1832 	zval			*mysql_link;
1833 	MYSQLI_RESOURCE	*mysqli_resource;
1834 
1835 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1836 		return;
1837 	}
1838 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1839 
1840 #if !defined(MYSQLI_USE_MYSQLND)
1841 	if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
1842 		php_error_docref(NULL, E_WARNING, "All data must be fetched before a new statement prepare takes place");
1843 		RETURN_FALSE;
1844 	}
1845 #endif
1846 
1847 	stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1848 
1849 	if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1850 		if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1851 			/* mysql_stmt_close() clears errors, so we have to store them temporarily */
1852 #if !defined(MYSQLI_USE_MYSQLND)
1853 			char  last_error[MYSQL_ERRMSG_SIZE];
1854 			char  sqlstate[SQLSTATE_LENGTH+1];
1855 			unsigned int last_errno;
1856 
1857 			last_errno = stmt->stmt->last_errno;
1858 			memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
1859 			memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
1860 #else
1861 			MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
1862 			mysql->mysql->data->error_info->error_list.head = NULL;
1863 			mysql->mysql->data->error_info->error_list.tail = NULL;
1864 			mysql->mysql->data->error_info->error_list.count = 0;
1865 #endif
1866 			mysqli_stmt_close(stmt->stmt, FALSE);
1867 			stmt->stmt = NULL;
1868 
1869 			/* restore error messages */
1870 #if !defined(MYSQLI_USE_MYSQLND)
1871 			mysql->mysql->net.last_errno = last_errno;
1872 			memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
1873 			memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
1874 #else
1875 			zend_llist_clean(&mysql->mysql->data->error_info->error_list);
1876 			*mysql->mysql->data->error_info = error_info;
1877 #endif
1878 		}
1879 	}
1880 
1881 	/* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1882 	/* Get performance boost if reporting is switched off */
1883 	if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1884 		stmt->query = (char *)emalloc(query_len + 1);
1885 		memcpy(stmt->query, query, query_len);
1886 		stmt->query[query_len] = '\0';
1887 	}
1888 
1889 	/* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1890 	if (!stmt->stmt) {
1891 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1892 		efree(stmt);
1893 		RETURN_FALSE;
1894 	}
1895 #ifndef MYSQLI_USE_MYSQLND
1896 	ZVAL_COPY(&stmt->link_handle, mysql_link);
1897 #endif
1898 
1899 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1900 	mysqli_resource->ptr = (void *)stmt;
1901 
1902 	/* change status */
1903 	mysqli_resource->status = MYSQLI_STATUS_VALID;
1904 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1905 }
1906 /* }}} */
1907 
1908 /* {{{ proto bool mysqli_real_connect(object link [,string hostname [,string username [,string passwd [,string dbname [,int port [,string socket [,int flags]]]]]]])
1909    Open a connection to a mysql server */
1910 PHP_FUNCTION(mysqli_real_connect)
1911 {
1912 	mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE, FALSE);
1913 }
1914 /* }}} */
1915 
1916 /* {{{ proto bool mysqli_real_query(object link, string query)
1917    Binary-safe version of mysql_query() */
1918 PHP_FUNCTION(mysqli_real_query)
1919 {
1920 	MY_MYSQL	*mysql;
1921 	zval		*mysql_link;
1922 	char		*query = NULL;
1923 	size_t		query_len;
1924 
1925 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1926 		return;
1927 	}
1928 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1929 
1930 	MYSQLI_DISABLE_MQ; /* disable multi statements/queries */
1931 
1932 	if (mysql_real_query(mysql->mysql, query, query_len)) {
1933 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1934 		RETURN_FALSE;
1935 	}
1936 
1937 	if (!mysql_field_count(mysql->mysql)) {
1938 		if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1939 			php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
1940 		}
1941 	}
1942 
1943 	RETURN_TRUE;
1944 }
1945 /* }}} */
1946 
1947 #if defined(MYSQLI_USE_MYSQLND) || MYSQL_VERSION_ID < 50707 || defined(MARIADB_BASE_VERSION)
1948 # define mysql_real_escape_string_quote(mysql, to, from, length, quote) \
1949 	mysql_real_escape_string(mysql, to, from, length)
1950 #endif
1951 
1952 /* {{{ proto string mysqli_real_escape_string(object link, string escapestr)
1953    Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection */
1954 PHP_FUNCTION(mysqli_real_escape_string) {
1955 	MY_MYSQL	*mysql;
1956 	zval		*mysql_link = NULL;
1957 	char		*escapestr;
1958 	size_t			escapestr_len;
1959 	zend_string *newstr;
1960 
1961 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &escapestr, &escapestr_len) == FAILURE) {
1962 		return;
1963 	}
1964 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1965 
1966 	newstr = zend_string_alloc(2 * escapestr_len, 0);
1967 	ZSTR_LEN(newstr) = mysql_real_escape_string_quote(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len, '\'');
1968 	newstr = zend_string_truncate(newstr, ZSTR_LEN(newstr), 0);
1969 
1970 	RETURN_NEW_STR(newstr);
1971 }
1972 /* }}} */
1973 
1974 /* {{{ proto bool mysqli_rollback(object link)
1975    Undo actions from current transaction */
1976 PHP_FUNCTION(mysqli_rollback)
1977 {
1978 	MY_MYSQL	*mysql;
1979 	zval		*mysql_link;
1980 	zend_long		flags = TRANS_COR_NO_OPT;
1981 	char *		name = NULL;
1982 	size_t			name_len = 0;
1983 
1984 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1985 		return;
1986 	}
1987 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1988 
1989 #if !defined(MYSQLI_USE_MYSQLND)
1990 	if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) {
1991 #else
1992 	if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
1993 #endif
1994 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1995 		RETURN_FALSE;
1996 	}
1997 	RETURN_TRUE;
1998 }
1999 /* }}} */
2000 
2001 /* {{{ proto bool mysqli_stmt_send_long_data(object stmt, int param_nr, string data)
2002 */
2003 PHP_FUNCTION(mysqli_stmt_send_long_data)
2004 {
2005 	MY_STMT *stmt;
2006 	zval	*mysql_stmt;
2007 	char	*data;
2008 	zend_long	param_nr;
2009 	size_t		data_len;
2010 
2011 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, &param_nr, &data, &data_len) == FAILURE) {
2012 		return;
2013 	}
2014 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2015 
2016 	if (param_nr < 0) {
2017 		php_error_docref(NULL, E_WARNING, "Invalid parameter number");
2018 		RETURN_FALSE;
2019 	}
2020 	if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) {
2021 		RETURN_FALSE;
2022 	}
2023 	RETURN_TRUE;
2024 }
2025 /* }}} */
2026 
2027 /* {{{ proto string|int|false mysqli_stmt_affected_rows(object stmt)
2028    Return the number of rows affected in the last query for the given link. */
2029 PHP_FUNCTION(mysqli_stmt_affected_rows)
2030 {
2031 	MY_STMT			*stmt;
2032 	zval			*mysql_stmt;
2033 	my_ulonglong	rc;
2034 
2035 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2036 		return;
2037 	}
2038 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2039 
2040 	rc = mysql_stmt_affected_rows(stmt->stmt);
2041 	if (rc == (my_ulonglong) -1) {
2042 		RETURN_LONG(-1);
2043 	}
2044 	MYSQLI_RETURN_LONG_INT(rc)
2045 }
2046 /* }}} */
2047 
2048 /* {{{ proto bool mysqli_stmt_close(object stmt)
2049    Close statement */
2050 PHP_FUNCTION(mysqli_stmt_close)
2051 {
2052 	MY_STMT		*stmt;
2053 	zval		*mysql_stmt;
2054 
2055 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2056 		return;
2057 	}
2058 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2059 
2060 	mysqli_stmt_close(stmt->stmt, FALSE);
2061 	stmt->stmt = NULL;
2062 	php_clear_stmt_bind(stmt);
2063 	MYSQLI_CLEAR_RESOURCE(mysql_stmt);
2064 	RETURN_TRUE;
2065 }
2066 /* }}} */
2067 
2068 /* {{{ proto void mysqli_stmt_data_seek(object stmt, int offset)
2069    Move internal result pointer */
2070 PHP_FUNCTION(mysqli_stmt_data_seek)
2071 {
2072 	MY_STMT		*stmt;
2073 	zval		*mysql_stmt;
2074 	zend_long		offset;
2075 
2076 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
2077 		return;
2078 	}
2079 	if (offset < 0) {
2080 		php_error_docref(NULL, E_WARNING, "Offset must be positive");
2081 		RETURN_FALSE;
2082 	}
2083 
2084 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2085 
2086 	mysql_stmt_data_seek(stmt->stmt, offset);
2087 }
2088 /* }}} */
2089 
2090 /* {{{ proto int mysqli_stmt_field_count(object stmt) {
2091    Return the number of result columns for the given statement */
2092 PHP_FUNCTION(mysqli_stmt_field_count)
2093 {
2094 	MY_STMT		*stmt;
2095 	zval		*mysql_stmt;
2096 
2097 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2098 		return;
2099 	}
2100 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2101 
2102 	RETURN_LONG(mysql_stmt_field_count(stmt->stmt));
2103 }
2104 /* }}} */
2105 
2106 /* {{{ proto void mysqli_stmt_free_result(object stmt)
2107    Free stored result memory for the given statement handle */
2108 PHP_FUNCTION(mysqli_stmt_free_result)
2109 {
2110 	MY_STMT		*stmt;
2111 	zval		*mysql_stmt;
2112 
2113 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2114 		return;
2115 	}
2116 
2117 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2118 
2119 	mysql_stmt_free_result(stmt->stmt);
2120 }
2121 /* }}} */
2122 
2123 /* {{{ proto mixed mysqli_stmt_insert_id(object stmt)
2124    Get the ID generated from the previous INSERT operation */
2125 PHP_FUNCTION(mysqli_stmt_insert_id)
2126 {
2127 	MY_STMT			*stmt;
2128 	my_ulonglong	rc;
2129 	zval			*mysql_stmt;
2130 
2131 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2132 		return;
2133 	}
2134 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2135 	rc = mysql_stmt_insert_id(stmt->stmt);
2136 	MYSQLI_RETURN_LONG_INT(rc)
2137 }
2138 /* }}} */
2139 
2140 /* {{{ proto int mysqli_stmt_param_count(object stmt)
2141    Return the number of parameter for the given statement */
2142 PHP_FUNCTION(mysqli_stmt_param_count)
2143 {
2144 	MY_STMT		*stmt;
2145 	zval		*mysql_stmt;
2146 
2147 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2148 		return;
2149 	}
2150 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2151 
2152 	RETURN_LONG(mysql_stmt_param_count(stmt->stmt));
2153 }
2154 /* }}} */
2155 
2156 /* {{{ proto bool mysqli_stmt_reset(object stmt)
2157    reset a prepared statement */
2158 PHP_FUNCTION(mysqli_stmt_reset)
2159 {
2160 	MY_STMT		*stmt;
2161 	zval		*mysql_stmt;
2162 
2163 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2164 		return;
2165 	}
2166 
2167 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2168 
2169 	if (mysql_stmt_reset(stmt->stmt)) {
2170 		RETURN_FALSE;
2171 	}
2172 	RETURN_TRUE;
2173 }
2174 /* }}} */
2175 
2176 /* {{{ proto mixed mysqli_stmt_num_rows(object stmt)
2177    Return the number of rows in statements result set */
2178 PHP_FUNCTION(mysqli_stmt_num_rows)
2179 {
2180 	MY_STMT			*stmt;
2181 	zval			*mysql_stmt;
2182 	my_ulonglong	rc;
2183 
2184 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2185 		return;
2186 	}
2187 
2188 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2189 
2190 	rc = mysql_stmt_num_rows(stmt->stmt);
2191 	MYSQLI_RETURN_LONG_INT(rc)
2192 }
2193 /* }}} */
2194 
2195 /* {{{ proto bool mysqli_select_db(object link, string dbname)
2196    Select a MySQL database */
2197 PHP_FUNCTION(mysqli_select_db)
2198 {
2199 	MY_MYSQL	*mysql;
2200 	zval		*mysql_link;
2201 	char		*dbname;
2202 	size_t			dbname_len;
2203 
2204 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) {
2205 		return;
2206 	}
2207 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2208 
2209 	if (mysql_select_db(mysql->mysql, dbname)) {
2210 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2211 		RETURN_FALSE;
2212 	}
2213 	RETURN_TRUE;
2214 }
2215 /* }}} */
2216 
2217 /* {{{ proto string mysqli_sqlstate(object link)
2218    Returns the SQLSTATE error from previous MySQL operation */
2219 PHP_FUNCTION(mysqli_sqlstate)
2220 {
2221 	MY_MYSQL	*mysql;
2222 	zval		*mysql_link;
2223 	const char	*state;
2224 
2225 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2226 		return;
2227 	}
2228 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2229 	state = mysql_sqlstate(mysql->mysql);
2230 	if (state) {
2231 		RETURN_STRING(state);
2232 	}
2233 }
2234 /* }}} */
2235 
2236 /* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher])
2237 */
2238 PHP_FUNCTION(mysqli_ssl_set)
2239 {
2240 	MY_MYSQL	*mysql;
2241 	zval		*mysql_link;
2242 	char		*ssl_parm[5];
2243 	size_t			ssl_parm_len[5], i;
2244 
2245 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Osssss", &mysql_link, mysqli_link_class_entry, &ssl_parm[0], &ssl_parm_len[0], &ssl_parm[1], &ssl_parm_len[1], &ssl_parm[2], &ssl_parm_len[2], &ssl_parm[3], &ssl_parm_len[3], &ssl_parm[4], &ssl_parm_len[4])   == FAILURE) {
2246 		return;
2247 	}
2248 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2249 
2250 	for (i = 0; i < 5; i++) {
2251 		if (!ssl_parm_len[i]) {
2252 			ssl_parm[i] = NULL;
2253 		}
2254 	}
2255 
2256 	mysql_ssl_set(mysql->mysql, ssl_parm[0], ssl_parm[1], ssl_parm[2], ssl_parm[3], ssl_parm[4]);
2257 
2258 	RETURN_TRUE;
2259 }
2260 /* }}} */
2261 
2262 /* {{{ proto mixed mysqli_stat(object link)
2263    Get current system status */
2264 PHP_FUNCTION(mysqli_stat)
2265 {
2266 	MY_MYSQL	*mysql;
2267 	zval		*mysql_link;
2268 #if defined(MYSQLI_USE_MYSQLND)
2269 	zend_string *stat;
2270 #else
2271 	char		*stat;
2272 #endif
2273 
2274 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2275 		return;
2276 	}
2277 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2278 
2279 #if !defined(MYSQLI_USE_MYSQLND)
2280 	if ((stat = (char *)mysql_stat(mysql->mysql)))
2281 	{
2282 		RETURN_STRING(stat);
2283 #else
2284 	if (mysqlnd_stat(mysql->mysql, &stat) == PASS)
2285 	{
2286 		RETURN_STR(stat);
2287 #endif
2288 	} else {
2289 		RETURN_FALSE;
2290 	}
2291 }
2292 
2293 /* }}} */
2294 
2295 /* {{{ proto bool mysqli_refresh(object link, int options)
2296    Flush tables or caches, or reset replication server information */
2297 PHP_FUNCTION(mysqli_refresh)
2298 {
2299 	MY_MYSQL *mysql;
2300 	zval *mysql_link = NULL;
2301 	zend_long options;
2302 
2303 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &options) == FAILURE) {
2304 		return;
2305 	}
2306 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2307 #ifdef MYSQLI_USE_MYSQLND
2308 	RETURN_BOOL(!mysql_refresh(mysql->mysql, (uint8_t) options));
2309 #else
2310 	RETURN_BOOL(!mysql_refresh(mysql->mysql, options));
2311 #endif
2312 }
2313 /* }}} */
2314 
2315 /* {{{ proto int mysqli_stmt_attr_set(object stmt, int attr, int mode)
2316 */
2317 PHP_FUNCTION(mysqli_stmt_attr_set)
2318 {
2319 	MY_STMT	*stmt;
2320 	zval	*mysql_stmt;
2321 	zend_long	mode_in;
2322 #if MYSQL_VERSION_ID >= 50107
2323 	my_bool	mode_b;
2324 #endif
2325 	unsigned long	mode;
2326 	zend_long	attr;
2327 	void	*mode_p;
2328 
2329 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) {
2330 		return;
2331 	}
2332 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2333 
2334 	if (mode_in < 0) {
2335 		php_error_docref(NULL, E_WARNING, "mode should be non-negative, " ZEND_LONG_FMT " passed", mode_in);
2336 		RETURN_FALSE;
2337 	}
2338 
2339 	switch (attr) {
2340 #if MYSQL_VERSION_ID >= 50107
2341 	case STMT_ATTR_UPDATE_MAX_LENGTH:
2342 		mode_b = (my_bool) mode_in;
2343 		mode_p = &mode_b;
2344 		break;
2345 #endif
2346 	default:
2347 		mode = mode_in;
2348 		mode_p = &mode;
2349 		break;
2350 	}
2351 #if !defined(MYSQLI_USE_MYSQLND)
2352 	if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2353 #else
2354 	if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2355 #endif
2356 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2357 		RETURN_FALSE;
2358 	}
2359 	RETURN_TRUE;
2360 }
2361 /* }}} */
2362 
2363 /* {{{ proto int mysqli_stmt_attr_get(object stmt, int attr)
2364 */
2365 PHP_FUNCTION(mysqli_stmt_attr_get)
2366 {
2367 	MY_STMT	*stmt;
2368 	zval	*mysql_stmt;
2369 	unsigned long	value = 0;
2370 	zend_long	attr;
2371 	int		rc;
2372 
2373 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) {
2374 		return;
2375 	}
2376 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2377 
2378 	if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) {
2379 		RETURN_FALSE;
2380 	}
2381 
2382 #if MYSQL_VERSION_ID >= 50107
2383 	if (attr == STMT_ATTR_UPDATE_MAX_LENGTH)
2384 		value = *((my_bool *)&value);
2385 #endif
2386 	RETURN_LONG((unsigned long)value);
2387 }
2388 /* }}} */
2389 
2390 /* {{{ proto int mysqli_stmt_errno(object stmt)
2391 */
2392 PHP_FUNCTION(mysqli_stmt_errno)
2393 {
2394 	MY_STMT	*stmt;
2395 	zval	*mysql_stmt;
2396 
2397 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2398 		return;
2399 	}
2400 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2401 
2402 	RETURN_LONG(mysql_stmt_errno(stmt->stmt));
2403 }
2404 /* }}} */
2405 
2406 /* {{{ proto string mysqli_stmt_error(object stmt)
2407 */
2408 PHP_FUNCTION(mysqli_stmt_error)
2409 {
2410 	MY_STMT	*stmt;
2411 	zval 	*mysql_stmt;
2412 	const char * err;
2413 
2414 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2415 		return;
2416 	}
2417 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2418 
2419 	err = mysql_stmt_error(stmt->stmt);
2420 	if (err) {
2421 		RETURN_STRING(err);
2422 	}
2423 }
2424 /* }}} */
2425 
2426 /* {{{ proto mixed mysqli_stmt_init(object link)
2427    Initialize statement object
2428 */
2429 PHP_FUNCTION(mysqli_stmt_init)
2430 {
2431 	MY_MYSQL		*mysql;
2432 	MY_STMT			*stmt;
2433 	zval			*mysql_link;
2434 	MYSQLI_RESOURCE	*mysqli_resource;
2435 
2436 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",&mysql_link, mysqli_link_class_entry) == FAILURE) {
2437 		return;
2438 	}
2439 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2440 
2441 	stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
2442 
2443 	if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
2444 		efree(stmt);
2445 		RETURN_FALSE;
2446 	}
2447 #ifndef MYSQLI_USE_MYSQLND
2448 	ZVAL_COPY(&stmt->link_handle, mysql_link);
2449 #endif
2450 
2451 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2452 	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
2453 	mysqli_resource->ptr = (void *)stmt;
2454 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
2455 }
2456 /* }}} */
2457 
2458 /* {{{ proto bool mysqli_stmt_prepare(object stmt, string query)
2459    prepare server side statement with query
2460 */
2461 PHP_FUNCTION(mysqli_stmt_prepare)
2462 {
2463 	MY_STMT	*stmt;
2464 	zval 	*mysql_stmt;
2465 	char	*query;
2466 	size_t		query_len;
2467 
2468 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry, &query, &query_len) == FAILURE) {
2469 		return;
2470 	}
2471 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2472 
2473 	if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
2474 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2475 		RETURN_FALSE;
2476 	}
2477 	/* change status */
2478 	MYSQLI_SET_STATUS(mysql_stmt, MYSQLI_STATUS_VALID);
2479 	RETURN_TRUE;
2480 }
2481 /* }}} */
2482 
2483 /* {{{ proto mixed mysqli_stmt_result_metadata(object stmt)
2484    return result set from statement */
2485 PHP_FUNCTION(mysqli_stmt_result_metadata)
2486 {
2487 	MY_STMT			*stmt;
2488 	MYSQL_RES		*result;
2489 	zval			*mysql_stmt;
2490 	MYSQLI_RESOURCE	*mysqli_resource;
2491 
2492 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2493 		return;
2494 	}
2495 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2496 
2497 	if (!(result = mysql_stmt_result_metadata(stmt->stmt))){
2498 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2499 		RETURN_FALSE;
2500 	}
2501 
2502 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2503 	mysqli_resource->ptr = (void *)result;
2504 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2505 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2506 }
2507 /* }}} */
2508 
2509 /* {{{ proto bool mysqli_stmt_store_result(object stmt)
2510 */
2511 PHP_FUNCTION(mysqli_stmt_store_result)
2512 {
2513 	MY_STMT	*stmt;
2514 	zval	*mysql_stmt;
2515 
2516 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2517 		return;
2518 	}
2519 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2520 
2521 #if !defined(MYSQLI_USE_MYSQLND)
2522 	{
2523 		/*
2524 		  If the user wants to store the data and we have BLOBs/TEXTs we try to allocate
2525 		  not the maximal length of the type (which is 16MB even for LONGBLOB) but
2526 		  the maximal length of the field in the result set. If he/she has quite big
2527 		  BLOB/TEXT columns after calling store_result() the memory usage of PHP will
2528 		  double - but this is a known problem of the simple MySQL API ;)
2529 		*/
2530 		int	i = 0;
2531 
2532 		for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) {
2533 			if (stmt->stmt->fields && (stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB ||
2534 				stmt->stmt->fields[i].type == MYSQL_TYPE_MEDIUM_BLOB ||
2535 				stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB ||
2536 				stmt->stmt->fields[i].type == MYSQL_TYPE_GEOMETRY))
2537 			{
2538 #if MYSQL_VERSION_ID >= 50107
2539 				my_bool	tmp=1;
2540 #else
2541 				uint32_t tmp=1;
2542 #endif
2543 				mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
2544 				break;
2545 			}
2546 		}
2547 	}
2548 #endif
2549 
2550 	if (mysql_stmt_store_result(stmt->stmt)){
2551 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2552 		RETURN_FALSE;
2553 	}
2554 	RETURN_TRUE;
2555 }
2556 /* }}} */
2557 
2558 /* {{{ proto string mysqli_stmt_sqlstate(object stmt)
2559 */
2560 PHP_FUNCTION(mysqli_stmt_sqlstate)
2561 {
2562 	MY_STMT	*stmt;
2563 	zval	*mysql_stmt;
2564 	const char * state;
2565 
2566 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2567 		return;
2568 	}
2569 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2570 
2571 	state = mysql_stmt_sqlstate(stmt->stmt);
2572 	if (state) {
2573 		RETURN_STRING(state);
2574 	}
2575 }
2576 /* }}} */
2577 
2578 /* {{{ proto object mysqli_store_result(object link [, int flags])
2579    Buffer result set on client */
2580 PHP_FUNCTION(mysqli_store_result)
2581 {
2582 	MY_MYSQL		*mysql;
2583 	MYSQL_RES		*result;
2584 	zval			*mysql_link;
2585 	MYSQLI_RESOURCE	*mysqli_resource;
2586 	zend_long flags = 0;
2587 
2588 
2589 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_link, mysqli_link_class_entry, &flags) == FAILURE) {
2590 		return;
2591 	}
2592 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2593 #if MYSQLI_USE_MYSQLND
2594 	result = flags & MYSQLI_STORE_RESULT_COPY_DATA? mysqlnd_store_result_ofs(mysql->mysql) : mysqlnd_store_result(mysql->mysql);
2595 #else
2596 	result = mysql_store_result(mysql->mysql);
2597 #endif
2598 	if (!result) {
2599 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2600 		RETURN_FALSE;
2601 	}
2602 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2603 		php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2604 	}
2605 
2606 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2607 	mysqli_resource->ptr = (void *)result;
2608 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2609 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2610 }
2611 /* }}} */
2612 
2613 /* {{{ proto int mysqli_thread_id(object link)
2614    Return the current thread ID */
2615 PHP_FUNCTION(mysqli_thread_id)
2616 {
2617 	MY_MYSQL	*mysql;
2618 	zval		*mysql_link;
2619 
2620 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2621 		return;
2622 	}
2623 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2624 
2625 	RETURN_LONG((zend_long) mysql_thread_id(mysql->mysql));
2626 }
2627 /* }}} */
2628 
2629 /* {{{ proto bool mysqli_thread_safe(void)
2630    Return whether thread safety is given or not */
2631 PHP_FUNCTION(mysqli_thread_safe)
2632 {
2633 	RETURN_BOOL(mysql_thread_safe());
2634 }
2635 /* }}} */
2636 
2637 /* {{{ proto mixed mysqli_use_result(object link)
2638    Directly retrieve query results - do not buffer results on client side */
2639 PHP_FUNCTION(mysqli_use_result)
2640 {
2641 	MY_MYSQL		*mysql;
2642 	MYSQL_RES		*result;
2643 	zval			*mysql_link;
2644 	MYSQLI_RESOURCE	*mysqli_resource;
2645 
2646 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2647 		return;
2648 	}
2649 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2650 
2651 	if (!(result = mysql_use_result(mysql->mysql))) {
2652 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2653 		RETURN_FALSE;
2654 	}
2655 
2656 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2657 		php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2658 	}
2659 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2660 	mysqli_resource->ptr = (void *)result;
2661 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2662 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2663 }
2664 /* }}} */
2665 
2666 /* {{{ proto int mysqli_warning_count(object link)
2667    Return number of warnings from the last query for the given link */
2668 PHP_FUNCTION(mysqli_warning_count)
2669 {
2670 	MY_MYSQL	*mysql;
2671 	zval		*mysql_link;
2672 
2673 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2674 		return;
2675 	}
2676 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2677 
2678 	RETURN_LONG(mysql_warning_count(mysql->mysql));
2679 }
2680 /* }}} */
2681