📄 mysqlnd.c
字号:
} } PACKET_FREE_ALLOCA(ok_response); break; } case PROT_EOF_PACKET:{ php_mysql_packet_eof ok_response; PACKET_INIT_ALLOCA(ok_response, PROT_EOF_PACKET); if (FAIL == (ret = PACKET_READ_ALLOCA(ok_response, conn))) { SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet"); if (!silent) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading %s's EOF packet", mysqlnd_command_to_text[command]); } } else if (0xFF == ok_response.field_count) { /* The server signalled error. Set the error */ SET_CLIENT_ERROR(conn->error_info, ok_response.error_no, ok_response.sqlstate, ok_response.error); conn->upsert_status.affected_rows = (mynd_ulonglong) ~0; } else if (0xFE != ok_response.field_count) { SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet"); if (!silent) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response.field_count); } } else {#ifndef MYSQLND_SILENT php_printf("\tOK from server\n");#endif } PACKET_FREE_ALLOCA(ok_response); break; } default: ret = FAIL; SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet"); php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong response packet %d passed to the function", ok_packet); break; } return ret;}/* }}} *//* {{{ mysqlnd_simple_command */enum_func_statusmysqlnd_simple_command(MYSQLND *conn, enum php_mysqlnd_server_command command, const char * const arg, size_t arg_len, enum php_mysql_packet_type ok_packet, zend_bool silent TSRMLS_DC){ enum_func_status ret = PASS; php_mysql_packet_command cmd_packet; switch (conn->state) { case CONN_READY: break; case CONN_QUIT_SENT: SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); return FAIL; default: SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); return FAIL; } /* clean UPSERT info */ memset(&conn->upsert_status, 0, sizeof(conn->upsert_status)); conn->upsert_status.affected_rows = (mynd_ulonglong) ~0; SET_EMPTY_ERROR(conn->error_info); PACKET_INIT_ALLOCA(cmd_packet, PROT_CMD_PACKET); cmd_packet.command = command; if (arg && arg_len) { cmd_packet.argument = arg; cmd_packet.arg_len = arg_len; } if (! PACKET_WRITE_ALLOCA(cmd_packet, conn)) { if (!silent) { php_error(E_WARNING, "Error while sending %s packet", mysqlnd_command_to_text[command]); } SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); ret = FAIL; } else if (ok_packet != PROT_LAST) { ret = mysqlnd_simple_command_handle_response(conn, ok_packet, silent, command TSRMLS_CC); } /* There is no need to call FREE_ALLOCA on cmd_packet as the only allocated string is cmd_packet.argument and it was passed to us. We should not free it. */ return ret;}/* }}} *//* {{{ _mysqlnd_set_server_option */static enum_func_status_mysqlnd_set_server_option(MYSQLND * const conn, enum_mysqlnd_server_option option TSRMLS_DC){ char buffer[2]; int2store(buffer, (uint) option); return mysqlnd_simple_command(conn, COM_SET_OPTION, buffer, sizeof(buffer), PROT_EOF_PACKET, FALSE TSRMLS_CC);}/* }}} *//* {{{ mysqlnd_start_psession */PHPAPI void mysqlnd_restart_psession(MYSQLND *conn) { MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CONNECT_REUSED);}/* }}} *//* {{{ mysqlnd_end_psession */PHPAPI void mysqlnd_end_psession(MYSQLND *conn){}/* }}} *//* {{{ mysqlnd_connect */PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn, char *host, char *user, char *passwd, unsigned int passwd_len, char *db, unsigned int db_len, unsigned int port, char *socket, unsigned int mysql_flags, MYSQLND_ZVAL_PCACHE *zval_cache TSRMLS_DC){ char *transport = NULL, *errstr = NULL; int transport_len, errcode = 0; unsigned int streams_options = ENFORCE_SAFE_MODE; unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT; zend_bool self_alloced = FALSE; struct timeval tv; zend_bool unix_socket = FALSE; php_mysql_packet_greet greet_packet; php_mysql_packet_auth *auth_packet; php_mysql_packet_ok ok_packet; if (conn && conn->state != CONN_ALLOCED) { SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); return NULL; } if (!host || !host[0]) { host = "localhost"; } if (!user || !user[0]) { user = php_get_current_user(); } if (!passwd) { passwd = ""; passwd_len = 0; } if (!db) { db = ""; db_len = 0; } if (!port && !socket) { port = 3306; }#ifndef PHP_WIN32 if (!strncasecmp(host, "localhost", sizeof("localhost") - 1)) { if (!socket) { socket = "/tmp/mysql.sock"; } transport_len = spprintf(&transport, 0, "unix://%s", socket); unix_socket = TRUE; } else #endif { transport_len = spprintf(&transport, 0, "tcp://%s:%d", host, port); } PACKET_INIT_ALLOCA(greet_packet, PROT_GREET_PACKET); PACKET_INIT(auth_packet, PROT_AUTH_PACKET, php_mysql_packet_auth *); PACKET_INIT_ALLOCA(ok_packet, PROT_OK_PACKET); if (!conn) { conn = mysqlnd_init(FALSE); self_alloced = TRUE; } conn->state = CONN_ALLOCED; conn->net.packet_no = 0; if (conn->options.timeout_connect) { tv.tv_sec = conn->options.timeout_connect; tv.tv_usec = 0; } if (conn->persistent) { conn->scheme = pestrndup(transport, transport_len, 1); efree(transport); } else { conn->scheme = transport; } conn->net.stream = php_stream_xport_create(conn->scheme, transport_len, streams_options, streams_flags, (conn->persistent) ? "mysqli_plink" : NULL, (conn->options.timeout_connect) ? &tv : NULL, NULL /*ctx*/, &errstr, &errcode); if (errstr || !conn->net.stream) { goto err; } if (conn->options.timeout_read) { tv.tv_sec = conn->options.timeout_read; tv.tv_usec = 0; php_stream_set_option(conn->net.stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv); } if (!unix_socket) { /* Set TCP_NODELAY */ mysqlnd_set_sock_no_delay(conn->net.stream); } if (FAIL == PACKET_READ_ALLOCA(greet_packet, conn)) {#ifndef MYSQLND_SILENT php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading greeting packet");#endif goto err; } else if (greet_packet.error_no) { SET_CLIENT_ERROR(conn->error_info, greet_packet.error_no, greet_packet.sqlstate, greet_packet.error); goto err; } else if (greet_packet.pre41) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 " " is not supported. Server is %-.32s", greet_packet.server_version); SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Connecting to 3.22, 3.23 & 4.0 servers is not supported"); goto err; } conn->thread_id = greet_packet.thread_id; conn->protocol_version = greet_packet.protocol_version; conn->server_version = greet_packet.server_version; greet_packet.server_version = NULL; /* The string will be freed otherwise */ /* we allow load data local infile by default */ mysql_flags |= CLIENT_LOCAL_FILES; auth_packet->user = user; auth_packet->password = passwd; auth_packet->charset_no = greet_packet.charset_no; auth_packet->db = db; auth_packet->db_len = db_len; auth_packet->max_packet_size= 3UL*1024UL*1024UL*1024UL; auth_packet->client_flags= mysql_flags; conn->scramble = auth_packet->server_scramble_buf = pemalloc(SCRAMBLE_LENGTH, conn->persistent); memcpy(auth_packet->server_scramble_buf, greet_packet.scramble_buf, SCRAMBLE_LENGTH); PACKET_WRITE(auth_packet, conn); if (FAIL == PACKET_READ_ALLOCA(ok_packet, conn) || ok_packet.field_count >= 0xFE) { if (ok_packet.field_count == 0xFE) { /* pre41 server !*/ php_error_docref(NULL TSRMLS_CC, E_WARNING, "mysqlnd cannot connect to MySQL < 4.1 servers"); } else if (ok_packet.field_count == 0xFF) { if (ok_packet.sqlstate[0]) { if (!self_alloced) { strncpy(conn->error_info.sqlstate, ok_packet.sqlstate, sizeof(conn->error_info.sqlstate)); }#ifndef MYSQLND_SILENT php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERROR:%d [SQLSTATE:%s] %s", ok_packet.error_no, ok_packet.sqlstate, ok_packet.error);#endif } if (!self_alloced) { conn->error_info.error_no = ok_packet.error_no; strncpy(conn->error_info.error, ok_packet.error, sizeof(conn->error_info.error)); } } } else { conn->state = CONN_READY; conn->user = pestrdup(user, conn->persistent); conn->passwd = pestrndup(passwd, passwd_len, conn->persistent); conn->port = port; if (host && !socket) { char *p; conn->host = pestrdup(host, conn->persistent); spprintf(&p, 0, "MySQL host info: %s via TCP/IP", conn->host); if (conn->persistent) { conn->host_info = pestrdup(p, 1); efree(p); } else { conn->host_info = p; } } else { conn->unix_socket = pestrdup(socket, conn->persistent); conn->host_info = pestrdup("MySQL host info: Localhost via UNIX socket", conn->persistent); } conn->client_flag = auth_packet->client_flags; conn->max_packet_size = auth_packet->max_packet_size; /* todo: check if charset is available */ conn->charset = mysqlnd_find_charset_nr(greet_packet.charset_no); conn->server_capabilities = greet_packet.server_capabilities; conn->upsert_status.warning_count = 0; conn->upsert_status.server_status = greet_packet.server_status; SET_NEW_MESSAGE(conn->last_message, conn->last_message_len, ok_packet.message, ok_packet.message_len); SET_EMPTY_ERROR(conn->error_info); PACKET_FREE_ALLOCA(greet_packet); PACKET_FREE(auth_packet); PACKET_FREE_ALLOCA(ok_packet); conn->zval_cache = mysqlnd_palloc_get_cache_reference(zval_cache); conn->net.cmd_buffer.length = 128L*1024L; conn->net.cmd_buffer.buffer = pemalloc(conn->net.cmd_buffer.length, conn->persistent); MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CONNECT_SUCCESS); { uint as_unicode = 1; conn->m->set_client_option(conn, MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE, (char *)&as_unicode); } return conn; }err: PACKET_FREE_ALLOCA(greet_packet); PACKET_FREE(auth_packet); PACKET_FREE_ALLOCA(ok_packet); if (errstr) { SET_CLIENT_ERROR(conn->error_info, errcode, UNKNOWN_SQLSTATE, errstr); php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%d] %.64s (trying to connect via %s)", errcode, errstr, conn->scheme); efree(errstr); } if (conn->scheme) { pefree(conn->scheme, conn->persistent); conn->scheme = NULL; } /* This will also close conn->net.stream if it has been opened */ conn->m->free_contents(conn TSRMLS_CC); if (self_alloced) { /* We have alloced, thus there are no references to this object - we are free to kill it! */ conn->m->dtor(conn TSRMLS_CC); } else { MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CONNECT_FAILURE); } return NULL;}/* }}} *//* {{{ mysqlnd_handle_numeric *//* The following code is stolen from ZE - HANDLE_NUMERIC() macro from zend_hash.c and modified for the needs of mysqlnd.*/staticzend_bool mysqlnd_is_key_numeric(char *key, size_t length, long *idx){ register char *tmp=key; if (*tmp=='-') { tmp++; } if ((*tmp>='0' && *tmp<='9')) { do { /* possibly a numeric index */ char *end=key+length-1; if (*tmp++=='0' && length>2) { /* don't accept numbers with leading zeros */ break; } while (tmp<end) { if (!(*tmp>='0' && *tmp<='9')) { break; } tmp++; } if (tmp==end && *tmp=='\0') { /* a numeric index */ if (*key=='-') { *idx = strtol(key, NULL, 10); if (*idx!=LONG_MIN) { return TRUE; } } else { *idx = strtol(key, NULL, 10); if (*idx!=LONG_MAX) { return TRUE; } } } } while (0); } return FALSE;}/* }}} */#if PHP_MAJOR_VERSION >= 6/* {{{ mysqlnd_unicode_is_key_numeric */staticzend_bool mysqlnd_unicode_is_key_numeric(UChar *key, size_t length, long *idx){ register UChar *tmp=key; if (*tmp==0x2D /*'-'*/) { tmp++; } if ((*tmp>=0x30 /*'0'*/ && *tmp<=0x39 /*'9'*/)) { /* possibly a numeric index */ do { UChar *end=key+length-1; if (*tmp++==0x30 && length>2) { /* don't accept numbers with leading zeros */ break; } while (tmp<end) { if (!(*tmp>=0x30 /*'0'*/ && *tmp<=0x39 /*'9'*/)) { break; } tmp++; } if (tmp==end && *tmp==0) { /* a numeric index */ if (*key==0x2D /*'-'*/) { *idx = zend_u_strtol(key, NULL, 10); if (*idx!=LONG_MIN) { return TRUE; } } else { *idx = zend_u_strtol(key, NULL, 10); if (*idx!=LONG_MAX) { return TRUE; } } } } while (0); } return FALSE;}/* }}} */#endif/* {{{ mysqlnd_read_result_metadata */enum_func_status
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -