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