1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Georg Richter <georg@php.net> |
16 | Andrey Hristov <andrey@php.net> |
17 | Ulf Wendel <uw@php.net> |
18 +----------------------------------------------------------------------+
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <signal.h>
26
27 #include "php.h"
28 #include "php_ini.h"
29 #include "php_globals.h"
30 #include "ext/standard/info.h"
31 #include "zend_smart_str.h"
32 #include "php_mysqli_structs.h"
33 #include "mysqli_priv.h"
34 #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 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 RETURN_FALSE;
759 }
760 RETURN_TRUE;
761 }
762 /* }}} */
763
764 /* {{{ proto bool mysqli_data_seek(object result, int offset)
765 Move internal result pointer */
766 PHP_FUNCTION(mysqli_data_seek)
767 {
768 MYSQL_RES *result;
769 zval *mysql_result;
770 zend_long offset;
771
772 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
773 return;
774 }
775
776 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
777
778 if (mysqli_result_is_unbuffered(result)) {
779 php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
780 RETURN_FALSE;
781 }
782
783 if (offset < 0 || (uint64_t)offset >= mysql_num_rows(result)) {
784 RETURN_FALSE;
785 }
786
787 mysql_data_seek(result, offset);
788 RETURN_TRUE;
789 }
790 /* }}} */
791
792 /* {{{ proto void mysqli_debug(string debug)
793 */
794 PHP_FUNCTION(mysqli_debug)
795 {
796 char *debug;
797 size_t debug_len;
798
799 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &debug, &debug_len) == FAILURE) {
800 return;
801 }
802
803 mysql_debug(debug);
804 RETURN_TRUE;
805 }
806 /* }}} */
807
808 /* {{{ proto bool mysqli_dump_debug_info(object link)
809 */
810 PHP_FUNCTION(mysqli_dump_debug_info)
811 {
812 MY_MYSQL *mysql;
813 zval *mysql_link;
814
815 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
816 return;
817 }
818 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
819
820 RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql))
821 }
822 /* }}} */
823
824 /* {{{ proto int mysqli_errno(object link)
825 Returns the numerical value of the error message from previous MySQL operation */
826 PHP_FUNCTION(mysqli_errno)
827 {
828 MY_MYSQL *mysql;
829 zval *mysql_link;
830
831 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
832 return;
833 }
834 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
835 RETURN_LONG(mysql_errno(mysql->mysql));
836 }
837 /* }}} */
838
839 /* {{{ proto string mysqli_error(object link)
840 Returns the text of the error message from previous MySQL operation */
841 PHP_FUNCTION(mysqli_error)
842 {
843 MY_MYSQL *mysql;
844 zval *mysql_link;
845 const char *err;
846
847 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
848 return;
849 }
850 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
851 err = mysql_error(mysql->mysql);
852 if (err) {
853 RETURN_STRING(err);
854 }
855 }
856 /* }}} */
857
858 /* {{{ proto bool mysqli_stmt_execute(object stmt)
859 Execute a prepared statement */
860 PHP_FUNCTION(mysqli_stmt_execute)
861 {
862 MY_STMT *stmt;
863 zval *mysql_stmt;
864 #ifndef MYSQLI_USE_MYSQLND
865 unsigned int i;
866 #endif
867
868 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
869 return;
870 }
871 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
872
873 #ifndef MYSQLI_USE_MYSQLND
874 if (stmt->param.var_cnt) {
875 int j;
876 for (i = 0; i < stmt->param.var_cnt; i++) {
877 if (!Z_ISREF(stmt->param.vars[i])) {
878 continue;
879 }
880 for (j = i + 1; j < stmt->param.var_cnt; j++) {
881 /* Oops, someone binding the same variable - clone */
882 if (Z_ISREF(stmt->param.vars[j]) &&
883 Z_REFVAL(stmt->param.vars[j]) == Z_REFVAL(stmt->param.vars[i])) {
884 /*SEPARATE_ZVAL(&stmt->param.vars[j]);*/
885 Z_DELREF_P(&stmt->param.vars[j]);
886 ZVAL_COPY(&stmt->param.vars[j], Z_REFVAL(stmt->param.vars[j]));
887 break;
888 }
889 }
890 }
891 }
892 for (i = 0; i < stmt->param.var_cnt; i++) {
893 if (!Z_ISUNDEF(stmt->param.vars[i])) {
894 zval *param;
895 if (Z_ISREF(stmt->param.vars[i])) {
896 param = Z_REFVAL(stmt->param.vars[i]);
897 } else {
898 param = &stmt->param.vars[i];
899 }
900 if (!(stmt->param.is_null[i] = (Z_ISNULL_P(param)))) {
901 switch (stmt->stmt->params[i].buffer_type) {
902 case MYSQL_TYPE_VAR_STRING:
903 convert_to_string_ex(param);
904 stmt->stmt->params[i].buffer = Z_STRVAL_P(param);
905 stmt->stmt->params[i].buffer_length = Z_STRLEN_P(param);
906 break;
907 case MYSQL_TYPE_DOUBLE:
908 convert_to_double_ex(param);
909 stmt->stmt->params[i].buffer = &Z_DVAL_P(param);
910 break;
911 case MYSQL_TYPE_LONGLONG:
912 case MYSQL_TYPE_LONG:
913 convert_to_long_ex(param);
914 stmt->stmt->params[i].buffer = &Z_LVAL_P(param);
915 break;
916 default:
917 break;
918 }
919 }
920 }
921 }
922 #endif
923
924 if (mysql_stmt_execute(stmt->stmt)) {
925 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
926 RETVAL_FALSE;
927 } else {
928 RETVAL_TRUE;
929 }
930
931 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
932 php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt));
933 }
934 }
935 /* }}} */
936
937 #ifndef MYSQLI_USE_MYSQLND
938 /* {{{ void mysqli_stmt_fetch_libmysql
939 Fetch results from a prepared statement into the bound variables */
940 void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
941 {
942 MY_STMT *stmt;
943 zval *mysql_stmt;
944 unsigned int i;
945 zend_ulong ret;
946 unsigned int uval;
947 my_ulonglong llval;
948
949
950 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
951 return;
952 }
953 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
954
955 /* reset buffers */
956 for (i = 0; i < stmt->result.var_cnt; i++) {
957 if (stmt->result.buf[i].type == IS_STRING) {
958 memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen);
959 }
960 }
961 ret = mysql_stmt_fetch(stmt->stmt);
962 #ifdef MYSQL_DATA_TRUNCATED
963 if (!ret || ret == MYSQL_DATA_TRUNCATED) {
964 #else
965 if (!ret) {
966 #endif
967 for (i = 0; i < stmt->result.var_cnt; i++) {
968 zval *result;
969 /* it must be a reference, isn't it? */
970 if (Z_ISREF(stmt->result.vars[i])) {
971 result = Z_REFVAL(stmt->result.vars[i]);
972 } else {
973 result = &stmt->result.vars[i];
974 }
975 /*
976 QQ: Isn't it quite better to call zval_dtor(). What if the user has
977 assigned a resource, or an array to the bound variable? We are going
978 to leak probably. zval_dtor() will handle also Unicode/Non-unicode mode.
979 */
980 /* Even if the string is of length zero there is one byte alloced so efree() in all cases */
981 zval_ptr_dtor(result);
982 if (!stmt->result.is_null[i]) {
983 switch (stmt->result.buf[i].type) {
984 case IS_LONG:
985 if ((stmt->stmt->fields[i].type == MYSQL_TYPE_LONG)
986 && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG))
987 {
988 /* unsigned int (11) */
989 uval= *(unsigned int *) stmt->result.buf[i].val;
990 #if SIZEOF_ZEND_LONG==4
991 if (uval > INT_MAX) {
992 char *tmp, *p;
993 int j = 10;
994 tmp = emalloc(11);
995 p= &tmp[9];
996 do {
997 *p-- = (uval % 10) + 48;
998 uval = uval / 10;
999 } while (--j > 0);
1000 tmp[10]= '\0';
1001 /* unsigned int > INT_MAX is 10 digits - ALWAYS */
1002 ZVAL_STRINGL(result, tmp, 10);
1003 efree(tmp);
1004 break;
1005 }
1006 #endif
1007 }
1008 if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) {
1009 ZVAL_LONG(result, *(unsigned int *)stmt->result.buf[i].val);
1010 } else {
1011 ZVAL_LONG(result, *(int *)stmt->result.buf[i].val);
1012 }
1013 break;
1014 case IS_DOUBLE:
1015 {
1016 double dval;
1017 if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_FLOAT) {
1018 #ifndef NOT_FIXED_DEC
1019 # define NOT_FIXED_DEC 31
1020 #endif
1021 dval = mysql_float_to_double(*(float *)stmt->result.buf[i].val,
1022 (stmt->stmt->fields[i].decimals >= NOT_FIXED_DEC) ? -1 :
1023 stmt->stmt->fields[i].decimals);
1024 } else {
1025 dval = *((double *)stmt->result.buf[i].val);
1026 }
1027
1028 ZVAL_DOUBLE(result, dval);
1029 break;
1030 }
1031 case IS_STRING:
1032 if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
1033 #if MYSQL_VERSION_ID > 50002
1034 || stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT
1035 #endif
1036 ) {
1037 my_bool uns = (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0;
1038 #if MYSQL_VERSION_ID > 50002
1039 if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) {
1040 switch (stmt->result.buf[i].output_len) {
1041 case 8:llval = (my_ulonglong) bit_uint8korr(stmt->result.buf[i].val);break;
1042 case 7:llval = (my_ulonglong) bit_uint7korr(stmt->result.buf[i].val);break;
1043 case 6:llval = (my_ulonglong) bit_uint6korr(stmt->result.buf[i].val);break;
1044 case 5:llval = (my_ulonglong) bit_uint5korr(stmt->result.buf[i].val);break;
1045 case 4:llval = (my_ulonglong) bit_uint4korr(stmt->result.buf[i].val);break;
1046 case 3:llval = (my_ulonglong) bit_uint3korr(stmt->result.buf[i].val);break;
1047 case 2:llval = (my_ulonglong) bit_uint2korr(stmt->result.buf[i].val);break;
1048 case 1:llval = (my_ulonglong) uint1korr(stmt->result.buf[i].val);break;
1049 }
1050 } else
1051 #endif
1052 {
1053 llval= *(my_ulonglong *) stmt->result.buf[i].val;
1054 }
1055 #if SIZEOF_ZEND_LONG==8
1056 if (uns && llval > 9223372036854775807L) {
1057 #elif SIZEOF_ZEND_LONG==4
1058 if ((uns && llval > L64(2147483647)) ||
1059 (!uns && (( L64(2147483647) < (my_longlong) llval) ||
1060 (L64(-2147483648) > (my_longlong) llval))))
1061 {
1062 #endif
1063 char tmp[22];
1064 /* even though lval is declared as unsigned, the value
1065 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
1066 * use MYSQLI_LL_SPEC.
1067 */
1068 snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1069 ZVAL_STRING(result, tmp);
1070 } else {
1071 ZVAL_LONG(result, llval);
1072 }
1073 } else {
1074 #if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002
1075 if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) {
1076 /* result was truncated */
1077 ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length);
1078 } else {
1079 #else
1080 {
1081 #endif
1082 ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->result.buf[i].output_len);
1083 }
1084 }
1085 break;
1086 default:
1087 break;
1088 }
1089 } else {
1090 ZVAL_NULL(result);
1091 }
1092 }
1093 } else {
1094 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1095 }
1096
1097 switch (ret) {
1098 case 0:
1099 #ifdef MYSQL_DATA_TRUNCATED
1100 /* according to SQL standard truncation (e.g. loss of precision is
1101 not an error) - for detecting possible truncation you have to
1102 check mysqli_stmt_warning
1103 */
1104 case MYSQL_DATA_TRUNCATED:
1105 #endif
1106 RETURN_TRUE;
1107 break;
1108 case 1:
1109 RETURN_FALSE;
1110 break;
1111 default:
1112 RETURN_NULL();
1113 break;
1114 }
1115 }
1116 /* }}} */
1117 #else
1118 /* {{{ mixed mysqli_stmt_fetch_mysqlnd */
1119 void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)
1120 {
1121 MY_STMT *stmt;
1122 zval *mysql_stmt;
1123 zend_bool fetched_anything;
1124
1125 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1126 return;
1127 }
1128 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1129
1130 if (FAIL == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) {
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_more_results(mysql->mysql)) {
1613 php_error_docref(NULL, E_STRICT, "There is no next result set. "
1614 "Please, call mysqli_more_results()/mysqli::more_results() to check "
1615 "whether to call this function/method");
1616 }
1617
1618 RETURN_BOOL(!mysql_next_result(mysql->mysql));
1619 }
1620 /* }}} */
1621
1622 #if defined(HAVE_STMT_NEXT_RESULT) && defined(MYSQLI_USE_MYSQLND)
1623 /* {{{ proto bool mysqli_stmt_next_result(object link)
1624 check if there any more query results from a multi query */
1625 PHP_FUNCTION(mysqli_stmt_more_results)
1626 {
1627 MY_STMT *stmt;
1628 zval *mysql_stmt;
1629
1630 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1631 return;
1632 }
1633 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1634
1635 RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1636 }
1637 /* }}} */
1638
1639 /* {{{ proto bool mysqli_stmt_next_result(object link)
1640 read next result from multi_query */
1641 PHP_FUNCTION(mysqli_stmt_next_result) {
1642 MY_STMT *stmt;
1643 zval *mysql_stmt;
1644
1645 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1646 return;
1647 }
1648 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1649
1650 if (!mysqlnd_stmt_more_results(stmt->stmt)) {
1651 php_error_docref(NULL, E_STRICT, "There is no next result set. "
1652 "Please, call mysqli_stmt_more_results()/mysqli_stmt::more_results() to check "
1653 "whether to call this function/method");
1654 }
1655
1656 RETURN_BOOL(!mysql_stmt_next_result(stmt->stmt));
1657 }
1658 /* }}} */
1659 #endif
1660
1661 /* {{{ proto int mysqli_num_fields(object result)
1662 Get number of fields in result */
1663 PHP_FUNCTION(mysqli_num_fields)
1664 {
1665 MYSQL_RES *result;
1666 zval *mysql_result;
1667
1668 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1669 return;
1670 }
1671 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1672
1673 RETURN_LONG(mysql_num_fields(result));
1674 }
1675 /* }}} */
1676
1677 /* {{{ proto mixed mysqli_num_rows(object result)
1678 Get number of rows in result */
1679 PHP_FUNCTION(mysqli_num_rows)
1680 {
1681 MYSQL_RES *result;
1682 zval *mysql_result;
1683
1684 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1685 return;
1686 }
1687 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1688
1689 if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) {
1690 php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
1691 RETURN_LONG(0);
1692 }
1693
1694 MYSQLI_RETURN_LONG_INT(mysql_num_rows(result));
1695 }
1696 /* }}} */
1697
1698 /* {{{ mysqli_options_get_option_zval_type */
1699 static int mysqli_options_get_option_zval_type(int option)
1700 {
1701 switch (option) {
1702 #ifdef MYSQLI_USE_MYSQLND
1703 case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
1704 case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
1705 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
1706 case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
1707 #endif
1708 #endif /* MYSQLI_USE_MYSQLND */
1709 case MYSQL_OPT_CONNECT_TIMEOUT:
1710 #ifdef MYSQL_REPORT_DATA_TRUNCATION
1711 case MYSQL_REPORT_DATA_TRUNCATION:
1712 #endif
1713 case MYSQL_OPT_LOCAL_INFILE:
1714 case MYSQL_OPT_NAMED_PIPE:
1715 #ifdef MYSQL_OPT_PROTOCOL
1716 case MYSQL_OPT_PROTOCOL:
1717 #endif /* MySQL 4.1.0 */
1718 case MYSQL_OPT_READ_TIMEOUT:
1719 case MYSQL_OPT_WRITE_TIMEOUT:
1720 #ifdef MYSQL_OPT_GUESS_CONNECTION /* removed in MySQL-8.0 */
1721 case MYSQL_OPT_GUESS_CONNECTION:
1722 case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
1723 case MYSQL_OPT_USE_REMOTE_CONNECTION:
1724 case MYSQL_SECURE_AUTH:
1725 #endif
1726 #ifdef MYSQL_OPT_RECONNECT
1727 case MYSQL_OPT_RECONNECT:
1728 #endif /* MySQL 5.0.13 */
1729 #ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
1730 case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
1731 #endif /* MySQL 5.0.23 */
1732 #ifdef MYSQL_OPT_COMPRESS
1733 case MYSQL_OPT_COMPRESS:
1734 #endif /* mysqlnd @ PHP 5.3.2 */
1735 #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
1736 case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
1737 #endif
1738 return IS_LONG;
1739
1740 #ifdef MYSQL_SHARED_MEMORY_BASE_NAME
1741 case MYSQL_SHARED_MEMORY_BASE_NAME:
1742 #endif /* MySQL 4.1.0 */
1743 #ifdef MYSQL_SET_CLIENT_IP
1744 case MYSQL_SET_CLIENT_IP:
1745 #endif /* MySQL 4.1.1 */
1746 case MYSQL_READ_DEFAULT_FILE:
1747 case MYSQL_READ_DEFAULT_GROUP:
1748 case MYSQL_INIT_COMMAND:
1749 case MYSQL_SET_CHARSET_NAME:
1750 case MYSQL_SET_CHARSET_DIR:
1751 #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
1752 case MYSQL_SERVER_PUBLIC_KEY:
1753 #endif
1754 return IS_STRING;
1755
1756 default:
1757 return IS_NULL;
1758 }
1759 }
1760 /* }}} */
1761
1762 /* {{{ proto bool mysqli_options(object link, int flags, mixed values)
1763 Set options */
1764 PHP_FUNCTION(mysqli_options)
1765 {
1766 MY_MYSQL *mysql;
1767 zval *mysql_link = NULL;
1768 zval *mysql_value;
1769 zend_long mysql_option;
1770 unsigned int l_value;
1771 zend_long ret;
1772 int expected_type;
1773
1774 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
1775 return;
1776 }
1777 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
1778
1779 #if !defined(MYSQLI_USE_MYSQLND)
1780 if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
1781 if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
1782 RETURN_FALSE;
1783 }
1784 }
1785 #endif
1786 expected_type = mysqli_options_get_option_zval_type(mysql_option);
1787 if (expected_type != Z_TYPE_P(mysql_value)) {
1788 switch (expected_type) {
1789 case IS_STRING:
1790 convert_to_string_ex(mysql_value);
1791 break;
1792 case IS_LONG:
1793 convert_to_long_ex(mysql_value);
1794 break;
1795 default:
1796 break;
1797 }
1798 }
1799 switch (expected_type) {
1800 case IS_STRING:
1801 ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value));
1802 break;
1803 case IS_LONG:
1804 l_value = Z_LVAL_P(mysql_value);
1805 ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
1806 break;
1807 default:
1808 ret = 1;
1809 break;
1810 }
1811
1812 RETURN_BOOL(!ret);
1813 }
1814 /* }}} */
1815
1816 /* {{{ proto bool mysqli_ping(object link)
1817 Ping a server connection or reconnect if there is no connection */
1818 PHP_FUNCTION(mysqli_ping)
1819 {
1820 MY_MYSQL *mysql;
1821 zval *mysql_link;
1822 zend_long rc;
1823
1824 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1825 return;
1826 }
1827 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1828 rc = mysql_ping(mysql->mysql);
1829 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1830
1831 RETURN_BOOL(!rc);
1832 }
1833 /* }}} */
1834
1835 /* {{{ proto mixed mysqli_prepare(object link, string query)
1836 Prepare a SQL statement for execution */
1837 PHP_FUNCTION(mysqli_prepare)
1838 {
1839 MY_MYSQL *mysql;
1840 MY_STMT *stmt;
1841 char *query = NULL;
1842 size_t query_len;
1843 zval *mysql_link;
1844 MYSQLI_RESOURCE *mysqli_resource;
1845
1846 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1847 return;
1848 }
1849 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1850
1851 #if !defined(MYSQLI_USE_MYSQLND)
1852 if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
1853 php_error_docref(NULL, E_WARNING, "All data must be fetched before a new statement prepare takes place");
1854 RETURN_FALSE;
1855 }
1856 #endif
1857
1858 stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1859
1860 if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1861 if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1862 /* mysql_stmt_close() clears errors, so we have to store them temporarily */
1863 #if !defined(MYSQLI_USE_MYSQLND)
1864 char last_error[MYSQL_ERRMSG_SIZE];
1865 char sqlstate[SQLSTATE_LENGTH+1];
1866 unsigned int last_errno;
1867
1868 last_errno = stmt->stmt->last_errno;
1869 memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
1870 memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
1871 #else
1872 MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
1873 mysql->mysql->data->error_info->error_list.head = NULL;
1874 mysql->mysql->data->error_info->error_list.tail = NULL;
1875 mysql->mysql->data->error_info->error_list.count = 0;
1876 #endif
1877 mysqli_stmt_close(stmt->stmt, FALSE);
1878 stmt->stmt = NULL;
1879
1880 /* restore error messages */
1881 #if !defined(MYSQLI_USE_MYSQLND)
1882 mysql->mysql->net.last_errno = last_errno;
1883 memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
1884 memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
1885 #else
1886 zend_llist_clean(&mysql->mysql->data->error_info->error_list);
1887 *mysql->mysql->data->error_info = error_info;
1888 #endif
1889 }
1890 }
1891
1892 /* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1893 /* Get performance boost if reporting is switched off */
1894 if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1895 stmt->query = (char *)emalloc(query_len + 1);
1896 memcpy(stmt->query, query, query_len);
1897 stmt->query[query_len] = '\0';
1898 }
1899
1900 /* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1901 if (!stmt->stmt) {
1902 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1903 efree(stmt);
1904 RETURN_FALSE;
1905 }
1906 #ifndef MYSQLI_USE_MYSQLND
1907 ZVAL_COPY(&stmt->link_handle, mysql_link);
1908 #endif
1909
1910 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1911 mysqli_resource->ptr = (void *)stmt;
1912
1913 /* change status */
1914 mysqli_resource->status = MYSQLI_STATUS_VALID;
1915 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1916 }
1917 /* }}} */
1918
1919 /* {{{ proto bool mysqli_real_connect(object link [,string hostname [,string username [,string passwd [,string dbname [,int port [,string socket [,int flags]]]]]]])
1920 Open a connection to a mysql server */
1921 PHP_FUNCTION(mysqli_real_connect)
1922 {
1923 mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE, FALSE);
1924 }
1925 /* }}} */
1926
1927 /* {{{ proto bool mysqli_real_query(object link, string query)
1928 Binary-safe version of mysql_query() */
1929 PHP_FUNCTION(mysqli_real_query)
1930 {
1931 MY_MYSQL *mysql;
1932 zval *mysql_link;
1933 char *query = NULL;
1934 size_t query_len;
1935
1936 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1937 return;
1938 }
1939 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1940
1941 MYSQLI_DISABLE_MQ; /* disable multi statements/queries */
1942
1943 if (mysql_real_query(mysql->mysql, query, query_len)) {
1944 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1945 RETURN_FALSE;
1946 }
1947
1948 if (!mysql_field_count(mysql->mysql)) {
1949 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1950 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
1951 }
1952 }
1953
1954 RETURN_TRUE;
1955 }
1956 /* }}} */
1957
1958 #if defined(MYSQLI_USE_MYSQLND) || MYSQL_VERSION_ID < 50707 || defined(MARIADB_BASE_VERSION)
1959 # define mysql_real_escape_string_quote(mysql, to, from, length, quote) \
1960 mysql_real_escape_string(mysql, to, from, length)
1961 #endif
1962
1963 /* {{{ proto string mysqli_real_escape_string(object link, string escapestr)
1964 Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection */
1965 PHP_FUNCTION(mysqli_real_escape_string) {
1966 MY_MYSQL *mysql;
1967 zval *mysql_link = NULL;
1968 char *escapestr;
1969 size_t escapestr_len;
1970 zend_string *newstr;
1971
1972 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &escapestr, &escapestr_len) == FAILURE) {
1973 return;
1974 }
1975 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1976
1977 newstr = zend_string_alloc(2 * escapestr_len, 0);
1978 ZSTR_LEN(newstr) = mysql_real_escape_string_quote(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len, '\'');
1979 newstr = zend_string_truncate(newstr, ZSTR_LEN(newstr), 0);
1980
1981 RETURN_NEW_STR(newstr);
1982 }
1983 /* }}} */
1984
1985 /* {{{ proto bool mysqli_rollback(object link)
1986 Undo actions from current transaction */
1987 PHP_FUNCTION(mysqli_rollback)
1988 {
1989 MY_MYSQL *mysql;
1990 zval *mysql_link;
1991 zend_long flags = TRANS_COR_NO_OPT;
1992 char * name = NULL;
1993 size_t name_len = 0;
1994
1995 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1996 return;
1997 }
1998 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1999
2000 #if !defined(MYSQLI_USE_MYSQLND)
2001 if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) {
2002 #else
2003 if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
2004 #endif
2005 RETURN_FALSE;
2006 }
2007 RETURN_TRUE;
2008 }
2009 /* }}} */
2010
2011 /* {{{ proto bool mysqli_stmt_send_long_data(object stmt, int param_nr, string data)
2012 */
2013 PHP_FUNCTION(mysqli_stmt_send_long_data)
2014 {
2015 MY_STMT *stmt;
2016 zval *mysql_stmt;
2017 char *data;
2018 zend_long param_nr;
2019 size_t data_len;
2020
2021 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, ¶m_nr, &data, &data_len) == FAILURE) {
2022 return;
2023 }
2024 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2025
2026 if (param_nr < 0) {
2027 php_error_docref(NULL, E_WARNING, "Invalid parameter number");
2028 RETURN_FALSE;
2029 }
2030 if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) {
2031 RETURN_FALSE;
2032 }
2033 RETURN_TRUE;
2034 }
2035 /* }}} */
2036
2037 /* {{{ proto string|int|false mysqli_stmt_affected_rows(object stmt)
2038 Return the number of rows affected in the last query for the given link. */
2039 PHP_FUNCTION(mysqli_stmt_affected_rows)
2040 {
2041 MY_STMT *stmt;
2042 zval *mysql_stmt;
2043 my_ulonglong rc;
2044
2045 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2046 return;
2047 }
2048 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2049
2050 rc = mysql_stmt_affected_rows(stmt->stmt);
2051 if (rc == (my_ulonglong) -1) {
2052 RETURN_LONG(-1);
2053 }
2054 MYSQLI_RETURN_LONG_INT(rc)
2055 }
2056 /* }}} */
2057
2058 /* {{{ proto bool mysqli_stmt_close(object stmt)
2059 Close statement */
2060 PHP_FUNCTION(mysqli_stmt_close)
2061 {
2062 MY_STMT *stmt;
2063 zval *mysql_stmt;
2064
2065 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2066 return;
2067 }
2068 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2069
2070 mysqli_stmt_close(stmt->stmt, FALSE);
2071 stmt->stmt = NULL;
2072 php_clear_stmt_bind(stmt);
2073 MYSQLI_CLEAR_RESOURCE(mysql_stmt);
2074 RETURN_TRUE;
2075 }
2076 /* }}} */
2077
2078 /* {{{ proto void mysqli_stmt_data_seek(object stmt, int offset)
2079 Move internal result pointer */
2080 PHP_FUNCTION(mysqli_stmt_data_seek)
2081 {
2082 MY_STMT *stmt;
2083 zval *mysql_stmt;
2084 zend_long offset;
2085
2086 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
2087 return;
2088 }
2089 if (offset < 0) {
2090 php_error_docref(NULL, E_WARNING, "Offset must be positive");
2091 RETURN_FALSE;
2092 }
2093
2094 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2095
2096 mysql_stmt_data_seek(stmt->stmt, offset);
2097 }
2098 /* }}} */
2099
2100 /* {{{ proto int mysqli_stmt_field_count(object stmt) {
2101 Return the number of result columns for the given statement */
2102 PHP_FUNCTION(mysqli_stmt_field_count)
2103 {
2104 MY_STMT *stmt;
2105 zval *mysql_stmt;
2106
2107 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2108 return;
2109 }
2110 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2111
2112 RETURN_LONG(mysql_stmt_field_count(stmt->stmt));
2113 }
2114 /* }}} */
2115
2116 /* {{{ proto void mysqli_stmt_free_result(object stmt)
2117 Free stored result memory for the given statement handle */
2118 PHP_FUNCTION(mysqli_stmt_free_result)
2119 {
2120 MY_STMT *stmt;
2121 zval *mysql_stmt;
2122
2123 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2124 return;
2125 }
2126
2127 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2128
2129 mysql_stmt_free_result(stmt->stmt);
2130 }
2131 /* }}} */
2132
2133 /* {{{ proto mixed mysqli_stmt_insert_id(object stmt)
2134 Get the ID generated from the previous INSERT operation */
2135 PHP_FUNCTION(mysqli_stmt_insert_id)
2136 {
2137 MY_STMT *stmt;
2138 my_ulonglong rc;
2139 zval *mysql_stmt;
2140
2141 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2142 return;
2143 }
2144 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2145 rc = mysql_stmt_insert_id(stmt->stmt);
2146 MYSQLI_RETURN_LONG_INT(rc)
2147 }
2148 /* }}} */
2149
2150 /* {{{ proto int mysqli_stmt_param_count(object stmt)
2151 Return the number of parameter for the given statement */
2152 PHP_FUNCTION(mysqli_stmt_param_count)
2153 {
2154 MY_STMT *stmt;
2155 zval *mysql_stmt;
2156
2157 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2158 return;
2159 }
2160 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2161
2162 RETURN_LONG(mysql_stmt_param_count(stmt->stmt));
2163 }
2164 /* }}} */
2165
2166 /* {{{ proto bool mysqli_stmt_reset(object stmt)
2167 reset a prepared statement */
2168 PHP_FUNCTION(mysqli_stmt_reset)
2169 {
2170 MY_STMT *stmt;
2171 zval *mysql_stmt;
2172
2173 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2174 return;
2175 }
2176
2177 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2178
2179 if (mysql_stmt_reset(stmt->stmt)) {
2180 RETURN_FALSE;
2181 }
2182 RETURN_TRUE;
2183 }
2184 /* }}} */
2185
2186 /* {{{ proto mixed mysqli_stmt_num_rows(object stmt)
2187 Return the number of rows in statements result set */
2188 PHP_FUNCTION(mysqli_stmt_num_rows)
2189 {
2190 MY_STMT *stmt;
2191 zval *mysql_stmt;
2192 my_ulonglong rc;
2193
2194 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2195 return;
2196 }
2197
2198 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2199
2200 rc = mysql_stmt_num_rows(stmt->stmt);
2201 MYSQLI_RETURN_LONG_INT(rc)
2202 }
2203 /* }}} */
2204
2205 /* {{{ proto bool mysqli_select_db(object link, string dbname)
2206 Select a MySQL database */
2207 PHP_FUNCTION(mysqli_select_db)
2208 {
2209 MY_MYSQL *mysql;
2210 zval *mysql_link;
2211 char *dbname;
2212 size_t dbname_len;
2213
2214 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) {
2215 return;
2216 }
2217 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2218
2219 if (mysql_select_db(mysql->mysql, dbname)) {
2220 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2221 RETURN_FALSE;
2222 }
2223 RETURN_TRUE;
2224 }
2225 /* }}} */
2226
2227 /* {{{ proto string mysqli_sqlstate(object link)
2228 Returns the SQLSTATE error from previous MySQL operation */
2229 PHP_FUNCTION(mysqli_sqlstate)
2230 {
2231 MY_MYSQL *mysql;
2232 zval *mysql_link;
2233 const char *state;
2234
2235 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2236 return;
2237 }
2238 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2239 state = mysql_sqlstate(mysql->mysql);
2240 if (state) {
2241 RETURN_STRING(state);
2242 }
2243 }
2244 /* }}} */
2245
2246 /* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher])
2247 */
2248 PHP_FUNCTION(mysqli_ssl_set)
2249 {
2250 MY_MYSQL *mysql;
2251 zval *mysql_link;
2252 char *ssl_parm[5];
2253 size_t ssl_parm_len[5], i;
2254
2255 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) {
2256 return;
2257 }
2258 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2259
2260 for (i = 0; i < 5; i++) {
2261 if (!ssl_parm_len[i]) {
2262 ssl_parm[i] = NULL;
2263 }
2264 }
2265
2266 mysql_ssl_set(mysql->mysql, ssl_parm[0], ssl_parm[1], ssl_parm[2], ssl_parm[3], ssl_parm[4]);
2267
2268 RETURN_TRUE;
2269 }
2270 /* }}} */
2271
2272 /* {{{ proto mixed mysqli_stat(object link)
2273 Get current system status */
2274 PHP_FUNCTION(mysqli_stat)
2275 {
2276 MY_MYSQL *mysql;
2277 zval *mysql_link;
2278 #if defined(MYSQLI_USE_MYSQLND)
2279 zend_string *stat;
2280 #else
2281 char *stat;
2282 #endif
2283
2284 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2285 return;
2286 }
2287 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2288
2289 #if !defined(MYSQLI_USE_MYSQLND)
2290 if ((stat = (char *)mysql_stat(mysql->mysql)))
2291 {
2292 RETURN_STRING(stat);
2293 #else
2294 if (mysqlnd_stat(mysql->mysql, &stat) == PASS)
2295 {
2296 RETURN_STR(stat);
2297 #endif
2298 } else {
2299 RETURN_FALSE;
2300 }
2301 }
2302
2303 /* }}} */
2304
2305 /* {{{ proto bool mysqli_refresh(object link, int options)
2306 Flush tables or caches, or reset replication server information */
2307 PHP_FUNCTION(mysqli_refresh)
2308 {
2309 MY_MYSQL *mysql;
2310 zval *mysql_link = NULL;
2311 zend_long options;
2312
2313 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &options) == FAILURE) {
2314 return;
2315 }
2316 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2317 #ifdef MYSQLI_USE_MYSQLND
2318 RETURN_BOOL(!mysql_refresh(mysql->mysql, (uint8_t) options));
2319 #else
2320 RETURN_BOOL(!mysql_refresh(mysql->mysql, options));
2321 #endif
2322 }
2323 /* }}} */
2324
2325 /* {{{ proto int mysqli_stmt_attr_set(object stmt, int attr, int mode)
2326 */
2327 PHP_FUNCTION(mysqli_stmt_attr_set)
2328 {
2329 MY_STMT *stmt;
2330 zval *mysql_stmt;
2331 zend_long mode_in;
2332 #if MYSQL_VERSION_ID >= 50107
2333 my_bool mode_b;
2334 #endif
2335 unsigned long mode;
2336 zend_long attr;
2337 void *mode_p;
2338
2339 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) {
2340 return;
2341 }
2342 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2343
2344 if (mode_in < 0) {
2345 php_error_docref(NULL, E_WARNING, "mode should be non-negative, " ZEND_LONG_FMT " passed", mode_in);
2346 RETURN_FALSE;
2347 }
2348
2349 switch (attr) {
2350 #if MYSQL_VERSION_ID >= 50107
2351 case STMT_ATTR_UPDATE_MAX_LENGTH:
2352 mode_b = (my_bool) mode_in;
2353 mode_p = &mode_b;
2354 break;
2355 #endif
2356 default:
2357 mode = mode_in;
2358 mode_p = &mode;
2359 break;
2360 }
2361 #if !defined(MYSQLI_USE_MYSQLND)
2362 if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2363 #else
2364 if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2365 #endif
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
2691 /*
2692 * Local variables:
2693 * tab-width: 4
2694 * c-basic-offset: 4
2695 * End:
2696 * vim600: noet sw=4 ts=4 fdm=marker
2697 * vim<600: noet sw=4 ts=4
2698 */
2699