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