implement restrictions on TE
[m6w6/ext-http] / php_http_client_curl.c
index 02c72ac5b5e4378e0373316639d2fb76b15959ad..c6e80b45c237a033a048c248693db84b8362d069 100644 (file)
@@ -70,6 +70,7 @@ typedef struct php_http_client_curl_handler {
        struct {
                HashTable cache;
 
+               struct curl_slist *proxyheaders;
                struct curl_slist *headers;
                struct curl_slist *resolve;
                php_http_buffer_t cookies;
@@ -593,8 +594,9 @@ static int compare_queue(php_http_client_enqueue_t *e, void *handle)
 
 static php_http_message_t *php_http_curlm_responseparser(php_http_client_curl_handler_t *h TSRMLS_DC)
 {
-       php_http_message_t *response = NULL;
+       php_http_message_t *response;
        php_http_header_parser_t parser;
+       zval *zh;
 
        response = php_http_message_init(NULL, 0, h->response.body TSRMLS_CC);
        php_http_header_parser_init(&parser TSRMLS_CC);
@@ -613,6 +615,22 @@ static php_http_message_t *php_http_curlm_responseparser(php_http_client_curl_ha
        }
        php_http_message_body_addref(h->response.body);
 
+       /* let's update the response headers */
+       if ((zh = php_http_message_header(response, ZEND_STRL("Content-Length"), 1))) {
+               zend_hash_update(&response->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), &zh, sizeof(zval *), NULL);
+       }
+       if ((zh = php_http_message_header(response, ZEND_STRL("Transfer-Encoding"), 0))) {
+               zend_hash_update(&response->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &zh, sizeof(zval *), NULL);
+               zend_hash_del(&response->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
+       }
+       if ((zh = php_http_message_header(response, ZEND_STRL("Content-Range"), 0))) {
+               zend_hash_update(&response->hdrs, "X-Original-Content-Range", sizeof("X-Original-Content-Range"), &zh, sizeof(zval *), NULL);
+               zend_hash_del(&response->hdrs, "Content-Range", sizeof("Content-Range"));
+       }
+       if ((zh = php_http_message_header(response, ZEND_STRL("Content-Encoding"), 0))) {
+               zend_hash_update(&response->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), &zh, sizeof(zval *), NULL);
+               zend_hash_del(&response->hdrs, "Content-Encoding", sizeof("Content-Encoding"));
+       }
        php_http_message_update_headers(response);
 
        return response;
@@ -638,8 +656,10 @@ static void php_http_curlm_responsehandler(php_http_client_t *context)
                                php_http_client_curl_handler_t *handler = enqueue->opaque;
                                php_http_message_t *response = php_http_curlm_responseparser(handler TSRMLS_CC);
 
-                               context->callback.response.func(context->callback.response.arg, context, &handler->queue, &response);
-                               php_http_message_free(&response);
+                               if (response) {
+                                       context->callback.response.func(context->callback.response.arg, context, &handler->queue, &response);
+                                       php_http_message_free(&response);
+                               }
                        }
                }
        } while (remaining);
@@ -1076,6 +1096,43 @@ static STATUS php_http_curle_option_set_portrange(php_http_option_t *opt, zval *
        return SUCCESS;
 }
 
+#if PHP_HTTP_CURL_VERSION(7,37,0)
+static STATUS php_http_curle_option_set_proxyheader(php_http_option_t *opt, zval *val, void *userdata)
+{
+       php_http_client_curl_handler_t *curl = userdata;
+       TSRMLS_FETCH_FROM_CTX(curl->client->ts);
+
+       if (val && Z_TYPE_P(val) != IS_NULL) {
+               php_http_array_hashkey_t header_key = php_http_array_hashkey_init(0);
+               zval **header_val, *header_cpy;
+               HashPosition pos;
+               php_http_buffer_t header;
+
+               php_http_buffer_init(&header);
+               FOREACH_KEYVAL(pos, val, header_key, header_val) {
+                       if (header_key.type == HASH_KEY_IS_STRING) {
+                               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.proxyheaders = curl_slist_append(curl->options.proxyheaders, header.data);
+                               php_http_buffer_reset(&header);
+
+                               zval_ptr_dtor(&header_cpy);
+                       }
+               }
+               php_http_buffer_dtor(&header);
+       }
+       if (CURLE_OK != curl_easy_setopt(curl->handle, CURLOPT_PROXYHEADER, curl->options.proxyheaders)) {
+               return FAILURE;
+       }
+       if (CURLE_OK != curl_easy_setopt(curl->handle, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE)) {
+               curl_easy_setopt(curl->handle, CURLOPT_PROXYHEADER, NULL);
+               return FAILURE;
+       }
+       return SUCCESS;
+}
+#endif
+
 #if PHP_HTTP_CURL_VERSION(7,21,3)
 static STATUS php_http_curle_option_set_resolve(php_http_option_t *opt, zval *val, void *userdata)
 {
@@ -1127,6 +1184,12 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
        php_http_option_register(registry, ZEND_STRL("noproxy"), CURLOPT_NOPROXY, IS_STRING);
 #endif
 
+#if PHP_HTTP_CURL_VERSION(7,37,0)
+       if ((opt = php_http_option_register(registry, ZEND_STRL("proxyheader"), CURLOPT_PROXYHEADER, IS_ARRAY))) {
+               opt->setter = php_http_curle_option_set_proxyheader;
+       }
+#endif
+
        /* dns */
        if ((opt = php_http_option_register(registry, ZEND_STRL("dns_cache_timeout"), CURLOPT_DNS_CACHE_TIMEOUT, IS_LONG))) {
                Z_LVAL(opt->defval) = 60;
@@ -1381,6 +1444,12 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
                if ((opt = php_http_option_register(registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, IS_BOOL))) {
                        ZVAL_BOOL(&opt->defval, 1);
                }
+#endif
+#if PHP_HTTP_CURL_VERSION(7,39,0)
+               if ((opt = php_http_option_register(registry, ZEND_STRL("pinned_publickey"), CURLOPT_PINNEDPUBLICKEY, IS_STRING))) {
+                       opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+                       opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
+               }
 #endif
        }
 }
@@ -1525,6 +1594,10 @@ static STATUS php_http_client_curl_handler_reset(php_http_client_curl_handler_t
                curl_slist_free_all(curl->options.headers);
                curl->options.headers = NULL;
        }
+       if (curl->options.proxyheaders) {
+               curl_slist_free_all(curl->options.proxyheaders);
+               curl->options.proxyheaders = NULL;
+       }
 
        php_http_buffer_reset(&curl->options.cookies);
        php_http_buffer_reset(&curl->options.ranges);