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 $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 != (size_t)(argc - start)) {
358 /* number of bind variables doesn't match number of elements in type definition string */
359 php_error_docref(NULL, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables");
360 RETURN_FALSE;
361 }
362
363 if (types_len != mysql_stmt_param_count(stmt->stmt)) {
364 php_error_docref(NULL, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement");
365 RETURN_FALSE;
366 }
367
368 args = safe_emalloc(argc, sizeof(zval), 0);
369
370 if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
371 zend_wrong_param_count();
372 rc = 1;
373 } else {
374 rc = mysqli_stmt_bind_param_do_bind(stmt, argc, num_vars, args, start, types);
375 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
376 }
377
378 efree(args);
379
380 RETURN_BOOL(!rc);
381 }
382 /* }}} */
383
384 /* {{{ mysqli_stmt_bind_result_do_bind */
385 #ifndef MYSQLI_USE_MYSQLND
386 /* TODO:
387 do_alloca, free_alloca
388 */
389 static int
mysqli_stmt_bind_result_do_bind(MY_STMT * stmt,zval * args,unsigned int argc)390 mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)
391 {
392 MYSQL_BIND *bind;
393 int i, ofs;
394 int var_cnt = argc;
395 zend_long col_type;
396 zend_ulong rc;
397
398 /* prevent leak if variables are already bound */
399 if (stmt->result.var_cnt) {
400 php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
401 }
402
403 bind = (MYSQL_BIND *)ecalloc(var_cnt, sizeof(MYSQL_BIND));
404 {
405 int size;
406 char *p = emalloc(size= var_cnt * (sizeof(char) + sizeof(VAR_BUFFER)));
407 stmt->result.buf = (VAR_BUFFER *) p;
408 stmt->result.is_null = p + var_cnt * sizeof(VAR_BUFFER);
409 memset(p, 0, size);
410 }
411
412 for (i = 0; i < var_cnt; i++) {
413 ofs = i;
414 col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING;
415
416 switch (col_type) {
417 case MYSQL_TYPE_FLOAT:
418 stmt->result.buf[ofs].type = IS_DOUBLE;
419 stmt->result.buf[ofs].buflen = sizeof(float);
420
421 stmt->result.buf[ofs].val = (char *)emalloc(sizeof(float));
422 bind[ofs].buffer_type = MYSQL_TYPE_FLOAT;
423 bind[ofs].buffer = stmt->result.buf[ofs].val;
424 bind[ofs].is_null = &stmt->result.is_null[ofs];
425 break;
426
427 case MYSQL_TYPE_DOUBLE:
428 stmt->result.buf[ofs].type = IS_DOUBLE;
429 stmt->result.buf[ofs].buflen = sizeof(double);
430
431 /* allocate buffer for double */
432 stmt->result.buf[ofs].val = (char *)emalloc(sizeof(double));
433 bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
434 bind[ofs].buffer = stmt->result.buf[ofs].val;
435 bind[ofs].is_null = &stmt->result.is_null[ofs];
436 break;
437
438 case MYSQL_TYPE_NULL:
439 stmt->result.buf[ofs].type = IS_NULL;
440 /*
441 don't initialize to 0 :
442 1. stmt->result.buf[ofs].buflen
443 2. bind[ofs].buffer
444 3. bind[ofs].buffer_length
445 because memory was allocated with ecalloc
446 */
447 bind[ofs].buffer_type = MYSQL_TYPE_NULL;
448 bind[ofs].is_null = &stmt->result.is_null[ofs];
449 break;
450
451 case MYSQL_TYPE_SHORT:
452 case MYSQL_TYPE_TINY:
453 case MYSQL_TYPE_LONG:
454 case MYSQL_TYPE_INT24:
455 case MYSQL_TYPE_YEAR:
456 stmt->result.buf[ofs].type = IS_LONG;
457 /* don't set stmt->result.buf[ofs].buflen to 0, we used ecalloc */
458 stmt->result.buf[ofs].val = (char *)emalloc(sizeof(int));
459 bind[ofs].buffer_type = MYSQL_TYPE_LONG;
460 bind[ofs].buffer = stmt->result.buf[ofs].val;
461 bind[ofs].is_null = &stmt->result.is_null[ofs];
462 bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
463 break;
464
465 case MYSQL_TYPE_LONGLONG:
466 #if MYSQL_VERSION_ID > 50002 || defined(MYSQLI_USE_MYSQLND)
467 case MYSQL_TYPE_BIT:
468 #endif
469 stmt->result.buf[ofs].type = IS_STRING;
470 stmt->result.buf[ofs].buflen = sizeof(my_ulonglong);
471 stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
472 bind[ofs].buffer_type = col_type;
473 bind[ofs].buffer = stmt->result.buf[ofs].val;
474 bind[ofs].is_null = &stmt->result.is_null[ofs];
475 bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
476 bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
477 bind[ofs].length = &stmt->result.buf[ofs].output_len;
478 break;
479
480 case MYSQL_TYPE_DATE:
481 case MYSQL_TYPE_TIME:
482 case MYSQL_TYPE_DATETIME:
483 case MYSQL_TYPE_NEWDATE:
484 case MYSQL_TYPE_VAR_STRING:
485 case MYSQL_TYPE_STRING:
486 case MYSQL_TYPE_TINY_BLOB:
487 case MYSQL_TYPE_BLOB:
488 case MYSQL_TYPE_MEDIUM_BLOB:
489 case MYSQL_TYPE_LONG_BLOB:
490 case MYSQL_TYPE_TIMESTAMP:
491 case MYSQL_TYPE_DECIMAL:
492 case MYSQL_TYPE_GEOMETRY:
493 #ifdef FIELD_TYPE_NEWDECIMAL
494 case MYSQL_TYPE_NEWDECIMAL:
495 #endif
496 {
497 #if MYSQL_VERSION_ID >= 50107
498 /* Changed to my_bool in MySQL 5.1. See MySQL Bug #16144 */
499 my_bool tmp;
500 #else
501 zend_ulong tmp = 0;
502 #endif
503 stmt->result.buf[ofs].type = IS_STRING;
504 /*
505 If the user has called $stmt->store_result() then we have asked
506 max_length to be updated. this is done only for BLOBS because we don't want to allocate
507 big chunkgs of memory 2^16 or 2^24
508 */
509 if (stmt->stmt->fields[ofs].max_length == 0 &&
510 !mysql_stmt_attr_get(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp) && !tmp)
511 {
512 /*
513 Allocate directly 256 because it's easier to allocate a bit more
514 than update max length even for text columns. Try SELECT UNION SELECT UNION with
515 different lengths and you will see that we get different lengths in stmt->stmt->fields[ofs].length
516 The just take 256 and saves us from realloc-ing.
517 */
518 stmt->result.buf[ofs].buflen =
519 (stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256;
520
521 } else {
522 /*
523 the user has called store_result(). if he does not there is no way to determine the
524 libmysql does not allow us to allocate 0 bytes for a buffer so we try 1
525 */
526 if (!(stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length))
527 ++stmt->result.buf[ofs].buflen;
528 }
529 stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
530 bind[ofs].buffer_type = MYSQL_TYPE_STRING;
531 bind[ofs].buffer = stmt->result.buf[ofs].val;
532 bind[ofs].is_null = &stmt->result.is_null[ofs];
533 bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
534 bind[ofs].length = &stmt->result.buf[ofs].output_len;
535 break;
536 }
537 default:
538 php_error_docref(NULL, E_WARNING, "Server returned unknown type %ld. Probably your client library is incompatible with the server version you use!", col_type);
539 break;
540 }
541 }
542
543 rc = mysql_stmt_bind_result(stmt->stmt, bind);
544 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
545
546 if (rc) {
547 /* 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 ((uint)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 #if defined(MYSQLI_USE_MYSQLND)
1272 const size_t *ret;
1273 #else
1274 const zend_ulong *ret;
1275 #endif
1276
1277 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1278 return;
1279 }
1280
1281 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1282
1283 if (!(ret = mysql_fetch_lengths(result))) {
1284 RETURN_FALSE;
1285 }
1286
1287 array_init(return_value);
1288 num_fields = mysql_num_fields(result);
1289
1290 for (i = 0; i < num_fields; i++) {
1291 add_index_long(return_value, i, ret[i]);
1292 }
1293 }
1294 /* }}} */
1295
1296 /* {{{ proto array mysqli_fetch_row (object result)
1297 Get a result row as an enumerated array */
1298 PHP_FUNCTION(mysqli_fetch_row)
1299 {
1300 php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM, 0);
1301 }
1302 /* }}} */
1303
1304 /* {{{ proto int mysqli_field_count(object link)
1305 Fetch the number of fields returned by the last query for the given link
1306 */
1307 PHP_FUNCTION(mysqli_field_count)
1308 {
1309 MY_MYSQL *mysql;
1310 zval *mysql_link;
1311
1312 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1313 return;
1314 }
1315 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1316
1317 RETURN_LONG(mysql_field_count(mysql->mysql));
1318 }
1319 /* }}} */
1320
1321 /* {{{ proto int mysqli_field_seek(object result, int fieldnr)
1322 Set result pointer to a specified field offset
1323 */
1324 PHP_FUNCTION(mysqli_field_seek)
1325 {
1326 MYSQL_RES *result;
1327 zval *mysql_result;
1328 zend_long fieldnr;
1329
1330 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) {
1331 return;
1332 }
1333 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1334
1335 if (fieldnr < 0 || (uint)fieldnr >= mysql_num_fields(result)) {
1336 php_error_docref(NULL, E_WARNING, "Invalid field offset");
1337 RETURN_FALSE;
1338 }
1339
1340 mysql_field_seek(result, fieldnr);
1341 RETURN_TRUE;
1342 }
1343 /* }}} */
1344
1345 /* {{{ proto int mysqli_field_tell(object result)
1346 Get current field offset of result pointer */
1347 PHP_FUNCTION(mysqli_field_tell)
1348 {
1349 MYSQL_RES *result;
1350 zval *mysql_result;
1351
1352 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1353 return;
1354 }
1355 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1356
1357 RETURN_LONG(mysql_field_tell(result));
1358 }
1359 /* }}} */
1360
1361 /* {{{ proto void mysqli_free_result(object result)
1362 Free query result memory for the given result handle */
1363 PHP_FUNCTION(mysqli_free_result)
1364 {
1365 MYSQL_RES *result;
1366 zval *mysql_result;
1367
1368 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1369 return;
1370 }
1371 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1372
1373 mysqli_free_result(result, FALSE);
1374 MYSQLI_CLEAR_RESOURCE(mysql_result);
1375 }
1376 /* }}} */
1377
1378 /* {{{ proto string mysqli_get_client_info(void)
1379 Get MySQL client info */
1380 PHP_FUNCTION(mysqli_get_client_info)
1381 {
1382 const char * info = mysql_get_client_info();
1383 if (info) {
1384 RETURN_STRING(info);
1385 }
1386 }
1387 /* }}} */
1388
1389 /* {{{ proto int mysqli_get_client_version(void)
1390 Get MySQL client info */
1391 PHP_FUNCTION(mysqli_get_client_version)
1392 {
1393 RETURN_LONG((zend_long)mysql_get_client_version());
1394 }
1395 /* }}} */
1396
1397 /* {{{ proto string mysqli_get_host_info (object link)
1398 Get MySQL host info */
1399 PHP_FUNCTION(mysqli_get_host_info)
1400 {
1401 MY_MYSQL *mysql;
1402 zval *mysql_link = NULL;
1403
1404 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1405 return;
1406 }
1407 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1408 #if !defined(MYSQLI_USE_MYSQLND)
1409 RETURN_STRING((mysql->mysql->host_info) ? mysql->mysql->host_info : "");
1410 #else
1411 RETURN_STRING((mysql->mysql->data->host_info) ? mysql->mysql->data->host_info : "");
1412 #endif
1413 }
1414 /* }}} */
1415
1416 /* {{{ proto int mysqli_get_proto_info(object link)
1417 Get MySQL protocol information */
1418 PHP_FUNCTION(mysqli_get_proto_info)
1419 {
1420 MY_MYSQL *mysql;
1421 zval *mysql_link = NULL;
1422
1423 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1424 return;
1425 }
1426 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1427 RETURN_LONG(mysql_get_proto_info(mysql->mysql));
1428 }
1429 /* }}} */
1430
1431 /* {{{ proto string mysqli_get_server_info(object link)
1432 Get MySQL server info */
1433 PHP_FUNCTION(mysqli_get_server_info)
1434 {
1435 MY_MYSQL *mysql;
1436 zval *mysql_link = NULL;
1437 const char *info;
1438
1439 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1440 return;
1441 }
1442 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1443
1444 info = mysql_get_server_info(mysql->mysql);
1445 if (info) {
1446 RETURN_STRING(info);
1447 }
1448 }
1449 /* }}} */
1450
1451 /* {{{ proto int mysqli_get_server_version(object link)
1452 Return the MySQL version for the server referenced by the given link */
1453 PHP_FUNCTION(mysqli_get_server_version)
1454 {
1455 MY_MYSQL *mysql;
1456 zval *mysql_link = NULL;
1457
1458 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1459 return;
1460 }
1461 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1462
1463 RETURN_LONG(mysql_get_server_version(mysql->mysql));
1464 }
1465 /* }}} */
1466
1467 /* {{{ proto string mysqli_info(object link)
1468 Get information about the most recent query */
1469 PHP_FUNCTION(mysqli_info)
1470 {
1471 MY_MYSQL *mysql;
1472 zval *mysql_link = NULL;
1473 const char *info;
1474
1475 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1476 return;
1477 }
1478 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1479
1480 info = mysql_info(mysql->mysql);
1481 if (info) {
1482 RETURN_STRING(info);
1483 }
1484 }
1485 /* }}} */
1486
1487 /* {{{ php_mysqli_init() */
1488 void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_method)
1489 {
1490 MYSQLI_RESOURCE *mysqli_resource;
1491 MY_MYSQL *mysql;
1492
1493 if (is_method && (Z_MYSQLI_P(getThis()))->ptr) {
1494 return;
1495 }
1496
1497 mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL));
1498
1499 #if !defined(MYSQLI_USE_MYSQLND)
1500 if (!(mysql->mysql = mysql_init(NULL)))
1501 #else
1502 /*
1503 We create always persistent, as if the user want to connecto
1504 to p:somehost, we can't convert the handle then
1505 */
1506 if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, TRUE)))
1507 #endif
1508 {
1509 efree(mysql);
1510 RETURN_FALSE;
1511 }
1512
1513 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1514 mysqli_resource->ptr = (void *)mysql;
1515 mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
1516
1517 if (!is_method) {
1518 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
1519 } else {
1520 (Z_MYSQLI_P(getThis()))->ptr = mysqli_resource;
1521 }
1522 }
1523 /* }}} */
1524
1525 /* {{{ proto resource mysqli_init(void)
1526 Initialize mysqli and return a resource for use with mysql_real_connect */
1527 PHP_FUNCTION(mysqli_init)
1528 {
1529 php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE);
1530 }
1531 /* }}} */
1532
1533 /* {{{ proto resource mysqli::init(void)
1534 Initialize mysqli and return a resource for use with mysql_real_connect */
1535 PHP_FUNCTION(mysqli_init_method)
1536 {
1537 php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE);
1538 }
1539 /* }}} */
1540
1541 /* {{{ proto mixed mysqli_insert_id(object link)
1542 Get the ID generated from the previous INSERT operation */
1543 PHP_FUNCTION(mysqli_insert_id)
1544 {
1545 MY_MYSQL *mysql;
1546 my_ulonglong rc;
1547 zval *mysql_link;
1548
1549 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1550 return;
1551 }
1552 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1553 rc = mysql_insert_id(mysql->mysql);
1554 MYSQLI_RETURN_LONG_INT(rc)
1555 }
1556 /* }}} */
1557
1558 /* {{{ proto bool mysqli_kill(object link, int processid)
1559 Kill a mysql process on the server */
1560 PHP_FUNCTION(mysqli_kill)
1561 {
1562 MY_MYSQL *mysql;
1563 zval *mysql_link;
1564 zend_long processid;
1565
1566 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) {
1567 return;
1568 }
1569 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1570
1571 if (processid <= 0) {
1572 php_error_docref(NULL, E_WARNING, "processid should have positive value");
1573 RETURN_FALSE;
1574 }
1575
1576 if (mysql_kill(mysql->mysql, processid)) {
1577 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1578 RETURN_FALSE;
1579 }
1580 RETURN_TRUE;
1581 }
1582 /* }}} */
1583
1584 /* {{{ proto bool mysqli_more_results(object link)
1585 check if there any more query results from a multi query */
1586 PHP_FUNCTION(mysqli_more_results)
1587 {
1588 MY_MYSQL *mysql;
1589 zval *mysql_link;
1590
1591 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1592 return;
1593 }
1594 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1595
1596 RETURN_BOOL(mysql_more_results(mysql->mysql));
1597 }
1598 /* }}} */
1599
1600 /* {{{ proto bool mysqli_next_result(object link)
1601 read next result from multi_query */
1602 PHP_FUNCTION(mysqli_next_result) {
1603 MY_MYSQL *mysql;
1604 zval *mysql_link;
1605
1606 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1607 return;
1608 }
1609 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1610
1611 if (!mysql_more_results(mysql->mysql)) {
1612 php_error_docref(NULL, E_STRICT, "There is no next result set. "
1613 "Please, call mysqli_more_results()/mysqli::more_results() to check "
1614 "whether to call this function/method");
1615 }
1616
1617 RETURN_BOOL(!mysql_next_result(mysql->mysql));
1618 }
1619 /* }}} */
1620
1621 #if defined(HAVE_STMT_NEXT_RESULT) && defined(MYSQLI_USE_MYSQLND)
1622 /* {{{ proto bool mysqli_stmt_next_result(object link)
1623 check if there any more query results from a multi query */
1624 PHP_FUNCTION(mysqli_stmt_more_results)
1625 {
1626 MY_STMT *stmt;
1627 zval *mysql_stmt;
1628
1629 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1630 return;
1631 }
1632 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1633
1634 RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1635 }
1636 /* }}} */
1637
1638 /* {{{ proto bool mysqli_stmt_next_result(object link)
1639 read next result from multi_query */
1640 PHP_FUNCTION(mysqli_stmt_next_result) {
1641 MY_STMT *stmt;
1642 zval *mysql_stmt;
1643
1644 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1645 return;
1646 }
1647 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1648
1649 if (!mysqlnd_stmt_more_results(stmt->stmt)) {
1650 php_error_docref(NULL, E_STRICT, "There is no next result set. "
1651 "Please, call mysqli_stmt_more_results()/mysqli_stmt::more_results() to check "
1652 "whether to call this function/method");
1653 }
1654
1655 RETURN_BOOL(!mysql_stmt_next_result(stmt->stmt));
1656 }
1657 /* }}} */
1658 #endif
1659
1660 /* {{{ proto int mysqli_num_fields(object result)
1661 Get number of fields in result */
1662 PHP_FUNCTION(mysqli_num_fields)
1663 {
1664 MYSQL_RES *result;
1665 zval *mysql_result;
1666
1667 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1668 return;
1669 }
1670 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1671
1672 RETURN_LONG(mysql_num_fields(result));
1673 }
1674 /* }}} */
1675
1676 /* {{{ proto mixed mysqli_num_rows(object result)
1677 Get number of rows in result */
1678 PHP_FUNCTION(mysqli_num_rows)
1679 {
1680 MYSQL_RES *result;
1681 zval *mysql_result;
1682
1683 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1684 return;
1685 }
1686 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1687
1688 if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) {
1689 php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
1690 RETURN_LONG(0);
1691 }
1692
1693 MYSQLI_RETURN_LONG_INT(mysql_num_rows(result));
1694 }
1695 /* }}} */
1696
1697 /* {{{ mysqli_options_get_option_zval_type */
1698 static int mysqli_options_get_option_zval_type(int option)
1699 {
1700 switch (option) {
1701 #ifdef MYSQLI_USE_MYSQLND
1702 case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
1703 case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
1704 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
1705 case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
1706 #endif
1707 #endif /* MYSQLI_USE_MYSQLND */
1708 case MYSQL_OPT_CONNECT_TIMEOUT:
1709 #ifdef MYSQL_REPORT_DATA_TRUNCATION
1710 case MYSQL_REPORT_DATA_TRUNCATION:
1711 #endif
1712 case MYSQL_OPT_LOCAL_INFILE:
1713 case MYSQL_OPT_NAMED_PIPE:
1714 #ifdef MYSQL_OPT_PROTOCOL
1715 case MYSQL_OPT_PROTOCOL:
1716 #endif /* MySQL 4.1.0 */
1717 #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 (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
1783 if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
1784 RETURN_FALSE;
1785 }
1786 }
1787 #endif
1788 expected_type = mysqli_options_get_option_zval_type(mysql_option);
1789 if (expected_type != Z_TYPE_P(mysql_value)) {
1790 switch (expected_type) {
1791 case IS_STRING:
1792 convert_to_string_ex(mysql_value);
1793 break;
1794 case IS_LONG:
1795 convert_to_long_ex(mysql_value);
1796 break;
1797 default:
1798 break;
1799 }
1800 }
1801 switch (expected_type) {
1802 case IS_STRING:
1803 ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value));
1804 break;
1805 case IS_LONG:
1806 l_value = Z_LVAL_P(mysql_value);
1807 ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
1808 break;
1809 default:
1810 ret = 1;
1811 break;
1812 }
1813
1814 RETURN_BOOL(!ret);
1815 }
1816 /* }}} */
1817
1818 /* {{{ proto bool mysqli_ping(object link)
1819 Ping a server connection or reconnect if there is no connection */
1820 PHP_FUNCTION(mysqli_ping)
1821 {
1822 MY_MYSQL *mysql;
1823 zval *mysql_link;
1824 zend_long rc;
1825
1826 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1827 return;
1828 }
1829 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1830 rc = mysql_ping(mysql->mysql);
1831 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1832
1833 RETURN_BOOL(!rc);
1834 }
1835 /* }}} */
1836
1837 /* {{{ proto mixed mysqli_prepare(object link, string query)
1838 Prepare a SQL statement for execution */
1839 PHP_FUNCTION(mysqli_prepare)
1840 {
1841 MY_MYSQL *mysql;
1842 MY_STMT *stmt;
1843 char *query = NULL;
1844 size_t query_len;
1845 zval *mysql_link;
1846 MYSQLI_RESOURCE *mysqli_resource;
1847
1848 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1849 return;
1850 }
1851 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1852
1853 #if !defined(MYSQLI_USE_MYSQLND)
1854 if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
1855 php_error_docref(NULL, E_WARNING, "All data must be fetched before a new statement prepare takes place");
1856 RETURN_FALSE;
1857 }
1858 #endif
1859
1860 stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1861
1862 if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1863 if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1864 /* mysql_stmt_close() clears errors, so we have to store them temporarily */
1865 #if !defined(MYSQLI_USE_MYSQLND)
1866 char last_error[MYSQL_ERRMSG_SIZE];
1867 char sqlstate[SQLSTATE_LENGTH+1];
1868 unsigned int last_errno;
1869
1870 last_errno = stmt->stmt->last_errno;
1871 memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
1872 memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
1873 #else
1874 MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
1875 #endif
1876 mysqli_stmt_close(stmt->stmt, FALSE);
1877 stmt->stmt = NULL;
1878
1879 /* restore error messages */
1880 #if !defined(MYSQLI_USE_MYSQLND)
1881 mysql->mysql->net.last_errno = last_errno;
1882 memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
1883 memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
1884 #else
1885 *mysql->mysql->data->error_info = error_info;
1886 #endif
1887 }
1888 }
1889
1890 /* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1891 /* Get performance boost if reporting is switched off */
1892 if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1893 stmt->query = (char *)emalloc(query_len + 1);
1894 memcpy(stmt->query, query, query_len);
1895 stmt->query[query_len] = '\0';
1896 }
1897
1898 /* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1899 if (!stmt->stmt) {
1900 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1901 efree(stmt);
1902 RETURN_FALSE;
1903 }
1904 #ifndef MYSQLI_USE_MYSQLND
1905 ZVAL_COPY(&stmt->link_handle, mysql_link);
1906 #endif
1907
1908 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1909 mysqli_resource->ptr = (void *)stmt;
1910
1911 /* change status */
1912 mysqli_resource->status = MYSQLI_STATUS_VALID;
1913 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1914 }
1915 /* }}} */
1916
1917 /* {{{ proto bool mysqli_real_connect(object link [,string hostname [,string username [,string passwd [,string dbname [,int port [,string socket [,int flags]]]]]]])
1918 Open a connection to a mysql server */
1919 PHP_FUNCTION(mysqli_real_connect)
1920 {
1921 mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE, FALSE);
1922 }
1923 /* }}} */
1924
1925 /* {{{ proto bool mysqli_real_query(object link, string query)
1926 Binary-safe version of mysql_query() */
1927 PHP_FUNCTION(mysqli_real_query)
1928 {
1929 MY_MYSQL *mysql;
1930 zval *mysql_link;
1931 char *query = NULL;
1932 size_t query_len;
1933
1934 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1935 return;
1936 }
1937 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1938
1939 MYSQLI_DISABLE_MQ; /* disable multi statements/queries */
1940
1941 if (mysql_real_query(mysql->mysql, query, query_len)) {
1942 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1943 RETURN_FALSE;
1944 }
1945
1946 if (!mysql_field_count(mysql->mysql)) {
1947 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1948 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
1949 }
1950 }
1951
1952 RETURN_TRUE;
1953 }
1954 /* }}} */
1955
1956 /* {{{ proto string mysqli_real_escape_string(object link, string escapestr)
1957 Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection */
1958 PHP_FUNCTION(mysqli_real_escape_string) {
1959 MY_MYSQL *mysql;
1960 zval *mysql_link = NULL;
1961 char *escapestr;
1962 size_t escapestr_len;
1963 zend_string *newstr;
1964
1965 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &escapestr, &escapestr_len) == FAILURE) {
1966 return;
1967 }
1968 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1969
1970 newstr = zend_string_alloc(2 * escapestr_len, 0);
1971 ZSTR_LEN(newstr) = mysql_real_escape_string(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len);
1972 newstr = zend_string_truncate(newstr, ZSTR_LEN(newstr), 0);
1973
1974 RETURN_NEW_STR(newstr);
1975 }
1976 /* }}} */
1977
1978 /* {{{ proto bool mysqli_rollback(object link)
1979 Undo actions from current transaction */
1980 PHP_FUNCTION(mysqli_rollback)
1981 {
1982 MY_MYSQL *mysql;
1983 zval *mysql_link;
1984 zend_long flags = TRANS_COR_NO_OPT;
1985 char * name = NULL;
1986 size_t name_len = 0;
1987
1988 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1989 return;
1990 }
1991 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1992
1993 #if !defined(MYSQLI_USE_MYSQLND)
1994 if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) {
1995 #else
1996 if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
1997 #endif
1998 RETURN_FALSE;
1999 }
2000 RETURN_TRUE;
2001 }
2002 /* }}} */
2003
2004 /* {{{ proto bool mysqli_stmt_send_long_data(object stmt, int param_nr, string data)
2005 */
2006 PHP_FUNCTION(mysqli_stmt_send_long_data)
2007 {
2008 MY_STMT *stmt;
2009 zval *mysql_stmt;
2010 char *data;
2011 zend_long param_nr;
2012 size_t data_len;
2013
2014 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, ¶m_nr, &data, &data_len) == FAILURE) {
2015 return;
2016 }
2017 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2018
2019 if (param_nr < 0) {
2020 php_error_docref(NULL, E_WARNING, "Invalid parameter number");
2021 RETURN_FALSE;
2022 }
2023 if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) {
2024 RETURN_FALSE;
2025 }
2026 RETURN_TRUE;
2027 }
2028 /* }}} */
2029
2030 /* {{{ proto mixed mysqli_stmt_affected_rows(object stmt)
2031 Return the number of rows affected in the last query for the given link */
2032 PHP_FUNCTION(mysqli_stmt_affected_rows)
2033 {
2034 MY_STMT *stmt;
2035 zval *mysql_stmt;
2036 my_ulonglong rc;
2037
2038 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2039 return;
2040 }
2041 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2042
2043 rc = mysql_stmt_affected_rows(stmt->stmt);
2044 if (rc == (my_ulonglong) -1) {
2045 RETURN_LONG(-1);
2046 }
2047 MYSQLI_RETURN_LONG_INT(rc)
2048 }
2049 /* }}} */
2050
2051 /* {{{ proto bool mysqli_stmt_close(object stmt)
2052 Close statement */
2053 PHP_FUNCTION(mysqli_stmt_close)
2054 {
2055 MY_STMT *stmt;
2056 zval *mysql_stmt;
2057
2058 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2059 return;
2060 }
2061 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2062
2063 mysqli_stmt_close(stmt->stmt, FALSE);
2064 stmt->stmt = NULL;
2065 php_clear_stmt_bind(stmt);
2066 MYSQLI_CLEAR_RESOURCE(mysql_stmt);
2067 RETURN_TRUE;
2068 }
2069 /* }}} */
2070
2071 /* {{{ proto void mysqli_stmt_data_seek(object stmt, int offset)
2072 Move internal result pointer */
2073 PHP_FUNCTION(mysqli_stmt_data_seek)
2074 {
2075 MY_STMT *stmt;
2076 zval *mysql_stmt;
2077 zend_long offset;
2078
2079 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
2080 return;
2081 }
2082 if (offset < 0) {
2083 php_error_docref(NULL, E_WARNING, "Offset must be positive");
2084 RETURN_FALSE;
2085 }
2086
2087 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2088
2089 mysql_stmt_data_seek(stmt->stmt, offset);
2090 }
2091 /* }}} */
2092
2093 /* {{{ proto int mysqli_stmt_field_count(object stmt) {
2094 Return the number of result columns for the given statement */
2095 PHP_FUNCTION(mysqli_stmt_field_count)
2096 {
2097 MY_STMT *stmt;
2098 zval *mysql_stmt;
2099
2100 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2101 return;
2102 }
2103 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2104
2105 RETURN_LONG(mysql_stmt_field_count(stmt->stmt));
2106 }
2107 /* }}} */
2108
2109 /* {{{ proto void mysqli_stmt_free_result(object stmt)
2110 Free stored result memory for the given statement handle */
2111 PHP_FUNCTION(mysqli_stmt_free_result)
2112 {
2113 MY_STMT *stmt;
2114 zval *mysql_stmt;
2115
2116 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2117 return;
2118 }
2119
2120 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2121
2122 mysql_stmt_free_result(stmt->stmt);
2123 }
2124 /* }}} */
2125
2126 /* {{{ proto mixed mysqli_stmt_insert_id(object stmt)
2127 Get the ID generated from the previous INSERT operation */
2128 PHP_FUNCTION(mysqli_stmt_insert_id)
2129 {
2130 MY_STMT *stmt;
2131 my_ulonglong rc;
2132 zval *mysql_stmt;
2133
2134 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2135 return;
2136 }
2137 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2138 rc = mysql_stmt_insert_id(stmt->stmt);
2139 MYSQLI_RETURN_LONG_INT(rc)
2140 }
2141 /* }}} */
2142
2143 /* {{{ proto int mysqli_stmt_param_count(object stmt)
2144 Return the number of parameter for the given statement */
2145 PHP_FUNCTION(mysqli_stmt_param_count)
2146 {
2147 MY_STMT *stmt;
2148 zval *mysql_stmt;
2149
2150 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2151 return;
2152 }
2153 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2154
2155 RETURN_LONG(mysql_stmt_param_count(stmt->stmt));
2156 }
2157 /* }}} */
2158
2159 /* {{{ proto bool mysqli_stmt_reset(object stmt)
2160 reset a prepared statement */
2161 PHP_FUNCTION(mysqli_stmt_reset)
2162 {
2163 MY_STMT *stmt;
2164 zval *mysql_stmt;
2165
2166 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2167 return;
2168 }
2169
2170 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2171
2172 if (mysql_stmt_reset(stmt->stmt)) {
2173 RETURN_FALSE;
2174 }
2175 RETURN_TRUE;
2176 }
2177 /* }}} */
2178
2179 /* {{{ proto mixed mysqli_stmt_num_rows(object stmt)
2180 Return the number of rows in statements result set */
2181 PHP_FUNCTION(mysqli_stmt_num_rows)
2182 {
2183 MY_STMT *stmt;
2184 zval *mysql_stmt;
2185 my_ulonglong rc;
2186
2187 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2188 return;
2189 }
2190
2191 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2192
2193 rc = mysql_stmt_num_rows(stmt->stmt);
2194 MYSQLI_RETURN_LONG_INT(rc)
2195 }
2196 /* }}} */
2197
2198 /* {{{ proto bool mysqli_select_db(object link, string dbname)
2199 Select a MySQL database */
2200 PHP_FUNCTION(mysqli_select_db)
2201 {
2202 MY_MYSQL *mysql;
2203 zval *mysql_link;
2204 char *dbname;
2205 size_t dbname_len;
2206
2207 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) {
2208 return;
2209 }
2210 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2211
2212 if (mysql_select_db(mysql->mysql, dbname)) {
2213 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2214 RETURN_FALSE;
2215 }
2216 RETURN_TRUE;
2217 }
2218 /* }}} */
2219
2220 /* {{{ proto string mysqli_sqlstate(object link)
2221 Returns the SQLSTATE error from previous MySQL operation */
2222 PHP_FUNCTION(mysqli_sqlstate)
2223 {
2224 MY_MYSQL *mysql;
2225 zval *mysql_link;
2226 const char *state;
2227
2228 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2229 return;
2230 }
2231 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2232 state = mysql_sqlstate(mysql->mysql);
2233 if (state) {
2234 RETURN_STRING(state);
2235 }
2236 }
2237 /* }}} */
2238
2239 /* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher])
2240 */
2241 PHP_FUNCTION(mysqli_ssl_set)
2242 {
2243 MY_MYSQL *mysql;
2244 zval *mysql_link;
2245 char *ssl_parm[5];
2246 size_t ssl_parm_len[5], i;
2247
2248 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) {
2249 return;
2250 }
2251 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2252
2253 for (i = 0; i < 5; i++) {
2254 if (!ssl_parm_len[i]) {
2255 ssl_parm[i] = NULL;
2256 }
2257 }
2258
2259 mysql_ssl_set(mysql->mysql, ssl_parm[0], ssl_parm[1], ssl_parm[2], ssl_parm[3], ssl_parm[4]);
2260
2261 RETURN_TRUE;
2262 }
2263 /* }}} */
2264
2265 /* {{{ proto mixed mysqli_stat(object link)
2266 Get current system status */
2267 PHP_FUNCTION(mysqli_stat)
2268 {
2269 MY_MYSQL *mysql;
2270 zval *mysql_link;
2271 #if defined(MYSQLI_USE_MYSQLND)
2272 zend_string *stat;
2273 #else
2274 char *stat;
2275 #endif
2276
2277 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2278 return;
2279 }
2280 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2281
2282 #if !defined(MYSQLI_USE_MYSQLND)
2283 if ((stat = (char *)mysql_stat(mysql->mysql)))
2284 {
2285 RETURN_STRING(stat);
2286 #else
2287 if (mysqlnd_stat(mysql->mysql, &stat) == PASS)
2288 {
2289 RETURN_STR(stat);
2290 #endif
2291 } else {
2292 RETURN_FALSE;
2293 }
2294 }
2295
2296 /* }}} */
2297
2298 /* {{{ proto bool mysqli_refresh(object link, long options)
2299 Flush tables or caches, or reset replication server information */
2300 PHP_FUNCTION(mysqli_refresh)
2301 {
2302 MY_MYSQL *mysql;
2303 zval *mysql_link = NULL;
2304 zend_long options;
2305
2306 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &options) == FAILURE) {
2307 return;
2308 }
2309 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2310 #ifdef MYSQLI_USE_MYSQLND
2311 RETURN_BOOL(!mysql_refresh(mysql->mysql, (uint8_t) options));
2312 #else
2313 RETURN_BOOL(!mysql_refresh(mysql->mysql, options));
2314 #endif
2315 }
2316 /* }}} */
2317
2318 /* {{{ proto int mysqli_stmt_attr_set(object stmt, long attr, long mode)
2319 */
2320 PHP_FUNCTION(mysqli_stmt_attr_set)
2321 {
2322 MY_STMT *stmt;
2323 zval *mysql_stmt;
2324 zend_long mode_in;
2325 #if MYSQL_VERSION_ID >= 50107
2326 my_bool mode_b;
2327 #endif
2328 zend_ulong mode;
2329 zend_long attr;
2330 void *mode_p;
2331
2332 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) {
2333 return;
2334 }
2335 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2336
2337 if (mode_in < 0) {
2338 php_error_docref(NULL, E_WARNING, "mode should be non-negative, " ZEND_LONG_FMT " passed", mode_in);
2339 RETURN_FALSE;
2340 }
2341
2342 switch (attr) {
2343 #if MYSQL_VERSION_ID >= 50107
2344 case STMT_ATTR_UPDATE_MAX_LENGTH:
2345 mode_b = (my_bool) mode_in;
2346 mode_p = &mode_b;
2347 break;
2348 #endif
2349 default:
2350 mode = mode_in;
2351 mode_p = &mode;
2352 break;
2353 }
2354 #if !defined(MYSQLI_USE_MYSQLND)
2355 if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2356 #else
2357 if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2358 #endif
2359 RETURN_FALSE;
2360 }
2361 RETURN_TRUE;
2362 }
2363 /* }}} */
2364
2365 /* {{{ proto int mysqli_stmt_attr_get(object stmt, long attr)
2366 */
2367 PHP_FUNCTION(mysqli_stmt_attr_get)
2368 {
2369 MY_STMT *stmt;
2370 zval *mysql_stmt;
2371 zend_ulong value = 0;
2372 zend_long attr;
2373 int rc;
2374
2375 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) {
2376 return;
2377 }
2378 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2379
2380 if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) {
2381 RETURN_FALSE;
2382 }
2383
2384 #if MYSQL_VERSION_ID >= 50107
2385 if (attr == STMT_ATTR_UPDATE_MAX_LENGTH)
2386 value = *((my_bool *)&value);
2387 #endif
2388 RETURN_LONG((zend_ulong)value);
2389 }
2390 /* }}} */
2391
2392 /* {{{ proto int mysqli_stmt_errno(object stmt)
2393 */
2394 PHP_FUNCTION(mysqli_stmt_errno)
2395 {
2396 MY_STMT *stmt;
2397 zval *mysql_stmt;
2398
2399 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2400 return;
2401 }
2402 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2403
2404 RETURN_LONG(mysql_stmt_errno(stmt->stmt));
2405 }
2406 /* }}} */
2407
2408 /* {{{ proto string mysqli_stmt_error(object stmt)
2409 */
2410 PHP_FUNCTION(mysqli_stmt_error)
2411 {
2412 MY_STMT *stmt;
2413 zval *mysql_stmt;
2414 const char * err;
2415
2416 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2417 return;
2418 }
2419 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2420
2421 err = mysql_stmt_error(stmt->stmt);
2422 if (err) {
2423 RETURN_STRING(err);
2424 }
2425 }
2426 /* }}} */
2427
2428 /* {{{ proto mixed mysqli_stmt_init(object link)
2429 Initialize statement object
2430 */
2431 PHP_FUNCTION(mysqli_stmt_init)
2432 {
2433 MY_MYSQL *mysql;
2434 MY_STMT *stmt;
2435 zval *mysql_link;
2436 MYSQLI_RESOURCE *mysqli_resource;
2437
2438 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",&mysql_link, mysqli_link_class_entry) == FAILURE) {
2439 return;
2440 }
2441 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2442
2443 stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
2444
2445 if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
2446 efree(stmt);
2447 RETURN_FALSE;
2448 }
2449 #ifndef MYSQLI_USE_MYSQLND
2450 ZVAL_COPY(&stmt->link_handle, mysql_link);
2451 #endif
2452
2453 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2454 mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
2455 mysqli_resource->ptr = (void *)stmt;
2456 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
2457 }
2458 /* }}} */
2459
2460 /* {{{ proto bool mysqli_stmt_prepare(object stmt, string query)
2461 prepare server side statement with query
2462 */
2463 PHP_FUNCTION(mysqli_stmt_prepare)
2464 {
2465 MY_STMT *stmt;
2466 zval *mysql_stmt;
2467 char *query;
2468 size_t query_len;
2469
2470 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry, &query, &query_len) == FAILURE) {
2471 return;
2472 }
2473 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2474
2475 if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
2476 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2477 RETURN_FALSE;
2478 }
2479 /* change status */
2480 MYSQLI_SET_STATUS(mysql_stmt, MYSQLI_STATUS_VALID);
2481 RETURN_TRUE;
2482 }
2483 /* }}} */
2484
2485 /* {{{ proto mixed mysqli_stmt_result_metadata(object stmt)
2486 return result set from statement */
2487 PHP_FUNCTION(mysqli_stmt_result_metadata)
2488 {
2489 MY_STMT *stmt;
2490 MYSQL_RES *result;
2491 zval *mysql_stmt;
2492 MYSQLI_RESOURCE *mysqli_resource;
2493
2494 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2495 return;
2496 }
2497 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2498
2499 if (!(result = mysql_stmt_result_metadata(stmt->stmt))){
2500 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2501 RETURN_FALSE;
2502 }
2503
2504 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2505 mysqli_resource->ptr = (void *)result;
2506 mysqli_resource->status = MYSQLI_STATUS_VALID;
2507 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2508 }
2509 /* }}} */
2510
2511 /* {{{ proto bool mysqli_stmt_store_result(object stmt)
2512 */
2513 PHP_FUNCTION(mysqli_stmt_store_result)
2514 {
2515 MY_STMT *stmt;
2516 zval *mysql_stmt;
2517
2518 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2519 return;
2520 }
2521 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2522
2523 #if !defined(MYSQLI_USE_MYSQLND)
2524 {
2525 /*
2526 If the user wants to store the data and we have BLOBs/TEXTs we try to allocate
2527 not the maximal length of the type (which is 16MB even for LONGBLOB) but
2528 the maximal length of the field in the result set. If he/she has quite big
2529 BLOB/TEXT columns after calling store_result() the memory usage of PHP will
2530 double - but this is a known problem of the simple MySQL API ;)
2531 */
2532 int i = 0;
2533
2534 for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) {
2535 if (stmt->stmt->fields && (stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB ||
2536 stmt->stmt->fields[i].type == MYSQL_TYPE_MEDIUM_BLOB ||
2537 stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB ||
2538 stmt->stmt->fields[i].type == MYSQL_TYPE_GEOMETRY))
2539 {
2540 #if MYSQL_VERSION_ID >= 50107
2541 my_bool tmp=1;
2542 #else
2543 uint tmp=1;
2544 #endif
2545 mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
2546 break;
2547 }
2548 }
2549 }
2550 #endif
2551
2552 if (mysql_stmt_store_result(stmt->stmt)){
2553 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2554 RETURN_FALSE;
2555 }
2556 RETURN_TRUE;
2557 }
2558 /* }}} */
2559
2560 /* {{{ proto string mysqli_stmt_sqlstate(object stmt)
2561 */
2562 PHP_FUNCTION(mysqli_stmt_sqlstate)
2563 {
2564 MY_STMT *stmt;
2565 zval *mysql_stmt;
2566 const char * state;
2567
2568 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2569 return;
2570 }
2571 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2572
2573 state = mysql_stmt_sqlstate(stmt->stmt);
2574 if (state) {
2575 RETURN_STRING(state);
2576 }
2577 }
2578 /* }}} */
2579
2580 /* {{{ proto object mysqli_store_result(object link [, int flags])
2581 Buffer result set on client */
2582 PHP_FUNCTION(mysqli_store_result)
2583 {
2584 MY_MYSQL *mysql;
2585 MYSQL_RES *result;
2586 zval *mysql_link;
2587 MYSQLI_RESOURCE *mysqli_resource;
2588 zend_long flags = 0;
2589
2590
2591 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_link, mysqli_link_class_entry, &flags) == FAILURE) {
2592 return;
2593 }
2594 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2595 #if MYSQLI_USE_MYSQLND
2596 result = flags & MYSQLI_STORE_RESULT_COPY_DATA? mysqlnd_store_result_ofs(mysql->mysql) : mysqlnd_store_result(mysql->mysql);
2597 #else
2598 result = mysql_store_result(mysql->mysql);
2599 #endif
2600 if (!result) {
2601 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2602 RETURN_FALSE;
2603 }
2604 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2605 php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2606 }
2607
2608 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2609 mysqli_resource->ptr = (void *)result;
2610 mysqli_resource->status = MYSQLI_STATUS_VALID;
2611 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2612 }
2613 /* }}} */
2614
2615 /* {{{ proto int mysqli_thread_id(object link)
2616 Return the current thread ID */
2617 PHP_FUNCTION(mysqli_thread_id)
2618 {
2619 MY_MYSQL *mysql;
2620 zval *mysql_link;
2621
2622 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2623 return;
2624 }
2625 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2626
2627 RETURN_LONG((zend_long) mysql_thread_id(mysql->mysql));
2628 }
2629 /* }}} */
2630
2631 /* {{{ proto bool mysqli_thread_safe(void)
2632 Return whether thread safety is given or not */
2633 PHP_FUNCTION(mysqli_thread_safe)
2634 {
2635 RETURN_BOOL(mysql_thread_safe());
2636 }
2637 /* }}} */
2638
2639 /* {{{ proto mixed mysqli_use_result(object link)
2640 Directly retrieve query results - do not buffer results on client side */
2641 PHP_FUNCTION(mysqli_use_result)
2642 {
2643 MY_MYSQL *mysql;
2644 MYSQL_RES *result;
2645 zval *mysql_link;
2646 MYSQLI_RESOURCE *mysqli_resource;
2647
2648 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2649 return;
2650 }
2651 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2652
2653 if (!(result = mysql_use_result(mysql->mysql))) {
2654 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2655 RETURN_FALSE;
2656 }
2657
2658 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2659 php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2660 }
2661 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2662 mysqli_resource->ptr = (void *)result;
2663 mysqli_resource->status = MYSQLI_STATUS_VALID;
2664 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2665 }
2666 /* }}} */
2667
2668 /* {{{ proto int mysqli_warning_count (object link)
2669 Return number of warnings from the last query for the given link */
2670 PHP_FUNCTION(mysqli_warning_count)
2671 {
2672 MY_MYSQL *mysql;
2673 zval *mysql_link;
2674
2675 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2676 return;
2677 }
2678 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2679
2680 RETURN_LONG(mysql_warning_count(mysql->mysql));
2681 }
2682 /* }}} */
2683
2684 /*
2685 * Local variables:
2686 * tab-width: 4
2687 * c-basic-offset: 4
2688 * End:
2689 * vim600: noet sw=4 ts=4 fdm=marker
2690 * vim<600: noet sw=4 ts=4
2691 */
2692