Skip to content

Commit 6f786eb

Browse files
author
Stefan Roehrich
committed
Commit patch as discussed on LinuxTag and posted to php-dev in June.
Disables zlib.output_compression for scripts with image/ content-type header (fixes bug #16109) and makes it possible to switch zlib.output_compression during script execution before the headers are sent. @- zlib.output_compression is disabled for "image/" content-type @ headers and can be changed during script execution. (Stefan)
1 parent 24b570d commit 6f786eb

File tree

3 files changed

+68
-20
lines changed

3 files changed

+68
-20
lines changed

ext/zlib/php_zlib.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ extern php_stream_wrapper php_stream_gzip_wrapper;
6666

6767
#define phpext_zlib_ptr zlib_module_ptr
6868

69+
#define CODING_GZIP 1
70+
#define CODING_DEFLATE 2
71+
6972
#endif /* PHP_ZLIB_H */
7073

7174
/*

ext/zlib/zlib.c

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@
7474
#endif
7575

7676
#define OS_CODE 0x03 /* FIXME */
77-
#define CODING_GZIP 1
78-
#define CODING_DEFLATE 2
7977
#define GZIP_HEADER_LENGTH 10
8078
#define GZIP_FOOTER_LENGTH 8
8179

@@ -144,6 +142,26 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression)
144142
return FAILURE;
145143
}
146144

145+
if(new_value == NULL)
146+
return FAILURE;
147+
148+
if(!strncasecmp(new_value, "off", sizeof("off"))) {
149+
new_value = "0";
150+
new_value_length = sizeof("0");
151+
} else if(!strncasecmp(new_value, "on", sizeof("on"))) {
152+
new_value = "4096";
153+
new_value_length = sizeof("4096");
154+
} else if(stage == PHP_INI_STAGE_RUNTIME &&
155+
strncmp(new_value, "0", sizeof("0")) && strncmp(new_value, "1", sizeof("1"))) {
156+
php_error(E_WARNING, "Cannot change zlib.output_compression buffer size during script execution");
157+
return FAILURE;
158+
}
159+
160+
if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) {
161+
php_error(E_WARNING, "Cannot change zlib.output_compression - headers already sent");
162+
return FAILURE;
163+
}
164+
147165
OnUpdateInt(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
148166

149167
return SUCCESS;
@@ -161,7 +179,7 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression_level)
161179

162180

163181
PHP_INI_BEGIN()
164-
STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdate_zlib_output_compression, output_compression, zend_zlib_globals, zlib_globals)
182+
STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression, zend_zlib_globals, zlib_globals)
165183
STD_PHP_INI_ENTRY("zlib.output_compression_level", "-1", PHP_INI_ALL, OnUpdate_zlib_output_compression_level, output_compression_level, zend_zlib_globals, zlib_globals)
166184
PHP_INI_END()
167185

@@ -197,6 +215,7 @@ PHP_MINIT_FUNCTION(zlib)
197215
PHP_RINIT_FUNCTION(zlib)
198216
{
199217
ZLIBG(ob_gzhandler_status) = 0;
218+
ZLIBG(ob_gzip_coding) = 0;
200219
switch (ZLIBG(output_compression)) {
201220
case 0:
202221
break;
@@ -947,11 +966,15 @@ static void php_gzip_output_handler(char *output, uint output_len, char **handle
947966
{
948967
zend_bool do_start, do_end;
949968

950-
do_start = (mode & PHP_OUTPUT_HANDLER_START ? 1 : 0);
951-
do_end = (mode & PHP_OUTPUT_HANDLER_END ? 1 : 0);
952-
if (php_deflate_string(output, output_len, handled_output, handled_output_len, ZLIBG(ob_gzip_coding), do_start, do_end, ZLIBG(output_compression_level) TSRMLS_CC)!=SUCCESS) {
953-
zend_error(E_ERROR, "Compression failed");
954-
}
969+
if (!ZLIBG(output_compression)) {
970+
*handled_output = NULL;
971+
} else {
972+
do_start = (mode & PHP_OUTPUT_HANDLER_START ? 1 : 0);
973+
do_end = (mode & PHP_OUTPUT_HANDLER_END ? 1 : 0);
974+
if (php_deflate_string(output, output_len, handled_output, handled_output_len, ZLIBG(ob_gzip_coding), do_start, do_end, ZLIBG(output_compression_level) TSRMLS_CC)!=SUCCESS) {
975+
zend_error(E_ERROR, "Compression failed");
976+
}
977+
}
955978
}
956979
/* }}} */
957980

@@ -968,20 +991,8 @@ int php_enable_output_compression(int buffer_size TSRMLS_DC)
968991
}
969992
convert_to_string_ex(a_encoding);
970993
if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
971-
if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1)==FAILURE) {
972-
return FAILURE;
973-
}
974-
if (sapi_add_header("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1)==FAILURE) {
975-
return FAILURE;
976-
}
977994
ZLIBG(ob_gzip_coding) = CODING_GZIP;
978995
} else if(php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
979-
if (sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1)==FAILURE) {
980-
return FAILURE;
981-
}
982-
if (sapi_add_header("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1)==FAILURE) {
983-
return FAILURE;
984-
}
985996
ZLIBG(ob_gzip_coding) = CODING_DEFLATE;
986997
} else {
987998
return FAILURE;

main/SAPI.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
#if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)
3131
#include "ext/pcre/php_pcre.h"
3232
#endif
33+
#if HAVE_ZLIB
34+
#include "ext/zlib/php_zlib.h"
35+
ZEND_EXTERN_MODULE_GLOBALS(zlib)
36+
#endif
3337
#ifdef ZTS
3438
#include "TSRM.h"
3539
#endif
@@ -485,6 +489,11 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
485489
if (!STRCASECMP(header_line, "Content-Type")) {
486490
char *ptr = colon_offset+1, *mimetype = NULL, *newheader;
487491
size_t len = header_line_len - (ptr - header_line), newlen;
492+
#if HAVE_ZLIB
493+
if(strncmp(ptr, "image/", sizeof("image/"))) {
494+
ZLIBG(output_compression) = 0;
495+
}
496+
#endif
488497
while (*ptr == ' ' && *ptr != '\0') {
489498
ptr++;
490499
}
@@ -633,6 +642,31 @@ SAPI_API int sapi_send_headers(TSRMLS_D)
633642
return SUCCESS;
634643
}
635644

645+
#if HAVE_ZLIB
646+
/* Add output compression headers at this late stage in order to make
647+
it possible to switch it off inside the script. */
648+
if (ZLIBG(output_compression)) {
649+
switch (ZLIBG(ob_gzip_coding)) {
650+
case CODING_GZIP:
651+
if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1)==FAILURE) {
652+
return FAILURE;
653+
}
654+
if (sapi_add_header("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1)==FAILURE) {
655+
return FAILURE;
656+
}
657+
break;
658+
case CODING_DEFLATE:
659+
if (sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1)==FAILURE) {
660+
return FAILURE;
661+
}
662+
if (sapi_add_header("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1)==FAILURE) {
663+
return FAILURE;
664+
}
665+
break;
666+
}
667+
}
668+
#endif
669+
636670
/* Success-oriented. We set headers_sent to 1 here to avoid an infinite loop
637671
* in case of an error situation.
638672
*/

0 commit comments

Comments
 (0)