/** * override __call() * it require two parameters, func_name and args **/ PHP_METHOD(McpackHessianClient, __call) { zend_class_entry *ce; zval *p_this, *args, *params, *result, *method, *tmp; char *func_name, *ret_str = NULL; int func_name_len = 0; size_t return_len = 0, max_len = 1024 * 1024 * 1024; p_this = getThis(); if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, p_this, "Osz", &ce, mcphessian_ce_ptr, &func_name, &func_name_len, &args) == FAILURE) { php_error(E_WARNING, "parse parameters error."); RETURN_NULL(); } // init params MAKE_STD_ZVAL(params); array_init(params); add_assoc_string(params, "jsonrpc", "2.0", 0); add_assoc_string(params, "method", func_name, 0); add_assoc_zval(params, "params", args); add_assoc_string(params, "id", "123456", 0); zval *pack = array2mcpack(params); // post data zval *z_url = zend_read_property(mcphessian_ce_ptr, p_this, ZEND_STRL("url"), 1 TSRMLS_CC); convert_to_string(z_url); char *url = Z_STRVAL_P(z_url); php_stream_context *context = php_stream_context_alloc(); MAKE_STD_ZVAL(method); ZVAL_STRING(method, "POST", 0); php_stream_context_set_option(context, "http", "method", method); php_stream_context_set_option(context, "http", "content", pack); // read data from stream php_stream *stream = php_stream_open_wrapper_ex(url, "rb", REPORT_ERRORS, NULL, context); if (stream) { ret_str = php_stream_get_line(stream, NULL, max_len, &return_len); } else { php_error(E_WARNING, "failed to open stream %s.", url); RETURN_NULL(); } MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, ret_str, return_len, 0); result = mcpack2array(tmp); php_stream_close(stream); efree(ret_str); // get result from array zval **ret_val; if (zend_hash_exists(Z_ARRVAL_P(result), "result", 7)) { zend_hash_find(Z_ARRVAL_P(result), "result", 7, (void **)&ret_val); RETURN_ZVAL(*ret_val, 1, 0); } else { php_error(E_WARNING, "return value illegal."); RETURN_NULL(); } }
/* {{{ mysqlnd_vio::enable_ssl */ static enum_func_status MYSQLND_METHOD(mysqlnd_vio, enable_ssl)(MYSQLND_VIO * const net) { #ifdef MYSQLND_SSL_SUPPORTED php_stream_context * context = php_stream_context_alloc(); php_stream * net_stream = net->data->m.get_stream(net); zend_bool any_flag = FALSE; DBG_ENTER("mysqlnd_vio::enable_ssl"); if (!context) { DBG_RETURN(FAIL); } if (net->data->options.ssl_key) { zval key_zval; ZVAL_STRING(&key_zval, net->data->options.ssl_key); php_stream_context_set_option(context, "ssl", "local_pk", &key_zval); zval_ptr_dtor(&key_zval); any_flag = TRUE; } if (net->data->options.ssl_cert) { zval cert_zval; ZVAL_STRING(&cert_zval, net->data->options.ssl_cert); php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval); if (!net->data->options.ssl_key) { php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval); } zval_ptr_dtor(&cert_zval); any_flag = TRUE; } if (net->data->options.ssl_ca) { zval cafile_zval; ZVAL_STRING(&cafile_zval, net->data->options.ssl_ca); php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval); any_flag = TRUE; } if (net->data->options.ssl_capath) { zval capath_zval; ZVAL_STRING(&capath_zval, net->data->options.ssl_capath); php_stream_context_set_option(context, "ssl", "capath", &capath_zval); zval_ptr_dtor(&capath_zval); any_flag = TRUE; } if (net->data->options.ssl_passphrase) { zval passphrase_zval; ZVAL_STRING(&passphrase_zval, net->data->options.ssl_passphrase); php_stream_context_set_option(context, "ssl", "passphrase", &passphrase_zval); zval_ptr_dtor(&passphrase_zval); any_flag = TRUE; } if (net->data->options.ssl_cipher) { zval cipher_zval; ZVAL_STRING(&cipher_zval, net->data->options.ssl_cipher); php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval); zval_ptr_dtor(&cipher_zval); any_flag = TRUE; } { zval verify_peer_zval; zend_bool verify; if (net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_DEFAULT) { net->data->options.ssl_verify_peer = any_flag? MYSQLND_SSL_PEER_DEFAULT_ACTION:MYSQLND_SSL_PEER_DONT_VERIFY; } verify = net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_VERIFY? TRUE:FALSE; DBG_INF_FMT("VERIFY=%d", verify); ZVAL_BOOL(&verify_peer_zval, verify); php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval); php_stream_context_set_option(context, "ssl", "verify_peer_name", &verify_peer_zval); if (net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_DONT_VERIFY) { ZVAL_TRUE(&verify_peer_zval); php_stream_context_set_option(context, "ssl", "allow_self_signed", &verify_peer_zval); } } #if PHP_API_VERSION >= 20131106 php_stream_context_set(net_stream, context); #else php_stream_context_set(net_stream, context); #endif if (php_stream_xport_crypto_setup(net_stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL) < 0 || php_stream_xport_crypto_enable(net_stream, 1) < 0) { DBG_ERR("Cannot connect to MySQL by using SSL"); php_error_docref(NULL, E_WARNING, "Cannot connect to MySQL by using SSL"); DBG_RETURN(FAIL); } net->data->ssl = TRUE; /* get rid of the context. we are persistent and if this is a real pconn used by mysql/mysqli, then the context would not survive cleaning of EG(regular_list), where it is registered, as a resource. What happens is that after this destruction any use of the network will mean usage of the context, which means usage of already freed memory, bad. Actually we don't need this context anymore after we have enabled SSL on the connection. Thus it is very simple, we remove it. */ #if PHP_API_VERSION >= 20131106 php_stream_context_set(net_stream, NULL); #else php_stream_context_set(net_stream, NULL); #endif if (net->data->options.timeout_read) { struct timeval tv; DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->data->options.timeout_read); tv.tv_sec = net->data->options.timeout_read; tv.tv_usec = 0; php_stream_set_option(net_stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv); } DBG_RETURN(PASS); #else DBG_ENTER("mysqlnd_vio::enable_ssl"); DBG_INF("MYSQLND_SSL_SUPPORTED is not defined"); DBG_RETURN(PASS); #endif }