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