1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 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 "ext/standard/info.h"
32 #include "php_mysqli_structs.h"
33 #include "mysqli_priv.h"
34
35 #define SAFE_STR(a) ((a)?a:"")
36
37 #ifndef zend_parse_parameters_none
38 #define zend_parse_parameters_none() \
39 zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
40 #endif
41
42 /* {{{ php_mysqli_set_error
43 */
php_mysqli_set_error(long mysql_errno,char * mysql_err TSRMLS_DC)44 static void php_mysqli_set_error(long mysql_errno, char *mysql_err TSRMLS_DC)
45 {
46 MyG(error_no) = mysql_errno;
47 if (MyG(error_msg)) {
48 efree(MyG(error_msg));
49 }
50 if(mysql_err && *mysql_err) {
51 MyG(error_msg) = estrdup(mysql_err);
52 } else {
53 MyG(error_msg) = NULL;
54 }
55 }
56 /* }}} */
57
58
mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS,zend_bool is_real_connect,zend_bool in_ctor)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 int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0;
66 zend_bool persistent = FALSE;
67 long port = 0, flags = 0;
68 uint hash_len;
69 char *hash_key = NULL;
70 zend_bool new_connection = FALSE;
71 zend_rsrc_list_entry *le;
72 mysqli_plist_entry *plist = NULL;
73 zend_bool self_alloced = 0;
74
75
76 #if !defined(MYSQL_USE_MYSQLND)
77 if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) {
78 php_error_docref(NULL TSRMLS_CC, E_WARNING,
79 "Headers and client library minor version mismatch. Headers:%d Library:%ld",
80 MYSQL_VERSION_ID, mysql_get_client_version());
81 }
82 #endif
83
84 if (getThis() && !ZEND_NUM_ARGS() && in_ctor) {
85 php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU);
86 return;
87 }
88 hostname = username = dbname = passwd = socket = NULL;
89
90 if (!is_real_connect) {
91 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ssssls", &hostname, &hostname_len, &username, &username_len,
92 &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len) == FAILURE) {
93 return;
94 }
95
96 if (object && instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {
97 mysqli_resource = ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr;
98 if (mysqli_resource && mysqli_resource->ptr) {
99 mysql = (MY_MYSQL*) mysqli_resource->ptr;
100 }
101 }
102 if (!mysql) {
103 mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
104 self_alloced = 1;
105 }
106 flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */
107 } else {
108 /* We have flags too */
109 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|sssslsl", &object, mysqli_link_class_entry,
110 &hostname, &hostname_len, &username, &username_len, &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len,
111 &flags) == FAILURE) {
112 return;
113 }
114
115 mysqli_resource = ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr;
116 MYSQLI_FETCH_RESOURCE_CONN(mysql, &object, MYSQLI_STATUS_INITIALIZED);
117
118 /* set some required options */
119 flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */
120 /* remove some insecure options */
121 flags &= ~CLIENT_MULTI_STATEMENTS; /* don't allow multi_queries via connect parameter */
122 if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
123 flags &= ~CLIENT_LOCAL_FILES;
124 }
125 }
126
127 if (!socket_len || !socket) {
128 socket = MyG(default_socket);
129 }
130 if (!port){
131 port = MyG(default_port);
132 }
133 if (!passwd) {
134 passwd = MyG(default_pw);
135 passwd_len = strlen(SAFE_STR(passwd));
136 }
137 if (!username){
138 username = MyG(default_user);
139 }
140 if (!hostname || !hostname_len) {
141 hostname = MyG(default_host);
142 }
143
144 if (mysql->mysql && mysqli_resource &&
145 (mysqli_resource->status > MYSQLI_STATUS_INITIALIZED))
146 {
147 /* already connected, we should close the connection */
148 php_mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT, mysqli_resource->status TSRMLS_CC);
149 }
150
151 if (strlen(SAFE_STR(hostname)) > 2 && !strncasecmp(hostname, "p:", 2)) {
152 hostname += 2;
153 if (!MyG(allow_persistent)) {
154 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Persistent connections are disabled. Downgrading to normal");
155 } else {
156 mysql->persistent = persistent = TRUE;
157
158 hash_len = spprintf(&hash_key, 0, "mysqli_%s_%s%ld%s%s%s", SAFE_STR(hostname), SAFE_STR(socket),
159 port, SAFE_STR(username), SAFE_STR(dbname),
160 SAFE_STR(passwd));
161
162 mysql->hash_key = hash_key;
163
164 /* check if we can reuse exisiting connection ... */
165 if (zend_hash_find(&EG(persistent_list), hash_key, hash_len + 1, (void **)&le) == SUCCESS) {
166 if (Z_TYPE_P(le) == php_le_pmysqli()) {
167 plist = (mysqli_plist_entry *) le->ptr;
168
169 do {
170 if (zend_ptr_stack_num_elements(&plist->free_links)) {
171 mysql->mysql = zend_ptr_stack_pop(&plist->free_links);
172
173 MyG(num_inactive_persistent)--;
174 /* reset variables */
175
176 #ifndef MYSQLI_NO_CHANGE_USER_ON_PCONNECT
177 if (!mysqli_change_user_silent(mysql->mysql, username, passwd, dbname)) {
178 #else
179 if (!mysql_ping(mysql->mysql)) {
180 #endif
181 #ifdef MYSQLI_USE_MYSQLND
182 mysqlnd_restart_psession(mysql->mysql);
183 #endif
184 MyG(num_active_persistent)++;
185 goto end;
186 } else {
187 mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT);
188 mysql->mysql = NULL;
189 }
190 }
191 } while (0);
192 }
193 } else {
194 zend_rsrc_list_entry le;
195 le.type = php_le_pmysqli();
196 le.ptr = plist = calloc(1, sizeof(mysqli_plist_entry));
197
198 zend_ptr_stack_init_ex(&plist->free_links, 1);
199 zend_hash_update(&EG(persistent_list), hash_key, hash_len + 1, (void *)&le, sizeof(le), NULL);
200 }
201 }
202 }
203 if (MyG(max_links) != -1 && MyG(num_links) >= MyG(max_links)) {
204 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MyG(num_links));
205 goto err;
206 }
207
208 if (persistent && MyG(max_persistent) != -1 &&
209 (MyG(num_active_persistent) + MyG(num_inactive_persistent))>= MyG(max_persistent))
210 {
211 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)",
212 MyG(num_active_persistent) + MyG(num_inactive_persistent));
213 goto err;
214 }
215 if (!mysql->mysql) {
216 #if !defined(MYSQLI_USE_MYSQLND)
217 if (!(mysql->mysql = mysql_init(NULL))) {
218 #else
219 if (!(mysql->mysql = mysqlnd_init(persistent))) {
220 #endif
221 goto err;
222 }
223 new_connection = TRUE;
224 }
225
226 #ifdef HAVE_EMBEDDED_MYSQLI
227 if (hostname_len) {
228 unsigned int external=1;
229 mysql_options(mysql->mysql, MYSQL_OPT_USE_REMOTE_CONNECTION, (char *)&external);
230 } else {
231 mysql_options(mysql->mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, 0);
232 }
233 #endif
234
235 #if !defined(MYSQLI_USE_MYSQLND)
236 /* BC for prior to bug fix #53425 */
237 flags |= CLIENT_MULTI_RESULTS;
238
239 if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, flags) == NULL)
240 #else
241 if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
242 port, socket, flags TSRMLS_CC) == NULL)
243 #endif
244 {
245 /* Save error messages - for mysqli_connect_error() & mysqli_connect_errno() */
246 php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql) TSRMLS_CC);
247 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
248 "%s", mysql_error(mysql->mysql));
249 if (!is_real_connect) {
250 /* free mysql structure */
251 mysqli_close(mysql->mysql, MYSQLI_CLOSE_DISCONNECTED);
252 mysql->mysql = NULL;
253 }
254 goto err;
255 }
256
257 /* clear error */
258 php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql) TSRMLS_CC);
259
260 #if !defined(MYSQLI_USE_MYSQLND)
261 mysql->mysql->reconnect = MyG(reconnect);
262
263 /* set our own local_infile handler */
264 php_set_local_infile_handler_default(mysql);
265 #endif
266
267 mysql_options(mysql->mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&MyG(allow_local_infile));
268
269 end:
270 if (!mysqli_resource) {
271 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
272 mysqli_resource->ptr = (void *)mysql;
273 }
274 mysqli_resource->status = MYSQLI_STATUS_VALID;
275
276 /* store persistent connection */
277 if (persistent && (new_connection || is_real_connect)) {
278 MyG(num_active_persistent)++;
279 }
280
281 MyG(num_links)++;
282
283 mysql->multi_query = 0;
284
285 if (!object || !instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {
286 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
287 } else {
288 ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr = mysqli_resource;
289 }
290 if (!is_real_connect) {
291 return;
292 } else {
293 RETURN_TRUE;
294 }
295
296 err:
297 if (mysql->hash_key) {
298 efree(mysql->hash_key);
299 mysql->hash_key = NULL;
300 mysql->persistent = FALSE;
301 }
302 if (!is_real_connect && self_alloced) {
303 efree(mysql);
304 }
305 RETVAL_FALSE;
306 }
307
308
309 /* {{{ proto object mysqli_connect([string hostname [,string username [,string passwd [,string dbname [,int port [,string socket]]]]]])
310 Open a connection to a mysql server */
311 PHP_FUNCTION(mysqli_connect)
312 {
313 mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE, FALSE);
314 }
315 /* }}} */
316
317
318 /* {{{ proto object mysqli_link_construct()
319 */
320 PHP_FUNCTION(mysqli_link_construct)
321 {
322 mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE, TRUE);
323 }
324 /* }}} */
325
326
327 /* {{{ proto int mysqli_connect_errno(void)
328 Returns the numerical value of the error message from last connect command */
329 PHP_FUNCTION(mysqli_connect_errno)
330 {
331 RETURN_LONG(MyG(error_no));
332 }
333 /* }}} */
334
335 /* {{{ proto string mysqli_connect_error(void)
336 Returns the text of the error message from previous MySQL operation */
337 PHP_FUNCTION(mysqli_connect_error)
338 {
339 if (MyG(error_msg)) {
340 RETURN_STRING(MyG(error_msg),1);
341 } else {
342 RETURN_NULL();
343 }
344 }
345 /* }}} */
346
347
348 /* {{{ proto mixed mysqli_fetch_array (object result [,int resulttype])
349 Fetch a result row as an associative array, a numeric array, or both */
350 PHP_FUNCTION(mysqli_fetch_array)
351 {
352 php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
353 }
354 /* }}} */
355
356 /* {{{ proto mixed mysqli_fetch_assoc (object result)
357 Fetch a result row as an associative array */
358 PHP_FUNCTION(mysqli_fetch_assoc)
359 {
360 php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 0);
361 }
362 /* }}} */
363
364
365 /* {{{ proto mixed mysqli_fetch_all (object result [,int resulttype])
366 Fetches all result rows as an associative array, a numeric array, or both */
367 #if defined(MYSQLI_USE_MYSQLND)
368 PHP_FUNCTION(mysqli_fetch_all)
369 {
370 MYSQL_RES *result;
371 zval *mysql_result;
372 long mode = MYSQLND_FETCH_NUM;
373
374 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &mode) == FAILURE) {
375 return;
376 }
377 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
378
379 if (!mode || (mode & ~MYSQLND_FETCH_BOTH)) {
380 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Mode can be only MYSQLI_FETCH_NUM, "
381 "MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH");
382 RETURN_FALSE;
383 }
384
385 mysqlnd_fetch_all(result, mode, return_value);
386 }
387 /* }}} */
388
389
390 /* {{{ proto array mysqli_cache_stats(void) U
391 Returns statistics about the zval cache */
392 PHP_FUNCTION(mysqli_get_cache_stats)
393 {
394 if (zend_parse_parameters_none() == FAILURE) {
395 return;
396 }
397 array_init(return_value);
398 }
399 /* }}} */
400
401
402 /* {{{ proto array mysqli_get_client_stats(void)
403 Returns statistics about the zval cache */
404 PHP_FUNCTION(mysqli_get_client_stats)
405 {
406 if (zend_parse_parameters_none() == FAILURE) {
407 return;
408 }
409 mysqlnd_get_client_stats(return_value);
410 }
411 /* }}} */
412
413
414 /* {{{ proto array mysqli_get_connection_stats(void)
415 Returns statistics about the zval cache */
416 PHP_FUNCTION(mysqli_get_connection_stats)
417 {
418 MY_MYSQL *mysql;
419 zval *mysql_link;
420
421 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
422 &mysql_link, mysqli_link_class_entry) == FAILURE) {
423 return;
424 }
425 MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
426
427 mysqlnd_get_connection_stats(mysql->mysql, return_value);
428 }
429 #endif
430 /* }}} */
431
432
433 /* {{{ proto mixed mysqli_fetch_object (object result [, string class_name [, NULL|array ctor_params]])
434 Fetch a result row as an object */
435 PHP_FUNCTION(mysqli_fetch_object)
436 {
437 php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 1);
438 }
439 /* }}} */
440
441 /* {{{ proto bool mysqli_multi_query(object link, string query)
442 allows to execute multiple queries */
443 PHP_FUNCTION(mysqli_multi_query)
444 {
445 MY_MYSQL *mysql;
446 zval *mysql_link;
447 char *query = NULL;
448 int query_len;
449
450 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
451 return;
452 }
453 MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
454
455 MYSQLI_ENABLE_MQ;
456 if (mysql_real_query(mysql->mysql, query, query_len)) {
457 #ifndef MYSQLI_USE_MYSQLND
458 char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1];
459 unsigned int s_errno;
460 /* we have to save error information, cause
461 MYSQLI_DISABLE_MQ will reset error information */
462 strcpy(s_error, mysql_error(mysql->mysql));
463 strcpy(s_sqlstate, mysql_sqlstate(mysql->mysql));
464 s_errno = mysql_errno(mysql->mysql);
465 #else
466 MYSQLND_ERROR_INFO error_info = mysql->mysql->error_info;
467 #endif
468 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
469 MYSQLI_DISABLE_MQ;
470
471 #ifndef MYSQLI_USE_MYSQLND
472 /* restore error information */
473 strcpy(mysql->mysql->net.last_error, s_error);
474 strcpy(mysql->mysql->net.sqlstate, s_sqlstate);
475 mysql->mysql->net.last_errno = s_errno;
476 #else
477 mysql->mysql->error_info = error_info;
478 #endif
479 RETURN_FALSE;
480 }
481 RETURN_TRUE;
482 }
483 /* }}} */
484
485 /* {{{ proto mixed mysqli_query(object link, string query [,int resultmode]) */
486 PHP_FUNCTION(mysqli_query)
487 {
488 MY_MYSQL *mysql;
489 zval *mysql_link;
490 MYSQLI_RESOURCE *mysqli_resource;
491 MYSQL_RES *result;
492 char *query = NULL;
493 int query_len;
494 long resultmode = MYSQLI_STORE_RESULT;
495
496 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", &mysql_link, mysqli_link_class_entry, &query, &query_len, &resultmode) == FAILURE) {
497 return;
498 }
499
500 if (!query_len) {
501 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query");
502 RETURN_FALSE;
503 }
504 if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT) {
505 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
506 RETURN_FALSE;
507 }
508
509 MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
510
511 MYSQLI_DISABLE_MQ;
512
513
514 #ifdef MYSQLI_USE_MYSQLND
515 if (resultmode & MYSQLI_ASYNC) {
516 if (mysqli_async_query(mysql->mysql, query, query_len)) {
517 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
518 RETURN_FALSE;
519 }
520 mysql->async_result_fetch_type = resultmode & ~MYSQLI_ASYNC;
521 RETURN_TRUE;
522 }
523 #endif
524
525 if (mysql_real_query(mysql->mysql, query, query_len)) {
526 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
527 RETURN_FALSE;
528 }
529
530 if (!mysql_field_count(mysql->mysql)) {
531 /* no result set - not a SELECT */
532 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
533 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql) TSRMLS_CC);
534 }
535 RETURN_TRUE;
536 }
537
538 switch (resultmode) {
539 case MYSQLI_STORE_RESULT:
540 result = mysql_store_result(mysql->mysql);
541 break;
542 case MYSQLI_USE_RESULT:
543 result = mysql_use_result(mysql->mysql);
544 break;
545 }
546 if (!result) {
547 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
548 "%s", mysql_error(mysql->mysql));
549 RETURN_FALSE;
550 }
551
552 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
553 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql) TSRMLS_CC);
554 }
555
556 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
557 mysqli_resource->ptr = (void *)result;
558 mysqli_resource->status = MYSQLI_STATUS_VALID;
559 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
560 }
561 /* }}} */
562
563
564 #if defined(MYSQLI_USE_MYSQLND)
565 #include "php_network.h"
566 /* {{{ mysqlnd_zval_array_to_mysqlnd_array functions */
567 static int mysqlnd_zval_array_to_mysqlnd_array(zval *in_array, MYSQLND ***out_array TSRMLS_DC)
568 {
569 zval **elem;
570 int i = 0, current = 0;
571
572 if (Z_TYPE_P(in_array) != IS_ARRAY) {
573 return 0;
574 }
575 *out_array = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(in_array)) + 1, sizeof(MYSQLND *));
576 for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(in_array));
577 zend_hash_get_current_data(Z_ARRVAL_P(in_array), (void **) &elem) == SUCCESS;
578 zend_hash_move_forward(Z_ARRVAL_P(in_array))) {
579 i++;
580 if (Z_TYPE_PP(elem) != IS_OBJECT ||
581 !instanceof_function(Z_OBJCE_PP(elem), mysqli_link_class_entry TSRMLS_CC)) {
582 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter %d not a mysqli object", i);
583 } else {
584 MY_MYSQL *mysql;
585 MYSQLI_RESOURCE *my_res;
586 mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC);
587 if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
588 php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%d] Couldn't fetch %s", i, intern->zo.ce->name);
589 continue;
590 }
591 mysql = (MY_MYSQL*) my_res->ptr;
592 if (MYSQLI_STATUS_VALID && my_res->status < MYSQLI_STATUS_VALID) {
593 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object %d or resource %s", i, intern->zo.ce->name);
594 continue;
595 }
596 (*out_array)[current++] = mysql->mysql;
597 }
598 }
599 return 0;
600 }
601 /* }}} */
602
603
604 /* {{{ mysqlnd_zval_array_from_mysqlnd_array */
605 static int mysqlnd_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *out_array TSRMLS_DC)
606 {
607 MYSQLND **p = in_array;
608 HashTable *new_hash;
609 zval **elem, **dest_elem;
610 int ret = 0, i = 0;
611
612 ALLOC_HASHTABLE(new_hash);
613 zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(out_array)), NULL, ZVAL_PTR_DTOR, 0);
614
615 for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(out_array));
616 zend_hash_get_current_data(Z_ARRVAL_P(out_array), (void **) &elem) == SUCCESS;
617 zend_hash_move_forward(Z_ARRVAL_P(out_array)))
618 {
619 i++;
620 if (Z_TYPE_PP(elem) != IS_OBJECT || !instanceof_function(Z_OBJCE_PP(elem), mysqli_link_class_entry TSRMLS_CC)) {
621 continue;
622 }
623 {
624 MY_MYSQL *mysql;
625 MYSQLI_RESOURCE *my_res;
626 mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC);
627 if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
628 php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%d] Couldn't fetch %s", i, intern->zo.ce->name);
629 continue;
630 }
631 mysql = (MY_MYSQL *) my_res->ptr;
632 if (mysql->mysql == *p) {
633 zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
634 if (dest_elem) {
635 zval_add_ref(dest_elem);
636 }
637 ret++;
638 p++;
639 }
640 }
641 }
642
643 /* destroy old array and add new one */
644 zend_hash_destroy(Z_ARRVAL_P(out_array));
645 efree(Z_ARRVAL_P(out_array));
646
647 zend_hash_internal_pointer_reset(new_hash);
648 Z_ARRVAL_P(out_array) = new_hash;
649
650 return 0;
651 }
652 /* }}} */
653
654
655 /* {{{ mysqlnd_dont_poll_zval_array_from_mysqlnd_array */
656 static int mysqlnd_dont_poll_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *in_zval_array, zval *out_array TSRMLS_DC)
657 {
658 MYSQLND **p = in_array;
659 HashTable *new_hash;
660 zval **elem, **dest_elem;
661 int ret = 0;
662
663 ALLOC_HASHTABLE(new_hash);
664 zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(in_zval_array)), NULL, ZVAL_PTR_DTOR, 0);
665 if (in_array) {
666 for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(in_zval_array));
667 zend_hash_get_current_data(Z_ARRVAL_P(in_zval_array), (void **) &elem) == SUCCESS;
668 zend_hash_move_forward(Z_ARRVAL_P(in_zval_array)))
669 {
670 MY_MYSQL *mysql;
671 mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC);
672 mysql = (MY_MYSQL *) ((MYSQLI_RESOURCE *)intern->ptr)->ptr;
673 if (mysql->mysql == *p) {
674 zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
675 if (dest_elem) {
676 zval_add_ref(dest_elem);
677 }
678 ret++;
679 p++;
680 }
681 }
682 }
683
684 /* destroy old array and add new one */
685 zend_hash_destroy(Z_ARRVAL_P(out_array));
686 efree(Z_ARRVAL_P(out_array));
687
688 zend_hash_internal_pointer_reset(new_hash);
689 Z_ARRVAL_P(out_array) = new_hash;
690
691 return 0;
692 }
693 /* }}} */
694
695
696 /* {{{ proto int mysqli_poll(array read, array write, array error, long sec [, long usec]) U
697 Poll connections */
698 PHP_FUNCTION(mysqli_poll)
699 {
700 zval *r_array, *e_array, *dont_poll_array;
701 MYSQLND **new_r_array = NULL, **new_e_array = NULL, **new_dont_poll_array = NULL;
702 long sec = 0, usec = 0;
703 enum_func_status ret;
704 uint desc_num;
705
706 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!al|l", &r_array, &e_array, &dont_poll_array, &sec, &usec) == FAILURE) {
707 return;
708 }
709 if (sec < 0 || usec < 0) {
710 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Negative values passed for sec and/or usec");
711 RETURN_FALSE;
712 }
713
714 if (!r_array && !e_array) {
715 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stream arrays were passed");
716 RETURN_FALSE;
717 }
718
719 if (r_array != NULL) {
720 mysqlnd_zval_array_to_mysqlnd_array(r_array, &new_r_array TSRMLS_CC);
721 }
722 if (e_array != NULL) {
723 mysqlnd_zval_array_to_mysqlnd_array(e_array, &new_e_array TSRMLS_CC);
724 }
725
726 ret = mysqlnd_poll(new_r_array, new_e_array, &new_dont_poll_array, sec, usec, &desc_num);
727
728 mysqlnd_dont_poll_zval_array_from_mysqlnd_array(r_array != NULL ? new_dont_poll_array:NULL, r_array, dont_poll_array TSRMLS_CC);
729
730 if (r_array != NULL) {
731 mysqlnd_zval_array_from_mysqlnd_array(new_r_array, r_array TSRMLS_CC);
732 }
733 if (e_array != NULL) {
734 mysqlnd_zval_array_from_mysqlnd_array(new_e_array, e_array TSRMLS_CC);
735 }
736
737 if (new_dont_poll_array) {
738 efree(new_dont_poll_array);
739 }
740 if (new_r_array) {
741 efree(new_r_array);
742 }
743 if (new_e_array) {
744 efree(new_e_array);
745 }
746 if (ret == PASS) {
747 RETURN_LONG(desc_num);
748 } else {
749 RETURN_FALSE;
750 }
751 }
752 /* }}} */
753
754
755 /* {{{ proto int mysqli_reap_async_query(object link) U
756 Poll connections */
757 PHP_FUNCTION(mysqli_reap_async_query)
758 {
759 MY_MYSQL *mysql;
760 zval *mysql_link;
761 MYSQLI_RESOURCE *mysqli_resource;
762 MYSQL_RES *result;
763
764 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
765 return;
766 }
767
768 MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
769
770 if (FAIL == mysqlnd_reap_async_query(mysql->mysql)) {
771 RETURN_FALSE;
772 }
773
774 if (!mysql_field_count(mysql->mysql)) {
775 /* no result set - not a SELECT */
776 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
777 /* php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC); */
778 }
779 RETURN_TRUE;
780 }
781
782 switch (mysql->async_result_fetch_type) {
783 case MYSQLI_STORE_RESULT:
784 result = mysql_store_result(mysql->mysql);
785 break;
786 case MYSQLI_USE_RESULT:
787 result = mysql_use_result(mysql->mysql);
788 break;
789 }
790
791 if (!result) {
792 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC,
793 "%s", mysql_error(mysql->mysql));
794 RETURN_FALSE;
795 }
796
797 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
798 /* php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC); */
799 }
800
801 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
802 mysqli_resource->ptr = (void *)result;
803 mysqli_resource->status = MYSQLI_STATUS_VALID;
804 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
805 }
806 /* }}} */
807
808
809 /* {{{ proto object mysqli_stmt_get_result(object link) U
810 Buffer result set on client */
811 PHP_FUNCTION(mysqli_stmt_get_result)
812 {
813 MYSQL_RES *result;
814 MYSQLI_RESOURCE *mysqli_resource;
815 MY_STMT *stmt;
816 zval *mysql_stmt;
817
818 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
819 return;
820 }
821 MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
822
823 if (!(result = mysqlnd_stmt_get_result(stmt->stmt))) {
824 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
825 RETURN_FALSE;
826 }
827
828 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
829 mysqli_resource->ptr = (void *)result;
830 mysqli_resource->status = MYSQLI_STATUS_VALID;
831 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
832 }
833 /* }}} */
834 #endif
835
836
837 /* {{{ proto object mysqli_get_warnings(object link) */
838 PHP_FUNCTION(mysqli_get_warnings)
839 {
840 MY_MYSQL *mysql;
841 zval *mysql_link;
842 MYSQLI_RESOURCE *mysqli_resource;
843 MYSQLI_WARNING *w;
844
845 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
846 return;
847 }
848 MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
849
850 if (mysql_warning_count(mysql->mysql)) {
851 w = php_get_warnings(mysql->mysql TSRMLS_CC);
852 } else {
853 RETURN_FALSE;
854 }
855 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
856 mysqli_resource->ptr = mysqli_resource->info = (void *)w;
857 mysqli_resource->status = MYSQLI_STATUS_VALID;
858 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
859 }
860 /* }}} */
861
862 /* {{{ proto object mysqli_stmt_get_warnings(object link) */
863 PHP_FUNCTION(mysqli_stmt_get_warnings)
864 {
865 MY_STMT *stmt;
866 zval *stmt_link;
867 MYSQLI_RESOURCE *mysqli_resource;
868 MYSQLI_WARNING *w;
869
870 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &stmt_link, mysqli_stmt_class_entry) == FAILURE) {
871 return;
872 }
873 MYSQLI_FETCH_RESOURCE_STMT(stmt, &stmt_link, MYSQLI_STATUS_VALID);
874
875 if (mysqli_stmt_warning_count(stmt->stmt)) {
876 w = php_get_warnings(mysqli_stmt_get_connection(stmt->stmt) TSRMLS_CC);
877 } else {
878 RETURN_FALSE;
879 }
880 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
881 mysqli_resource->ptr = mysqli_resource->info = (void *)w;
882 mysqli_resource->status = MYSQLI_STATUS_VALID;
883 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
884 }
885 /* }}} */
886
887 #ifdef HAVE_MYSQLI_SET_CHARSET
888 /* {{{ proto bool mysqli_set_charset(object link, string csname)
889 sets client character set */
890 PHP_FUNCTION(mysqli_set_charset)
891 {
892 MY_MYSQL *mysql;
893 zval *mysql_link;
894 char *cs_name;
895 int csname_len;
896
897 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &csname_len) == FAILURE) {
898 return;
899 }
900 MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
901
902 if (mysql_set_character_set(mysql->mysql, cs_name)) {
903 RETURN_FALSE;
904 }
905 RETURN_TRUE;
906 }
907 /* }}} */
908 #endif
909
910 #ifdef HAVE_MYSQLI_GET_CHARSET
911 /* {{{ proto object mysqli_get_charset(object link) U
912 returns a character set object */
913 PHP_FUNCTION(mysqli_get_charset)
914 {
915 MY_MYSQL *mysql;
916 zval *mysql_link;
917 const char *name = NULL, *collation = NULL, *dir = NULL, *comment = NULL;
918 uint minlength, maxlength, number, state;
919 #if !defined(MYSQLI_USE_MYSQLND)
920 MY_CHARSET_INFO cs;
921 #else
922 const MYSQLND_CHARSET *cs;
923 #endif
924
925 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
926 return;
927 }
928 MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
929
930
931 #if !defined(MYSQLI_USE_MYSQLND)
932 mysql_get_character_set_info(mysql->mysql, &cs);
933 name = (char *)cs.csname;
934 collation = (char *)cs.name;
935 dir = (char *)cs.dir;
936 minlength = cs.mbminlen;
937 maxlength = cs.mbmaxlen;
938 number = cs.number;
939 state = cs.state;
940 comment = cs.comment;
941 #else
942 cs = mysql->mysql->charset;
943 if (!cs) {
944 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The connection has no charset associated");
945 RETURN_NULL();
946 }
947 name = cs->name;
948 collation = cs->collation;
949 minlength = cs->char_minlen;
950 maxlength = cs->char_maxlen;
951 number = cs->nr;
952 comment = cs->comment;
953 state = 1; /* all charsets are compiled in */
954 #endif
955 object_init(return_value);
956
957 add_property_string(return_value, "charset", (name) ? (char *)name : "", 1);
958 add_property_string(return_value, "collation",(collation) ? (char *)collation : "", 1);
959 add_property_string(return_value, "dir", (dir) ? (char *)dir : "", 1);
960 add_property_long(return_value, "min_length", minlength);
961 add_property_long(return_value, "max_length", maxlength);
962 add_property_long(return_value, "number", number);
963 add_property_long(return_value, "state", state);
964 add_property_string(return_value, "comment", (comment) ? (char *)comment : "", 1);
965 }
966 /* }}} */
967 #endif
968
969 /*
970 * Local variables:
971 * tab-width: 4
972 * c-basic-offset: 4
973 * End:
974 * vim600: noet sw=4 ts=4 fdm=marker
975 * vim<600: noet sw=4 ts=4
976 */
977