int unfinished; /* int because of curl_multi_perform() */
#if PHP_HTTP_HAVE_EVENT
+ struct event_base *evbase;
struct event *timeout;
unsigned useevents:1;
#endif
} else if (php_memnstr(data, ZEND_STRL("Operation timed out"), data + length)) {
h->progress.info = "timeout";
} else {
-#if PHP_DEBUG
+#if 0
h->progress.info = data;
data[length - 1] = '\0';
#endif
case CURLSSLBACKEND_NSS:
backend = "nss";
break;
+#if !PHP_HTTP_CURL_VERSION(7,39,0)
case CURLSSLBACKEND_QSOSSL:
backend = "qsossl";
break;
+#endif
case CURLSSLBACKEND_GSKIT:
backend = "gskit";
break;
return -1;
}
- event_assign(&ev->evnt, PHP_HTTP_G->curl.event_base, sock, events, php_http_curlm_event_callback, context);
+ event_assign(&ev->evnt, curl->evbase, sock, events, php_http_curlm_event_callback, context);
event_add(&ev->evnt, NULL);
}
php_http_curlm_timeout_callback(CURL_SOCKET_TIMEOUT, /*EV_READ|EV_WRITE*/0, context);
} else if (timeout_ms > 0 || !event_initialized(curl->timeout) || !event_pending(curl->timeout, EV_TIMEOUT, NULL)) {
struct timeval timeout;
- TSRMLS_FETCH_FROM_CTX(context->ts);
if (!event_initialized(curl->timeout)) {
- event_assign(curl->timeout, PHP_HTTP_G->curl.event_base, CURL_SOCKET_TIMEOUT, 0, php_http_curlm_timeout_callback, context);
- } else if (event_pending(curl->timeout, EV_TIMEOUT, NULL)) {
- event_del(curl->timeout);
+ event_assign(curl->timeout, curl->evbase, CURL_SOCKET_TIMEOUT, 0, php_http_curlm_timeout_callback, context);
}
timeout.tv_sec = timeout_ms / 1000;
return FAILURE;
}
} else {
- if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_TIMEVALUE, (long) PHP_HTTP_G->env.request.time + Z_LVAL_P(val))) {
+ if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_TIMEVALUE, (long) sapi_get_request_time(TSRMLS_C) + Z_LVAL_P(val))) {
return FAILURE;
}
}
}
curl_easy_setopt(ch, CURLOPT_URL, NULL);
+ curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, NULL);
+ curl_easy_setopt(ch, CURLOPT_HTTPGET, 1L);
+ curl_easy_setopt(ch, CURLOPT_NOBODY, 0L);
/* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
#if PHP_HTTP_CURL_VERSION(7,19,1)
curl_easy_setopt(ch, CURLOPT_PROXYUSERNAME, NULL);
if (storage->url) {
pefree(storage->url, 1);
}
- storage->url = pestrdup(PHP_HTTP_INFO(msg).request.url, 1);
+ php_http_url_to_string(PHP_HTTP_INFO(msg).request.url, &storage->url, NULL, 1);
curl_easy_setopt(curl->handle, CURLOPT_URL, storage->url);
/* request method */
php_http_message_update_headers(msg);
if (zend_hash_num_elements(&msg->hdrs)) {
php_http_array_hashkey_t header_key = php_http_array_hashkey_init(0);
- zval **header_val;
+ zval **header_val, *header_cpy;
HashPosition pos;
php_http_buffer_t header;
+#if !PHP_HTTP_CURL_VERSION(7,23,0)
+ zval **ct = NULL;
+
+ zend_hash_find(&msg->hdrs, ZEND_STRS("Content-Length"), (void *) &ct);
+#endif
php_http_buffer_init(&header);
FOREACH_HASH_KEYVAL(pos, &msg->hdrs, header_key, header_val) {
if (header_key.type == HASH_KEY_IS_STRING) {
- zval *header_cpy = php_http_ztyp(IS_STRING, *header_val);
-
+#if !PHP_HTTP_CURL_VERSION(7,23,0)
+ /* avoid duplicate content-length header */
+ if (ct && *ct == *header_val) {
+ continue;
+ }
+#endif
+ header_cpy = php_http_ztyp(IS_STRING, *header_val);
php_http_buffer_appendf(&header, "%s: %s", header_key.str, Z_STRVAL_P(header_cpy));
php_http_buffer_fix(&header);
curl->options.headers = curl_slist_append(curl->options.headers, header.data);
return SUCCESS;
}
-static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *handler)
+static void php_http_client_curl_handler_clear(php_http_client_curl_handler_t *handler)
{
- TSRMLS_FETCH_FROM_CTX(handler->client->ts);
-
curl_easy_setopt(handler->handle, CURLOPT_NOPROGRESS, 1L);
#if PHP_HTTP_CURL_VERSION(7,32,0)
curl_easy_setopt(handler->handle, CURLOPT_XFERINFOFUNCTION, NULL);
#endif
curl_easy_setopt(handler->handle, CURLOPT_VERBOSE, 0L);
curl_easy_setopt(handler->handle, CURLOPT_DEBUGFUNCTION, NULL);
+}
+
+static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *handler)
+{
+ TSRMLS_FETCH_FROM_CTX(handler->client->ts);
+
+ php_http_client_curl_handler_clear(handler);
php_resource_factory_handle_dtor(handler->rf, handler->handle TSRMLS_CC);
php_resource_factory_free(&handler->rf);
efree(curl->timeout);
curl->timeout = NULL;
}
+ if (curl->evbase) {
+ event_base_free(curl->evbase);
+ curl->evbase = NULL;
+ }
#endif
curl->unfinished = 0;
php_http_client_curl_handler_dtor(handler);
}
-static php_resource_factory_t *create_rf(const char *url TSRMLS_DC)
+static php_resource_factory_t *create_rf(php_http_url_t *url TSRMLS_DC)
{
- php_url *purl;
+ php_persistent_handle_factory_t *pf;
php_resource_factory_t *rf = NULL;
+ char *id_str = NULL;
+ size_t id_len;
- if (!url || !*url) {
+ if (!url || (!url->host && !url->path)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot request empty URL");
return NULL;
}
- purl = php_url_parse(url);
+ id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(url->host), url->port ? url->port : 80);
- if (!purl) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse URL '%s'", url);
- return NULL;
+ pf = php_persistent_handle_concede(NULL, ZEND_STRL("http\\Client\\Curl\\Request"), id_str, id_len, NULL, NULL TSRMLS_CC);
+ if (pf) {
+ rf = php_resource_factory_init(NULL, php_persistent_handle_get_resource_factory_ops(), pf, (void (*)(void*)) php_persistent_handle_abandon);
} else {
- char *id_str = NULL;
- size_t id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(purl->host), purl->port ? purl->port : 80);
- php_persistent_handle_factory_t *pf = php_persistent_handle_concede(NULL, ZEND_STRL("http\\Client\\Curl\\Request"), id_str, id_len, NULL, NULL TSRMLS_CC);
-
- if (pf) {
- rf = php_resource_factory_init(NULL, php_persistent_handle_get_resource_factory_ops(), pf, (void (*)(void*)) php_persistent_handle_abandon);
- }
-
- php_url_free(purl);
- efree(id_str);
- }
-
- if (!rf) {
rf = php_resource_factory_init(NULL, &php_http_curle_resource_factory_ops, NULL, NULL);
}
+ efree(id_str);
+
return rf;
}
php_http_client_curl_handler_t *handler = enqueue->opaque;
TSRMLS_FETCH_FROM_CTX(h->ts);
+ php_http_client_curl_handler_clear(handler);
if (CURLM_OK == (rs = curl_multi_remove_handle(curl->handle, handler->handle))) {
zend_llist_del_element(&h->requests, handler->handle, (int (*)(void *, void *)) compare_queue);
return SUCCESS;
}
}
+static inline void php_http_client_curl_get_timeout(php_http_client_curl_t *curl, long max_tout, struct timeval *timeout)
+{
+ if ((CURLM_OK == curl_multi_timeout(curl->handle, &max_tout)) && (max_tout > 0)) {
+ timeout->tv_sec = max_tout / 1000;
+ timeout->tv_usec = (max_tout % 1000) * 1000;
+ } else {
+ timeout->tv_sec = 0;
+ timeout->tv_usec = 1000;
+ }
+}
+
#ifdef PHP_WIN32
# define SELECT_ERROR SOCKET_ERROR
#else
#if PHP_HTTP_HAVE_EVENT
if (curl->useevents) {
- TSRMLS_FETCH_FROM_CTX(h->ts);
+ if (!event_initialized(curl->timeout)) {
+ event_assign(curl->timeout, curl->evbase, CURL_SOCKET_TIMEOUT, 0, php_http_curlm_timeout_callback, h);
+ } else if (custom_timeout && timerisset(custom_timeout)) {
+ event_add(curl->timeout, custom_timeout);
+ } else if (!event_pending(curl->timeout, EV_TIMEOUT, NULL)) {
+ php_http_client_curl_get_timeout(curl, 1000, &timeout);
+ event_add(curl->timeout, &timeout);
+ }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "not implemented");
- return FAILURE;
+ event_base_loop(curl->evbase, EVLOOP_ONCE);
+
+ return SUCCESS;
}
#endif
if (custom_timeout && timerisset(custom_timeout)) {
timeout = *custom_timeout;
} else {
- long max_tout = 1000;
-
- if ((CURLM_OK == curl_multi_timeout(curl->handle, &max_tout)) && (max_tout > 0)) {
- timeout.tv_sec = max_tout / 1000;
- timeout.tv_usec = (max_tout % 1000) * 1000;
- } else {
- timeout.tv_sec = 0;
- timeout.tv_usec = 1000;
- }
+ php_http_client_curl_get_timeout(curl, 1000, &timeout);
}
if (MAX == -1) {
#if PHP_HTTP_HAVE_EVENT
if (curl->useevents) {
- TSRMLS_FETCH_FROM_CTX(h->ts);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "not implemented");
- return FAILURE;
- }
+ event_base_loop(curl->evbase, EVLOOP_NONBLOCK);
+ } else
#endif
-
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl->handle, &curl->unfinished));
php_http_curlm_responsehandler(h);
if (curl->useevents) {
php_http_curlm_timeout_callback(CURL_SOCKET_TIMEOUT, /*EV_READ|EV_WRITE*/0, h);
do {
- int ev_rc = event_base_dispatch(PHP_HTTP_G->curl.event_base);
+ int ev_rc = event_base_dispatch(curl->evbase);
#if DBG_EVENTS
fprintf(stderr, "%c", "X.0"[ev_rc+1]);
case PHP_HTTP_CLIENT_OPT_USE_EVENTS:
#if PHP_HTTP_HAVE_EVENT
if ((curl->useevents = *((zend_bool *) arg))) {
+ if (!curl->evbase) {
+ curl->evbase = event_base_new();
+ }
if (!curl->timeout) {
curl->timeout = ecalloc(1, sizeof(struct event));
}
* SSL Version Constants
*/
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1", CURL_SSLVERSION_TLSv1, CONST_CS|CONST_PERSISTENT);
+#if PHP_HTTP_CURL_VERSION(7,34,0)
+ REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_0", CURL_SSLVERSION_TLSv1_0, CONST_CS|CONST_PERSISTENT);
+ REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_1", CURL_SSLVERSION_TLSv1_1, CONST_CS|CONST_PERSISTENT);
+ REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_2", CURL_SSLVERSION_TLSv1_2, CONST_CS|CONST_PERSISTENT);
+#endif
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_SSLv2", CURL_SSLVERSION_SSLv2, CONST_CS|CONST_PERSISTENT);
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_SSLv3", CURL_SSLVERSION_SSLv3, CONST_CS|CONST_PERSISTENT);
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_ANY", CURL_SSLVERSION_DEFAULT, CONST_CS|CONST_PERSISTENT);
#endif
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_NTLM", CURLAUTH_NTLM, CONST_CS|CONST_PERSISTENT);
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_GSSNEG", CURLAUTH_GSSNEGOTIATE, CONST_CS|CONST_PERSISTENT);
+#if PHP_HTTP_CURL_VERSION(7,38,0)
+ REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_SPNEGO", CURLAUTH_NEGOTIATE, CONST_CS|CONST_PERSISTENT);
+#endif
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_ANY", CURLAUTH_ANY, CONST_CS|CONST_PERSISTENT);
/*
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5, CONST_CS|CONST_PERSISTENT);
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS5", CURLPROXY_SOCKS5, CONST_CS|CONST_PERSISTENT);
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_HTTP", CURLPROXY_HTTP, CONST_CS|CONST_PERSISTENT);
-# if PHP_HTTP_CURL_VERSION(7,19,4)
+#if PHP_HTTP_CURL_VERSION(7,19,4)
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_HTTP_1_0", CURLPROXY_HTTP_1_0, CONST_CS|CONST_PERSISTENT);
-# endif
+#endif
/*
* Post Redirection Constants
#if PHP_HTTP_CURL_VERSION(7,19,1)
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "POSTREDIR_301", CURL_REDIR_POST_301, CONST_CS|CONST_PERSISTENT);
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "POSTREDIR_302", CURL_REDIR_POST_302, CONST_CS|CONST_PERSISTENT);
+#if PHP_HTTP_CURL_VERSION(7,26,0)
+ REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "POSTREDIR_303", CURL_REDIR_POST_303, CONST_CS|CONST_PERSISTENT);
+#endif
REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "POSTREDIR_ALL", CURL_REDIR_POST_ALL, CONST_CS|CONST_PERSISTENT);
#endif
return SUCCESS;
}
-#if PHP_HTTP_HAVE_EVENT
-PHP_RINIT_FUNCTION(http_client_curl)
-{
- if (!PHP_HTTP_G->curl.event_base && !(PHP_HTTP_G->curl.event_base = event_base_new())) {
- return FAILURE;
- }
- return SUCCESS;
-}
-PHP_RSHUTDOWN_FUNCTION(http_client_curl)
-{
- if (PHP_HTTP_G->curl.event_base) {
- event_base_free(PHP_HTTP_G->curl.event_base);
- PHP_HTTP_G->curl.event_base = NULL;
- }
- return SUCCESS;
-}
-#endif /* PHP_HTTP_HAVE_EVENT */
-
#endif /* PHP_HTTP_HAVE_CURL */
/*