X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=http_encoding_api.c;h=8ce0280ca22c5e0911d2e5115674f972b47ba27f;hp=959031d0bcf47b6631a89ffd50cae2ca2f9a09f6;hb=ad5f896b03adaa073134a00108a9cdf00720673a;hpb=e6eb95d3183f3a00257c9bb698ad74919e0d181a diff --git a/http_encoding_api.c b/http_encoding_api.c index 959031d..8ce0280 100644 --- a/http_encoding_api.c +++ b/http_encoding_api.c @@ -6,7 +6,7 @@ | modification, are permitted provided that the conditions mentioned | | in the accompanying LICENSE file are met. | +--------------------------------------------------------------------+ - | Copyright (c) 2004-2006, Michael Wallner | + | Copyright (c) 2004-2010, Michael Wallner | +--------------------------------------------------------------------+ */ @@ -158,66 +158,71 @@ PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t enco /* }}} */ /* {{{ int http_encoding_response_start(size_t) */ -PHP_HTTP_API int _http_encoding_response_start(size_t content_length TSRMLS_DC) +PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC) { - if ( php_ob_handler_used("ob_gzhandler" TSRMLS_CC) || - php_ob_handler_used("zlib output compression" TSRMLS_CC)) { + int response = HTTP_G->send.deflate.response; + int ohandler = php_ob_handler_used("ob_gzhandler" TSRMLS_CC) || php_ob_handler_used("zlib output compression" TSRMLS_CC); + + if (!ohandler && !ignore_http_ohandler) { + ohandler = php_ob_handler_used("ob_deflatehandler" TSRMLS_CC) || php_ob_handler_used("http deflate" TSRMLS_CC); + } + + if (response && !ohandler) { +#ifdef HTTP_HAVE_ZLIB + HashTable *selected; + zval zsupported; + HTTP_G->send.deflate.encoding = 0; - } else { - if (!HTTP_G->send.deflate.encoding) { - /* emit a content-length header */ - if (content_length) { - char cl_header_str[128]; - size_t cl_header_len; - cl_header_len = snprintf(cl_header_str, lenof(cl_header_str), "Content-Length: %zu", content_length); - http_send_header_string_ex(cl_header_str, cl_header_len, 1); - } - } else { -#ifndef HTTP_HAVE_ZLIB - HTTP_G->send.deflate.encoding = 0; - php_start_ob_buffer_named("ob_gzhandler", 0, 0 TSRMLS_CC); -#else - HashTable *selected; - zval zsupported; - - INIT_PZVAL(&zsupported); - array_init(&zsupported); - add_next_index_stringl(&zsupported, "gzip", lenof("gzip"), 1); - add_next_index_stringl(&zsupported, "x-gzip", lenof("x-gzip"), 1); - add_next_index_stringl(&zsupported, "deflate", lenof("deflate"), 1); - - HTTP_G->send.deflate.encoding = 0; + + INIT_PZVAL(&zsupported); + array_init(&zsupported); + add_next_index_stringl(&zsupported, "gzip", lenof("gzip"), 1); + add_next_index_stringl(&zsupported, "x-gzip", lenof("x-gzip"), 1); + add_next_index_stringl(&zsupported, "deflate", lenof("deflate"), 1); + + if ((selected = http_negotiate_encoding(&zsupported))) { + STATUS hs = FAILURE; + char *encoding = NULL; + ulong idx; - if ((selected = http_negotiate_encoding(&zsupported))) { - STATUS hs = FAILURE; - char *encoding = NULL; - ulong idx; - - if (HASH_KEY_IS_STRING == zend_hash_get_current_key(selected, &encoding, &idx, 0) && encoding) { - if (!strcmp(encoding, "gzip") || !strcmp(encoding, "x-gzip")) { - if (SUCCESS == (hs = http_send_header_string("Content-Encoding: gzip"))) { - HTTP_G->send.deflate.encoding = HTTP_ENCODING_GZIP; - } - } else if (!strcmp(encoding, "deflate")) { - if (SUCCESS == (hs = http_send_header_string("Content-Encoding: deflate"))) { - HTTP_G->send.deflate.encoding = HTTP_ENCODING_DEFLATE; - } + if (HASH_KEY_IS_STRING == zend_hash_get_current_key(selected, &encoding, &idx, 0) && encoding) { + if (!strcmp(encoding, "gzip") || !strcmp(encoding, "x-gzip")) { + if (SUCCESS == (hs = http_send_header_string("Content-Encoding: gzip"))) { + HTTP_G->send.deflate.encoding = HTTP_ENCODING_GZIP; } - if (SUCCESS == hs) { - http_send_header_string("Vary: Accept-Encoding"); + } else if (!strcmp(encoding, "deflate")) { + if (SUCCESS == (hs = http_send_header_string("Content-Encoding: deflate"))) { + HTTP_G->send.deflate.encoding = HTTP_ENCODING_DEFLATE; } } - - zend_hash_destroy(selected); - FREE_HASHTABLE(selected); + if (SUCCESS == hs) { + http_send_header_string("Vary: Accept-Encoding"); + } } - zval_dtor(&zsupported); - return HTTP_G->send.deflate.encoding; -#endif + zend_hash_destroy(selected); + FREE_HASHTABLE(selected); } + + zval_dtor(&zsupported); +#else + HTTP_G->send.deflate.encoding = 0; + php_start_ob_buffer_named("ob_gzhandler", 0, 0 TSRMLS_CC); +#endif /* HTTP_HAVE_ZLIB */ + } else if (content_length && !ohandler) { + /* emit a content-length header */ + phpstr header; + + phpstr_init(&header); + phpstr_appendf(&header, "Content-Length: %zu", content_length); + phpstr_fix(&header); + http_send_header_string_ex(PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1); + phpstr_dtor(&header); + } else { + HTTP_G->send.deflate.encoding = 0; } - return 0; + + return HTTP_G->send.deflate.encoding; } /* }}} */ @@ -325,9 +330,13 @@ retry_raw_inflate: Z.avail_in = data_len; switch (status = http_inflate_rounds(&Z, Z_NO_FLUSH, decoded, decoded_len)) { - case Z_OK: case Z_STREAM_END: + inflateEnd(&Z); return SUCCESS; + + case Z_OK: + status = Z_DATA_ERROR; + break; case Z_DATA_ERROR: /* raw deflated data? */ @@ -338,6 +347,10 @@ retry_raw_inflate: } } inflateEnd(&Z); + + if (decoded_len && *decoded) { + efree(*decoded); + } } http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not inflate data: %s", zError(status)); @@ -655,6 +668,8 @@ PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TS /* {{{ void http_ob_deflatehandler(char *, uint, char **, uint *, int) */ void _http_ob_deflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) { + int encoding; + *handled_output = NULL; *handled_output_len = 0; @@ -666,9 +681,11 @@ void _http_ob_deflatehandler(char *output, uint output_len, char **handled_outpu return; } - HTTP_G->send.deflate.encoding = !0; + HTTP_G->send.deflate.response = 1; + encoding = http_encoding_response_start(0, 1); + HTTP_G->send.deflate.response = 0; - switch (http_encoding_response_start(0)) { + switch (encoding) { case HTTP_ENCODING_GZIP: flags = HTTP_DEFLATE_TYPE_GZIP; break; @@ -686,7 +703,12 @@ void _http_ob_deflatehandler(char *output, uint output_len, char **handled_outpu } if (HTTP_G->send.deflate.stream) { - http_encoding_deflate_stream_update((http_encoding_stream *) HTTP_G->send.deflate.stream, output, output_len, handled_output, handled_output_len); + if (output_len) { + size_t tmp_len; + + http_encoding_deflate_stream_update((http_encoding_stream *) HTTP_G->send.deflate.stream, output, output_len, handled_output, &tmp_len); + *handled_output_len = tmp_len; + } if (mode & PHP_OUTPUT_HANDLER_END) { char *remaining = NULL; @@ -723,7 +745,12 @@ void _http_ob_inflatehandler(char *output, uint output_len, char **handled_outpu } if (HTTP_G->send.inflate.stream) { - http_encoding_inflate_stream_update((http_encoding_stream *) HTTP_G->send.inflate.stream, output, output_len, handled_output, handled_output_len); + if (output_len) { + size_t tmp_len; + + http_encoding_inflate_stream_update((http_encoding_stream *) HTTP_G->send.inflate.stream, output, output_len, handled_output, &tmp_len); + *handled_output_len = tmp_len; + } if (mode & PHP_OUTPUT_HANDLER_END) { char *remaining = NULL;