diff options
author | Aaron Piotrowski <aaron@trowski.com> | 2016-06-10 22:02:23 -0500 |
---|---|---|
committer | Aaron Piotrowski <aaron@trowski.com> | 2016-06-10 22:02:23 -0500 |
commit | e3c681aa5cc71122a8d2fae42e6513fc413ccac8 (patch) | |
tree | 5f1df62f7b666028edb0ee1adf083a52d63df45a /ext/soap/php_http.c | |
parent | fb4e3085cbaa76eb8f28eebf848a81d1c0190067 (diff) | |
parent | 792e89385ca6fc722a03590722eb7745a2374720 (diff) | |
download | php-git-e3c681aa5cc71122a8d2fae42e6513fc413ccac8.tar.gz |
Merge branch 'master' into throw-error-in-extensions
Diffstat (limited to 'ext/soap/php_http.c')
-rw-r--r-- | ext/soap/php_http.c | 179 |
1 files changed, 97 insertions, 82 deletions
diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 3b42a6bf06..7c9183613c 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2015 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -25,7 +25,7 @@ #include "ext/standard/php_rand.h" static char *get_http_header_value(char *headers, char *type); -static int get_http_body(php_stream *socketd, int close, char *headers, char **response, int *out_size); +static zend_string *get_http_body(php_stream *socketd, int close, char *headers); static zend_string *get_http_headers(php_stream *socketd); #define smart_str_append_const(str, const) \ @@ -326,25 +326,25 @@ static int in_domain(const char *host, const char *domain) } } -int make_http_soap_request(zval *this_ptr, - char *buf, - int buf_size, - char *location, - char *soapaction, - int soap_version, - zval *return_value) +int make_http_soap_request(zval *this_ptr, + zend_string *buf, + char *location, + char *soapaction, + int soap_version, + zval *return_value) { - char *request; + zend_string *request; smart_str soap_headers = {0}; smart_str soap_headers_z = {0}; - int request_size, err; + int err; php_url *phpurl = NULL; php_stream *stream; zval *trace, *tmp; int use_proxy = 0; int use_ssl; - char *http_body, *content_type, *http_version, *cookie_itt; - int http_body_size, http_close; + zend_string *http_body; + char *content_type, *http_version, *cookie_itt; + int http_close; zend_string *http_headers; char *connection; int http_1_1; @@ -363,8 +363,7 @@ int make_http_soap_request(zval *this_ptr, return FALSE; } - request = buf; - request_size = buf_size; + request = buf; /* Compress request */ if ((tmp = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "compression", sizeof("compression")-1)) != NULL && Z_TYPE_P(tmp) == IS_LONG) { int level = Z_LVAL_P(tmp) & 0x0f; @@ -381,7 +380,7 @@ int make_http_soap_request(zval *this_ptr, zval params[3]; int n; - ZVAL_STRINGL(¶ms[0], buf, buf_size); + ZVAL_STR_COPY(¶ms[0], buf); ZVAL_LONG(¶ms[1], level); if (kind == SOAP_COMPRESSION_DEFLATE) { n = 2; @@ -397,13 +396,13 @@ int make_http_soap_request(zval *this_ptr, Z_TYPE(retval) == IS_STRING) { zval_ptr_dtor(¶ms[0]); zval_ptr_dtor(&func); -// TODO: free retval ??? - request = Z_STRVAL(retval); - request_size = Z_STRLEN(retval); + request = Z_STR(retval); } else { zval_ptr_dtor(¶ms[0]); zval_ptr_dtor(&func); - if (request != buf) {efree(request);} + if (request != buf) { + zend_string_release(request); + } smart_str_free(&soap_headers_z); return FALSE; } @@ -439,7 +438,9 @@ int make_http_soap_request(zval *this_ptr, try_again: if (phpurl == NULL || phpurl->host == NULL) { if (phpurl != NULL) {php_url_free(phpurl);} - if (request != buf) {efree(request);} + if (request != buf) { + zend_string_release(request); + } add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL); smart_str_free(&soap_headers_z); return FALSE; @@ -450,7 +451,9 @@ try_again: use_ssl = 1; } else if (phpurl->scheme == NULL || strcmp(phpurl->scheme, "http") != 0) { php_url_free(phpurl); - if (request != buf) {efree(request);} + if (request != buf) { + zend_string_release(request); + } add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL); smart_str_free(&soap_headers_z); return FALSE; @@ -460,7 +463,9 @@ try_again: PG(allow_url_fopen) = 1; if (use_ssl && php_stream_locate_url_wrapper("https://", NULL, STREAM_LOCATE_WRAPPERS_ONLY) == NULL) { php_url_free(phpurl); - if (request != buf) {efree(request);} + if (request != buf) { + zend_string_release(request); + } add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL); PG(allow_url_fopen) = old_allow_url_fopen; smart_str_free(&soap_headers_z); @@ -507,10 +512,13 @@ try_again: if (stream) { php_stream_auto_cleanup(stream); add_property_resource(this_ptr, "httpsocket", stream->res); + GC_REFCOUNT(stream->res)++; add_property_long(this_ptr, "_use_proxy", use_proxy); } else { php_url_free(phpurl); - if (request != buf) {efree(request);} + if (request != buf) { + zend_string_release(request); + } add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL); PG(allow_url_fopen) = old_allow_url_fopen; smart_str_free(&soap_headers_z); @@ -524,6 +532,7 @@ try_again: zend_resource *ret = zend_register_resource(phpurl, le_url); add_property_resource(this_ptr, "httpurl", ret); + GC_REFCOUNT(ret)++; /*zend_list_addref(ret);*/ if (context && @@ -618,7 +627,7 @@ try_again: } } smart_str_append_const(&soap_headers,"Content-Length: "); - smart_str_append_long(&soap_headers, request_size); + smart_str_append_long(&soap_headers, request->len); smart_str_append_const(&soap_headers, "\r\n"); /* HTTP Authentication */ @@ -691,16 +700,6 @@ try_again: PHP_MD5Update(&md5ctx, (unsigned char*)phpurl->query, strlen(phpurl->query)); } - /* TODO: Support for qop="auth-int" */ -/* - if (zend_hash_find(Z_ARRVAL_PP(digest), "qop", sizeof("qop"), (void **)&tmp) == SUCCESS && - Z_TYPE_PP(tmp) == IS_STRING && - Z_STRLEN_PP(tmp) == sizeof("auth-int")-1 && - stricmp(Z_STRVAL_PP(tmp), "auth-int") == 0) { - PHP_MD5Update(&md5ctx, ":", 1); - PHP_MD5Update(&md5ctx, HEntity, HASHHEXLEN); - } -*/ PHP_MD5Final(hash, &md5ctx); make_digest(HA2, hash); @@ -813,18 +812,21 @@ try_again: zend_hash_internal_pointer_reset(Z_ARRVAL_P(cookies)); smart_str_append_const(&soap_headers, "Cookie: "); for (i = 0; i < n; i++) { + zend_ulong numindx; + int res = zend_hash_get_current_key(Z_ARRVAL_P(cookies), &key, &numindx); data = zend_hash_get_current_data(Z_ARRVAL_P(cookies)); - zend_hash_get_current_key_ex(Z_ARRVAL_P(cookies), &key, NULL, NULL); - - if (Z_TYPE_P(data) == IS_ARRAY) { + + if (res == HASH_KEY_IS_STRING && Z_TYPE_P(data) == IS_ARRAY) { zval *value; if ((value = zend_hash_index_find(Z_ARRVAL_P(data), 0)) != NULL && Z_TYPE_P(value) == IS_STRING) { zval *tmp; if (((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 1)) == NULL || + Z_TYPE_P(tmp) != IS_STRING || strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_P(tmp),Z_STRLEN_P(tmp)) == 0) && ((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 2)) == NULL || + Z_TYPE_P(tmp) != IS_STRING || in_domain(phpurl->host,Z_STRVAL_P(tmp))) && (use_ssl || (tmp = zend_hash_index_find(Z_ARRVAL_P(data), 3)) == NULL)) { smart_str_append(&soap_headers, key); @@ -848,12 +850,14 @@ try_again: (Z_TYPE_P(trace) == IS_TRUE || (Z_TYPE_P(trace) == IS_LONG && Z_LVAL_P(trace) != 0))) { add_property_stringl(this_ptr, "__last_request_headers", ZSTR_VAL(soap_headers.s), ZSTR_LEN(soap_headers.s)); } - smart_str_appendl(&soap_headers, request, request_size); + smart_str_appendl(&soap_headers, request->val, request->len); smart_str_0(&soap_headers); err = php_stream_write(stream, ZSTR_VAL(soap_headers.s), ZSTR_LEN(soap_headers.s)); if (err != ZSTR_LEN(soap_headers.s)) { - if (request != buf) {efree(request);} + if (request != buf) { + zend_string_release(request); + } php_stream_close(stream); zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpurl", sizeof("httpurl")-1); zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket")-1); @@ -880,7 +884,9 @@ try_again: do { http_headers = get_http_headers(stream); if (!http_headers) { - if (request != buf) {efree(request);} + if (request != buf) { + zend_string_release(request); + } php_stream_close(stream); zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket")-1); zend_hash_str_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy")-1); @@ -1050,8 +1056,12 @@ try_again: } } - if (!get_http_body(stream, http_close, ZSTR_VAL(http_headers), &http_body, &http_body_size)) { - if (request != buf) {efree(request);} + + http_body = get_http_body(stream, http_close, ZSTR_VAL(http_headers)); + if (!http_body) { + if (request != buf) { + zend_string_release(request); + } php_stream_close(stream); zend_string_release(http_headers); zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket")-1); @@ -1064,7 +1074,9 @@ try_again: return FALSE; } - if (request != buf) {efree(request);} + if (request != buf) { + zend_string_release(request); + } if (http_close) { php_stream_close(stream); @@ -1082,7 +1094,7 @@ try_again: if (new_url != NULL) { zend_string_release(http_headers); - efree(http_body); + zend_string_release(http_body); efree(loc); if (new_url->scheme == NULL && new_url->path != NULL) { new_url->scheme = phpurl->scheme ? estrdup(phpurl->scheme) : NULL; @@ -1190,7 +1202,7 @@ try_again: efree(auth); zend_string_release(http_headers); - efree(http_body); + zend_string_release(http_body); goto try_again; } @@ -1240,15 +1252,15 @@ try_again: strcmp(content_encoding,"x-gzip") == 0) && zend_hash_str_exists(EG(function_table), "gzinflate", sizeof("gzinflate")-1)) { ZVAL_STRING(&func, "gzinflate"); - ZVAL_STRINGL(¶ms[0], http_body+10, http_body_size-10); + ZVAL_STRINGL(¶ms[0], http_body->val+10, http_body->len-10); } else if (strcmp(content_encoding,"deflate") == 0 && zend_hash_str_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress")-1)) { ZVAL_STRING(&func, "gzuncompress"); - ZVAL_STRINGL(¶ms[0], http_body, http_body_size); + ZVAL_STR_COPY(¶ms[0], http_body); } else { efree(content_encoding); zend_string_release(http_headers); - efree(http_body); + zend_string_release(http_body); if (http_msg) { efree(http_msg); } @@ -1259,14 +1271,14 @@ try_again: Z_TYPE(retval) == IS_STRING) { zval_ptr_dtor(¶ms[0]); zval_ptr_dtor(&func); - efree(http_body); + zend_string_release(http_body); ZVAL_COPY_VALUE(return_value, &retval); } else { zval_ptr_dtor(¶ms[0]); zval_ptr_dtor(&func); efree(content_encoding); zend_string_release(http_headers); - efree(http_body); + zend_string_release(http_body); add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL); if (http_msg) { efree(http_msg); @@ -1275,11 +1287,7 @@ try_again: } efree(content_encoding); } else { - // TODO: avoid reallocation ??? - //???*buffer = http_body; - //???*buffer_len = http_body_size; - ZVAL_STRINGL(return_value, http_body, http_body_size); - efree(http_body); + ZVAL_STR(return_value, http_body); } zend_string_release(http_headers); @@ -1356,9 +1364,10 @@ static char *get_http_header_value(char *headers, char *type) return NULL; } -static int get_http_body(php_stream *stream, int close, char *headers, char **response, int *out_size) +static zend_string* get_http_body(php_stream *stream, int close, char *headers) { - char *header, *http_buf = NULL; + zend_string *http_buf = NULL; + char *header; int header_close = close, header_chunked = 0, header_length = 0, http_buf_size = 0; if (!close) { @@ -1379,11 +1388,7 @@ static int get_http_body(php_stream *stream, int close, char *headers, char **r efree(header); if (!header_length && !header_chunked) { /* Empty response */ - http_buf = emalloc(1); - http_buf[0] = '\0'; - (*response) = http_buf; - (*out_size) = 0; - return TRUE; + return ZSTR_EMPTY_ALLOC(); } } @@ -1401,13 +1406,20 @@ static int get_http_body(php_stream *stream, int close, char *headers, char **r int len_size = 0; if (http_buf_size + buf_size + 1 < 0) { - efree(http_buf); - return FALSE; + if (http_buf) { + zend_string_release(http_buf); + } + return NULL; + } + + if (http_buf) { + http_buf = zend_string_realloc(http_buf, http_buf_size + buf_size, 0); + } else { + http_buf = zend_string_alloc(buf_size, 0); } - http_buf = erealloc(http_buf, http_buf_size + buf_size + 1); while (len_size < buf_size) { - int len_read = php_stream_read(stream, http_buf + http_buf_size, buf_size - len_size); + int len_read = php_stream_read(stream, http_buf->val + http_buf_size, buf_size - len_size); if (len_read <= 0) { /* Error or EOF */ done = TRUE; @@ -1425,17 +1437,17 @@ static int get_http_body(php_stream *stream, int close, char *headers, char **r if (ch != '\n') { /* Somthing wrong in chunked encoding */ if (http_buf) { - efree(http_buf); + zend_string_release(http_buf); } - return FALSE; + return NULL; } } } else { /* Somthing wrong in chunked encoding */ if (http_buf) { - efree(http_buf); + zend_string_release(http_buf); } - return FALSE; + return NULL; } if (buf_size == 0) { done = TRUE; @@ -1456,16 +1468,16 @@ static int get_http_body(php_stream *stream, int close, char *headers, char **r } if (http_buf == NULL) { - http_buf = emalloc(1); + return ZSTR_EMPTY_ALLOC(); } } else if (header_length) { if (header_length < 0 || header_length >= INT_MAX) { - return FALSE; + return NULL; } - http_buf = safe_emalloc(1, header_length, 1); + http_buf = zend_string_alloc(header_length, 0); while (http_buf_size < header_length) { - int len_read = php_stream_read(stream, http_buf + http_buf_size, header_length - http_buf_size); + int len_read = php_stream_read(stream, http_buf->val + http_buf_size, header_length - http_buf_size); if (len_read <= 0) { break; } @@ -1474,20 +1486,23 @@ static int get_http_body(php_stream *stream, int close, char *headers, char **r } else if (header_close) { do { int len_read; - http_buf = erealloc(http_buf, http_buf_size + 4096 + 1); - len_read = php_stream_read(stream, http_buf + http_buf_size, 4096); + if (http_buf) { + http_buf = zend_string_realloc(http_buf, http_buf_size + 4096, 0); + } else { + http_buf = zend_string_alloc(4096, 0); + } + len_read = php_stream_read(stream, http_buf->val + http_buf_size, 4096); if (len_read > 0) { http_buf_size += len_read; } } while(!php_stream_eof(stream)); } else { - return FALSE; + return NULL; } - http_buf[http_buf_size] = '\0'; - (*response) = http_buf; - (*out_size) = http_buf_size; - return TRUE; + http_buf->val[http_buf_size] = '\0'; + http_buf->len = http_buf_size; + return http_buf; } static zend_string *get_http_headers(php_stream *stream) |