mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Add support for connect attributes, as of MySQL 5.6
This commit is contained in:
parent
be07f815f2
commit
1ff4352263
8 changed files with 171 additions and 8 deletions
|
@ -95,6 +95,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_options)(MYSQLND_CONN_DATA * conn TSRMLS_
|
|||
mnd_pefree(conn->options->cfg_section, pers);
|
||||
conn->options->cfg_section = NULL;
|
||||
}
|
||||
if (conn->options->connect_attr) {
|
||||
zend_hash_destroy(conn->options->connect_attr);
|
||||
mnd_pefree(conn->options->connect_attr, pers);
|
||||
conn->options->connect_attr = NULL;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -797,13 +802,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
|
|||
goto err;
|
||||
}
|
||||
|
||||
conn->client_flag = mysql_flags;
|
||||
conn->server_capabilities = greet_packet->server_capabilities;
|
||||
|
||||
if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
|
||||
greet_packet, conn->options, mysql_flags TSRMLS_CC))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
conn->client_flag = mysql_flags;
|
||||
conn->server_capabilities = greet_packet->server_capabilities;
|
||||
conn->upsert_status->warning_count = 0;
|
||||
conn->upsert_status->server_status = greet_packet->server_status;
|
||||
conn->upsert_status->affected_rows = 0;
|
||||
|
@ -811,6 +817,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
|
|||
PACKET_FREE(greet_packet);
|
||||
DBG_RETURN(PASS);
|
||||
err:
|
||||
conn->client_flag = 0;
|
||||
conn->server_capabilities = 0;
|
||||
PACKET_FREE(greet_packet);
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
@ -1086,6 +1094,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
|
|||
DBG_ENTER("mysqlnd_conn::connect");
|
||||
|
||||
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
|
||||
mysqlnd_options4(conn_handle, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_name", "mysqlnd");
|
||||
ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
|
||||
|
||||
conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
|
||||
|
@ -2375,6 +2384,19 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
|
|||
conn->options->flags &= ~CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS;
|
||||
}
|
||||
break;
|
||||
case MYSQL_OPT_CONNECT_ATTR_RESET:
|
||||
if (conn->options->connect_attr) {
|
||||
DBG_INF_FMT("Before reset %d attribute(s)", zend_hash_num_elements(conn->options->connect_attr));
|
||||
zend_hash_clean(conn->options->connect_attr);
|
||||
}
|
||||
break;
|
||||
case MYSQL_OPT_CONNECT_ATTR_DELETE:
|
||||
if (conn->options->connect_attr && value) {
|
||||
DBG_INF_FMT("Before delete %d attribute(s)", zend_hash_num_elements(conn->options->connect_attr));
|
||||
zend_hash_del(conn->options->connect_attr, value, strlen(value));
|
||||
DBG_INF_FMT("%d left", zend_hash_num_elements(conn->options->connect_attr));
|
||||
}
|
||||
break;
|
||||
#ifdef WHEN_SUPPORTED_BY_MYSQLI
|
||||
case MYSQL_SHARED_MEMORY_BASE_NAME:
|
||||
case MYSQL_OPT_USE_RESULT:
|
||||
|
@ -2395,6 +2417,69 @@ end:
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ connect_attr_item_dtor */
|
||||
static void
|
||||
connect_attr_item_dtor(void * pDest)
|
||||
{
|
||||
#ifdef ZTS
|
||||
TSRMLS_FETCH();
|
||||
#endif
|
||||
DBG_ENTER("connect_attr_item_dtor");
|
||||
mnd_pefree(*(char **) pDest, 1);
|
||||
DBG_VOID_RETURN;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_conn_data::set_client_option_2d */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * const conn,
|
||||
enum mysqlnd_option option,
|
||||
const char * const key,
|
||||
const char * const value
|
||||
TSRMLS_DC)
|
||||
{
|
||||
size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_client_option_2d);
|
||||
enum_func_status ret = PASS;
|
||||
DBG_ENTER("mysqlnd_conn_data::set_client_option_2d");
|
||||
DBG_INF_FMT("conn=%llu option=%u", conn->thread_id, option);
|
||||
|
||||
if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
|
||||
goto end;
|
||||
}
|
||||
switch (option) {
|
||||
case MYSQL_OPT_CONNECT_ATTR_ADD:
|
||||
if (!conn->options->connect_attr) {
|
||||
DBG_INF("Initializing connect_attr hash");
|
||||
conn->options->connect_attr = mnd_pemalloc(sizeof(HashTable), conn->persistent);
|
||||
if (!conn->options->connect_attr) {
|
||||
goto oom;
|
||||
}
|
||||
zend_hash_init(conn->options->connect_attr, 0, NULL, NULL, conn->persistent);
|
||||
}
|
||||
DBG_INF_FMT("Adding [%s][%s]", key, value);
|
||||
{
|
||||
const char * copyv = mnd_pestrdup(value, 1);
|
||||
if (!copyv) {
|
||||
goto oom;
|
||||
}
|
||||
zend_hash_update(conn->options->connect_attr, key, strlen(key), ©v, sizeof(char *), NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = FAIL;
|
||||
}
|
||||
conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
|
||||
DBG_RETURN(ret);
|
||||
oom:
|
||||
SET_OOM_ERROR(*conn->error_info);
|
||||
conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
|
||||
end:
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ mysqlnd_conn_data::use_result */
|
||||
static MYSQLND_RES *
|
||||
MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
|
||||
|
@ -2662,7 +2747,9 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
|
|||
MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags),
|
||||
MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake),
|
||||
MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request),
|
||||
MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name)
|
||||
MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name),
|
||||
|
||||
MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)
|
||||
MYSQLND_CLASS_METHODS_END;
|
||||
|
||||
|
||||
|
|
|
@ -207,6 +207,7 @@ PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, con
|
|||
#define mysqlnd_set_character_set(conn, cs) ((conn)->data)->m->set_charset((conn)->data, (cs) TSRMLS_CC)
|
||||
#define mysqlnd_stat(conn, msg, msg_len) ((conn)->data)->m->get_server_statistics(((conn)->data), (msg), (msg_len) TSRMLS_CC)
|
||||
#define mysqlnd_options(conn, opt, value) ((conn)->data)->m->set_client_option((conn)->data, (opt), (value) TSRMLS_CC)
|
||||
#define mysqlnd_options4(conn, opt, k, v) ((conn)->data)->m->set_client_option_2d((conn)->data, (opt), (k), (v) TSRMLS_CC)
|
||||
#define mysqlnd_set_server_option(conn, op) ((conn)->data)->m->set_server_option((conn)->data, (op) TSRMLS_CC)
|
||||
|
||||
/* Escaping */
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "mysqlnd_charset.h"
|
||||
#include "mysqlnd_debug.h"
|
||||
|
||||
|
||||
/* {{{ mysqlnd_auth_handshake */
|
||||
enum_func_status
|
||||
mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
|
||||
|
@ -100,6 +99,10 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
|
|||
auth_packet->auth_data_len = auth_plugin_data_len;
|
||||
auth_packet->auth_plugin_name = auth_protocol;
|
||||
|
||||
if (conn->server_capabilities & CLIENT_CONNECT_ATTRS) {
|
||||
auth_packet->connect_attr = conn->options->connect_attr;
|
||||
}
|
||||
|
||||
if (!PACKET_WRITE(auth_packet, conn)) {
|
||||
goto end;
|
||||
}
|
||||
|
|
|
@ -168,6 +168,9 @@ typedef enum mysqlnd_option
|
|||
MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
|
||||
MYSQL_PLUGIN_DIR,
|
||||
MYSQL_DEFAULT_AUTH,
|
||||
MYSQL_OPT_CONNECT_ATTR_RESET,
|
||||
MYSQL_OPT_CONNECT_ATTR_ADD,
|
||||
MYSQL_OPT_CONNECT_ATTR_DELETE,
|
||||
MYSQL_SERVER_PUBLIC_KEY,
|
||||
MYSQL_ENABLE_CLEARTEXT_PLUGIN,
|
||||
MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
|
||||
|
|
|
@ -106,7 +106,8 @@
|
|||
#define mysql_stmt_more_results(s) mysqlnd_stmt_more_results((s))
|
||||
#define mysql_thread_safe() mysqlnd_thread_safe()
|
||||
#define mysql_info(r) mysqlnd_info((r))
|
||||
#define mysql_options(r,a,b) mysqlnd_options((r), (a), (b))
|
||||
#define mysql_options(c,a,v) mysqlnd_options((c), (a), (v))
|
||||
#define mysql_options4(c,a,k,v) mysqlnd_options4((c), (a), (k), (v))
|
||||
#define mysql_stmt_init(r) mysqlnd_stmt_init((r))
|
||||
#define mysql_free_result(r) mysqlnd_free_result((r), FALSE)
|
||||
#define mysql_store_result(r) mysqlnd_store_result((r))
|
||||
|
|
|
@ -172,7 +172,7 @@ typedef struct st_mysqlnd_options
|
|||
The ABI will be broken and the methods structure will be somewhere else
|
||||
in the memory which can crash external code. Feel free to reuse these.
|
||||
*/
|
||||
char * unused2;
|
||||
HashTable * connect_attr;
|
||||
char * unused3;
|
||||
char * unused4;
|
||||
char * unused5;
|
||||
|
@ -489,6 +489,8 @@ typedef enum_func_status (*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CO
|
|||
typedef enum_func_status (*func_mysqlnd_conn_data__simple_command_send_request)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC);
|
||||
typedef struct st_mysqlnd_authentication_plugin * (*func_mysqlnd_conn_data__fetch_auth_plugin_by_name)(const char * const requested_protocol TSRMLS_DC);
|
||||
|
||||
typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_option option, const char * const key, const char * const value TSRMLS_DC);
|
||||
|
||||
struct st_mysqlnd_conn_data_methods
|
||||
{
|
||||
func_mysqlnd_conn_data__init init;
|
||||
|
@ -573,6 +575,8 @@ struct st_mysqlnd_conn_data_methods
|
|||
func_mysqlnd_conn_data__connect_handshake connect_handshake;
|
||||
func_mysqlnd_conn_data__simple_command_send_request simple_command_send_request;
|
||||
func_mysqlnd_conn_data__fetch_auth_plugin_by_name fetch_auth_plugin_by_name;
|
||||
|
||||
func_mysqlnd_conn_data__set_client_option_2d set_client_option_2d;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -212,6 +212,24 @@ php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length)
|
|||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ php_mysqlnd_net_store_length_size */
|
||||
size_t
|
||||
php_mysqlnd_net_store_length_size(uint64_t length)
|
||||
{
|
||||
if (length < (uint64_t) L64(251)) {
|
||||
return 1;
|
||||
}
|
||||
if (length < (uint64_t) L64(65536)) {
|
||||
return 3;
|
||||
}
|
||||
if (length < (uint64_t) L64(16777216)) {
|
||||
return 4;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ php_mysqlnd_read_error_from_line */
|
||||
static enum_func_status
|
||||
php_mysqlnd_read_error_from_line(zend_uchar *buf, size_t buf_len,
|
||||
|
@ -459,7 +477,7 @@ void php_mysqlnd_greet_free_mem(void * _packet, zend_bool stack_allocation TSRML
|
|||
/* }}} */
|
||||
|
||||
|
||||
#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 1024)
|
||||
#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 4096)
|
||||
|
||||
/* {{{ php_mysqlnd_auth_write */
|
||||
static
|
||||
|
@ -540,6 +558,52 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC
|
|||
p+= len;
|
||||
*p++= '\0';
|
||||
}
|
||||
|
||||
if (packet->connect_attr && zend_hash_num_elements(packet->connect_attr)) {
|
||||
HashPosition pos_value;
|
||||
const char ** entry_value;
|
||||
size_t ca_payload_len = 0;
|
||||
zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
|
||||
while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
|
||||
char *s_key;
|
||||
unsigned int s_len;
|
||||
unsigned long num_key;
|
||||
size_t value_len = strlen(*entry_value);
|
||||
|
||||
if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, 0, &pos_value)) {
|
||||
ca_payload_len += php_mysqlnd_net_store_length_size(s_len);
|
||||
ca_payload_len += s_len;
|
||||
ca_payload_len += php_mysqlnd_net_store_length_size(value_len);
|
||||
ca_payload_len += value_len;
|
||||
}
|
||||
zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
|
||||
}
|
||||
|
||||
if ((sizeof(buffer) - (p - buffer)) >= (ca_payload_len + php_mysqlnd_net_store_length_size(ca_payload_len))) {
|
||||
p = php_mysqlnd_net_store_length(p, ca_payload_len);
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
|
||||
while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
|
||||
char *s_key;
|
||||
unsigned int s_len;
|
||||
unsigned long num_key;
|
||||
size_t value_len = strlen(*entry_value);
|
||||
if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, 0, &pos_value)) {
|
||||
/* copy key */
|
||||
p = php_mysqlnd_net_store_length(p, s_len);
|
||||
memcpy(p, s_key, s_len);
|
||||
p+= s_len;
|
||||
/* copy value */
|
||||
p = php_mysqlnd_net_store_length(p, value_len);
|
||||
memcpy(p, *entry_value, value_len);
|
||||
p+= value_len;
|
||||
}
|
||||
zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
|
||||
}
|
||||
} else {
|
||||
/* cannot put the data - skip */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (packet->is_change_user_packet) {
|
||||
if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE,
|
||||
|
|
|
@ -103,7 +103,7 @@ typedef struct st_mysqlnd_packet_auth {
|
|||
zend_bool send_auth_data;
|
||||
zend_bool is_change_user_packet;
|
||||
zend_bool silent;
|
||||
|
||||
HashTable *connect_attr;
|
||||
} MYSQLND_PACKET_AUTH;
|
||||
|
||||
/* Auth response packet */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue