diff options
author | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:34:21 -0400 |
---|---|---|
committer | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:34:21 -0400 |
commit | 0e920280a2e04b110827bb766b9f29e3d581c4ee (patch) | |
tree | 8f2125f3d00fe3089e3b94adb06f04479ee15f2a /ext/mysql/php_mysql.c | |
download | php-0e920280a2e04b110827bb766b9f29e3d581c4ee.tar.gz |
Imported Upstream version 5.0.4upstream/5.0.4
Diffstat (limited to 'ext/mysql/php_mysql.c')
-rw-r--r-- | ext/mysql/php_mysql.c | 2521 |
1 files changed, 2521 insertions, 0 deletions
diff --git a/ext/mysql/php_mysql.c b/ext/mysql/php_mysql.c new file mode 100644 index 000000000..2b7173d4d --- /dev/null +++ b/ext/mysql/php_mysql.c @@ -0,0 +1,2521 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2004 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Zeev Suraski <zeev@zend.com> | + | Zak Greant <zak@mysql.com> | + | Georg Richter <georg@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: php_mysql.c,v 1.209.2.1 2005/02/22 14:59:30 iliaa Exp $ */ + +/* TODO: + * + * ? Safe mode implementation + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "php.h" +#include "php_globals.h" +#include "ext/standard/info.h" +#include "ext/standard/php_string.h" +#include "zend_exceptions.h" + +#if HAVE_MYSQL + +#ifdef PHP_WIN32 +# include <winsock2.h> +# define signal(a, b) NULL +#elif defined(NETWARE) +# include <sys/socket.h> +# define signal(a, b) NULL +#else +# if HAVE_SIGNAL_H +# include <signal.h> +# endif +# if HAVE_SYS_TYPES_H +# include <sys/types.h> +# endif +# include <netdb.h> +# include <netinet/in.h> +#endif + +#include <mysql.h> +#include "php_ini.h" +#include "php_mysql.h" + +/* True globals, no need for thread safety */ +static int le_result, le_link, le_plink; + +#ifdef HAVE_MYSQL_REAL_CONNECT +# ifdef HAVE_ERRMSG_H +# include <errmsg.h> +# endif +#endif + +#define SAFE_STRING(s) ((s)?(s):"") + +#if MYSQL_VERSION_ID > 32199 +# define mysql_row_length_type unsigned long +# define HAVE_MYSQL_ERRNO +#else +# define mysql_row_length_type unsigned int +# ifdef mysql_errno +# define HAVE_MYSQL_ERRNO +# endif +#endif + +#if MYSQL_VERSION_ID >= 32032 +#define HAVE_GETINFO_FUNCS +#endif + +#if MYSQL_VERSION_ID > 32133 || defined(FIELD_TYPE_TINY) +#define MYSQL_HAS_TINY +#endif + +#if MYSQL_VERSION_ID >= 32200 +#define MYSQL_HAS_YEAR +#endif + +#define MYSQL_ASSOC 1<<0 +#define MYSQL_NUM 1<<1 +#define MYSQL_BOTH (MYSQL_ASSOC|MYSQL_NUM) + +#define MYSQL_USE_RESULT 0 +#define MYSQL_STORE_RESULT 1 + +#if MYSQL_VERSION_ID < 32224 +#define PHP_MYSQL_VALID_RESULT(mysql) \ + (mysql_num_fields(mysql)>0) +#else +#define PHP_MYSQL_VALID_RESULT(mysql) \ + (mysql_field_count(mysql)>0) +#endif + +typedef struct _php_mysql_conn { + MYSQL conn; + int active_result_id; +} php_mysql_conn; + +/* {{{ mysql_functions[] + */ +function_entry mysql_functions[] = { + PHP_FE(mysql_connect, NULL) + PHP_FE(mysql_pconnect, NULL) + PHP_FE(mysql_close, NULL) + PHP_FE(mysql_select_db, NULL) +#ifndef NETWARE /* The below two functions not supported on NetWare */ +#if MYSQL_VERSION_ID < 40000 + PHP_FE(mysql_create_db, NULL) + PHP_FE(mysql_drop_db, NULL) +#endif +#endif /* NETWARE */ + PHP_FE(mysql_query, NULL) + PHP_FE(mysql_unbuffered_query, NULL) + PHP_FE(mysql_db_query, NULL) + PHP_FE(mysql_list_dbs, NULL) + PHP_FE(mysql_list_tables, NULL) + PHP_FE(mysql_list_fields, NULL) + PHP_FE(mysql_list_processes, NULL) + PHP_FE(mysql_error, NULL) +#ifdef HAVE_MYSQL_ERRNO + PHP_FE(mysql_errno, NULL) +#endif + PHP_FE(mysql_affected_rows, NULL) + PHP_FE(mysql_insert_id, NULL) + PHP_FE(mysql_result, NULL) + PHP_FE(mysql_num_rows, NULL) + PHP_FE(mysql_num_fields, NULL) + PHP_FE(mysql_fetch_row, NULL) + PHP_FE(mysql_fetch_array, NULL) + PHP_FE(mysql_fetch_assoc, NULL) + PHP_FE(mysql_fetch_object, NULL) + PHP_FE(mysql_data_seek, NULL) + PHP_FE(mysql_fetch_lengths, NULL) + PHP_FE(mysql_fetch_field, NULL) + PHP_FE(mysql_field_seek, NULL) + PHP_FE(mysql_free_result, NULL) + PHP_FE(mysql_field_name, NULL) + PHP_FE(mysql_field_table, NULL) + PHP_FE(mysql_field_len, NULL) + PHP_FE(mysql_field_type, NULL) + PHP_FE(mysql_field_flags, NULL) + PHP_FE(mysql_escape_string, NULL) + PHP_FE(mysql_real_escape_string, NULL) + PHP_FE(mysql_stat, NULL) + PHP_FE(mysql_thread_id, NULL) + PHP_FE(mysql_client_encoding, NULL) + PHP_FE(mysql_ping, NULL) +#ifdef HAVE_GETINFO_FUNCS + PHP_FE(mysql_get_client_info, NULL) + PHP_FE(mysql_get_host_info, NULL) + PHP_FE(mysql_get_proto_info, NULL) + PHP_FE(mysql_get_server_info, NULL) +#endif + + PHP_FE(mysql_info, NULL) + + /* for downwards compatability */ + PHP_FALIAS(mysql, mysql_db_query, NULL) + PHP_FALIAS(mysql_fieldname, mysql_field_name, NULL) + PHP_FALIAS(mysql_fieldtable, mysql_field_table, NULL) + PHP_FALIAS(mysql_fieldlen, mysql_field_len, NULL) + PHP_FALIAS(mysql_fieldtype, mysql_field_type, NULL) + PHP_FALIAS(mysql_fieldflags, mysql_field_flags, NULL) + PHP_FALIAS(mysql_selectdb, mysql_select_db, NULL) +#ifndef NETWARE /* The below two functions not supported on NetWare */ +#if MYSQL_VERSION_ID < 40000 + PHP_FALIAS(mysql_createdb, mysql_create_db, NULL) + PHP_FALIAS(mysql_dropdb, mysql_drop_db, NULL) +#endif +#endif /* NETWARE */ + PHP_FALIAS(mysql_freeresult, mysql_free_result, NULL) + PHP_FALIAS(mysql_numfields, mysql_num_fields, NULL) + PHP_FALIAS(mysql_numrows, mysql_num_rows, NULL) + PHP_FALIAS(mysql_listdbs, mysql_list_dbs, NULL) + PHP_FALIAS(mysql_listtables, mysql_list_tables, NULL) + PHP_FALIAS(mysql_listfields, mysql_list_fields, NULL) + PHP_FALIAS(mysql_db_name, mysql_result, NULL) + PHP_FALIAS(mysql_dbname, mysql_result, NULL) + PHP_FALIAS(mysql_tablename, mysql_result, NULL) + PHP_FALIAS(mysql_table_name, mysql_result, NULL) + {NULL, NULL, NULL} +}; +/* }}} */ + +/* {{{ mysql_module_entry + */ +zend_module_entry mysql_module_entry = { + STANDARD_MODULE_HEADER, + "mysql", + mysql_functions, + ZEND_MODULE_STARTUP_N(mysql), + PHP_MSHUTDOWN(mysql), + PHP_RINIT(mysql), + PHP_RSHUTDOWN(mysql), + PHP_MINFO(mysql), + NO_VERSION_YET, + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +ZEND_DECLARE_MODULE_GLOBALS(mysql) + +#ifdef COMPILE_DL_MYSQL +ZEND_GET_MODULE(mysql) +#endif + +void timeout(int sig); + +#define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } } + +#define PHPMY_UNBUFFERED_QUERY_CHECK() \ +{ \ + if (mysql->active_result_id) { \ + do { \ + int type; \ + MYSQL_RES *mysql_result; \ + \ + mysql_result = (MYSQL_RES *) zend_list_find(mysql->active_result_id, &type); \ + if (mysql_result && type==le_result) { \ + if (!mysql_eof(mysql_result)) { \ + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Function called without first fetching all rows from a previous unbuffered query"); \ + while (mysql_fetch_row(mysql_result)); \ + } \ + zend_list_delete(mysql->active_result_id); \ + mysql->active_result_id = 0; \ + } \ + } while(0); \ + } \ +} \ + +/* {{{ _free_mysql_result + * This wrapper is required since mysql_free_result() returns an integer, and + * thus, cannot be used directly + */ +static void _free_mysql_result(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + MYSQL_RES *mysql_result = (MYSQL_RES *)rsrc->ptr; + + mysql_free_result(mysql_result); + MySG(result_allocated)--; +} +/* }}} */ + +/* {{{ php_mysql_set_default_link + */ +static void php_mysql_set_default_link(int id TSRMLS_DC) +{ + if (MySG(default_link) != -1) { + zend_list_delete(MySG(default_link)); + } + MySG(default_link) = id; + zend_list_addref(id); +} +/* }}} */ + +/* {{{ php_mysql_select_db +*/ +static int php_mysql_select_db(php_mysql_conn *mysql, char *db TSRMLS_DC) +{ + PHPMY_UNBUFFERED_QUERY_CHECK(); + + if (mysql_select_db(&mysql->conn, db) != 0) { + return 0; + } else { + return 1; + } +} +/* }}} */ + +/* {{{ _close_mysql_link + */ +static void _close_mysql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + php_mysql_conn *link = (php_mysql_conn *)rsrc->ptr; + void (*handler) (int); + + handler = signal(SIGPIPE, SIG_IGN); + mysql_close(&link->conn); + signal(SIGPIPE, handler); + efree(link); + MySG(num_links)--; +} +/* }}} */ + +/* {{{ _close_mysql_plink + */ +static void _close_mysql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + php_mysql_conn *link = (php_mysql_conn *)rsrc->ptr; + void (*handler) (int); + + handler = signal(SIGPIPE, SIG_IGN); + mysql_close(&link->conn); + signal(SIGPIPE, handler); + + free(link); + MySG(num_persistent)--; + MySG(num_links)--; +} +/* }}} */ + +/* {{{ PHP_INI_MH + */ +static PHP_INI_MH(OnMySQLPort) +{ + if (new_value != NULL) { /* default port */ + MySG(default_port) = atoi(new_value); + } else { + MySG(default_port) = -1; + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_INI */ +PHP_INI_BEGIN() + STD_PHP_INI_BOOLEAN("mysql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_persistent, zend_mysql_globals, mysql_globals) + STD_PHP_INI_ENTRY_EX("mysql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_mysql_globals, mysql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("mysql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_mysql_globals, mysql_globals, display_link_numbers) + STD_PHP_INI_ENTRY("mysql.default_host", NULL, PHP_INI_ALL, OnUpdateString, default_host, zend_mysql_globals, mysql_globals) + STD_PHP_INI_ENTRY("mysql.default_user", NULL, PHP_INI_ALL, OnUpdateString, default_user, zend_mysql_globals, mysql_globals) + STD_PHP_INI_ENTRY("mysql.default_password", NULL, PHP_INI_ALL, OnUpdateString, default_password, zend_mysql_globals, mysql_globals) + PHP_INI_ENTRY("mysql.default_port", NULL, PHP_INI_ALL, OnMySQLPort) + STD_PHP_INI_ENTRY("mysql.default_socket", NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_socket, zend_mysql_globals, mysql_globals) + STD_PHP_INI_ENTRY("mysql.connect_timeout", "60", PHP_INI_ALL, OnUpdateLong, connect_timeout, zend_mysql_globals, mysql_globals) + STD_PHP_INI_BOOLEAN("mysql.trace_mode", "0", PHP_INI_ALL, OnUpdateLong, trace_mode, zend_mysql_globals, mysql_globals) +PHP_INI_END() +/* }}} */ + +/* {{{ php_mysql_init_globals + */ +static void php_mysql_init_globals(zend_mysql_globals *mysql_globals) +{ + mysql_globals->num_persistent = 0; + mysql_globals->default_socket = NULL; + mysql_globals->default_host = NULL; + mysql_globals->default_user = NULL; + mysql_globals->default_password = NULL; + mysql_globals->connect_errno = 0; + mysql_globals->connect_error = NULL; + mysql_globals->connect_timeout = 0; + mysql_globals->trace_mode = 0; + mysql_globals->result_allocated = 0; +} +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION + */ +ZEND_MODULE_STARTUP_D(mysql) +{ + ZEND_INIT_MODULE_GLOBALS(mysql, php_mysql_init_globals, NULL); + + REGISTER_INI_ENTRIES(); + le_result = zend_register_list_destructors_ex(_free_mysql_result, NULL, "mysql result", module_number); + le_link = zend_register_list_destructors_ex(_close_mysql_link, NULL, "mysql link", module_number); + le_plink = zend_register_list_destructors_ex(NULL, _close_mysql_plink, "mysql link persistent", module_number); + Z_TYPE(mysql_module_entry) = type; + + REGISTER_LONG_CONSTANT("MYSQL_ASSOC", MYSQL_ASSOC, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQL_NUM", MYSQL_NUM, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQL_BOTH", MYSQL_BOTH, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQL_CLIENT_COMPRESS", CLIENT_COMPRESS, CONST_CS | CONST_PERSISTENT); +#if MYSQL_VERSION_ID >= 40000 + REGISTER_LONG_CONSTANT("MYSQL_CLIENT_SSL", CLIENT_SSL, CONST_CS | CONST_PERSISTENT); +#endif + REGISTER_LONG_CONSTANT("MYSQL_CLIENT_INTERACTIVE", CLIENT_INTERACTIVE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQL_CLIENT_IGNORE_SPACE", CLIENT_IGNORE_SPACE, CONST_CS | CONST_PERSISTENT); + + +#ifdef ZTS +# if MYSQL_VERSION_ID >= 40000 + mysql_thread_init(); +# endif +#endif + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(mysql) +{ +#ifdef ZTS +# if MYSQL_VERSION_ID >= 40000 + mysql_thread_end(); +# endif +#endif + + UNREGISTER_INI_ENTRIES(); + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(mysql) +{ + MySG(default_link)=-1; + MySG(num_links) = MySG(num_persistent); + /* Reset connect error/errno on every request */ + MySG(connect_error) = NULL; + MySG(connect_errno) =0; + MySG(result_allocated) = 0; + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(mysql) +{ + if (MySG(trace_mode)) { + if (MySG(result_allocated)){ + php_error_docref("function.mysql-free-result" TSRMLS_CC, E_WARNING, "%lu result set(s) not freed. Use mysql_free_result to free result sets which were requested using mysql_query()", MySG(result_allocated)); + } + } + + if (MySG(connect_error)!=NULL) { + efree(MySG(connect_error)); + } + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(mysql) +{ + char buf[32]; + + php_info_print_table_start(); + php_info_print_table_header(2, "MySQL Support", "enabled"); + sprintf(buf, "%ld", MySG(num_persistent)); + php_info_print_table_row(2, "Active Persistent Links", buf); + sprintf(buf, "%ld", MySG(num_links)); + php_info_print_table_row(2, "Active Links", buf); + php_info_print_table_row(2, "Client API version", mysql_get_client_info()); +#if !defined (PHP_WIN32) && !defined (NETWARE) + php_info_print_table_row(2, "MYSQL_MODULE_TYPE", PHP_MYSQL_TYPE); + php_info_print_table_row(2, "MYSQL_SOCKET", MYSQL_UNIX_ADDR); + php_info_print_table_row(2, "MYSQL_INCLUDE", PHP_MYSQL_INCLUDE); + php_info_print_table_row(2, "MYSQL_LIBS", PHP_MYSQL_LIBS); +#endif + + php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); + +} +/* }}} */ + +/* {{{ php_mysql_do_connect + */ +#define MYSQL_DO_CONNECT_CLEANUP() \ + if (free_host) { \ + efree(host); \ + } + +#define MYSQL_DO_CONNECT_RETURN_FALSE() \ + MYSQL_DO_CONNECT_CLEANUP(); \ + RETURN_FALSE; + +static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) +{ + char *user=NULL, *passwd=NULL, *host_and_port=NULL, *socket=NULL, *tmp=NULL, *host=NULL; + char *hashed_details=NULL; + int hashed_details_length, port = MYSQL_PORT; + int client_flags = 0; + php_mysql_conn *mysql=NULL; +#if MYSQL_VERSION_ID <= 32230 + void (*handler) (int); +#endif + zval **z_host=NULL, **z_user=NULL, **z_passwd=NULL, **z_new_link=NULL, **z_client_flags=NULL; + zend_bool free_host=0, new_link=0; + long connect_timeout; + + + connect_timeout = MySG(connect_timeout); + + socket = MySG(default_socket); + + if (MySG(default_port) < 0) { +#if !defined(PHP_WIN32) && !defined(NETWARE) + struct servent *serv_ptr; + char *env; + + MySG(default_port) = MYSQL_PORT; + if ((serv_ptr = getservbyname("mysql", "tcp"))) { + MySG(default_port) = (uint) ntohs((ushort) serv_ptr->s_port); + } + if ((env = getenv("MYSQL_TCP_PORT"))) { + MySG(default_port) = (uint) atoi(env); + } +#else + MySG(default_port) = MYSQL_PORT; +#endif + } + + if (PG(sql_safe_mode)) { + if (ZEND_NUM_ARGS()>0) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "SQL safe mode in effect - ignoring host/user/password information"); + } + host_and_port=passwd=NULL; + user=php_get_current_user(); + hashed_details_length = strlen(user)+5+3; + hashed_details = (char *) emalloc(hashed_details_length+1); + sprintf(hashed_details, "mysql__%s_", user); + client_flags = CLIENT_INTERACTIVE; + } else { + host_and_port = MySG(default_host); + user = MySG(default_user); + passwd = MySG(default_password); + + switch(ZEND_NUM_ARGS()) { + case 0: /* defaults */ + break; + case 1: { + if (zend_get_parameters_ex(1, &z_host)==FAILURE) { + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + } + break; + case 2: { + if (zend_get_parameters_ex(2, &z_host, &z_user)==FAILURE) { + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + convert_to_string_ex(z_user); + user = Z_STRVAL_PP(z_user); + } + break; + case 3: { + if (zend_get_parameters_ex(3, &z_host, &z_user, &z_passwd) == FAILURE) { + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + convert_to_string_ex(z_user); + convert_to_string_ex(z_passwd); + user = Z_STRVAL_PP(z_user); + passwd = Z_STRVAL_PP(z_passwd); + } + break; + case 4: { + if (!persistent) { + if (zend_get_parameters_ex(4, &z_host, &z_user, &z_passwd, &z_new_link) == FAILURE) { + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + convert_to_string_ex(z_user); + convert_to_string_ex(z_passwd); + convert_to_boolean_ex(z_new_link); + user = Z_STRVAL_PP(z_user); + passwd = Z_STRVAL_PP(z_passwd); + new_link = Z_BVAL_PP(z_new_link); + } + else { + if (zend_get_parameters_ex(4, &z_host, &z_user, &z_passwd, &z_client_flags) == FAILURE) { + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + convert_to_string_ex(z_user); + convert_to_string_ex(z_passwd); + convert_to_long_ex(z_client_flags); + user = Z_STRVAL_PP(z_user); + passwd = Z_STRVAL_PP(z_passwd); + client_flags = Z_LVAL_PP(z_client_flags); + } + } + break; + case 5: { + if (zend_get_parameters_ex(5, &z_host, &z_user, &z_passwd, &z_new_link, &z_client_flags) == FAILURE) { + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + convert_to_string_ex(z_user); + convert_to_string_ex(z_passwd); + convert_to_boolean_ex(z_new_link); + convert_to_long_ex(z_client_flags); + user = Z_STRVAL_PP(z_user); + passwd = Z_STRVAL_PP(z_passwd); + new_link = Z_BVAL_PP(z_new_link); + client_flags = Z_LVAL_PP(z_client_flags); + } + break; + default: + WRONG_PARAM_COUNT; + break; + } + /* disable local infile option for open_basedir */ + if (PG(open_basedir) && strlen(PG(open_basedir)) && (client_flags & CLIENT_LOCAL_FILES)) { + client_flags ^= CLIENT_LOCAL_FILES; + } + + if (z_host) { + SEPARATE_ZVAL(z_host); /* We may modify z_host if it contains a port, separate */ + convert_to_string_ex(z_host); + host_and_port = Z_STRVAL_PP(z_host); + if (z_user) { + convert_to_string_ex(z_user); + user = Z_STRVAL_PP(z_user); + if (z_passwd) { + convert_to_string_ex(z_passwd); + passwd = Z_STRVAL_PP(z_passwd); + } + } + } + + hashed_details_length = sizeof("mysql___")-1 + strlen(SAFE_STRING(host_and_port))+strlen(SAFE_STRING(user))+strlen(SAFE_STRING(passwd)); + hashed_details = (char *) emalloc(hashed_details_length+1); + sprintf(hashed_details, "mysql_%s_%s_%s", SAFE_STRING(host_and_port), SAFE_STRING(user), SAFE_STRING(passwd)); + } + + /* We cannot use mysql_port anymore in windows, need to use + * mysql_real_connect() to set the port. + */ + if (host_and_port && (tmp=strchr(host_and_port, ':'))) { + host = estrndup(host_and_port, tmp-host_and_port); + free_host = 1; + tmp++; + if (tmp[0] != '/') { + port = atoi(tmp); + if ((tmp=strchr(tmp, ':'))) { + tmp++; + socket=tmp; + } + } else { + socket = tmp; + } + } else { + host = host_and_port; + port = MySG(default_port); + } + +#if MYSQL_VERSION_ID < 32200 + mysql_port = port; +#endif + + if (!MySG(allow_persistent)) { + persistent=0; + } + if (persistent) { + list_entry *le; + + /* try to find if we already have this link in our persistent list */ + if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) { /* we don't */ + list_entry new_le; + + if (MySG(max_links)!=-1 && MySG(num_links)>=MySG(max_links)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MySG(num_links)); + efree(hashed_details); + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + if (MySG(max_persistent)!=-1 && MySG(num_persistent)>=MySG(max_persistent)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)", MySG(num_persistent)); + efree(hashed_details); + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + /* create the link */ + mysql = (php_mysql_conn *) malloc(sizeof(php_mysql_conn)); + mysql->active_result_id = 0; +#if MYSQL_VERSION_ID > 32199 /* this lets us set the port number */ + mysql_init(&mysql->conn); + + if (connect_timeout != -1) + mysql_options(&mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout); + + if (mysql_real_connect(&mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL) { +#else + if (mysql_connect(&mysql->conn, host, user, passwd)==NULL) { +#endif + /* Populate connect error globals so that the error functions can read them */ + if (MySG(connect_error)!=NULL) efree(MySG(connect_error)); + MySG(connect_error)=estrdup(mysql_error(&mysql->conn)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", MySG(connect_error)); +#if defined(HAVE_MYSQL_ERRNO) + MySG(connect_errno)=mysql_errno(&mysql->conn); +#endif + free(mysql); + efree(hashed_details); + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + + /* hash it up */ + Z_TYPE(new_le) = le_plink; + new_le.ptr = mysql; + if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry), NULL)==FAILURE) { + free(mysql); + efree(hashed_details); + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + MySG(num_persistent)++; + MySG(num_links)++; + } else { /* The link is in our list of persistent connections */ + if (Z_TYPE_P(le) != le_plink) { + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + /* ensure that the link did not die */ +#if MYSQL_VERSION_ID > 32230 /* Use mysql_ping to ensure link is alive (and to reconnect if needed) */ + if (mysql_ping(le->ptr)) { +#else /* Use mysql_stat() to check if server is alive */ + handler=signal(SIGPIPE, SIG_IGN); +#if defined(HAVE_MYSQL_ERRNO) && defined(CR_SERVER_GONE_ERROR) + mysql_stat(le->ptr); + if (mysql_errno(&((php_mysql_conn *) le->ptr)->conn) == CR_SERVER_GONE_ERROR) { +#else + if (!strcasecmp(mysql_stat(le->ptr), "mysql server has gone away")) { /* the link died */ +#endif + signal(SIGPIPE, handler); +#endif /* end mysql_ping */ +#if MYSQL_VERSION_ID > 32199 /* this lets us set the port number */ + if (mysql_real_connect(le->ptr, host, user, passwd, NULL, port, socket, client_flags)==NULL) { +#else + if (mysql_connect(le->ptr, host, user, passwd)==NULL) { +#endif + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect"); + zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1); + efree(hashed_details); + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + } +#if MYSQL_VERSION_ID < 32231 + signal(SIGPIPE, handler); +#endif + + mysql = (php_mysql_conn *) le->ptr; + } + ZEND_REGISTER_RESOURCE(return_value, mysql, le_plink); + } else { /* non persistent */ + list_entry *index_ptr, new_index_ptr; + + /* first we check the hash for the hashed_details key. if it exists, + * it should point us to the right offset where the actual mysql link sits. + * if it doesn't, open a new mysql link, add it to the resource list, + * and add a pointer to it with hashed_details as the key. + */ + if (!new_link && zend_hash_find(&EG(regular_list), hashed_details, hashed_details_length+1,(void **) &index_ptr)==SUCCESS) { + int type; + long link; + void *ptr; + + if (Z_TYPE_P(index_ptr) != le_index_ptr) { + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + link = (long) index_ptr->ptr; + ptr = zend_list_find(link,&type); /* check if the link is still there */ + if (ptr && (type==le_link || type==le_plink)) { + zend_list_addref(link); + Z_LVAL_P(return_value) = link; + php_mysql_set_default_link(link TSRMLS_CC); + Z_TYPE_P(return_value) = IS_RESOURCE; + efree(hashed_details); + MYSQL_DO_CONNECT_CLEANUP(); + return; + } else { + zend_hash_del(&EG(regular_list), hashed_details, hashed_details_length+1); + } + } + if (MySG(max_links)!=-1 && MySG(num_links)>=MySG(max_links)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MySG(num_links)); + efree(hashed_details); + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + + mysql = (php_mysql_conn *) emalloc(sizeof(php_mysql_conn)); + mysql->active_result_id = 0; +#if MYSQL_VERSION_ID > 32199 /* this lets us set the port number */ + mysql_init(&mysql->conn); + + if (connect_timeout != -1) + mysql_options(&mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout); + + if (mysql_real_connect(&mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL) { +#else + if (mysql_connect(&mysql->conn, host, user, passwd)==NULL) { +#endif + /* Populate connect error globals so that the error functions can read them */ + if (MySG(connect_error)!=NULL) efree(MySG(connect_error)); + MySG(connect_error)=estrdup(mysql_error(&mysql->conn)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", MySG(connect_error)); +#if defined(HAVE_MYSQL_ERRNO) + MySG(connect_errno)=mysql_errno(&mysql->conn); +#endif + efree(hashed_details); + efree(mysql); + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + + /* add it to the list */ + ZEND_REGISTER_RESOURCE(return_value, mysql, le_link); + + /* add it to the hash */ + new_index_ptr.ptr = (void *) Z_LVAL_P(return_value); + Z_TYPE(new_index_ptr) = le_index_ptr; + if (zend_hash_update(&EG(regular_list), hashed_details, hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) { + efree(hashed_details); + MYSQL_DO_CONNECT_RETURN_FALSE(); + } + MySG(num_links)++; + } + + efree(hashed_details); + php_mysql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC); + MYSQL_DO_CONNECT_CLEANUP(); +} +/* }}} */ + +/* {{{ php_mysql_get_default_link + */ +static int php_mysql_get_default_link(INTERNAL_FUNCTION_PARAMETERS) +{ + if (MySG(default_link)==-1) { /* no link opened yet, implicitly open one */ + ht = 0; + php_mysql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + } + return MySG(default_link); +} +/* }}} */ + +/* {{{ proto resource mysql_connect([string hostname[:port][:/path/to/socket] [, string username [, string password [, bool new [, int flags]]]]]) + Opens a connection to a MySQL Server */ +PHP_FUNCTION(mysql_connect) +{ + php_mysql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto resource mysql_pconnect([string hostname[:port][:/path/to/socket] [, string username [, string password [, int flags]]]]) + Opens a persistent connection to a MySQL Server */ +PHP_FUNCTION(mysql_pconnect) +{ + php_mysql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + +/* {{{ proto bool mysql_close([int link_identifier]) + Close a MySQL connection */ +PHP_FUNCTION(mysql_close) +{ + zval **mysql_link=NULL; + int id; + php_mysql_conn *mysql; + + switch (ZEND_NUM_ARGS()) { + case 0: + id = MySG(default_link); + break; + case 1: + if (zend_get_parameters_ex(1, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + if (id==-1) { /* explicit resource number */ + PHPMY_UNBUFFERED_QUERY_CHECK(); + zend_list_delete(Z_RESVAL_PP(mysql_link)); + } + + if (id!=-1 + || (mysql_link && Z_RESVAL_PP(mysql_link)==MySG(default_link))) { + PHPMY_UNBUFFERED_QUERY_CHECK(); + zend_list_delete(MySG(default_link)); + MySG(default_link) = -1; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool mysql_select_db(string database_name [, int link_identifier]) + Selects a MySQL database */ +PHP_FUNCTION(mysql_select_db) +{ + zval **db, **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &db)==FAILURE) { + RETURN_FALSE; + } + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 2: + if (zend_get_parameters_ex(2, &db, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + convert_to_string_ex(db); + + if (php_mysql_select_db(mysql, Z_STRVAL_PP(db) TSRMLS_CC)) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} */ + +#ifdef HAVE_GETINFO_FUNCS + +/* {{{ proto string mysql_get_client_info(void) + Returns a string that represents the client library version */ +PHP_FUNCTION(mysql_get_client_info) +{ + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT; + } + + RETURN_STRING((char *)mysql_get_client_info(),1); +} +/* }}} */ + +/* {{{ proto string mysql_get_host_info([int link_identifier]) + Returns a string describing the type of connection in use, including the server host name */ +PHP_FUNCTION(mysql_get_host_info) +{ + zval **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1,&mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + RETURN_STRING((char *)mysql_get_host_info(&mysql->conn),1); +} +/* }}} */ + +/* {{{ proto int mysql_get_proto_info([int link_identifier]) + Returns the protocol version used by current connection */ +PHP_FUNCTION(mysql_get_proto_info) +{ + zval **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1,&mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + RETURN_LONG(mysql_get_proto_info(&mysql->conn)); +} +/* }}} */ + +/* {{{ proto string mysql_get_server_info([int link_identifier]) + Returns a string that represents the server version number */ +PHP_FUNCTION(mysql_get_server_info) +{ + zval **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1,&mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + RETURN_STRING((char *)mysql_get_server_info(&mysql->conn),1); +} +/* }}} */ + +/* {{{ proto string mysql_info([int link_identifier]) + Returns a string containing information about the most recent query */ +PHP_FUNCTION(mysql_info) +{ + zval *mysql_link; + int id = -1; + char *str; + php_mysql_conn *mysql; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) { + return; + } + + if (ZEND_NUM_ARGS() == 0) { + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink); + + if ((str = (char *)mysql_info(&mysql->conn))) { + RETURN_STRING(str,1); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto int mysql_thread_id([int link_identifier]) + Returns the thread id of current connection */ +PHP_FUNCTION(mysql_thread_id) +{ + zval *mysql_link = NULL; + int id = -1; + php_mysql_conn *mysql; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) { + return; + } + + if (ZEND_NUM_ARGS() == 0) { + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + } + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink); + + RETURN_LONG(mysql_thread_id(&mysql->conn)); +} +/* }}} */ + +/* {{{ proto string mysql_stat([int link_identifier]) + Returns a string containing status information */ +PHP_FUNCTION(mysql_stat) +{ + zval *mysql_link = NULL; + int id = -1; + php_mysql_conn *mysql; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) { + return; + } + + if (ZEND_NUM_ARGS() == 0) { + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + } + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink); + + PHPMY_UNBUFFERED_QUERY_CHECK(); + + RETURN_STRING((char *)mysql_stat(&mysql->conn), 1); +} +/* }}} */ + +/* {{{ proto string mysql_client_encoding([int link_identifier]) + Returns the default character set for the current connection */ +PHP_FUNCTION(mysql_client_encoding) +{ + zval *mysql_link = NULL; + int id = -1; + php_mysql_conn *mysql; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) { + return; + } + + if (ZEND_NUM_ARGS() == 0) { + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink); + + RETURN_STRING((char *)mysql_character_set_name(&mysql->conn), 1); +} +/* }}} */ +#endif + +#ifndef NETWARE /* The below two functions not supported on NetWare */ +#if MYSQL_VERSION_ID < 40000 +/* {{{ proto bool mysql_create_db(string database_name [, int link_identifier]) + Create a MySQL database */ +PHP_FUNCTION(mysql_create_db) +{ + zval **db, **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &db)==FAILURE) { + RETURN_FALSE; + } + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 2: + if (zend_get_parameters_ex(2, &db, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated, please use mysql_query() to issue a SQL CREATE DATABASE statement instead."); + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + PHPMY_UNBUFFERED_QUERY_CHECK(); + + convert_to_string_ex(db); + + if (mysql_create_db(&mysql->conn, Z_STRVAL_PP(db))==0) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool mysql_drop_db(string database_name [, int link_identifier]) + Drops (delete) a MySQL database */ +PHP_FUNCTION(mysql_drop_db) +{ + zval **db, **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &db)==FAILURE) { + RETURN_FALSE; + } + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 2: + if (zend_get_parameters_ex(2, &db, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated, please use mysql_query() to issue a SQL DROP DATABASE statement instead."); + + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + convert_to_string_ex(db); + + if (mysql_drop_db(&mysql->conn, Z_STRVAL_PP(db))==0) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} */ +#endif +#endif /* NETWARE */ + +/* {{{ php_mysql_do_query_general + */ +static void php_mysql_do_query_general(zval **query, zval **mysql_link, int link_id, zval **db, int use_store, zval *return_value TSRMLS_DC) +{ + php_mysql_conn *mysql; + MYSQL_RES *mysql_result; + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink); + + if (db) { + convert_to_string_ex(db); + if (!php_mysql_select_db(mysql, Z_STRVAL_PP(db) TSRMLS_CC)) { + RETURN_FALSE; + } + } + + PHPMY_UNBUFFERED_QUERY_CHECK(); + + convert_to_string_ex(query); + + /* check explain */ + if (MySG(trace_mode)) { + if (!strncasecmp("select", Z_STRVAL_PP(query), 6)){ + MYSQL_ROW row; + + char *newquery = (char *)emalloc(Z_STRLEN_PP(query) + 10); + sprintf ((char *)newquery, "EXPLAIN %s", Z_STRVAL_PP(query)); + mysql_real_query(&mysql->conn, newquery, strlen(newquery)); + efree (newquery); + if (mysql_errno(&mysql->conn)) { + php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn)); + RETURN_FALSE; + } + else { + mysql_result = mysql_use_result(&mysql->conn); + while ((row = mysql_fetch_row(mysql_result))) { + if (!strcmp("ALL", row[1])) { + php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "Your query requires a full tablescan (table %s, %s rows affected). Use EXPLAIN to optimize your query.", row[0], row[6]); + } else if (!strcmp("INDEX", row[1])) { + php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "Your query requires a full indexscan (table %s, %s rows affected). Use EXPLAIN to optimize your query.", row[0], row[6]); + } + } + mysql_free_result(mysql_result); + } + } + } /* end explain */ + + /* mysql_query is binary unsafe, use mysql_real_query */ +#if MYSQL_VERSION_ID > 32199 + if (mysql_real_query(&mysql->conn, Z_STRVAL_PP(query), Z_STRLEN_PP(query))!=0) { + /* check possible error */ + if (MySG(trace_mode)){ + if (mysql_errno(&mysql->conn)){ + php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn)); + } + } + RETURN_FALSE; + } +#else + if (mysql_query(&mysql->conn, Z_STRVAL_PP(query))!=0) { + /* check possible error */ + if (MySG(trace_mode)){ + if (mysql_errno(&mysql->conn)){ + php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn)); + } + } + RETURN_FALSE; + } +#endif + if(use_store == MYSQL_USE_RESULT) { + mysql_result=mysql_use_result(&mysql->conn); + } else { + mysql_result=mysql_store_result(&mysql->conn); + } + if (!mysql_result) { + if (PHP_MYSQL_VALID_RESULT(&mysql->conn)) { /* query should have returned rows */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save result set"); + RETURN_FALSE; + } else { + RETURN_TRUE; + } + } + MySG(result_allocated)++; + ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result); + if (use_store == MYSQL_USE_RESULT) { + mysql->active_result_id = Z_LVAL_P(return_value); + } +} +/* }}} */ + +/* {{{ php_mysql_do_query + */ +static void php_mysql_do_query(INTERNAL_FUNCTION_PARAMETERS, int use_store) +{ + zval **query, **mysql_link; + int id; + + switch(ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &query)==FAILURE) { + RETURN_FALSE; + } + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 2: + if (zend_get_parameters_ex(2, &query, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + php_mysql_do_query_general(query, mysql_link, id, NULL, use_store, return_value TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto resource mysql_query(string query [, int link_identifier]) + Sends an SQL query to MySQL */ +PHP_FUNCTION(mysql_query) +{ + php_mysql_do_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_STORE_RESULT); +} +/* }}} */ + + +/* {{{ proto resource mysql_unbuffered_query(string query [, int link_identifier]) + Sends an SQL query to MySQL, without fetching and buffering the result rows */ +PHP_FUNCTION(mysql_unbuffered_query) +{ + php_mysql_do_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_USE_RESULT); +} +/* }}} */ + + +/* {{{ proto resource mysql_db_query(string database_name, string query [, int link_identifier]) + Sends an SQL query to MySQL */ +PHP_FUNCTION(mysql_db_query) +{ + zval **db, **query, **mysql_link; + int id; + + switch(ZEND_NUM_ARGS()) { + case 2: + if (zend_get_parameters_ex(2, &db, &query)==FAILURE) { + RETURN_FALSE; + } + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 3: + if (zend_get_parameters_ex(3, &db, &query, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + if (MySG(trace_mode) || !strcasecmp(get_active_function_name(TSRMLS_C), "mysql")) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated; use mysql_query() instead."); + } + + php_mysql_do_query_general(query, mysql_link, id, db, MYSQL_STORE_RESULT, return_value TSRMLS_CC); +} +/* }}} */ + + +/* {{{ proto resource mysql_list_dbs([int link_identifier]) + List databases available on a MySQL server */ +PHP_FUNCTION(mysql_list_dbs) +{ + zval **mysql_link; + int id; + php_mysql_conn *mysql; + MYSQL_RES *mysql_result; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + PHPMY_UNBUFFERED_QUERY_CHECK(); + + if ((mysql_result=mysql_list_dbs(&mysql->conn, NULL))==NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result"); + RETURN_FALSE; + } + ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result); +} +/* }}} */ + + +/* {{{ proto resource mysql_list_tables(string database_name [, int link_identifier]) + List tables in a MySQL database */ +PHP_FUNCTION(mysql_list_tables) +{ + zval **db, **mysql_link; + int id; + php_mysql_conn *mysql; + MYSQL_RES *mysql_result; + + switch(ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &db)==FAILURE) { + RETURN_FALSE; + } + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 2: + if (zend_get_parameters_ex(2, &db, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + php_error_docref(NULL TSRMLS_CC, E_STRICT, "mysql_list_tables() is deprecated"); + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + convert_to_string_ex(db); + if (!php_mysql_select_db(mysql, Z_STRVAL_PP(db) TSRMLS_CC)) { + RETURN_FALSE; + } + + PHPMY_UNBUFFERED_QUERY_CHECK(); + + if ((mysql_result=mysql_list_tables(&mysql->conn, NULL))==NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result"); + RETURN_FALSE; + } + ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result); +} +/* }}} */ + + +/* {{{ proto resource mysql_list_fields(string database_name, string table_name [, int link_identifier]) + List MySQL result fields */ +PHP_FUNCTION(mysql_list_fields) +{ + zval **db, **table, **mysql_link; + int id; + php_mysql_conn *mysql; + MYSQL_RES *mysql_result; + + switch(ZEND_NUM_ARGS()) { + case 2: + if (zend_get_parameters_ex(2, &db, &table)==FAILURE) { + RETURN_FALSE; + } + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + break; + case 3: + if (zend_get_parameters_ex(3, &db, &table, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + convert_to_string_ex(db); + if (!php_mysql_select_db(mysql, Z_STRVAL_PP(db) TSRMLS_CC)) { + RETURN_FALSE; + } + + PHPMY_UNBUFFERED_QUERY_CHECK(); + + convert_to_string_ex(table); + if ((mysql_result=mysql_list_fields(&mysql->conn, Z_STRVAL_PP(table), NULL))==NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result"); + RETURN_FALSE; + } + ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result); +} +/* }}} */ + +/* {{{ proto resource mysql_list_processes([int link_identifier]) + Returns a result set describing the current server threads */ +PHP_FUNCTION(mysql_list_processes) +{ + zval *mysql_link = NULL; + int id = -1; + php_mysql_conn *mysql; + MYSQL_RES *mysql_result; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &mysql_link) == FAILURE) { + return; + } + + if (ZEND_NUM_ARGS() == 0) { + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink); + + PHPMY_UNBUFFERED_QUERY_CHECK(); + + mysql_result = mysql_list_processes(&mysql->conn); + if (mysql_result == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result"); + RETURN_FALSE; + } + + ZEND_REGISTER_RESOURCE(return_value, mysql_result, le_result); +} +/* }}} */ + + +/* {{{ proto string mysql_error([int link_identifier]) + Returns the text of the error message from previous MySQL operation */ +PHP_FUNCTION(mysql_error) +{ + zval **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = MySG(default_link); + if (id==-1) { + if (MySG(connect_error)!=NULL){ + RETURN_STRING(MySG(connect_error),1); + } else { + RETURN_FALSE; + } + } + break; + case 1: + if (zend_get_parameters_ex(1, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + RETURN_STRING((char *)mysql_error(&mysql->conn), 1); +} +/* }}} */ + + +/* {{{ proto int mysql_errno([int link_identifier]) + Returns the number of the error message from previous MySQL operation */ +#ifdef HAVE_MYSQL_ERRNO +PHP_FUNCTION(mysql_errno) +{ + zval **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = MySG(default_link); + if (id==-1) { + if (MySG(connect_errno)!=0){ + RETURN_LONG(MySG(connect_errno)); + } else { + RETURN_FALSE; + } + } + break; + case 1: + if (zend_get_parameters_ex(1, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + RETURN_LONG(mysql_errno(&mysql->conn)); +} +#endif +/* }}} */ + + +/* {{{ proto int mysql_affected_rows([int link_identifier]) + Gets number of affected rows in previous MySQL operation */ +PHP_FUNCTION(mysql_affected_rows) +{ + zval **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = MySG(default_link); + CHECK_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + /* conversion from int64 to long happing here */ + Z_LVAL_P(return_value) = (long) mysql_affected_rows(&mysql->conn); + Z_TYPE_P(return_value) = IS_LONG; +} +/* }}} */ + + +/* {{{ proto string mysql_escape_string(string to_be_escaped) + Escape string for mysql query */ +PHP_FUNCTION(mysql_escape_string) +{ + zval **str; + + if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &str) == FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } + convert_to_string_ex(str); + /* assume worst case situation, which is 2x of the original string. + * we don't realloc() down to the real size since it'd most probably not + * be worth it + */ + + Z_STRVAL_P(return_value) = (char *) safe_emalloc(Z_STRLEN_PP(str), 2, 1); + Z_STRLEN_P(return_value) = mysql_escape_string(Z_STRVAL_P(return_value), Z_STRVAL_PP(str), Z_STRLEN_PP(str)); + Z_TYPE_P(return_value) = IS_STRING; + + if (MySG(trace_mode)){ + php_error_docref("function.mysql-real-escape-string" TSRMLS_CC, E_WARNING, "This function is deprecated; use mysql_real_escape_string() instead."); + } + +} +/* }}} */ + +/* {{{ proto string mysql_real_escape_string(string to_be_escaped [, int link_identifier]) + Escape special characters in a string for use in a SQL statement, taking into account the current charset of the connection */ +PHP_FUNCTION(mysql_real_escape_string) +{ + zval *mysql_link = NULL; + char *str; + char *new_str; + int id = -1, str_len, new_str_len; + php_mysql_conn *mysql; + + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &str, &str_len, &mysql_link) == FAILURE) { + return; + } + + if (ZEND_NUM_ARGS() == 1) { + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink); + + new_str = safe_emalloc(str_len, 2, 1); + new_str_len = mysql_real_escape_string(&mysql->conn, new_str, str, str_len); + new_str = erealloc(new_str, new_str_len + 1); + + RETURN_STRINGL(new_str, new_str_len, 0); +} +/* }}} */ + +/* {{{ proto int mysql_insert_id([int link_identifier]) + Gets the ID generated from the previous INSERT operation */ +PHP_FUNCTION(mysql_insert_id) +{ + zval **mysql_link; + int id; + php_mysql_conn *mysql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = MySG(default_link); + CHECK_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1, &mysql_link)==FAILURE) { + RETURN_FALSE; + } + id = -1; + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink); + + /* conversion from int64 to long happing here */ + Z_LVAL_P(return_value) = (long) mysql_insert_id(&mysql->conn); + Z_TYPE_P(return_value) = IS_LONG; +} +/* }}} */ + + +/* {{{ proto mixed mysql_result(resource result, int row [, mixed field]) + Gets result data */ +PHP_FUNCTION(mysql_result) +{ + zval **result, **row, **field=NULL; + MYSQL_RES *mysql_result; + MYSQL_ROW sql_row; + mysql_row_length_type *sql_row_lengths; + int field_offset=0; + + switch (ZEND_NUM_ARGS()) { + case 2: + if (zend_get_parameters_ex(2, &result, &row)==FAILURE) { + RETURN_FALSE; + } + break; + case 3: + if (zend_get_parameters_ex(3, &result, &row, &field)==FAILURE) { + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + convert_to_long_ex(row); + if (Z_LVAL_PP(row)<0 || Z_LVAL_PP(row)>=(int)mysql_num_rows(mysql_result)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on MySQL result index %ld", Z_LVAL_PP(row), Z_LVAL_PP(result)); + RETURN_FALSE; + } + mysql_data_seek(mysql_result, Z_LVAL_PP(row)); + if ((sql_row=mysql_fetch_row(mysql_result))==NULL + || (sql_row_lengths=mysql_fetch_lengths(mysql_result))==NULL) { /* shouldn't happen? */ + RETURN_FALSE; + } + + if (field) { + switch(Z_TYPE_PP(field)) { + case IS_STRING: { + int i=0; + MYSQL_FIELD *tmp_field; + char *table_name, *field_name, *tmp; + + if ((tmp=strchr(Z_STRVAL_PP(field), '.'))) { + table_name = estrndup(Z_STRVAL_PP(field), tmp-Z_STRVAL_PP(field)); + field_name = estrdup(tmp+1); + } else { + table_name = NULL; + field_name = estrndup(Z_STRVAL_PP(field),Z_STRLEN_PP(field)); + } + mysql_field_seek(mysql_result, 0); + while ((tmp_field=mysql_fetch_field(mysql_result))) { + if ((!table_name || !strcasecmp(tmp_field->table, table_name)) && !strcasecmp(tmp_field->name, field_name)) { + field_offset = i; + break; + } + i++; + } + if (!tmp_field) { /* no match found */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s%s not found in MySQL result index %ld", + (table_name?table_name:""), (table_name?".":""), field_name, Z_LVAL_PP(result)); + efree(field_name); + if (table_name) { + efree(table_name); + } + RETURN_FALSE; + } + efree(field_name); + if (table_name) { + efree(table_name); + } + } + break; + default: + convert_to_long_ex(field); + field_offset = Z_LVAL_PP(field); + if (field_offset<0 || field_offset>=(int)mysql_num_fields(mysql_result)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified"); + RETURN_FALSE; + } + break; + } + } + + if (sql_row[field_offset]) { + Z_TYPE_P(return_value) = IS_STRING; + + if (PG(magic_quotes_runtime)) { + Z_STRVAL_P(return_value) = php_addslashes(sql_row[field_offset], sql_row_lengths[field_offset],&Z_STRLEN_P(return_value), 0 TSRMLS_CC); + } else { + Z_STRLEN_P(return_value) = sql_row_lengths[field_offset]; + Z_STRVAL_P(return_value) = (char *) safe_estrndup(sql_row[field_offset], Z_STRLEN_P(return_value)); + } + } else { + Z_TYPE_P(return_value) = IS_NULL; + } +} +/* }}} */ + + +/* {{{ proto int mysql_num_rows(resource result) + Gets number of rows in a result */ +PHP_FUNCTION(mysql_num_rows) +{ + zval **result; + MYSQL_RES *mysql_result; + + if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &result)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + /* conversion from int64 to long happing here */ + Z_LVAL_P(return_value) = (long) mysql_num_rows(mysql_result); + Z_TYPE_P(return_value) = IS_LONG; +} +/* }}} */ + +/* {{{ proto int mysql_num_fields(resource result) + Gets number of fields in a result */ +PHP_FUNCTION(mysql_num_fields) +{ + zval **result; + MYSQL_RES *mysql_result; + + if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &result)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + Z_LVAL_P(return_value) = mysql_num_fields(mysql_result); + Z_TYPE_P(return_value) = IS_LONG; +} +/* }}} */ + +/* {{{ php_mysql_fetch_hash + */ +static void php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type, int expected_args, int into_object) +{ + zval **result, **arg2; + MYSQL_RES *mysql_result; + MYSQL_ROW mysql_row; + MYSQL_FIELD *mysql_field; + mysql_row_length_type *mysql_row_lengths; + int i; + zval *res, *ctor_params = NULL; + zend_class_entry *ce; + + if (into_object) { + char *class_name; + int class_name_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|sz", &res, &class_name, &class_name_len, &ctor_params) == FAILURE) { + return; + } + result = &res; + if (ZEND_NUM_ARGS() < 2) { + ce = zend_standard_class_def; + } else { + ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + } + if (!ce) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name); + return; + } + result_type = MYSQL_ASSOC; + } else { + if (ZEND_NUM_ARGS() > expected_args) { + WRONG_PARAM_COUNT; + } + + switch (ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &result)==FAILURE) { + RETURN_FALSE; + } + if (!result_type) { + result_type = MYSQL_BOTH; + } + break; + case 2: + if (zend_get_parameters_ex(2, &result, &arg2)==FAILURE) { + RETURN_FALSE; + } + convert_to_long_ex(arg2); + result_type = Z_LVAL_PP(arg2); + break; + default: + WRONG_PARAM_COUNT; + break; + } + } + + if ((result_type & MYSQL_BOTH) == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQL_NUM, MYSQL_ASSOC or MYSQL_BOTH."); + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + if ((mysql_row=mysql_fetch_row(mysql_result))==NULL + || (mysql_row_lengths=mysql_fetch_lengths(mysql_result))==NULL) { + RETURN_FALSE; + } + + array_init(return_value); + + mysql_field_seek(mysql_result, 0); + for (mysql_field=mysql_fetch_field(mysql_result), i=0; mysql_field; mysql_field=mysql_fetch_field(mysql_result), i++) { + if (mysql_row[i]) { + zval *data; + + MAKE_STD_ZVAL(data); + + if (PG(magic_quotes_runtime)) { + Z_TYPE_P(data) = IS_STRING; + Z_STRVAL_P(data) = php_addslashes(mysql_row[i], mysql_row_lengths[i], &Z_STRLEN_P(data), 0 TSRMLS_CC); + } else { + ZVAL_STRINGL(data, mysql_row[i], mysql_row_lengths[i], 1); + } + + if (result_type & MYSQL_NUM) { + add_index_zval(return_value, i, data); + } + if (result_type & MYSQL_ASSOC) { + if (result_type & MYSQL_NUM) { + ZVAL_ADDREF(data); + } + add_assoc_zval(return_value, mysql_field->name, data); + } + } else { + /* NULL value. */ + if (result_type & MYSQL_NUM) { + add_index_null(return_value, i); + } + + if (result_type & MYSQL_ASSOC) { + add_assoc_null(return_value, mysql_field->name); + } + } + } + + if (into_object) { + zval dataset = *return_value; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + zval *retval_ptr; + + object_and_properties_init(return_value, ce, NULL); + zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC); + + if (ce->constructor) { + fci.size = sizeof(fci); + fci.function_table = &ce->function_table; + fci.function_name = NULL; + fci.symbol_table = NULL; + fci.object_pp = &return_value; + fci.retval_ptr_ptr = &retval_ptr; + if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) { + if (Z_TYPE_P(ctor_params) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(ctor_params); + Bucket *p; + + fci.param_count = 0; + fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0); + p = ht->pListHead; + while (p != NULL) { + fci.params[fci.param_count++] = (zval**)p->pData; + p = p->pListNext; + } + } else { + /* Two problems why we throw exceptions here: PHP is typeless + * and hence passing one argument that's not an array could be + * by mistake and the other way round is possible, too. The + * single value is an array. Also we'd have to make that one + * argument passed by reference. + */ + zend_throw_exception(zend_exception_get_default(), "Parameter ctor_params must be an array", 0 TSRMLS_CC); + return; + } + } else { + fci.param_count = 0; + fci.params = NULL; + } + fci.no_separation = 1; + + fcc.initialized = 1; + fcc.function_handler = ce->constructor; + fcc.calling_scope = EG(scope); + fcc.object_pp = &return_value; + + if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) { + zend_throw_exception_ex(zend_exception_get_default(), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name); + } else { + if (retval_ptr) { + zval_ptr_dtor(&retval_ptr); + } + } + if (fci.params) { + efree(fci.params); + } + } else if (ctor_params) { + zend_throw_exception_ex(zend_exception_get_default(), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name); + } + } +} +/* }}} */ + +/* {{{ proto array mysql_fetch_row(resource result) + Gets a result row as an enumerated array */ +PHP_FUNCTION(mysql_fetch_row) +{ + php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_NUM, 1, 0); +} +/* }}} */ + + +/* {{{ proto object mysql_fetch_object(resource result [, string class_name [, NULL|array ctor_params]]) + Fetch a result row as an object */ +PHP_FUNCTION(mysql_fetch_object) +{ + php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_ASSOC, 2, 1); + + if (Z_TYPE_P(return_value) == IS_ARRAY) { + object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value)); + } +} +/* }}} */ + + +/* {{{ proto array mysql_fetch_array(resource result [, int result_type]) + Fetch a result row as an array (associative, numeric or both) */ +PHP_FUNCTION(mysql_fetch_array) +{ + php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 2, 0); +} +/* }}} */ + + +/* {{{ proto array mysql_fetch_assoc(resource result) + Fetch a result row as an associative array */ +PHP_FUNCTION(mysql_fetch_assoc) +{ + php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_ASSOC, 1, 0); +} +/* }}} */ + +/* {{{ proto bool mysql_data_seek(resource result, int row_number) + Move internal result pointer */ +PHP_FUNCTION(mysql_data_seek) +{ + zval **result, **offset; + MYSQL_RES *mysql_result; + + if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &result, &offset)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + convert_to_long_ex(offset); + if (Z_LVAL_PP(offset)<0 || Z_LVAL_PP(offset)>=(int)mysql_num_rows(mysql_result)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset %ld is invalid for MySQL result index %ld (or the query data is unbuffered)", Z_LVAL_PP(offset), Z_LVAL_PP(result)); + RETURN_FALSE; + } + mysql_data_seek(mysql_result, Z_LVAL_PP(offset)); + RETURN_TRUE; +} +/* }}} */ + + +/* {{{ proto array mysql_fetch_lengths(resource result) + Gets max data size of each column in a result */ +PHP_FUNCTION(mysql_fetch_lengths) +{ + zval **result; + MYSQL_RES *mysql_result; + mysql_row_length_type *lengths; + int num_fields; + int i; + + if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &result)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + if ((lengths=mysql_fetch_lengths(mysql_result))==NULL) { + RETURN_FALSE; + } + array_init(return_value); + num_fields = mysql_num_fields(mysql_result); + + for (i=0; i<num_fields; i++) { + add_index_long(return_value, i, lengths[i]); + } +} +/* }}} */ + +/* {{{ php_mysql_get_field_name + */ +static char *php_mysql_get_field_name(int field_type) +{ + switch(field_type) { + case FIELD_TYPE_STRING: + case FIELD_TYPE_VAR_STRING: + return "string"; + break; +#ifdef MYSQL_HAS_TINY + case FIELD_TYPE_TINY: +#endif + case FIELD_TYPE_SHORT: + case FIELD_TYPE_LONG: + case FIELD_TYPE_LONGLONG: + case FIELD_TYPE_INT24: + return "int"; + break; + case FIELD_TYPE_FLOAT: + case FIELD_TYPE_DOUBLE: + case FIELD_TYPE_DECIMAL: + return "real"; + break; + case FIELD_TYPE_TIMESTAMP: + return "timestamp"; + break; +#ifdef MYSQL_HAS_YEAR + case FIELD_TYPE_YEAR: + return "year"; + break; +#endif + case FIELD_TYPE_DATE: + return "date"; + break; + case FIELD_TYPE_TIME: + return "time"; + break; + case FIELD_TYPE_DATETIME: + return "datetime"; + break; + case FIELD_TYPE_TINY_BLOB: + case FIELD_TYPE_MEDIUM_BLOB: + case FIELD_TYPE_LONG_BLOB: + case FIELD_TYPE_BLOB: + return "blob"; + break; + case FIELD_TYPE_NULL: + return "null"; + break; + default: + return "unknown"; + break; + } +} +/* }}} */ + +/* {{{ proto object mysql_fetch_field(resource result [, int field_offset]) + Gets column information from a result and return as an object */ +PHP_FUNCTION(mysql_fetch_field) +{ + zval **result, **field=NULL; + MYSQL_RES *mysql_result; + MYSQL_FIELD *mysql_field; + + switch (ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &result)==FAILURE) { + RETURN_FALSE; + } + break; + case 2: + if (zend_get_parameters_ex(2, &result, &field)==FAILURE) { + RETURN_FALSE; + } + convert_to_long_ex(field); + break; + default: + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + if (field) { + if (Z_LVAL_PP(field)<0 || Z_LVAL_PP(field)>=(int)mysql_num_fields(mysql_result)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset"); + RETURN_FALSE; + } + mysql_field_seek(mysql_result, Z_LVAL_PP(field)); + } + if ((mysql_field=mysql_fetch_field(mysql_result))==NULL) { + RETURN_FALSE; + } + object_init(return_value); + + add_property_string(return_value, "name",(mysql_field->name?mysql_field->name:empty_string), 1); + add_property_string(return_value, "table",(mysql_field->table?mysql_field->table:empty_string), 1); + add_property_string(return_value, "def",(mysql_field->def?mysql_field->def:empty_string), 1); + add_property_long(return_value, "max_length", mysql_field->max_length); + add_property_long(return_value, "not_null", IS_NOT_NULL(mysql_field->flags)?1:0); + add_property_long(return_value, "primary_key", IS_PRI_KEY(mysql_field->flags)?1:0); + add_property_long(return_value, "multiple_key",(mysql_field->flags&MULTIPLE_KEY_FLAG?1:0)); + add_property_long(return_value, "unique_key",(mysql_field->flags&UNIQUE_KEY_FLAG?1:0)); + add_property_long(return_value, "numeric", IS_NUM(Z_TYPE_P(mysql_field))?1:0); + add_property_long(return_value, "blob", IS_BLOB(mysql_field->flags)?1:0); + add_property_string(return_value, "type", php_mysql_get_field_name(Z_TYPE_P(mysql_field)), 1); + add_property_long(return_value, "unsigned",(mysql_field->flags&UNSIGNED_FLAG?1:0)); + add_property_long(return_value, "zerofill",(mysql_field->flags&ZEROFILL_FLAG?1:0)); +} +/* }}} */ + + +/* {{{ proto bool mysql_field_seek(resource result, int field_offset) + Sets result pointer to a specific field offset */ +PHP_FUNCTION(mysql_field_seek) +{ + zval **result, **offset; + MYSQL_RES *mysql_result; + + if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &result, &offset)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + convert_to_long_ex(offset); + if (Z_LVAL_PP(offset)<0 || Z_LVAL_PP(offset)>=(int)mysql_num_fields(mysql_result)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field %ld is invalid for MySQL result index %ld", Z_LVAL_PP(offset), Z_LVAL_PP(result)); + RETURN_FALSE; + } + mysql_field_seek(mysql_result, Z_LVAL_PP(offset)); + RETURN_TRUE; +} +/* }}} */ + + +#define PHP_MYSQL_FIELD_NAME 1 +#define PHP_MYSQL_FIELD_TABLE 2 +#define PHP_MYSQL_FIELD_LEN 3 +#define PHP_MYSQL_FIELD_TYPE 4 +#define PHP_MYSQL_FIELD_FLAGS 5 + +/* {{{ php_mysql_field_info + */ +static void php_mysql_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) +{ + zval **result, **field; + MYSQL_RES *mysql_result; + MYSQL_FIELD *mysql_field = {0}; + char buf[512]; + int len; + + if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &result, &field)==FAILURE) { + WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + convert_to_long_ex(field); + if (Z_LVAL_PP(field)<0 || Z_LVAL_PP(field)>=(int)mysql_num_fields(mysql_result)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field %ld is invalid for MySQL result index %ld", Z_LVAL_PP(field), Z_LVAL_PP(result)); + RETURN_FALSE; + } + mysql_field_seek(mysql_result, Z_LVAL_PP(field)); + if ((mysql_field=mysql_fetch_field(mysql_result))==NULL) { + RETURN_FALSE; + } + + switch (entry_type) { + case PHP_MYSQL_FIELD_NAME: + Z_STRLEN_P(return_value) = strlen(mysql_field->name); + Z_STRVAL_P(return_value) = estrndup(mysql_field->name, Z_STRLEN_P(return_value)); + Z_TYPE_P(return_value) = IS_STRING; + break; + case PHP_MYSQL_FIELD_TABLE: + Z_STRLEN_P(return_value) = strlen(mysql_field->table); + Z_STRVAL_P(return_value) = estrndup(mysql_field->table, Z_STRLEN_P(return_value)); + Z_TYPE_P(return_value) = IS_STRING; + break; + case PHP_MYSQL_FIELD_LEN: + Z_LVAL_P(return_value) = mysql_field->length; + Z_TYPE_P(return_value) = IS_LONG; + break; + case PHP_MYSQL_FIELD_TYPE: + Z_STRVAL_P(return_value) = php_mysql_get_field_name(Z_TYPE_P(mysql_field)); + Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value)); + Z_STRVAL_P(return_value) = estrndup(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value)); + Z_TYPE_P(return_value) = IS_STRING; + break; + case PHP_MYSQL_FIELD_FLAGS: + memcpy(buf, "", sizeof("")); +#ifdef IS_NOT_NULL + if (IS_NOT_NULL(mysql_field->flags)) { + strcat(buf, "not_null "); + } +#endif +#ifdef IS_PRI_KEY + if (IS_PRI_KEY(mysql_field->flags)) { + strcat(buf, "primary_key "); + } +#endif +#ifdef UNIQUE_KEY_FLAG + if (mysql_field->flags&UNIQUE_KEY_FLAG) { + strcat(buf, "unique_key "); + } +#endif +#ifdef MULTIPLE_KEY_FLAG + if (mysql_field->flags&MULTIPLE_KEY_FLAG) { + strcat(buf, "multiple_key "); + } +#endif +#ifdef IS_BLOB + if (IS_BLOB(mysql_field->flags)) { + strcat(buf, "blob "); + } +#endif +#ifdef UNSIGNED_FLAG + if (mysql_field->flags&UNSIGNED_FLAG) { + strcat(buf, "unsigned "); + } +#endif +#ifdef ZEROFILL_FLAG + if (mysql_field->flags&ZEROFILL_FLAG) { + strcat(buf, "zerofill "); + } +#endif +#ifdef BINARY_FLAG + if (mysql_field->flags&BINARY_FLAG) { + strcat(buf, "binary "); + } +#endif +#ifdef ENUM_FLAG + if (mysql_field->flags&ENUM_FLAG) { + strcat(buf, "enum "); + } +#endif +#ifdef SET_FLAG + if (mysql_field->flags&SET_FLAG) { + strcat(buf, "set "); + } +#endif +#ifdef AUTO_INCREMENT_FLAG + if (mysql_field->flags&AUTO_INCREMENT_FLAG) { + strcat(buf, "auto_increment "); + } +#endif +#ifdef TIMESTAMP_FLAG + if (mysql_field->flags&TIMESTAMP_FLAG) { + strcat(buf, "timestamp "); + } +#endif + len = strlen(buf); + /* remove trailing space, if present */ + if (len && buf[len-1] == ' ') { + buf[len-1] = 0; + len--; + } + + Z_STRLEN_P(return_value) = len; + Z_STRVAL_P(return_value) = estrndup(buf, len); + Z_TYPE_P(return_value) = IS_STRING; + break; + + default: + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto string mysql_field_name(resource result, int field_index) + Gets the name of the specified field in a result */ +PHP_FUNCTION(mysql_field_name) +{ + php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_NAME); +} +/* }}} */ + + +/* {{{ proto string mysql_field_table(resource result, int field_offset) + Gets name of the table the specified field is in */ +PHP_FUNCTION(mysql_field_table) +{ + php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_TABLE); +} +/* }}} */ + + +/* {{{ proto int mysql_field_len(resource result, int field_offset) + Returns the length of the specified field */ +PHP_FUNCTION(mysql_field_len) +{ + php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_LEN); +} +/* }}} */ + + +/* {{{ proto string mysql_field_type(resource result, int field_offset) + Gets the type of the specified field in a result */ +PHP_FUNCTION(mysql_field_type) +{ + php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_TYPE); +} +/* }}} */ + + +/* {{{ proto string mysql_field_flags(resource result, int field_offset) + Gets the flags associated with the specified field in a result */ +PHP_FUNCTION(mysql_field_flags) +{ + php_mysql_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_MYSQL_FIELD_FLAGS); +} +/* }}} */ + + +/* {{{ proto bool mysql_free_result(resource result) + Free result memory */ +PHP_FUNCTION(mysql_free_result) +{ + zval **result; + MYSQL_RES *mysql_result; + + if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &result)==FAILURE) { + WRONG_PARAM_COUNT; + } + + if (Z_TYPE_PP(result)==IS_RESOURCE && Z_LVAL_PP(result)==0) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(mysql_result, MYSQL_RES *, result, -1, "MySQL result", le_result); + + zend_list_delete(Z_LVAL_PP(result)); + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool mysql_ping([int link_identifier]) + Ping a server connection. If no connection then reconnect. */ +PHP_FUNCTION(mysql_ping) +{ + zval *mysql_link = NULL; + int id = -1; + php_mysql_conn *mysql; + + if (0 == ZEND_NUM_ARGS()) { + id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU); + CHECK_LINK(id); + } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mysql_link)==FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink); + + PHPMY_UNBUFFERED_QUERY_CHECK(); + + RETURN_BOOL(! mysql_ping(&mysql->conn)); +} +/* }}} */ + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ |