1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 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_FUNCTION(mysqli_affected_rows)140 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_FUNCTION(mysqli_autocommit)162 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 RETURN_FALSE;
175 }
176 RETURN_TRUE;
177 }
178 /* }}} */
179
180 /* {{{ mysqli_stmt_bind_param_do_bind */
181 #ifndef MYSQLI_USE_MYSQLND
182 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)183 int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars,
184 zval *args, unsigned int start, const char * const types)
185 {
186 int i, ofs;
187 MYSQL_BIND *bind;
188 unsigned long rc;
189
190 /* prevent leak if variables are already bound */
191 if (stmt->param.var_cnt) {
192 php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
193 }
194
195 stmt->param.is_null = ecalloc(num_vars, sizeof(char));
196 bind = (MYSQL_BIND *) ecalloc(num_vars, sizeof(MYSQL_BIND));
197
198 ofs = 0;
199 for (i = start; i < argc; i++) {
200 zval *param;
201 if (Z_ISREF(args[i])) {
202 param = Z_REFVAL(args[i]);
203 } else {
204 param = &args[i];
205 }
206 /* set specified type */
207 switch (types[ofs]) {
208 case 'd': /* Double */
209 bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
210 bind[ofs].buffer = &Z_DVAL_P(param);
211 bind[ofs].is_null = &stmt->param.is_null[ofs];
212 break;
213
214 case 'i': /* Integer */
215 #if SIZEOF_ZEND_LONG==8
216 bind[ofs].buffer_type = MYSQL_TYPE_LONGLONG;
217 #elif SIZEOF_ZEND_LONG==4
218 bind[ofs].buffer_type = MYSQL_TYPE_LONG;
219 #endif
220 bind[ofs].buffer = &Z_LVAL_P(param);
221 bind[ofs].is_null = &stmt->param.is_null[ofs];
222 break;
223
224 case 'b': /* Blob (send data) */
225 bind[ofs].buffer_type = MYSQL_TYPE_LONG_BLOB;
226 /* don't initialize is_null and length to 0 because we use ecalloc */
227 break;
228
229 case 's': /* string */
230 bind[ofs].buffer_type = MYSQL_TYPE_VAR_STRING;
231 /* don't initialize buffer and buffer_length because we use ecalloc */
232 bind[ofs].is_null = &stmt->param.is_null[ofs];
233 break;
234
235 default:
236 php_error_docref(NULL, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[ofs], i+1);
237 rc = 1;
238 goto end_1;
239 }
240 ofs++;
241 }
242 rc = mysql_stmt_bind_param(stmt->stmt, bind);
243
244 end_1:
245 if (rc) {
246 efree(stmt->param.is_null);
247 } else {
248 stmt->param.var_cnt = num_vars;
249 stmt->param.vars = safe_emalloc(num_vars, sizeof(zval), 0);
250 for (i = 0; i < num_vars; i++) {
251 if (bind[i].buffer_type != MYSQL_TYPE_LONG_BLOB) {
252 ZVAL_COPY(&stmt->param.vars[i], &args[i+start]);
253 } else {
254 ZVAL_UNDEF(&stmt->param.vars[i]);
255 }
256 }
257 }
258 efree(bind);
259
260 return rc;
261 }
262 #else
263 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)264 int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars,
265 zval *args, unsigned int start, const char * const types)
266 {
267 unsigned int i;
268 MYSQLND_PARAM_BIND *params;
269 enum_func_status ret = FAIL;
270
271 /* If no params -> skip binding and return directly */
272 if (argc == start) {
273 return PASS;
274 }
275 params = mysqlnd_stmt_alloc_param_bind(stmt->stmt);
276 if (!params) {
277 goto end;
278 }
279 for (i = 0; i < (argc - start); i++) {
280 zend_uchar type;
281 switch (types[i]) {
282 case 'd': /* Double */
283 type = MYSQL_TYPE_DOUBLE;
284 break;
285 case 'i': /* Integer */
286 #if SIZEOF_ZEND_LONG==8
287 type = MYSQL_TYPE_LONGLONG;
288 #elif SIZEOF_ZEND_LONG==4
289 type = MYSQL_TYPE_LONG;
290 #endif
291 break;
292 case 'b': /* Blob (send data) */
293 type = MYSQL_TYPE_LONG_BLOB;
294 break;
295 case 's': /* string */
296 type = MYSQL_TYPE_VAR_STRING;
297 break;
298 default:
299 /* We count parameters from 1 */
300 php_error_docref(NULL, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[i], i + start + 1);
301 ret = FAIL;
302 mysqlnd_stmt_free_param_bind(stmt->stmt, params);
303 goto end;
304 }
305 ZVAL_COPY_VALUE(¶ms[i].zv, &args[i + start]);
306 params[i].type = type;
307 }
308 ret = mysqlnd_stmt_bind_param(stmt->stmt, params);
309
310 end:
311 return ret;
312 }
313 #endif
314 /* }}} */
315
316 /* {{{ proto bool mysqli_stmt_bind_param(object stmt, string types, mixed variable [,mixed ...])
317 Bind variables to a prepared statement as parameters */
PHP_FUNCTION(mysqli_stmt_bind_param)318 PHP_FUNCTION(mysqli_stmt_bind_param)
319 {
320 zval *args;
321 int argc = ZEND_NUM_ARGS();
322 int num_vars;
323 int start = 2;
324 MY_STMT *stmt;
325 zval *mysql_stmt;
326 char *types;
327 size_t types_len;
328 zend_ulong rc;
329
330 /* calculate and check number of parameters */
331 if (argc < 2) {
332 /* there has to be at least one pair */
333 WRONG_PARAM_COUNT;
334 }
335
336 if (zend_parse_method_parameters((getThis()) ? 1:2, getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry,
337 &types, &types_len) == FAILURE) {
338 return;
339 }
340
341 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
342
343 num_vars = argc - 1;
344 if (getThis()) {
345 start = 1;
346 } else {
347 /* ignore handle parameter in procedural interface*/
348 --num_vars;
349 }
350 if (!types_len) {
351 php_error_docref(NULL, E_WARNING, "Invalid type or no types specified");
352 RETURN_FALSE;
353 }
354
355 if (types_len != (size_t)(argc - start)) {
356 /* number of bind variables doesn't match number of elements in type definition string */
357 php_error_docref(NULL, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables");
358 RETURN_FALSE;
359 }
360
361 if (types_len != mysql_stmt_param_count(stmt->stmt)) {
362 php_error_docref(NULL, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement");
363 RETURN_FALSE;
364 }
365
366 args = safe_emalloc(argc, sizeof(zval), 0);
367
368 if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
369 zend_wrong_param_count();
370 rc = 1;
371 } else {
372 rc = mysqli_stmt_bind_param_do_bind(stmt, argc, num_vars, args, start, types);
373 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
374 }
375
376 efree(args);
377
378 RETURN_BOOL(!rc);
379 }
380 /* }}} */
381
382 /* {{{ mysqli_stmt_bind_result_do_bind */
383 #ifndef MYSQLI_USE_MYSQLND
384 /* TODO:
385 do_alloca, free_alloca
386 */
387 static int
mysqli_stmt_bind_result_do_bind(MY_STMT * stmt,zval * args,unsigned int argc)388 mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)
389 {
390 MYSQL_BIND *bind;
391 int i, ofs;
392 int var_cnt = argc;
393 zend_long col_type;
394 zend_ulong rc;
395
396 /* prevent leak if variables are already bound */
397 if (stmt->result.var_cnt) {
398 php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
399 }
400
401 bind = (MYSQL_BIND *)ecalloc(var_cnt, sizeof(MYSQL_BIND));
402 {
403 int size;
404 char *p = emalloc(size= var_cnt * (sizeof(char) + sizeof(VAR_BUFFER)));
405 stmt->result.buf = (VAR_BUFFER *) p;
406 stmt->result.is_null = p + var_cnt * sizeof(VAR_BUFFER);
407 memset(p, 0, size);
408 }
409
410 for (i = 0; i < var_cnt; i++) {
411 ofs = i;
412 col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING;
413
414 switch (col_type) {
415 case MYSQL_TYPE_FLOAT:
416 stmt->result.buf[ofs].type = IS_DOUBLE;
417 stmt->result.buf[ofs].buflen = sizeof(float);
418
419 stmt->result.buf[ofs].val = (char *)emalloc(sizeof(float));
420 bind[ofs].buffer_type = MYSQL_TYPE_FLOAT;
421 bind[ofs].buffer = stmt->result.buf[ofs].val;
422 bind[ofs].is_null = &stmt->result.is_null[ofs];
423 break;
424
425 case MYSQL_TYPE_DOUBLE:
426 stmt->result.buf[ofs].type = IS_DOUBLE;
427 stmt->result.buf[ofs].buflen = sizeof(double);
428
429 /* allocate buffer for double */
430 stmt->result.buf[ofs].val = (char *)emalloc(sizeof(double));
431 bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
432 bind[ofs].buffer = stmt->result.buf[ofs].val;
433 bind[ofs].is_null = &stmt->result.is_null[ofs];
434 break;
435
436 case MYSQL_TYPE_NULL:
437 stmt->result.buf[ofs].type = IS_NULL;
438 /*
439 don't initialize to 0 :
440 1. stmt->result.buf[ofs].buflen
441 2. bind[ofs].buffer
442 3. bind[ofs].buffer_length
443 because memory was allocated with ecalloc
444 */
445 bind[ofs].buffer_type = MYSQL_TYPE_NULL;
446 bind[ofs].is_null = &stmt->result.is_null[ofs];
447 break;
448
449 case MYSQL_TYPE_SHORT:
450 case MYSQL_TYPE_TINY:
451 case MYSQL_TYPE_LONG:
452 case MYSQL_TYPE_INT24:
453 case MYSQL_TYPE_YEAR:
454 stmt->result.buf[ofs].type = IS_LONG;
455 /* don't set stmt->result.buf[ofs].buflen to 0, we used ecalloc */
456 stmt->result.buf[ofs].val = (char *)emalloc(sizeof(int));
457 bind[ofs].buffer_type = MYSQL_TYPE_LONG;
458 bind[ofs].buffer = stmt->result.buf[ofs].val;
459 bind[ofs].is_null = &stmt->result.is_null[ofs];
460 bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
461 break;
462
463 case MYSQL_TYPE_LONGLONG:
464 #if MYSQL_VERSION_ID > 50002 || defined(MYSQLI_USE_MYSQLND)
465 case MYSQL_TYPE_BIT:
466 #endif
467 stmt->result.buf[ofs].type = IS_STRING;
468 stmt->result.buf[ofs].buflen = sizeof(my_ulonglong);
469 stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
470 bind[ofs].buffer_type = col_type;
471 bind[ofs].buffer = stmt->result.buf[ofs].val;
472 bind[ofs].is_null = &stmt->result.is_null[ofs];
473 bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
474 bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
475 bind[ofs].length = &stmt->result.buf[ofs].output_len;
476 break;
477
478 case MYSQL_TYPE_DATE:
479 case MYSQL_TYPE_TIME:
480 case MYSQL_TYPE_DATETIME:
481 case MYSQL_TYPE_NEWDATE:
482 case MYSQL_TYPE_VAR_STRING:
483 case MYSQL_TYPE_STRING:
484 case MYSQL_TYPE_TINY_BLOB:
485 case MYSQL_TYPE_BLOB:
486 case MYSQL_TYPE_MEDIUM_BLOB:
487 case MYSQL_TYPE_LONG_BLOB:
488 case MYSQL_TYPE_TIMESTAMP:
489 case MYSQL_TYPE_DECIMAL:
490 case MYSQL_TYPE_GEOMETRY:
491 #ifdef FIELD_TYPE_NEWDECIMAL
492 case MYSQL_TYPE_NEWDECIMAL:
493 #endif
494 {
495 #if MYSQL_VERSION_ID >= 50107
496 /* Changed to my_bool in MySQL 5.1. See MySQL Bug #16144 */
497 my_bool tmp;
498 #else
499 zend_ulong tmp = 0;
500 #endif
501 stmt->result.buf[ofs].type = IS_STRING;
502 /*
503 If the user has called $stmt->store_result() then we have asked
504 max_length to be updated. this is done only for BLOBS because we don't want to allocate
505 big chunkgs of memory 2^16 or 2^24
506 */
507 if (stmt->stmt->fields[ofs].max_length == 0 &&
508 !mysql_stmt_attr_get(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp) && !tmp)
509 {
510 /*
511 Allocate directly 256 because it's easier to allocate a bit more
512 than update max length even for text columns. Try SELECT UNION SELECT UNION with
513 different lengths and you will see that we get different lengths in stmt->stmt->fields[ofs].length
514 The just take 256 and saves us from realloc-ing.
515 */
516 stmt->result.buf[ofs].buflen =
517 (stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256;
518
519 } else {
520 /*
521 the user has called store_result(). if he does not there is no way to determine the
522 libmysql does not allow us to allocate 0 bytes for a buffer so we try 1
523 */
524 if (!(stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length))
525 ++stmt->result.buf[ofs].buflen;
526 }
527 stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
528 bind[ofs].buffer_type = MYSQL_TYPE_STRING;
529 bind[ofs].buffer = stmt->result.buf[ofs].val;
530 bind[ofs].is_null = &stmt->result.is_null[ofs];
531 bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
532 bind[ofs].length = &stmt->result.buf[ofs].output_len;
533 break;
534 }
535 default:
536 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);
537 break;
538 }
539 }
540
541 rc = mysql_stmt_bind_result(stmt->stmt, bind);
542 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
543
544 if (rc) {
545 /* don't close the statement or subsequent usage (for example ->execute()) will lead to crash */
546 for (i=0; i < var_cnt ; i++) {
547 if (stmt->result.buf[i].val) {
548 efree(stmt->result.buf[i].val);
549 }
550 }
551 /* Don't free stmt->result.is_null because is_null & buf are one block of memory */
552 efree(stmt->result.buf);
553 } else {
554 stmt->result.var_cnt = var_cnt;
555 stmt->result.vars = safe_emalloc((var_cnt), sizeof(zval), 0);
556 for (i = 0; i < var_cnt; i++) {
557 ZVAL_COPY(&stmt->result.vars[i], &args[i]);
558 }
559 }
560 efree(bind);
561
562 return rc;
563 }
564 #else
565 static int
mysqli_stmt_bind_result_do_bind(MY_STMT * stmt,zval * args,unsigned int argc)566 mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)
567 {
568 unsigned int i;
569 MYSQLND_RESULT_BIND *params = mysqlnd_stmt_alloc_result_bind(stmt->stmt);
570 if (params) {
571 for (i = 0; i < argc; i++) {
572 ZVAL_COPY_VALUE(¶ms[i].zv, &args[i]);
573 }
574 return mysqlnd_stmt_bind_result(stmt->stmt, params);
575 }
576 return FAIL;
577 }
578 #endif
579 /* }}} */
580
581 /* {{{ proto bool mysqli_stmt_bind_result(object stmt, mixed var [,mixed ...])
582 Bind variables to a prepared statement for result storage */
PHP_FUNCTION(mysqli_stmt_bind_result)583 PHP_FUNCTION(mysqli_stmt_bind_result)
584 {
585 zval *args;
586 int argc;
587 zend_ulong rc;
588 MY_STMT *stmt;
589 zval *mysql_stmt;
590
591 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O+", &mysql_stmt, mysqli_stmt_class_entry, &args, &argc) == FAILURE) {
592 return;
593 }
594
595 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
596
597 if ((uint32_t)argc != mysql_stmt_field_count(stmt->stmt)) {
598 php_error_docref(NULL, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statement");
599 RETURN_FALSE;
600 }
601
602 rc = mysqli_stmt_bind_result_do_bind(stmt, args, argc);
603 RETURN_BOOL(!rc);
604 }
605 /* }}} */
606
607 /* {{{ proto bool mysqli_change_user(object link, string user, string password, string database)
608 Change logged-in user of the active connection */
PHP_FUNCTION(mysqli_change_user)609 PHP_FUNCTION(mysqli_change_user)
610 {
611 MY_MYSQL *mysql;
612 zval *mysql_link = NULL;
613 char *user, *password, *dbname;
614 size_t user_len, password_len, dbname_len;
615 zend_ulong rc;
616 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
617 MY_CHARSET_INFO old_charset;
618 #endif
619
620 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) {
621 return;
622 }
623 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
624
625 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
626 mysql_get_character_set_info(mysql->mysql, &old_charset);
627 #endif
628
629 #if defined(MYSQLI_USE_MYSQLND)
630 rc = mysqlnd_change_user_ex(mysql->mysql, user, password, dbname, FALSE, (size_t) password_len);
631 #else
632 rc = mysql_change_user(mysql->mysql, user, password, dbname);
633 #endif
634 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
635
636 if (rc) {
637 RETURN_FALSE;
638 }
639 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
640 if (mysql_get_server_version(mysql->mysql) < 50123L) {
641 /*
642 Request the current charset, or it will be reset to the system one.
643 5.0 doesn't support it. Support added in 5.1.23 by fixing the following bug :
644 Bug #30472 libmysql doesn't reset charset, insert_id after succ. mysql_change_user() call
645 */
646 rc = mysql_set_character_set(mysql->mysql, old_charset.csname);
647 }
648 #endif
649
650 RETURN_TRUE;
651 }
652 /* }}} */
653
654 /* {{{ proto string mysqli_character_set_name(object link)
655 Returns the name of the character set used for this connection */
PHP_FUNCTION(mysqli_character_set_name)656 PHP_FUNCTION(mysqli_character_set_name)
657 {
658 MY_MYSQL *mysql;
659 zval *mysql_link;
660 const char *cs_name;
661
662 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
663 return;
664 }
665
666 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
667 cs_name = mysql_character_set_name(mysql->mysql);
668 if (cs_name) {
669 RETURN_STRING(cs_name);
670 }
671 }
672 /* }}} */
673
674 /* {{{ php_mysqli_close */
php_mysqli_close(MY_MYSQL * mysql,int close_type,int resource_status)675 void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status)
676 {
677 if (resource_status > MYSQLI_STATUS_INITIALIZED) {
678 MyG(num_links)--;
679 }
680
681 if (!mysql->persistent) {
682 mysqli_close(mysql->mysql, close_type);
683 } else {
684 zend_resource *le;
685 if ((le = zend_hash_find_ptr(&EG(persistent_list), mysql->hash_key)) != NULL) {
686 if (le->type == php_le_pmysqli()) {
687 mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
688 #if defined(MYSQLI_USE_MYSQLND)
689 mysqlnd_end_psession(mysql->mysql);
690 #endif
691
692 if (MyG(rollback_on_cached_plink) &&
693 #if !defined(MYSQLI_USE_MYSQLND)
694 mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, TRANS_COR_NO_OPT, NULL))
695 #else
696 FAIL == mysqlnd_rollback(mysql->mysql, TRANS_COR_NO_OPT, NULL))
697 #endif
698 {
699 mysqli_close(mysql->mysql, close_type);
700 } else {
701 zend_ptr_stack_push(&plist->free_links, mysql->mysql);
702 MyG(num_inactive_persistent)++;
703 }
704 MyG(num_active_persistent)--;
705 }
706 }
707 mysql->persistent = FALSE;
708 }
709 mysql->mysql = NULL;
710
711 php_clear_mysql(mysql);
712 }
713 /* }}} */
714
715 /* {{{ proto bool mysqli_close(object link)
716 Close connection */
PHP_FUNCTION(mysqli_close)717 PHP_FUNCTION(mysqli_close)
718 {
719 zval *mysql_link;
720 MY_MYSQL *mysql;
721
722 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
723 return;
724 }
725
726 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
727
728 php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, ((MYSQLI_RESOURCE *)(Z_MYSQLI_P(mysql_link))->ptr)->status);
729 ((MYSQLI_RESOURCE *)(Z_MYSQLI_P(mysql_link))->ptr)->status = MYSQLI_STATUS_UNKNOWN;
730
731 MYSQLI_CLEAR_RESOURCE(mysql_link);
732 efree(mysql);
733 RETURN_TRUE;
734 }
735 /* }}} */
736
737 /* {{{ proto bool mysqli_commit(object link[, int flags [, string name ]])
738 Commit outstanding actions and close transaction */
PHP_FUNCTION(mysqli_commit)739 PHP_FUNCTION(mysqli_commit)
740 {
741 MY_MYSQL *mysql;
742 zval *mysql_link;
743 zend_long flags = TRANS_COR_NO_OPT;
744 char * name = NULL;
745 size_t name_len = 0;
746
747 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
748 return;
749 }
750 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
751
752 #if !defined(MYSQLI_USE_MYSQLND)
753 if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name)) {
754 #else
755 if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) {
756 #endif
757 RETURN_FALSE;
758 }
759 RETURN_TRUE;
760 }
761 /* }}} */
762
763 /* {{{ proto bool mysqli_data_seek(object result, int offset)
764 Move internal result pointer */
765 PHP_FUNCTION(mysqli_data_seek)
766 {
767 MYSQL_RES *result;
768 zval *mysql_result;
769 zend_long offset;
770
771 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
772 return;
773 }
774
775 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
776
777 if (mysqli_result_is_unbuffered(result)) {
778 php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
779 RETURN_FALSE;
780 }
781
782 if (offset < 0 || (uint64_t)offset >= mysql_num_rows(result)) {
783 RETURN_FALSE;
784 }
785
786 mysql_data_seek(result, offset);
787 RETURN_TRUE;
788 }
789 /* }}} */
790
791 /* {{{ proto void mysqli_debug(string debug)
792 */
793 PHP_FUNCTION(mysqli_debug)
794 {
795 char *debug;
796 size_t debug_len;
797
798 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &debug, &debug_len) == FAILURE) {
799 return;
800 }
801
802 mysql_debug(debug);
803 RETURN_TRUE;
804 }
805 /* }}} */
806
807 /* {{{ proto bool mysqli_dump_debug_info(object link)
808 */
809 PHP_FUNCTION(mysqli_dump_debug_info)
810 {
811 MY_MYSQL *mysql;
812 zval *mysql_link;
813
814 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
815 return;
816 }
817 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
818
819 RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql))
820 }
821 /* }}} */
822
823 /* {{{ proto int mysqli_errno(object link)
824 Returns the numerical value of the error message from previous MySQL operation */
825 PHP_FUNCTION(mysqli_errno)
826 {
827 MY_MYSQL *mysql;
828 zval *mysql_link;
829
830 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
831 return;
832 }
833 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
834 RETURN_LONG(mysql_errno(mysql->mysql));
835 }
836 /* }}} */
837
838 /* {{{ proto string mysqli_error(object link)
839 Returns the text of the error message from previous MySQL operation */
840 PHP_FUNCTION(mysqli_error)
841 {
842 MY_MYSQL *mysql;
843 zval *mysql_link;
844 const char *err;
845
846 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
847 return;
848 }
849 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
850 err = mysql_error(mysql->mysql);
851 if (err) {
852 RETURN_STRING(err);
853 }
854 }
855 /* }}} */
856
857 /* {{{ proto bool mysqli_stmt_execute(object stmt)
858 Execute a prepared statement */
859 PHP_FUNCTION(mysqli_stmt_execute)
860 {
861 MY_STMT *stmt;
862 zval *mysql_stmt;
863 #ifndef MYSQLI_USE_MYSQLND
864 unsigned int i;
865 #endif
866
867 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
868 return;
869 }
870 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
871
872 #ifndef MYSQLI_USE_MYSQLND
873 if (stmt->param.var_cnt) {
874 int j;
875 for (i = 0; i < stmt->param.var_cnt; i++) {
876 if (!Z_ISREF(stmt->param.vars[i])) {
877 continue;
878 }
879 for (j = i + 1; j < stmt->param.var_cnt; j++) {
880 /* Oops, someone binding the same variable - clone */
881 if (Z_ISREF(stmt->param.vars[j]) &&
882 Z_REFVAL(stmt->param.vars[j]) == Z_REFVAL(stmt->param.vars[i])) {
883 /*SEPARATE_ZVAL(&stmt->param.vars[j]);*/
884 Z_DELREF_P(&stmt->param.vars[j]);
885 ZVAL_COPY(&stmt->param.vars[j], Z_REFVAL(stmt->param.vars[j]));
886 break;
887 }
888 }
889 }
890 }
891 for (i = 0; i < stmt->param.var_cnt; i++) {
892 if (!Z_ISUNDEF(stmt->param.vars[i])) {
893 zval *param;
894 if (Z_ISREF(stmt->param.vars[i])) {
895 param = Z_REFVAL(stmt->param.vars[i]);
896 } else {
897 param = &stmt->param.vars[i];
898 }
899 if (!(stmt->param.is_null[i] = (Z_ISNULL_P(param)))) {
900 switch (stmt->stmt->params[i].buffer_type) {
901 case MYSQL_TYPE_VAR_STRING:
902 convert_to_string_ex(param);
903 stmt->stmt->params[i].buffer = Z_STRVAL_P(param);
904 stmt->stmt->params[i].buffer_length = Z_STRLEN_P(param);
905 break;
906 case MYSQL_TYPE_DOUBLE:
907 convert_to_double_ex(param);
908 stmt->stmt->params[i].buffer = &Z_DVAL_P(param);
909 break;
910 case MYSQL_TYPE_LONGLONG:
911 case MYSQL_TYPE_LONG:
912 convert_to_long_ex(param);
913 stmt->stmt->params[i].buffer = &Z_LVAL_P(param);
914 break;
915 default:
916 break;
917 }
918 }
919 }
920 }
921 #endif
922
923 if (mysql_stmt_execute(stmt->stmt)) {
924 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
925 RETVAL_FALSE;
926 } else {
927 RETVAL_TRUE;
928 }
929
930 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
931 php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt));
932 }
933 }
934 /* }}} */
935
936 #ifndef MYSQLI_USE_MYSQLND
937 /* {{{ void mysqli_stmt_fetch_libmysql
938 Fetch results from a prepared statement into the bound variables */
939 void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
940 {
941 MY_STMT *stmt;
942 zval *mysql_stmt;
943 unsigned int i;
944 zend_ulong ret;
945 unsigned int uval;
946 my_ulonglong llval;
947
948
949 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
950 return;
951 }
952 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
953
954 /* reset buffers */
955 for (i = 0; i < stmt->result.var_cnt; i++) {
956 if (stmt->result.buf[i].type == IS_STRING) {
957 memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen);
958 }
959 }
960 ret = mysql_stmt_fetch(stmt->stmt);
961 #ifdef MYSQL_DATA_TRUNCATED
962 if (!ret || ret == MYSQL_DATA_TRUNCATED) {
963 #else
964 if (!ret) {
965 #endif
966 for (i = 0; i < stmt->result.var_cnt; i++) {
967 zval *result;
968 /* it must be a reference, isn't it? */
969 if (Z_ISREF(stmt->result.vars[i])) {
970 result = Z_REFVAL(stmt->result.vars[i]);
971 } else {
972 result = &stmt->result.vars[i];
973 }
974 /*
975 QQ: Isn't it quite better to call zval_dtor(). What if the user has
976 assigned a resource, or an array to the bound variable? We are going
977 to leak probably. zval_dtor() will handle also Unicode/Non-unicode mode.
978 */
979 /* Even if the string is of length zero there is one byte alloced so efree() in all cases */
980 zval_ptr_dtor(result);
981 if (!stmt->result.is_null[i]) {
982 switch (stmt->result.buf[i].type) {
983 case IS_LONG:
984 if ((stmt->stmt->fields[i].type == MYSQL_TYPE_LONG)
985 && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG))
986 {
987 /* unsigned int (11) */
988 uval= *(unsigned int *) stmt->result.buf[i].val;
989 #if SIZEOF_ZEND_LONG==4
990 if (uval > INT_MAX) {
991 char *tmp, *p;
992 int j = 10;
993 tmp = emalloc(11);
994 p= &tmp[9];
995 do {
996 *p-- = (uval % 10) + 48;
997 uval = uval / 10;
998 } while (--j > 0);
999 tmp[10]= '\0';
1000 /* unsigned int > INT_MAX is 10 digits - ALWAYS */
1001 ZVAL_STRINGL(result, tmp, 10);
1002 efree(tmp);
1003 break;
1004 }
1005 #endif
1006 }
1007 if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) {
1008 ZVAL_LONG(result, *(unsigned int *)stmt->result.buf[i].val);
1009 } else {
1010 ZVAL_LONG(result, *(int *)stmt->result.buf[i].val);
1011 }
1012 break;
1013 case IS_DOUBLE:
1014 {
1015 double dval;
1016 if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_FLOAT) {
1017 #ifndef NOT_FIXED_DEC
1018 # define NOT_FIXED_DEC 31
1019 #endif
1020 dval = mysql_float_to_double(*(float *)stmt->result.buf[i].val,
1021 (stmt->stmt->fields[i].decimals >= NOT_FIXED_DEC) ? -1 :
1022 stmt->stmt->fields[i].decimals);
1023 } else {
1024 dval = *((double *)stmt->result.buf[i].val);
1025 }
1026
1027 ZVAL_DOUBLE(result, dval);
1028 break;
1029 }
1030 case IS_STRING:
1031 if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
1032 #if MYSQL_VERSION_ID > 50002
1033 || stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT
1034 #endif
1035 ) {
1036 my_bool uns = (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0;
1037 #if MYSQL_VERSION_ID > 50002
1038 if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) {
1039 switch (stmt->result.buf[i].output_len) {
1040 case 8:llval = (my_ulonglong) bit_uint8korr(stmt->result.buf[i].val);break;
1041 case 7:llval = (my_ulonglong) bit_uint7korr(stmt->result.buf[i].val);break;
1042 case 6:llval = (my_ulonglong) bit_uint6korr(stmt->result.buf[i].val);break;
1043 case 5:llval = (my_ulonglong) bit_uint5korr(stmt->result.buf[i].val);break;
1044 case 4:llval = (my_ulonglong) bit_uint4korr(stmt->result.buf[i].val);break;
1045 case 3:llval = (my_ulonglong) bit_uint3korr(stmt->result.buf[i].val);break;
1046 case 2:llval = (my_ulonglong) bit_uint2korr(stmt->result.buf[i].val);break;
1047 case 1:llval = (my_ulonglong) uint1korr(stmt->result.buf[i].val);break;
1048 }
1049 } else
1050 #endif
1051 {
1052 llval= *(my_ulonglong *) stmt->result.buf[i].val;
1053 }
1054 #if SIZEOF_ZEND_LONG==8
1055 if (uns && llval > 9223372036854775807L) {
1056 #elif SIZEOF_ZEND_LONG==4
1057 if ((uns && llval > L64(2147483647)) ||
1058 (!uns && (( L64(2147483647) < (my_longlong) llval) ||
1059 (L64(-2147483648) > (my_longlong) llval))))
1060 {
1061 #endif
1062 char tmp[22];
1063 /* even though lval is declared as unsigned, the value
1064 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
1065 * use MYSQLI_LL_SPEC.
1066 */
1067 snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1068 ZVAL_STRING(result, tmp);
1069 } else {
1070 ZVAL_LONG(result, llval);
1071 }
1072 } else {
1073 #if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002
1074 if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) {
1075 /* result was truncated */
1076 ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length);
1077 } else {
1078 #else
1079 {
1080 #endif
1081 ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->result.buf[i].output_len);
1082 }
1083 }
1084 break;
1085 default:
1086 break;
1087 }
1088 } else {
1089 ZVAL_NULL(result);
1090 }
1091 }
1092 } else {
1093 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1094 }
1095
1096 switch (ret) {
1097 case 0:
1098 #ifdef MYSQL_DATA_TRUNCATED
1099 /* according to SQL standard truncation (e.g. loss of precision is
1100 not an error) - for detecting possible truncation you have to
1101 check mysqli_stmt_warning
1102 */
1103 case MYSQL_DATA_TRUNCATED:
1104 #endif
1105 RETURN_TRUE;
1106 break;
1107 case 1:
1108 RETURN_FALSE;
1109 break;
1110 default:
1111 RETURN_NULL();
1112 break;
1113 }
1114 }
1115 /* }}} */
1116 #else
1117 /* {{{ mixed mysqli_stmt_fetch_mysqlnd */
1118 void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)
1119 {
1120 MY_STMT *stmt;
1121 zval *mysql_stmt;
1122 zend_bool fetched_anything;
1123
1124 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1125 return;
1126 }
1127 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1128
1129 if (FAIL == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) {
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 if (!mysql_more_results(mysql->mysql)) {
1612 php_error_docref(NULL, E_STRICT, "There is no next result set. "
1613 "Please, call mysqli_more_results()/mysqli::more_results() to check "
1614 "whether to call this function/method");
1615 }
1616
1617 RETURN_BOOL(!mysql_next_result(mysql->mysql));
1618 }
1619 /* }}} */
1620
1621 #if defined(HAVE_STMT_NEXT_RESULT) && defined(MYSQLI_USE_MYSQLND)
1622 /* {{{ proto bool mysqli_stmt_next_result(object link)
1623 check if there any more query results from a multi query */
1624 PHP_FUNCTION(mysqli_stmt_more_results)
1625 {
1626 MY_STMT *stmt;
1627 zval *mysql_stmt;
1628
1629 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1630 return;
1631 }
1632 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1633
1634 RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1635 }
1636 /* }}} */
1637
1638 /* {{{ proto bool mysqli_stmt_next_result(object link)
1639 read next result from multi_query */
1640 PHP_FUNCTION(mysqli_stmt_next_result) {
1641 MY_STMT *stmt;
1642 zval *mysql_stmt;
1643
1644 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1645 return;
1646 }
1647 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1648
1649 if (!mysqlnd_stmt_more_results(stmt->stmt)) {
1650 php_error_docref(NULL, E_STRICT, "There is no next result set. "
1651 "Please, call mysqli_stmt_more_results()/mysqli_stmt::more_results() to check "
1652 "whether to call this function/method");
1653 }
1654
1655 RETURN_BOOL(!mysql_stmt_next_result(stmt->stmt));
1656 }
1657 /* }}} */
1658 #endif
1659
1660 /* {{{ proto int mysqli_num_fields(object result)
1661 Get number of fields in result */
1662 PHP_FUNCTION(mysqli_num_fields)
1663 {
1664 MYSQL_RES *result;
1665 zval *mysql_result;
1666
1667 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1668 return;
1669 }
1670 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1671
1672 RETURN_LONG(mysql_num_fields(result));
1673 }
1674 /* }}} */
1675
1676 /* {{{ proto mixed mysqli_num_rows(object result)
1677 Get number of rows in result */
1678 PHP_FUNCTION(mysqli_num_rows)
1679 {
1680 MYSQL_RES *result;
1681 zval *mysql_result;
1682
1683 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1684 return;
1685 }
1686 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1687
1688 if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) {
1689 php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
1690 RETURN_LONG(0);
1691 }
1692
1693 MYSQLI_RETURN_LONG_INT(mysql_num_rows(result));
1694 }
1695 /* }}} */
1696
1697 /* {{{ mysqli_options_get_option_zval_type */
1698 static int mysqli_options_get_option_zval_type(int option)
1699 {
1700 switch (option) {
1701 #ifdef MYSQLI_USE_MYSQLND
1702 case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
1703 case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
1704 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
1705 case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
1706 #endif
1707 #endif /* MYSQLI_USE_MYSQLND */
1708 case MYSQL_OPT_CONNECT_TIMEOUT:
1709 #ifdef MYSQL_REPORT_DATA_TRUNCATION
1710 case MYSQL_REPORT_DATA_TRUNCATION:
1711 #endif
1712 case MYSQL_OPT_LOCAL_INFILE:
1713 case MYSQL_OPT_NAMED_PIPE:
1714 #ifdef MYSQL_OPT_PROTOCOL
1715 case MYSQL_OPT_PROTOCOL:
1716 #endif /* MySQL 4.1.0 */
1717 case MYSQL_OPT_READ_TIMEOUT:
1718 case MYSQL_OPT_WRITE_TIMEOUT:
1719 #ifdef MYSQL_OPT_GUESS_CONNECTION /* removed in MySQL-8.0 */
1720 case MYSQL_OPT_GUESS_CONNECTION:
1721 case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
1722 case MYSQL_OPT_USE_REMOTE_CONNECTION:
1723 case MYSQL_SECURE_AUTH:
1724 #endif
1725 #ifdef MYSQL_OPT_RECONNECT
1726 case MYSQL_OPT_RECONNECT:
1727 #endif /* MySQL 5.0.13 */
1728 #ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
1729 case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
1730 #endif /* MySQL 5.0.23 */
1731 #ifdef MYSQL_OPT_COMPRESS
1732 case MYSQL_OPT_COMPRESS:
1733 #endif /* mysqlnd @ PHP 5.3.2 */
1734 #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
1735 case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
1736 #endif
1737 return IS_LONG;
1738
1739 #ifdef MYSQL_SHARED_MEMORY_BASE_NAME
1740 case MYSQL_SHARED_MEMORY_BASE_NAME:
1741 #endif /* MySQL 4.1.0 */
1742 #ifdef MYSQL_SET_CLIENT_IP
1743 case MYSQL_SET_CLIENT_IP:
1744 #endif /* MySQL 4.1.1 */
1745 case MYSQL_READ_DEFAULT_FILE:
1746 case MYSQL_READ_DEFAULT_GROUP:
1747 case MYSQL_INIT_COMMAND:
1748 case MYSQL_SET_CHARSET_NAME:
1749 case MYSQL_SET_CHARSET_DIR:
1750 #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
1751 case MYSQL_SERVER_PUBLIC_KEY:
1752 #endif
1753 return IS_STRING;
1754
1755 default:
1756 return IS_NULL;
1757 }
1758 }
1759 /* }}} */
1760
1761 /* {{{ proto bool mysqli_options(object link, int flags, mixed values)
1762 Set options */
1763 PHP_FUNCTION(mysqli_options)
1764 {
1765 MY_MYSQL *mysql;
1766 zval *mysql_link = NULL;
1767 zval *mysql_value;
1768 zend_long mysql_option;
1769 unsigned int l_value;
1770 zend_long ret;
1771 int expected_type;
1772
1773 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
1774 return;
1775 }
1776 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
1777
1778 #if !defined(MYSQLI_USE_MYSQLND)
1779 if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
1780 if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
1781 RETURN_FALSE;
1782 }
1783 }
1784 #endif
1785 expected_type = mysqli_options_get_option_zval_type(mysql_option);
1786 if (expected_type != Z_TYPE_P(mysql_value)) {
1787 switch (expected_type) {
1788 case IS_STRING:
1789 convert_to_string_ex(mysql_value);
1790 break;
1791 case IS_LONG:
1792 convert_to_long_ex(mysql_value);
1793 break;
1794 default:
1795 break;
1796 }
1797 }
1798 switch (expected_type) {
1799 case IS_STRING:
1800 ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value));
1801 break;
1802 case IS_LONG:
1803 l_value = Z_LVAL_P(mysql_value);
1804 ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
1805 break;
1806 default:
1807 ret = 1;
1808 break;
1809 }
1810
1811 RETURN_BOOL(!ret);
1812 }
1813 /* }}} */
1814
1815 /* {{{ proto bool mysqli_ping(object link)
1816 Ping a server connection or reconnect if there is no connection */
1817 PHP_FUNCTION(mysqli_ping)
1818 {
1819 MY_MYSQL *mysql;
1820 zval *mysql_link;
1821 zend_long rc;
1822
1823 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1824 return;
1825 }
1826 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1827 rc = mysql_ping(mysql->mysql);
1828 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1829
1830 RETURN_BOOL(!rc);
1831 }
1832 /* }}} */
1833
1834 /* {{{ proto mixed mysqli_prepare(object link, string query)
1835 Prepare a SQL statement for execution */
1836 PHP_FUNCTION(mysqli_prepare)
1837 {
1838 MY_MYSQL *mysql;
1839 MY_STMT *stmt;
1840 char *query = NULL;
1841 size_t query_len;
1842 zval *mysql_link;
1843 MYSQLI_RESOURCE *mysqli_resource;
1844
1845 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1846 return;
1847 }
1848 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1849
1850 #if !defined(MYSQLI_USE_MYSQLND)
1851 if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
1852 php_error_docref(NULL, E_WARNING, "All data must be fetched before a new statement prepare takes place");
1853 RETURN_FALSE;
1854 }
1855 #endif
1856
1857 stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1858
1859 if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1860 if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1861 /* mysql_stmt_close() clears errors, so we have to store them temporarily */
1862 #if !defined(MYSQLI_USE_MYSQLND)
1863 char last_error[MYSQL_ERRMSG_SIZE];
1864 char sqlstate[SQLSTATE_LENGTH+1];
1865 unsigned int last_errno;
1866
1867 last_errno = stmt->stmt->last_errno;
1868 memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
1869 memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
1870 #else
1871 MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
1872 mysql->mysql->data->error_info->error_list.head = NULL;
1873 mysql->mysql->data->error_info->error_list.tail = NULL;
1874 mysql->mysql->data->error_info->error_list.count = 0;
1875 #endif
1876 mysqli_stmt_close(stmt->stmt, FALSE);
1877 stmt->stmt = NULL;
1878
1879 /* restore error messages */
1880 #if !defined(MYSQLI_USE_MYSQLND)
1881 mysql->mysql->net.last_errno = last_errno;
1882 memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
1883 memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
1884 #else
1885 zend_llist_clean(&mysql->mysql->data->error_info->error_list);
1886 *mysql->mysql->data->error_info = error_info;
1887 #endif
1888 }
1889 }
1890
1891 /* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1892 /* Get performance boost if reporting is switched off */
1893 if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1894 stmt->query = (char *)emalloc(query_len + 1);
1895 memcpy(stmt->query, query, query_len);
1896 stmt->query[query_len] = '\0';
1897 }
1898
1899 /* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1900 if (!stmt->stmt) {
1901 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1902 efree(stmt);
1903 RETURN_FALSE;
1904 }
1905 #ifndef MYSQLI_USE_MYSQLND
1906 ZVAL_COPY(&stmt->link_handle, mysql_link);
1907 #endif
1908
1909 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1910 mysqli_resource->ptr = (void *)stmt;
1911
1912 /* change status */
1913 mysqli_resource->status = MYSQLI_STATUS_VALID;
1914 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1915 }
1916 /* }}} */
1917
1918 /* {{{ proto bool mysqli_real_connect(object link [,string hostname [,string username [,string passwd [,string dbname [,int port [,string socket [,int flags]]]]]]])
1919 Open a connection to a mysql server */
1920 PHP_FUNCTION(mysqli_real_connect)
1921 {
1922 mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE, FALSE);
1923 }
1924 /* }}} */
1925
1926 /* {{{ proto bool mysqli_real_query(object link, string query)
1927 Binary-safe version of mysql_query() */
1928 PHP_FUNCTION(mysqli_real_query)
1929 {
1930 MY_MYSQL *mysql;
1931 zval *mysql_link;
1932 char *query = NULL;
1933 size_t query_len;
1934
1935 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1936 return;
1937 }
1938 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1939
1940 MYSQLI_DISABLE_MQ; /* disable multi statements/queries */
1941
1942 if (mysql_real_query(mysql->mysql, query, query_len)) {
1943 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1944 RETURN_FALSE;
1945 }
1946
1947 if (!mysql_field_count(mysql->mysql)) {
1948 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1949 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
1950 }
1951 }
1952
1953 RETURN_TRUE;
1954 }
1955 /* }}} */
1956
1957 #if defined(MYSQLI_USE_MYSQLND) || MYSQL_VERSION_ID < 50707 || defined(MARIADB_BASE_VERSION)
1958 # define mysql_real_escape_string_quote(mysql, to, from, length, quote) \
1959 mysql_real_escape_string(mysql, to, from, length)
1960 #endif
1961
1962 /* {{{ proto string mysqli_real_escape_string(object link, string escapestr)
1963 Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection */
1964 PHP_FUNCTION(mysqli_real_escape_string) {
1965 MY_MYSQL *mysql;
1966 zval *mysql_link = NULL;
1967 char *escapestr;
1968 size_t escapestr_len;
1969 zend_string *newstr;
1970
1971 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &escapestr, &escapestr_len) == FAILURE) {
1972 return;
1973 }
1974 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1975
1976 newstr = zend_string_alloc(2 * escapestr_len, 0);
1977 ZSTR_LEN(newstr) = mysql_real_escape_string_quote(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len, '\'');
1978 newstr = zend_string_truncate(newstr, ZSTR_LEN(newstr), 0);
1979
1980 RETURN_NEW_STR(newstr);
1981 }
1982 /* }}} */
1983
1984 /* {{{ proto bool mysqli_rollback(object link)
1985 Undo actions from current transaction */
1986 PHP_FUNCTION(mysqli_rollback)
1987 {
1988 MY_MYSQL *mysql;
1989 zval *mysql_link;
1990 zend_long flags = TRANS_COR_NO_OPT;
1991 char * name = NULL;
1992 size_t name_len = 0;
1993
1994 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1995 return;
1996 }
1997 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1998
1999 #if !defined(MYSQLI_USE_MYSQLND)
2000 if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) {
2001 #else
2002 if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
2003 #endif
2004 RETURN_FALSE;
2005 }
2006 RETURN_TRUE;
2007 }
2008 /* }}} */
2009
2010 /* {{{ proto bool mysqli_stmt_send_long_data(object stmt, int param_nr, string data)
2011 */
2012 PHP_FUNCTION(mysqli_stmt_send_long_data)
2013 {
2014 MY_STMT *stmt;
2015 zval *mysql_stmt;
2016 char *data;
2017 zend_long param_nr;
2018 size_t data_len;
2019
2020 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, ¶m_nr, &data, &data_len) == FAILURE) {
2021 return;
2022 }
2023 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2024
2025 if (param_nr < 0) {
2026 php_error_docref(NULL, E_WARNING, "Invalid parameter number");
2027 RETURN_FALSE;
2028 }
2029 if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) {
2030 RETURN_FALSE;
2031 }
2032 RETURN_TRUE;
2033 }
2034 /* }}} */
2035
2036 /* {{{ proto string|int|false mysqli_stmt_affected_rows(object stmt)
2037 Return the number of rows affected in the last query for the given link. */
2038 PHP_FUNCTION(mysqli_stmt_affected_rows)
2039 {
2040 MY_STMT *stmt;
2041 zval *mysql_stmt;
2042 my_ulonglong rc;
2043
2044 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2045 return;
2046 }
2047 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2048
2049 rc = mysql_stmt_affected_rows(stmt->stmt);
2050 if (rc == (my_ulonglong) -1) {
2051 RETURN_LONG(-1);
2052 }
2053 MYSQLI_RETURN_LONG_INT(rc)
2054 }
2055 /* }}} */
2056
2057 /* {{{ proto bool mysqli_stmt_close(object stmt)
2058 Close statement */
2059 PHP_FUNCTION(mysqli_stmt_close)
2060 {
2061 MY_STMT *stmt;
2062 zval *mysql_stmt;
2063
2064 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2065 return;
2066 }
2067 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2068
2069 mysqli_stmt_close(stmt->stmt, FALSE);
2070 stmt->stmt = NULL;
2071 php_clear_stmt_bind(stmt);
2072 MYSQLI_CLEAR_RESOURCE(mysql_stmt);
2073 RETURN_TRUE;
2074 }
2075 /* }}} */
2076
2077 /* {{{ proto void mysqli_stmt_data_seek(object stmt, int offset)
2078 Move internal result pointer */
2079 PHP_FUNCTION(mysqli_stmt_data_seek)
2080 {
2081 MY_STMT *stmt;
2082 zval *mysql_stmt;
2083 zend_long offset;
2084
2085 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
2086 return;
2087 }
2088 if (offset < 0) {
2089 php_error_docref(NULL, E_WARNING, "Offset must be positive");
2090 RETURN_FALSE;
2091 }
2092
2093 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2094
2095 mysql_stmt_data_seek(stmt->stmt, offset);
2096 }
2097 /* }}} */
2098
2099 /* {{{ proto int mysqli_stmt_field_count(object stmt) {
2100 Return the number of result columns for the given statement */
2101 PHP_FUNCTION(mysqli_stmt_field_count)
2102 {
2103 MY_STMT *stmt;
2104 zval *mysql_stmt;
2105
2106 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2107 return;
2108 }
2109 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2110
2111 RETURN_LONG(mysql_stmt_field_count(stmt->stmt));
2112 }
2113 /* }}} */
2114
2115 /* {{{ proto void mysqli_stmt_free_result(object stmt)
2116 Free stored result memory for the given statement handle */
2117 PHP_FUNCTION(mysqli_stmt_free_result)
2118 {
2119 MY_STMT *stmt;
2120 zval *mysql_stmt;
2121
2122 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2123 return;
2124 }
2125
2126 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2127
2128 mysql_stmt_free_result(stmt->stmt);
2129 }
2130 /* }}} */
2131
2132 /* {{{ proto mixed mysqli_stmt_insert_id(object stmt)
2133 Get the ID generated from the previous INSERT operation */
2134 PHP_FUNCTION(mysqli_stmt_insert_id)
2135 {
2136 MY_STMT *stmt;
2137 my_ulonglong rc;
2138 zval *mysql_stmt;
2139
2140 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2141 return;
2142 }
2143 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2144 rc = mysql_stmt_insert_id(stmt->stmt);
2145 MYSQLI_RETURN_LONG_INT(rc)
2146 }
2147 /* }}} */
2148
2149 /* {{{ proto int mysqli_stmt_param_count(object stmt)
2150 Return the number of parameter for the given statement */
2151 PHP_FUNCTION(mysqli_stmt_param_count)
2152 {
2153 MY_STMT *stmt;
2154 zval *mysql_stmt;
2155
2156 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2157 return;
2158 }
2159 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2160
2161 RETURN_LONG(mysql_stmt_param_count(stmt->stmt));
2162 }
2163 /* }}} */
2164
2165 /* {{{ proto bool mysqli_stmt_reset(object stmt)
2166 reset a prepared statement */
2167 PHP_FUNCTION(mysqli_stmt_reset)
2168 {
2169 MY_STMT *stmt;
2170 zval *mysql_stmt;
2171
2172 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2173 return;
2174 }
2175
2176 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2177
2178 if (mysql_stmt_reset(stmt->stmt)) {
2179 RETURN_FALSE;
2180 }
2181 RETURN_TRUE;
2182 }
2183 /* }}} */
2184
2185 /* {{{ proto mixed mysqli_stmt_num_rows(object stmt)
2186 Return the number of rows in statements result set */
2187 PHP_FUNCTION(mysqli_stmt_num_rows)
2188 {
2189 MY_STMT *stmt;
2190 zval *mysql_stmt;
2191 my_ulonglong rc;
2192
2193 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2194 return;
2195 }
2196
2197 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2198
2199 rc = mysql_stmt_num_rows(stmt->stmt);
2200 MYSQLI_RETURN_LONG_INT(rc)
2201 }
2202 /* }}} */
2203
2204 /* {{{ proto bool mysqli_select_db(object link, string dbname)
2205 Select a MySQL database */
2206 PHP_FUNCTION(mysqli_select_db)
2207 {
2208 MY_MYSQL *mysql;
2209 zval *mysql_link;
2210 char *dbname;
2211 size_t dbname_len;
2212
2213 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) {
2214 return;
2215 }
2216 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2217
2218 if (mysql_select_db(mysql->mysql, dbname)) {
2219 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2220 RETURN_FALSE;
2221 }
2222 RETURN_TRUE;
2223 }
2224 /* }}} */
2225
2226 /* {{{ proto string mysqli_sqlstate(object link)
2227 Returns the SQLSTATE error from previous MySQL operation */
2228 PHP_FUNCTION(mysqli_sqlstate)
2229 {
2230 MY_MYSQL *mysql;
2231 zval *mysql_link;
2232 const char *state;
2233
2234 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2235 return;
2236 }
2237 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2238 state = mysql_sqlstate(mysql->mysql);
2239 if (state) {
2240 RETURN_STRING(state);
2241 }
2242 }
2243 /* }}} */
2244
2245 /* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher])
2246 */
2247 PHP_FUNCTION(mysqli_ssl_set)
2248 {
2249 MY_MYSQL *mysql;
2250 zval *mysql_link;
2251 char *ssl_parm[5];
2252 size_t ssl_parm_len[5], i;
2253
2254 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) {
2255 return;
2256 }
2257 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2258
2259 for (i = 0; i < 5; i++) {
2260 if (!ssl_parm_len[i]) {
2261 ssl_parm[i] = NULL;
2262 }
2263 }
2264
2265 mysql_ssl_set(mysql->mysql, ssl_parm[0], ssl_parm[1], ssl_parm[2], ssl_parm[3], ssl_parm[4]);
2266
2267 RETURN_TRUE;
2268 }
2269 /* }}} */
2270
2271 /* {{{ proto mixed mysqli_stat(object link)
2272 Get current system status */
2273 PHP_FUNCTION(mysqli_stat)
2274 {
2275 MY_MYSQL *mysql;
2276 zval *mysql_link;
2277 #if defined(MYSQLI_USE_MYSQLND)
2278 zend_string *stat;
2279 #else
2280 char *stat;
2281 #endif
2282
2283 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2284 return;
2285 }
2286 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2287
2288 #if !defined(MYSQLI_USE_MYSQLND)
2289 if ((stat = (char *)mysql_stat(mysql->mysql)))
2290 {
2291 RETURN_STRING(stat);
2292 #else
2293 if (mysqlnd_stat(mysql->mysql, &stat) == PASS)
2294 {
2295 RETURN_STR(stat);
2296 #endif
2297 } else {
2298 RETURN_FALSE;
2299 }
2300 }
2301
2302 /* }}} */
2303
2304 /* {{{ proto bool mysqli_refresh(object link, int options)
2305 Flush tables or caches, or reset replication server information */
2306 PHP_FUNCTION(mysqli_refresh)
2307 {
2308 MY_MYSQL *mysql;
2309 zval *mysql_link = NULL;
2310 zend_long options;
2311
2312 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &options) == FAILURE) {
2313 return;
2314 }
2315 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2316 #ifdef MYSQLI_USE_MYSQLND
2317 RETURN_BOOL(!mysql_refresh(mysql->mysql, (uint8_t) options));
2318 #else
2319 RETURN_BOOL(!mysql_refresh(mysql->mysql, options));
2320 #endif
2321 }
2322 /* }}} */
2323
2324 /* {{{ proto int mysqli_stmt_attr_set(object stmt, int attr, int mode)
2325 */
2326 PHP_FUNCTION(mysqli_stmt_attr_set)
2327 {
2328 MY_STMT *stmt;
2329 zval *mysql_stmt;
2330 zend_long mode_in;
2331 #if MYSQL_VERSION_ID >= 50107
2332 my_bool mode_b;
2333 #endif
2334 unsigned long mode;
2335 zend_long attr;
2336 void *mode_p;
2337
2338 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) {
2339 return;
2340 }
2341 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2342
2343 if (mode_in < 0) {
2344 php_error_docref(NULL, E_WARNING, "mode should be non-negative, " ZEND_LONG_FMT " passed", mode_in);
2345 RETURN_FALSE;
2346 }
2347
2348 switch (attr) {
2349 #if MYSQL_VERSION_ID >= 50107
2350 case STMT_ATTR_UPDATE_MAX_LENGTH:
2351 mode_b = (my_bool) mode_in;
2352 mode_p = &mode_b;
2353 break;
2354 #endif
2355 default:
2356 mode = mode_in;
2357 mode_p = &mode;
2358 break;
2359 }
2360 #if !defined(MYSQLI_USE_MYSQLND)
2361 if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2362 #else
2363 if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2364 #endif
2365 RETURN_FALSE;
2366 }
2367 RETURN_TRUE;
2368 }
2369 /* }}} */
2370
2371 /* {{{ proto int mysqli_stmt_attr_get(object stmt, int attr)
2372 */
2373 PHP_FUNCTION(mysqli_stmt_attr_get)
2374 {
2375 MY_STMT *stmt;
2376 zval *mysql_stmt;
2377 unsigned long value = 0;
2378 zend_long attr;
2379 int rc;
2380
2381 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) {
2382 return;
2383 }
2384 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2385
2386 if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) {
2387 RETURN_FALSE;
2388 }
2389
2390 #if MYSQL_VERSION_ID >= 50107
2391 if (attr == STMT_ATTR_UPDATE_MAX_LENGTH)
2392 value = *((my_bool *)&value);
2393 #endif
2394 RETURN_LONG((unsigned long)value);
2395 }
2396 /* }}} */
2397
2398 /* {{{ proto int mysqli_stmt_errno(object stmt)
2399 */
2400 PHP_FUNCTION(mysqli_stmt_errno)
2401 {
2402 MY_STMT *stmt;
2403 zval *mysql_stmt;
2404
2405 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2406 return;
2407 }
2408 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2409
2410 RETURN_LONG(mysql_stmt_errno(stmt->stmt));
2411 }
2412 /* }}} */
2413
2414 /* {{{ proto string mysqli_stmt_error(object stmt)
2415 */
2416 PHP_FUNCTION(mysqli_stmt_error)
2417 {
2418 MY_STMT *stmt;
2419 zval *mysql_stmt;
2420 const char * err;
2421
2422 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2423 return;
2424 }
2425 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2426
2427 err = mysql_stmt_error(stmt->stmt);
2428 if (err) {
2429 RETURN_STRING(err);
2430 }
2431 }
2432 /* }}} */
2433
2434 /* {{{ proto mixed mysqli_stmt_init(object link)
2435 Initialize statement object
2436 */
2437 PHP_FUNCTION(mysqli_stmt_init)
2438 {
2439 MY_MYSQL *mysql;
2440 MY_STMT *stmt;
2441 zval *mysql_link;
2442 MYSQLI_RESOURCE *mysqli_resource;
2443
2444 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",&mysql_link, mysqli_link_class_entry) == FAILURE) {
2445 return;
2446 }
2447 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2448
2449 stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
2450
2451 if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
2452 efree(stmt);
2453 RETURN_FALSE;
2454 }
2455 #ifndef MYSQLI_USE_MYSQLND
2456 ZVAL_COPY(&stmt->link_handle, mysql_link);
2457 #endif
2458
2459 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2460 mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
2461 mysqli_resource->ptr = (void *)stmt;
2462 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
2463 }
2464 /* }}} */
2465
2466 /* {{{ proto bool mysqli_stmt_prepare(object stmt, string query)
2467 prepare server side statement with query
2468 */
2469 PHP_FUNCTION(mysqli_stmt_prepare)
2470 {
2471 MY_STMT *stmt;
2472 zval *mysql_stmt;
2473 char *query;
2474 size_t query_len;
2475
2476 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry, &query, &query_len) == FAILURE) {
2477 return;
2478 }
2479 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2480
2481 if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
2482 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2483 RETURN_FALSE;
2484 }
2485 /* change status */
2486 MYSQLI_SET_STATUS(mysql_stmt, MYSQLI_STATUS_VALID);
2487 RETURN_TRUE;
2488 }
2489 /* }}} */
2490
2491 /* {{{ proto mixed mysqli_stmt_result_metadata(object stmt)
2492 return result set from statement */
2493 PHP_FUNCTION(mysqli_stmt_result_metadata)
2494 {
2495 MY_STMT *stmt;
2496 MYSQL_RES *result;
2497 zval *mysql_stmt;
2498 MYSQLI_RESOURCE *mysqli_resource;
2499
2500 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2501 return;
2502 }
2503 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2504
2505 if (!(result = mysql_stmt_result_metadata(stmt->stmt))){
2506 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2507 RETURN_FALSE;
2508 }
2509
2510 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2511 mysqli_resource->ptr = (void *)result;
2512 mysqli_resource->status = MYSQLI_STATUS_VALID;
2513 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2514 }
2515 /* }}} */
2516
2517 /* {{{ proto bool mysqli_stmt_store_result(object stmt)
2518 */
2519 PHP_FUNCTION(mysqli_stmt_store_result)
2520 {
2521 MY_STMT *stmt;
2522 zval *mysql_stmt;
2523
2524 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2525 return;
2526 }
2527 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2528
2529 #if !defined(MYSQLI_USE_MYSQLND)
2530 {
2531 /*
2532 If the user wants to store the data and we have BLOBs/TEXTs we try to allocate
2533 not the maximal length of the type (which is 16MB even for LONGBLOB) but
2534 the maximal length of the field in the result set. If he/she has quite big
2535 BLOB/TEXT columns after calling store_result() the memory usage of PHP will
2536 double - but this is a known problem of the simple MySQL API ;)
2537 */
2538 int i = 0;
2539
2540 for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) {
2541 if (stmt->stmt->fields && (stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB ||
2542 stmt->stmt->fields[i].type == MYSQL_TYPE_MEDIUM_BLOB ||
2543 stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB ||
2544 stmt->stmt->fields[i].type == MYSQL_TYPE_GEOMETRY))
2545 {
2546 #if MYSQL_VERSION_ID >= 50107
2547 my_bool tmp=1;
2548 #else
2549 uint32_t tmp=1;
2550 #endif
2551 mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
2552 break;
2553 }
2554 }
2555 }
2556 #endif
2557
2558 if (mysql_stmt_store_result(stmt->stmt)){
2559 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2560 RETURN_FALSE;
2561 }
2562 RETURN_TRUE;
2563 }
2564 /* }}} */
2565
2566 /* {{{ proto string mysqli_stmt_sqlstate(object stmt)
2567 */
2568 PHP_FUNCTION(mysqli_stmt_sqlstate)
2569 {
2570 MY_STMT *stmt;
2571 zval *mysql_stmt;
2572 const char * state;
2573
2574 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2575 return;
2576 }
2577 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2578
2579 state = mysql_stmt_sqlstate(stmt->stmt);
2580 if (state) {
2581 RETURN_STRING(state);
2582 }
2583 }
2584 /* }}} */
2585
2586 /* {{{ proto object mysqli_store_result(object link [, int flags])
2587 Buffer result set on client */
2588 PHP_FUNCTION(mysqli_store_result)
2589 {
2590 MY_MYSQL *mysql;
2591 MYSQL_RES *result;
2592 zval *mysql_link;
2593 MYSQLI_RESOURCE *mysqli_resource;
2594 zend_long flags = 0;
2595
2596
2597 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_link, mysqli_link_class_entry, &flags) == FAILURE) {
2598 return;
2599 }
2600 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2601 #if MYSQLI_USE_MYSQLND
2602 result = flags & MYSQLI_STORE_RESULT_COPY_DATA? mysqlnd_store_result_ofs(mysql->mysql) : mysqlnd_store_result(mysql->mysql);
2603 #else
2604 result = mysql_store_result(mysql->mysql);
2605 #endif
2606 if (!result) {
2607 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2608 RETURN_FALSE;
2609 }
2610 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2611 php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2612 }
2613
2614 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2615 mysqli_resource->ptr = (void *)result;
2616 mysqli_resource->status = MYSQLI_STATUS_VALID;
2617 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2618 }
2619 /* }}} */
2620
2621 /* {{{ proto int mysqli_thread_id(object link)
2622 Return the current thread ID */
2623 PHP_FUNCTION(mysqli_thread_id)
2624 {
2625 MY_MYSQL *mysql;
2626 zval *mysql_link;
2627
2628 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2629 return;
2630 }
2631 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2632
2633 RETURN_LONG((zend_long) mysql_thread_id(mysql->mysql));
2634 }
2635 /* }}} */
2636
2637 /* {{{ proto bool mysqli_thread_safe(void)
2638 Return whether thread safety is given or not */
2639 PHP_FUNCTION(mysqli_thread_safe)
2640 {
2641 RETURN_BOOL(mysql_thread_safe());
2642 }
2643 /* }}} */
2644
2645 /* {{{ proto mixed mysqli_use_result(object link)
2646 Directly retrieve query results - do not buffer results on client side */
2647 PHP_FUNCTION(mysqli_use_result)
2648 {
2649 MY_MYSQL *mysql;
2650 MYSQL_RES *result;
2651 zval *mysql_link;
2652 MYSQLI_RESOURCE *mysqli_resource;
2653
2654 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2655 return;
2656 }
2657 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2658
2659 if (!(result = mysql_use_result(mysql->mysql))) {
2660 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2661 RETURN_FALSE;
2662 }
2663
2664 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2665 php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2666 }
2667 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2668 mysqli_resource->ptr = (void *)result;
2669 mysqli_resource->status = MYSQLI_STATUS_VALID;
2670 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2671 }
2672 /* }}} */
2673
2674 /* {{{ proto int mysqli_warning_count(object link)
2675 Return number of warnings from the last query for the given link */
2676 PHP_FUNCTION(mysqli_warning_count)
2677 {
2678 MY_MYSQL *mysql;
2679 zval *mysql_link;
2680
2681 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2682 return;
2683 }
2684 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2685
2686 RETURN_LONG(mysql_warning_count(mysql->mysql));
2687 }
2688 /* }}} */
2689
2690 /*
2691 * Local variables:
2692 * tab-width: 4
2693 * c-basic-offset: 4
2694 * End:
2695 * vim600: noet sw=4 ts=4 fdm=marker
2696 * vim<600: noet sw=4 ts=4
2697 */
2698