This source file includes following definitions.
- php_mysqli_set_error
- mysqli_common_connect
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- mysqlnd_zval_array_to_mysqlnd_array
- mysqlnd_zval_array_from_mysqlnd_array
- mysqlnd_dont_poll_zval_array_from_mysqlnd_array
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- mysqli_begin_transaction_libmysql
- PHP_FUNCTION
- mysqli_savepoint_libmysql
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 "ext/standard/info.h"
32 #include "zend_smart_str.h"
33 #include "php_mysqli_structs.h"
34 #include "mysqli_priv.h"
35
36 #define SAFE_STR(a) ((a)?a:"")
37
38 #ifndef zend_parse_parameters_none
39 #define zend_parse_parameters_none() \
40 zend_parse_parameters(ZEND_NUM_ARGS(), "")
41 #endif
42
43
44
45 static void php_mysqli_set_error(zend_long mysql_errno, char *mysql_err)
46 {
47 MyG(error_no) = mysql_errno;
48 if (MyG(error_msg)) {
49 efree(MyG(error_msg));
50 }
51 if(mysql_err && *mysql_err) {
52 MyG(error_msg) = estrdup(mysql_err);
53 } else {
54 MyG(error_msg) = NULL;
55 }
56 }
57
58
59 void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_connect, zend_bool in_ctor)
60 {
61 MY_MYSQL *mysql = NULL;
62 MYSQLI_RESOURCE *mysqli_resource = NULL;
63 zval *object = getThis();
64 char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL;
65 size_t hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0;
66 zend_bool persistent = FALSE;
67 zend_long port = 0, flags = 0;
68 zend_string *hash_key = NULL;
69 zend_bool new_connection = FALSE;
70 zend_resource *le;
71 mysqli_plist_entry *plist = NULL;
72 zend_bool self_alloced = 0;
73
74
75 #if !defined(MYSQL_USE_MYSQLND)
76 if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) {
77 php_error_docref(NULL, E_WARNING,
78 "Headers and client library minor version mismatch. Headers:%d Library:%ld",
79 MYSQL_VERSION_ID, mysql_get_client_version());
80 }
81 #endif
82
83 if (getThis() && !ZEND_NUM_ARGS() && in_ctor) {
84 php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, in_ctor);
85 return;
86 }
87 hostname = username = dbname = passwd = socket = NULL;
88
89 if (!is_real_connect) {
90 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ssssls", &hostname, &hostname_len, &username, &username_len,
91 &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len) == FAILURE) {
92 return;
93 }
94
95 if (object && instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry)) {
96 mysqli_resource = (Z_MYSQLI_P(object))->ptr;
97 if (mysqli_resource && mysqli_resource->ptr) {
98 mysql = (MY_MYSQL*) mysqli_resource->ptr;
99 }
100 }
101 if (!mysql) {
102 mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
103 self_alloced = 1;
104 }
105 flags |= CLIENT_MULTI_RESULTS;
106 } else {
107
108 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|sssslsl", &object, mysqli_link_class_entry,
109 &hostname, &hostname_len, &username, &username_len, &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len,
110 &flags) == FAILURE) {
111 return;
112 }
113
114 mysqli_resource = (Z_MYSQLI_P(object))->ptr;
115 MYSQLI_FETCH_RESOURCE_CONN(mysql, object, MYSQLI_STATUS_INITIALIZED);
116
117
118 flags |= CLIENT_MULTI_RESULTS;
119
120 flags &= ~CLIENT_MULTI_STATEMENTS;
121 #if !defined(MYSQLI_USE_MYSQLND)
122 if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
123 flags &= ~CLIENT_LOCAL_FILES;
124 }
125 #endif
126 }
127
128 if (!socket_len || !socket) {
129 socket = MyG(default_socket);
130 }
131 if (!port){
132 port = MyG(default_port);
133 }
134 if (!passwd) {
135 passwd = MyG(default_pw);
136 passwd_len = strlen(SAFE_STR(passwd));
137 }
138 if (!username){
139 username = MyG(default_user);
140 }
141 if (!hostname || !hostname_len) {
142 hostname = MyG(default_host);
143 }
144
145 if (mysql->mysql && mysqli_resource &&
146 (mysqli_resource->status > MYSQLI_STATUS_INITIALIZED))
147 {
148
149 php_mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT, mysqli_resource->status);
150 }
151
152 if (strlen(SAFE_STR(hostname)) > 2 && !strncasecmp(hostname, "p:", 2)) {
153 hostname += 2;
154 if (!MyG(allow_persistent)) {
155 php_error_docref(NULL, E_WARNING, "Persistent connections are disabled. Downgrading to normal");
156 } else {
157 mysql->persistent = persistent = TRUE;
158
159 hash_key = strpprintf(0, "mysqli_%s_%s%ld%s%s%s", SAFE_STR(hostname), SAFE_STR(socket),
160 port, SAFE_STR(username), SAFE_STR(dbname),
161 SAFE_STR(passwd));
162
163 mysql->hash_key = hash_key;
164
165
166 if ((le = zend_hash_find_ptr(&EG(persistent_list), hash_key)) != NULL) {
167 if (le->type == php_le_pmysqli()) {
168 plist = (mysqli_plist_entry *) le->ptr;
169
170 do {
171 if (zend_ptr_stack_num_elements(&plist->free_links)) {
172 mysql->mysql = zend_ptr_stack_pop(&plist->free_links);
173
174 MyG(num_inactive_persistent)--;
175
176
177 #ifndef MYSQLI_NO_CHANGE_USER_ON_PCONNECT
178 if (!mysqli_change_user_silent(mysql->mysql, username, passwd, dbname, passwd_len)) {
179 #else
180 if (!mysql_ping(mysql->mysql)) {
181 #endif
182 #ifdef MYSQLI_USE_MYSQLND
183 mysqlnd_restart_psession(mysql->mysql);
184 #endif
185 MyG(num_active_persistent)++;
186 goto end;
187 } else {
188 mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT);
189 mysql->mysql = NULL;
190 }
191 }
192 } while (0);
193 }
194 } else {
195 zend_resource le;
196 le.type = php_le_pmysqli();
197 le.ptr = plist = calloc(1, sizeof(mysqli_plist_entry));
198
199 zend_ptr_stack_init_ex(&plist->free_links, 1);
200 zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(hash_key), ZSTR_LEN(hash_key), &le, sizeof(le));
201 }
202 }
203 }
204 if (MyG(max_links) != -1 && MyG(num_links) >= MyG(max_links)) {
205 php_error_docref(NULL, E_WARNING, "Too many open links (%pd)", MyG(num_links));
206 goto err;
207 }
208
209 if (persistent && MyG(max_persistent) != -1 &&
210 (MyG(num_active_persistent) + MyG(num_inactive_persistent))>= MyG(max_persistent))
211 {
212 php_error_docref(NULL, E_WARNING, "Too many open persistent links (%pd)",
213 MyG(num_active_persistent) + MyG(num_inactive_persistent));
214 goto err;
215 }
216 if (!mysql->mysql) {
217 #if !defined(MYSQLI_USE_MYSQLND)
218 if (!(mysql->mysql = mysql_init(NULL))) {
219 #else
220 if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, persistent))) {
221 #endif
222 goto err;
223 }
224 new_connection = TRUE;
225 }
226
227 #ifdef HAVE_EMBEDDED_MYSQLI
228 if (hostname_len) {
229 unsigned int external=1;
230 mysql_options(mysql->mysql, MYSQL_OPT_USE_REMOTE_CONNECTION, (char *)&external);
231 } else {
232 mysql_options(mysql->mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, 0);
233 }
234 #endif
235
236 #if !defined(MYSQLI_USE_MYSQLND)
237
238 flags |= CLIENT_MULTI_RESULTS;
239
240 if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, flags) == NULL)
241 #else
242 if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
243 port, socket, flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA) == NULL)
244 #endif
245 {
246
247 php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql));
248 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql),
249 "%s", mysql_error(mysql->mysql));
250 if (!is_real_connect) {
251
252 mysqli_close(mysql->mysql, MYSQLI_CLOSE_DISCONNECTED);
253 mysql->mysql = NULL;
254 }
255 goto err;
256 }
257
258
259 php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql));
260
261 #if !defined(MYSQLI_USE_MYSQLND)
262 mysql->mysql->reconnect = MyG(reconnect);
263 #endif
264
265 mysql_options(mysql->mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&MyG(allow_local_infile));
266
267 end:
268 if (!mysqli_resource) {
269 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
270 mysqli_resource->ptr = (void *)mysql;
271 }
272 mysqli_resource->status = MYSQLI_STATUS_VALID;
273
274
275 if (persistent && (new_connection || is_real_connect)) {
276 MyG(num_active_persistent)++;
277 }
278
279 MyG(num_links)++;
280
281 mysql->multi_query = 0;
282
283 if (!object || !instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry)) {
284 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
285 } else {
286 (Z_MYSQLI_P(object))->ptr = mysqli_resource;
287 }
288 if (!is_real_connect) {
289 return;
290 } else {
291 RETURN_TRUE;
292 }
293
294 err:
295 if (mysql->hash_key) {
296 zend_string_release(mysql->hash_key);
297 mysql->hash_key = NULL;
298 mysql->persistent = FALSE;
299 }
300 if (!is_real_connect && self_alloced) {
301 efree(mysql);
302 }
303 RETVAL_FALSE;
304 }
305
306
307
308 PHP_FUNCTION(mysqli_connect)
309 {
310 mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE, FALSE);
311 }
312
313
314
315
316 PHP_FUNCTION(mysqli_link_construct)
317 {
318 mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE, TRUE);
319 }
320
321
322
323
324 PHP_FUNCTION(mysqli_connect_errno)
325 {
326 RETURN_LONG(MyG(error_no));
327 }
328
329
330
331
332 PHP_FUNCTION(mysqli_connect_error)
333 {
334 if (MyG(error_msg)) {
335 RETURN_STRING(MyG(error_msg));
336 } else {
337 RETURN_NULL();
338 }
339 }
340
341
342
343
344 PHP_FUNCTION(mysqli_fetch_array)
345 {
346 php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
347 }
348
349
350
351
352 PHP_FUNCTION(mysqli_fetch_assoc)
353 {
354 php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 0);
355 }
356
357
358
359
360 #if defined(MYSQLI_USE_MYSQLND)
361 PHP_FUNCTION(mysqli_fetch_all)
362 {
363 MYSQL_RES *result;
364 zval *mysql_result;
365 zend_long mode = MYSQLND_FETCH_NUM;
366
367 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &mode) == FAILURE) {
368 return;
369 }
370 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
371
372 if (!mode || (mode & ~MYSQLND_FETCH_BOTH)) {
373 php_error_docref(NULL, E_WARNING, "Mode can be only MYSQLI_FETCH_NUM, "
374 "MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH");
375 RETURN_FALSE;
376 }
377
378 mysqlnd_fetch_all(result, mode, return_value);
379 }
380
381
382
383
384 PHP_FUNCTION(mysqli_get_client_stats)
385 {
386 if (zend_parse_parameters_none() == FAILURE) {
387 return;
388 }
389 mysqlnd_get_client_stats(return_value);
390 }
391
392
393
394
395 PHP_FUNCTION(mysqli_get_connection_stats)
396 {
397 MY_MYSQL *mysql;
398 zval *mysql_link;
399
400 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
401 &mysql_link, mysqli_link_class_entry) == FAILURE) {
402 return;
403 }
404 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
405
406 mysqlnd_get_connection_stats(mysql->mysql, return_value);
407 }
408 #endif
409
410
411
412
413 PHP_FUNCTION(mysqli_error_list)
414 {
415 MY_MYSQL *mysql;
416 zval *mysql_link;
417
418 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
419 return;
420 }
421 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
422 array_init(return_value);
423 #if defined(MYSQLI_USE_MYSQLND)
424 if (mysql->mysql->data->error_info->error_list) {
425 MYSQLND_ERROR_LIST_ELEMENT * message;
426 zend_llist_position pos;
427 for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(mysql->mysql->data->error_info->error_list, &pos);
428 message;
429 message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(mysql->mysql->data->error_info->error_list, &pos))
430 {
431 zval single_error;
432 array_init(&single_error);
433 add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, message->error_no);
434 add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, message->sqlstate);
435 add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, message->error);
436 add_next_index_zval(return_value, &single_error);
437 }
438 }
439 #else
440 if (mysql_errno(mysql->mysql)) {
441 zval single_error;
442 array_init(&single_error);
443 add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, mysql_errno(mysql->mysql));
444 add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, mysql_sqlstate(mysql->mysql));
445 add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, mysql_error(mysql->mysql));
446 add_next_index_zval(return_value, &single_error);
447 }
448 #endif
449 }
450
451
452
453
454 PHP_FUNCTION(mysqli_stmt_error_list)
455 {
456 MY_STMT *stmt;
457 zval *mysql_stmt;
458
459 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
460 return;
461 }
462 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
463 array_init(return_value);
464 #if defined(MYSQLI_USE_MYSQLND)
465 if (stmt->stmt && stmt->stmt->data && stmt->stmt->data->error_info->error_list) {
466 MYSQLND_ERROR_LIST_ELEMENT * message;
467 zend_llist_position pos;
468 for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(stmt->stmt->data->error_info->error_list, &pos);
469 message;
470 message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(stmt->stmt->data->error_info->error_list, &pos))
471 {
472 zval single_error;
473 array_init(&single_error);
474 add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, message->error_no);
475 add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, message->sqlstate);
476 add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, message->error);
477 add_next_index_zval(return_value, &single_error);
478 }
479 }
480 #else
481 if (mysql_stmt_errno(stmt->stmt)) {
482 zval single_error;
483 array_init(&single_error);
484 add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, mysql_stmt_errno(stmt->stmt));
485 add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, mysql_stmt_sqlstate(stmt->stmt));
486 add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, mysql_stmt_error(stmt->stmt));
487 add_next_index_zval(return_value, &single_error);
488 }
489 #endif
490 }
491
492
493
494
495 PHP_FUNCTION(mysqli_fetch_object)
496 {
497 php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 1);
498 }
499
500
501
502
503 PHP_FUNCTION(mysqli_multi_query)
504 {
505 MY_MYSQL *mysql;
506 zval *mysql_link;
507 char *query = NULL;
508 size_t query_len;
509
510 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
511 return;
512 }
513 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
514
515 MYSQLI_ENABLE_MQ;
516 if (mysql_real_query(mysql->mysql, query, query_len)) {
517 #ifndef MYSQLI_USE_MYSQLND
518 char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1];
519 unsigned int s_errno;
520
521
522 strcpy(s_error, mysql_error(mysql->mysql));
523 strcpy(s_sqlstate, mysql_sqlstate(mysql->mysql));
524 s_errno = mysql_errno(mysql->mysql);
525 #else
526 MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
527 #endif
528 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
529 MYSQLI_DISABLE_MQ;
530
531 #ifndef MYSQLI_USE_MYSQLND
532
533 strcpy(mysql->mysql->net.last_error, s_error);
534 strcpy(mysql->mysql->net.sqlstate, s_sqlstate);
535 mysql->mysql->net.last_errno = s_errno;
536 #else
537 *mysql->mysql->data->error_info = error_info;
538 #endif
539 RETURN_FALSE;
540 }
541 RETURN_TRUE;
542 }
543
544
545
546 PHP_FUNCTION(mysqli_query)
547 {
548 MY_MYSQL *mysql;
549 zval *mysql_link;
550 MYSQLI_RESOURCE *mysqli_resource;
551 MYSQL_RES *result = NULL;
552 char *query = NULL;
553 size_t query_len;
554 zend_long resultmode = MYSQLI_STORE_RESULT;
555
556 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|l", &mysql_link, mysqli_link_class_entry, &query, &query_len, &resultmode) == FAILURE) {
557 return;
558 }
559
560 if (!query_len) {
561 php_error_docref(NULL, E_WARNING, "Empty query");
562 RETURN_FALSE;
563 }
564 #ifdef MYSQLI_USE_MYSQLND
565 if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) != MYSQLI_STORE_RESULT) {
566 #else
567 if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT) {
568 #endif
569 php_error_docref(NULL, E_WARNING, "Invalid value for resultmode");
570 RETURN_FALSE;
571 }
572
573 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
574
575 MYSQLI_DISABLE_MQ;
576
577
578 #ifdef MYSQLI_USE_MYSQLND
579 if (resultmode & MYSQLI_ASYNC) {
580 if (mysqli_async_query(mysql->mysql, query, query_len)) {
581 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
582 RETURN_FALSE;
583 }
584 mysql->async_result_fetch_type = resultmode & ~MYSQLI_ASYNC;
585 RETURN_TRUE;
586 }
587 #endif
588
589 if (mysql_real_query(mysql->mysql, query, query_len)) {
590 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
591 RETURN_FALSE;
592 }
593
594 if (!mysql_field_count(mysql->mysql)) {
595
596 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
597 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
598 }
599 RETURN_TRUE;
600 }
601
602 #ifdef MYSQLI_USE_MYSQLND
603 switch (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) {
604 #else
605 switch (resultmode & ~MYSQLI_ASYNC) {
606 #endif
607 case MYSQLI_STORE_RESULT:
608 #ifdef MYSQLI_USE_MYSQLND
609 if (resultmode & MYSQLI_STORE_RESULT_COPY_DATA) {
610 result = mysqlnd_store_result_ofs(mysql->mysql);
611 } else
612 #endif
613 result = mysql_store_result(mysql->mysql);
614 break;
615 case MYSQLI_USE_RESULT:
616 result = mysql_use_result(mysql->mysql);
617 break;
618 }
619 if (!result) {
620 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql),
621 "%s", mysql_error(mysql->mysql));
622 RETURN_FALSE;
623 }
624
625 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
626 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
627 }
628
629 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
630 mysqli_resource->ptr = (void *)result;
631 mysqli_resource->status = MYSQLI_STATUS_VALID;
632 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
633 }
634
635
636 #if defined(MYSQLI_USE_MYSQLND)
637 #include "php_network.h"
638
639 static int mysqlnd_zval_array_to_mysqlnd_array(zval *in_array, MYSQLND ***out_array)
640 {
641 zval *elem;
642 int i = 0, current = 0;
643
644 if (Z_TYPE_P(in_array) != IS_ARRAY) {
645 return 0;
646 }
647 *out_array = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(in_array)) + 1, sizeof(MYSQLND *));
648 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(in_array), elem) {
649 i++;
650 if (Z_TYPE_P(elem) != IS_OBJECT ||
651 !instanceof_function(Z_OBJCE_P(elem), mysqli_link_class_entry)) {
652 php_error_docref(NULL, E_WARNING, "Parameter %d not a mysqli object", i);
653 } else {
654 MY_MYSQL *mysql;
655 MYSQLI_RESOURCE *my_res;
656 mysqli_object *intern = Z_MYSQLI_P(elem);
657 if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
658 php_error_docref(NULL, E_WARNING, "[%d] Couldn't fetch %s", i, ZSTR_VAL(intern->zo.ce->name));
659 continue;
660 }
661 mysql = (MY_MYSQL*) my_res->ptr;
662 if (MYSQLI_STATUS_VALID && my_res->status < MYSQLI_STATUS_VALID) {
663 php_error_docref(NULL, E_WARNING, "Invalid object %d or resource %s", i, ZSTR_VAL(intern->zo.ce->name));
664 continue;
665 }
666 (*out_array)[current++] = mysql->mysql;
667 }
668 } ZEND_HASH_FOREACH_END();
669 return 0;
670 }
671
672
673
674 static int mysqlnd_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *out_array)
675 {
676 MYSQLND **p = in_array;
677 zval dest_array;
678 zval *elem, *dest_elem;
679 int ret = 0, i = 0;
680
681 array_init_size(&dest_array, zend_hash_num_elements(Z_ARRVAL_P(out_array)));
682
683 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(out_array), elem) {
684 i++;
685 if (Z_TYPE_P(elem) != IS_OBJECT ||
686 !instanceof_function(Z_OBJCE_P(elem), mysqli_link_class_entry)) {
687 continue;
688 }
689 {
690 MY_MYSQL *mysql;
691 MYSQLI_RESOURCE *my_res;
692 mysqli_object *intern = Z_MYSQLI_P(elem);
693 if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
694 php_error_docref(NULL, E_WARNING, "[%d] Couldn't fetch %s", i, ZSTR_VAL(intern->zo.ce->name));
695 continue;
696 }
697 mysql = (MY_MYSQL *) my_res->ptr;
698 if (mysql->mysql == *p) {
699 dest_elem = zend_hash_next_index_insert(Z_ARRVAL(dest_array), elem);
700 if (dest_elem) {
701 zval_add_ref(dest_elem);
702 }
703 ret++;
704 p++;
705 }
706 }
707 } ZEND_HASH_FOREACH_END();
708
709
710 zval_ptr_dtor(out_array);
711 ZVAL_COPY_VALUE(out_array, &dest_array);
712
713 return 0;
714 }
715
716
717
718 static int mysqlnd_dont_poll_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *in_zval_array, zval *out_array)
719 {
720 MYSQLND **p = in_array;
721 zval proxy, *elem, *dest_elem;
722 int ret = 0;
723
724 array_init(&proxy);
725 if (in_array) {
726 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(in_zval_array), elem) {
727 MY_MYSQL *mysql;
728 mysqli_object *intern = Z_MYSQLI_P(elem);
729 mysql = (MY_MYSQL *)((MYSQLI_RESOURCE *)intern->ptr)->ptr;
730 if (mysql->mysql == *p) {
731 dest_elem = zend_hash_next_index_insert(Z_ARRVAL(proxy), elem);
732 if (dest_elem) {
733 zval_add_ref(dest_elem);
734 }
735 ret++;
736 p++;
737 }
738 } ZEND_HASH_FOREACH_END();
739 }
740
741
742 zval_ptr_dtor(out_array);
743 ZVAL_COPY_VALUE(out_array, &proxy);
744
745 return 0;
746 }
747
748
749
750
751 PHP_FUNCTION(mysqli_poll)
752 {
753 zval *r_array, *e_array, *dont_poll_array;
754 MYSQLND **new_r_array = NULL, **new_e_array = NULL, **new_dont_poll_array = NULL;
755 zend_long sec = 0, usec = 0;
756 enum_func_status ret;
757 int desc_num;
758
759 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a!a!al|l", &r_array, &e_array, &dont_poll_array, &sec, &usec) == FAILURE) {
760 return;
761 }
762 if (sec < 0 || usec < 0) {
763 php_error_docref(NULL, E_WARNING, "Negative values passed for sec and/or usec");
764 RETURN_FALSE;
765 }
766
767 if (!r_array && !e_array) {
768 php_error_docref(NULL, E_WARNING, "No stream arrays were passed");
769 RETURN_FALSE;
770 }
771
772 if (r_array != NULL) {
773 mysqlnd_zval_array_to_mysqlnd_array(r_array, &new_r_array);
774 }
775 if (e_array != NULL) {
776 mysqlnd_zval_array_to_mysqlnd_array(e_array, &new_e_array);
777 }
778
779 ret = mysqlnd_poll(new_r_array, new_e_array, &new_dont_poll_array, sec, usec, &desc_num);
780
781 mysqlnd_dont_poll_zval_array_from_mysqlnd_array(r_array != NULL ? new_dont_poll_array:NULL, r_array, dont_poll_array);
782
783 if (r_array != NULL) {
784 mysqlnd_zval_array_from_mysqlnd_array(new_r_array, r_array);
785 }
786 if (e_array != NULL) {
787 mysqlnd_zval_array_from_mysqlnd_array(new_e_array, e_array);
788 }
789
790 if (new_dont_poll_array) {
791 efree(new_dont_poll_array);
792 }
793 if (new_r_array) {
794 efree(new_r_array);
795 }
796 if (new_e_array) {
797 efree(new_e_array);
798 }
799 if (ret == PASS) {
800 RETURN_LONG(desc_num);
801 } else {
802 RETURN_FALSE;
803 }
804 }
805
806
807
808
809 PHP_FUNCTION(mysqli_reap_async_query)
810 {
811 MY_MYSQL *mysql;
812 zval *mysql_link;
813 MYSQLI_RESOURCE *mysqli_resource;
814 MYSQL_RES *result = NULL;
815
816 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
817 return;
818 }
819
820 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
821
822 if (FAIL == mysqlnd_reap_async_query(mysql->mysql)) {
823 RETURN_FALSE;
824 }
825
826 if (!mysql_field_count(mysql->mysql)) {
827
828 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
829
830 }
831 RETURN_TRUE;
832 }
833
834 switch (mysql->async_result_fetch_type) {
835 case MYSQLI_STORE_RESULT:
836 result = mysql_store_result(mysql->mysql);
837 break;
838 case MYSQLI_USE_RESULT:
839 result = mysql_use_result(mysql->mysql);
840 break;
841 }
842
843 if (!result) {
844 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql),
845 "%s", mysql_error(mysql->mysql));
846 RETURN_FALSE;
847 }
848
849 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
850
851 }
852
853 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
854 mysqli_resource->ptr = (void *)result;
855 mysqli_resource->status = MYSQLI_STATUS_VALID;
856 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
857 }
858
859
860
861
862 PHP_FUNCTION(mysqli_stmt_get_result)
863 {
864 MYSQL_RES *result;
865 MYSQLI_RESOURCE *mysqli_resource;
866 MY_STMT *stmt;
867 zval *mysql_stmt;
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 if (!(result = mysqlnd_stmt_get_result(stmt->stmt))) {
875 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
876 RETURN_FALSE;
877 }
878
879 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
880 mysqli_resource->ptr = (void *)result;
881 mysqli_resource->status = MYSQLI_STATUS_VALID;
882 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
883 }
884
885 #endif
886
887
888 PHP_FUNCTION(mysqli_get_warnings)
889 {
890 MY_MYSQL *mysql;
891 zval *mysql_link;
892 MYSQLI_RESOURCE *mysqli_resource;
893 MYSQLI_WARNING *w;
894
895 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
896 return;
897 }
898 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
899
900 if (mysql_warning_count(mysql->mysql)) {
901 #ifdef MYSQLI_USE_MYSQLND
902 w = php_get_warnings(mysql->mysql->data);
903 #else
904 w = php_get_warnings(mysql->mysql);
905 #endif
906 } else {
907 RETURN_FALSE;
908 }
909 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
910 mysqli_resource->ptr = mysqli_resource->info = (void *)w;
911 mysqli_resource->status = MYSQLI_STATUS_VALID;
912 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
913 }
914
915
916
917 PHP_FUNCTION(mysqli_stmt_get_warnings)
918 {
919 MY_STMT *stmt;
920 zval *stmt_link;
921 MYSQLI_RESOURCE *mysqli_resource;
922 MYSQLI_WARNING *w;
923
924 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &stmt_link, mysqli_stmt_class_entry) == FAILURE) {
925 return;
926 }
927 MYSQLI_FETCH_RESOURCE_STMT(stmt, stmt_link, MYSQLI_STATUS_VALID);
928
929 if (mysqli_stmt_warning_count(stmt->stmt)) {
930 w = php_get_warnings(mysqli_stmt_get_connection(stmt->stmt));
931 } else {
932 RETURN_FALSE;
933 }
934 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
935 mysqli_resource->ptr = mysqli_resource->info = (void *)w;
936 mysqli_resource->status = MYSQLI_STATUS_VALID;
937 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
938 }
939
940
941 #ifdef HAVE_MYSQLI_SET_CHARSET
942
943
944 PHP_FUNCTION(mysqli_set_charset)
945 {
946 MY_MYSQL *mysql;
947 zval *mysql_link;
948 char *cs_name;
949 size_t csname_len;
950
951 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &csname_len) == FAILURE) {
952 return;
953 }
954 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
955
956 if (mysql_set_character_set(mysql->mysql, cs_name)) {
957 RETURN_FALSE;
958 }
959 RETURN_TRUE;
960 }
961
962 #endif
963
964 #ifdef HAVE_MYSQLI_GET_CHARSET
965
966
967 PHP_FUNCTION(mysqli_get_charset)
968 {
969 MY_MYSQL *mysql;
970 zval *mysql_link;
971 const char *name = NULL, *collation = NULL, *dir = NULL, *comment = NULL;
972 uint minlength, maxlength, number, state;
973 #if !defined(MYSQLI_USE_MYSQLND)
974 MY_CHARSET_INFO cs;
975 #else
976 const MYSQLND_CHARSET *cs;
977 #endif
978
979 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
980 return;
981 }
982 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
983
984
985 #if !defined(MYSQLI_USE_MYSQLND)
986 mysql_get_character_set_info(mysql->mysql, &cs);
987 name = (char *)cs.csname;
988 collation = (char *)cs.name;
989 dir = (char *)cs.dir;
990 minlength = cs.mbminlen;
991 maxlength = cs.mbmaxlen;
992 number = cs.number;
993 state = cs.state;
994 comment = cs.comment;
995 #else
996 cs = mysql->mysql->data->charset;
997 if (!cs) {
998 php_error_docref(NULL, E_WARNING, "The connection has no charset associated");
999 RETURN_NULL();
1000 }
1001 name = cs->name;
1002 collation = cs->collation;
1003 minlength = cs->char_minlen;
1004 maxlength = cs->char_maxlen;
1005 number = cs->nr;
1006 comment = cs->comment;
1007 state = 1;
1008 #endif
1009 object_init(return_value);
1010
1011 add_property_string(return_value, "charset", (name) ? (char *)name : "");
1012 add_property_string(return_value, "collation",(collation) ? (char *)collation : "");
1013 add_property_string(return_value, "dir", (dir) ? (char *)dir : "");
1014 add_property_long(return_value, "min_length", minlength);
1015 add_property_long(return_value, "max_length", maxlength);
1016 add_property_long(return_value, "number", number);
1017 add_property_long(return_value, "state", state);
1018 add_property_string(return_value, "comment", (comment) ? (char *)comment : "");
1019 }
1020
1021 #endif
1022
1023 #if !defined(MYSQLI_USE_MYSQLND)
1024 extern char * mysqli_escape_string_for_tx_name_in_comment(const char * const name);
1025
1026
1027 static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mode, const char * const name)
1028 {
1029 int ret;
1030 zend_bool err = FALSE;
1031 smart_str tmp_str = {0};
1032 if (mode & TRANS_START_WITH_CONSISTENT_SNAPSHOT) {
1033 if (tmp_str.s) {
1034 smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
1035 }
1036 smart_str_appendl(&tmp_str, "WITH CONSISTENT SNAPSHOT", sizeof("WITH CONSISTENT SNAPSHOT") - 1);
1037 }
1038 if (mode & (TRANS_START_READ_WRITE | TRANS_START_READ_ONLY)) {
1039 if (mysql_get_server_version(conn) < 50605L) {
1040 php_error_docref(NULL, E_WARNING, "This server version doesn't support 'READ WRITE' and 'READ ONLY'. Minimum 5.6.5 is required");
1041 err = TRUE;
1042 } else if (mode & TRANS_START_READ_WRITE) {
1043 if (tmp_str.s) {
1044 smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
1045 }
1046 smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
1047 } else if (mode & TRANS_START_READ_ONLY) {
1048 if (tmp_str.s) {
1049 smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
1050 }
1051 smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
1052 }
1053 }
1054 smart_str_0(&tmp_str);
1055
1056 if (err == FALSE){
1057 char * name_esc = mysqli_escape_string_for_tx_name_in_comment(name);
1058 char * query;
1059 unsigned int query_len = spprintf(&query, 0, "START TRANSACTION%s %s",
1060 name_esc? name_esc:"", tmp_str.s? ZSTR_VAL(tmp_str.s):"");
1061
1062 smart_str_free(&tmp_str);
1063 if (name_esc) {
1064 efree(name_esc);
1065 }
1066
1067 ret = mysql_real_query(conn, query, query_len);
1068 efree(query);
1069 }
1070 return ret;
1071 }
1072
1073 #endif
1074
1075
1076
1077 PHP_FUNCTION(mysqli_begin_transaction)
1078 {
1079 MY_MYSQL *mysql;
1080 zval *mysql_link;
1081 zend_long flags = TRANS_START_NO_OPT;
1082 char * name = NULL;
1083 size_t name_len = -1;
1084 zend_bool err = FALSE;
1085
1086 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1087 return;
1088 }
1089 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1090 if (flags < 0) {
1091 php_error_docref(NULL, E_WARNING, "Invalid value for parameter flags (%pd)", flags);
1092 err = TRUE;
1093 }
1094 if (!name_len) {
1095 php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty");
1096 err = TRUE;
1097 }
1098 if (TRUE == err) {
1099 RETURN_FALSE;
1100 }
1101
1102 #if !defined(MYSQLI_USE_MYSQLND)
1103 if (mysqli_begin_transaction_libmysql(mysql->mysql, flags, name)) {
1104 RETURN_FALSE;
1105 }
1106 #else
1107 if (FAIL == mysqlnd_begin_transaction(mysql->mysql, flags, name)) {
1108 RETURN_FALSE;
1109 }
1110 #endif
1111 RETURN_TRUE;
1112 }
1113
1114
1115 #if !defined(MYSQLI_USE_MYSQLND)
1116
1117 static int mysqli_savepoint_libmysql(MYSQL * conn, const char * const name, zend_bool release)
1118 {
1119 int ret;
1120 char * query;
1121 unsigned int query_len = spprintf(&query, 0, release? "RELEASE SAVEPOINT `%s`":"SAVEPOINT `%s`", name);
1122 ret = mysql_real_query(conn, query, query_len);
1123 efree(query);
1124 return ret;
1125 }
1126
1127 #endif
1128
1129
1130
1131 PHP_FUNCTION(mysqli_savepoint)
1132 {
1133 MY_MYSQL *mysql;
1134 zval *mysql_link;
1135 char * name = NULL;
1136 size_t name_len = -1;
1137
1138 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &name, &name_len) == FAILURE) {
1139 return;
1140 }
1141 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1142 if (!name || !name_len) {
1143 php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty");
1144 RETURN_FALSE;
1145 }
1146
1147 #if !defined(MYSQLI_USE_MYSQLND)
1148 if (mysqli_savepoint_libmysql(mysql->mysql, name, FALSE)) {
1149 #else
1150 if (FAIL == mysqlnd_savepoint(mysql->mysql, name)) {
1151 #endif
1152 RETURN_FALSE;
1153 }
1154 RETURN_TRUE;
1155 }
1156
1157
1158
1159
1160 PHP_FUNCTION(mysqli_release_savepoint)
1161 {
1162 MY_MYSQL *mysql;
1163 zval *mysql_link;
1164 char * name = NULL;
1165 size_t name_len = -1;
1166
1167 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &name, &name_len) == FAILURE) {
1168 return;
1169 }
1170 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1171 if (!name || !name_len) {
1172 php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty");
1173 RETURN_FALSE;
1174 }
1175 #if !defined(MYSQLI_USE_MYSQLND)
1176 if (mysqli_savepoint_libmysql(mysql->mysql, name, TRUE)) {
1177 #else
1178 if (FAIL == mysqlnd_savepoint(mysql->mysql, name)) {
1179 #endif
1180 RETURN_FALSE;
1181 }
1182 RETURN_TRUE;
1183 }
1184
1185
1186
1187
1188 PHP_FUNCTION(mysqli_get_links_stats)
1189 {
1190 if (ZEND_NUM_ARGS()) {
1191 php_error_docref(NULL, E_WARNING, "no parameters expected");
1192 return;
1193 }
1194 array_init(return_value);
1195 add_assoc_long_ex(return_value, "total", sizeof("total") - 1, MyG(num_links));
1196 add_assoc_long_ex(return_value, "active_plinks", sizeof("active_plinks") - 1, MyG(num_active_persistent));
1197 add_assoc_long_ex(return_value, "cached_plinks", sizeof("cached_plinks") - 1, MyG(num_inactive_persistent));
1198 }
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209