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