summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeev Suraski <zeev@php.net>2000-11-13 18:54:37 +0000
committerZeev Suraski <zeev@php.net>2000-11-13 18:54:37 +0000
commit0f7f5c2c0e616445d14b49641e85dbddcc1651e5 (patch)
tree83f0bce3ba6ba891798d828e5ad1c0334739513e
parent9b42296babc97defd3b7635b395506d5539aae20 (diff)
downloadphp-git-0f7f5c2c0e616445d14b49641e85dbddcc1651e5.tar.gz
- Import Jade Nicoletti's transparent gzip encoding support as an output
handler. Works quite nicely! - Fix buglets in output buffering - Add output_handler INI directive
-rw-r--r--NEWS3
-rw-r--r--ext/zlib/php_zlib.h20
-rw-r--r--ext/zlib/zlib.c242
-rw-r--r--main/SAPI.c5
-rw-r--r--main/SAPI.h3
-rw-r--r--main/main.c15
-rw-r--r--main/php_globals.h3
-rw-r--r--php.ini-dist6
-rw-r--r--php.ini-optimized6
-rw-r--r--php.ini-recommended6
-rw-r--r--sapi/apache/sapi_apache.c2
-rw-r--r--sapi/cgi/cgi_main.c7
12 files changed, 288 insertions, 30 deletions
diff --git a/NEWS b/NEWS
index e14c2e9d87..038b2d019e 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@ PHP 4.0 NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2000, Version 4.0.4
+- Added 'output_handler' INI directive (Zeev)
+- Fixed some buglets in the output buffering mechanism (Zeev)
+- Added transparent gzip compression support (Jade Nicoletti, Zeev)
- Major overhaul of domxml. Added basic XPath support as well (Uwe)
- Added 'r' flag to date() which generates an RFC822 formatted date, e.g.
"Thu, 9 Nov 2000 16:33:01 -0500" (Colin)
diff --git a/ext/zlib/php_zlib.h b/ext/zlib/php_zlib.h
index 518ae2543e..b856fc9fd0 100644
--- a/ext/zlib/php_zlib.h
+++ b/ext/zlib/php_zlib.h
@@ -22,10 +22,16 @@
#ifndef PHP_ZLIB_H
#define PHP_ZLIB_H
-#if HAVE_ZLIB
+#include <zlib.h>
+
typedef struct {
int gzgetss_state;
+
+ /* variables for transparent gzip encoding */
+ int compression_coding;
+ z_stream stream;
+ uLong crc;
} php_zlib_globals;
extern zend_module_entry php_zlib_module_entry;
@@ -52,21 +58,25 @@ PHP_FUNCTION(gzcompress);
PHP_FUNCTION(gzuncompress);
PHP_FUNCTION(gzdeflate);
PHP_FUNCTION(gzinflate);
+PHP_FUNCTION(gzencode);
+PHP_FUNCTION(ob_gzhandler);
#ifdef ZTS
#define ZLIBLS_D php_zlib_globals *zlib_globals
+#define ZLIBLS_DC , ZLIBLS_D
+#define ZLIBLS_C zlib_globals
+#define ZLIBLS_CC , ZLIBLS_C
#define ZLIBG(v) (zlib_globals->v)
#define ZLIBLS_FETCH() php_zlib_globals *zlib_globals = ts_resource(zlib_globals_id)
#else
#define ZLIBLS_D
+#define ZLIBLS_DC
+#define ZLIBLS_C
+#define ZLIBLS_CC
#define ZLIBG(v) (zlib_globals.v)
#define ZLIBLS_FETCH()
#endif
-#else
-#define zlib_module_ptr NULL
-#endif /* HAVE_ZLIB */
-
#define phpext_zlib_ptr zlib_module_ptr
#endif /* PHP_ZLIB_H */
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 7f4d4ec410..f70a911624 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -29,6 +29,7 @@
#endif
#include "php.h"
+#include "SAPI.h"
#include <stdlib.h>
#include <errno.h>
@@ -57,12 +58,10 @@
#include <pwd.h>
#endif
#endif
-#if HAVE_ZLIB
#if defined(HAVE_UNISTD_H) && defined(PHP_WIN32)
#undef HAVE_UNISTD_H
#endif
-#include <zlib.h>
#ifdef COMPILE_DL_ZLIB
#ifndef PUTS
@@ -86,8 +85,14 @@ static php_zlib_globals zlib_globals;
static FILE *zlib_fopen_wrapper(char *path, char *mode, int options, int *issock, int *socketd, char **opened_path);
#endif
+#define OS_CODE 0x03 /* FIXME */
+#define CODING_GZIP 1
+#define CODING_DEFLATE 2
+
/* True globals, no need for thread safety */
static int le_zp;
+static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
function_entry php_zlib_functions[] = {
PHP_FE(readgzfile, NULL)
@@ -109,6 +114,8 @@ function_entry php_zlib_functions[] = {
PHP_FE(gzuncompress, NULL)
PHP_FE(gzdeflate, NULL)
PHP_FE(gzinflate, NULL)
+ PHP_FE(gzencode, NULL)
+ PHP_FE(ob_gzhandler, NULL)
{NULL, NULL, NULL}
};
@@ -158,6 +165,9 @@ PHP_MINIT_FUNCTION(zlib)
}
#endif
+ REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT);
+
return SUCCESS;
}
@@ -201,7 +211,8 @@ static gzFile php_gzopen_wrapper(char *path, char *mode, int options)
/* {{{ proto array gzfile(string filename [, int use_include_path])
Read und uncompress entire .gz-file into an array */
-PHP_FUNCTION(gzfile) {
+PHP_FUNCTION(gzfile)
+{
pval **filename, **arg2;
gzFile zp;
char *slashed, buf[8192];
@@ -257,7 +268,8 @@ PHP_FUNCTION(gzfile) {
/* {{{ proto int gzopen(string filename, string mode [, int use_include_path])
Open a .gz-file and return a .gz-file pointer */
-PHP_FUNCTION(gzopen) {
+PHP_FUNCTION(gzopen)
+{
pval **arg1, **arg2, **arg3;
gzFile *zp;
char *p;
@@ -303,7 +315,8 @@ PHP_FUNCTION(gzopen) {
/* {{{ proto int gzclose(int zp)
Close an open .gz-file pointer */
-PHP_FUNCTION(gzclose) {
+PHP_FUNCTION(gzclose)
+{
pval **arg1;
gzFile *zp;
@@ -318,7 +331,8 @@ PHP_FUNCTION(gzclose) {
/* {{{ proto int gzeof(int zp)
Test for end-of-file on a .gz-file pointer */
-PHP_FUNCTION(gzeof) {
+PHP_FUNCTION(gzeof)
+{
pval **arg1;
gzFile *zp;
@@ -337,7 +351,8 @@ PHP_FUNCTION(gzeof) {
/* {{{ proto string gzgets(int zp, int length)
Get a line from .gz-file pointer */
-PHP_FUNCTION(gzgets) {
+PHP_FUNCTION(gzgets)
+{
pval **arg1, **arg2;
gzFile *zp;
int len;
@@ -373,7 +388,8 @@ PHP_FUNCTION(gzgets) {
/* {{{ proto string gzgetc(int zp)
Get a character from .gz-file pointer */
-PHP_FUNCTION(gzgetc) {
+PHP_FUNCTION(gzgetc)
+{
pval **arg1;
gzFile *zp;
int c;
@@ -456,7 +472,8 @@ PHP_FUNCTION(gzgetss)
/* {{{ proto int gzwrite(int zp, string str [, int length])
Binary-safe .gz-file write */
-PHP_FUNCTION(gzwrite) {
+PHP_FUNCTION(gzwrite)
+{
pval **arg1, **arg2, **arg3=NULL;
gzFile *zp;
int ret;
@@ -502,7 +519,8 @@ PHP_FUNCTION(gzwrite) {
/* {{{ proto int gzrewind(int zp)
Rewind the position of a .gz-file pointer */
-PHP_FUNCTION(gzrewind) {
+PHP_FUNCTION(gzrewind)
+{
pval **arg1;
gzFile *zp;
@@ -519,7 +537,8 @@ PHP_FUNCTION(gzrewind) {
/* {{{ proto int gztell(int zp)
Get .gz-file pointer's read/write position */
-PHP_FUNCTION(gztell) {
+PHP_FUNCTION(gztell)
+{
pval **arg1;
long pos;
gzFile *zp;
@@ -537,7 +556,8 @@ PHP_FUNCTION(gztell) {
/* {{{ proto int gzseek(int zp, int offset)
Seek on a file pointer */
-PHP_FUNCTION(gzseek) {
+PHP_FUNCTION(gzseek)
+{
pval **arg1, **arg2;
int ret;
gzFile *zp;
@@ -559,7 +579,8 @@ PHP_FUNCTION(gzseek) {
*/
/* {{{ proto int readgzfile(string filename [, int use_include_path])
Output a .gz-file */
-PHP_FUNCTION(readgzfile) {
+PHP_FUNCTION(readgzfile)
+{
pval **arg1, **arg2;
char buf[8192];
gzFile *zp;
@@ -610,7 +631,8 @@ PHP_FUNCTION(readgzfile) {
*/
/* {{{ proto int gzpassthru(int zp)
Output all remaining data from a .gz-file pointer */
-PHP_FUNCTION(gzpassthru) {
+PHP_FUNCTION(gzpassthru)
+{
pval **arg1;
gzFile *zp;
char buf[8192];
@@ -992,8 +1014,198 @@ static FILE *zlib_fopen_wrapper(char *path, char *mode, int options, int *issock
#endif
+static int php_do_deflate(uint str_length, Bytef **p_buffer, uint *p_buf_used ZLIBLS_DC)
+{
+ Bytef *buffer;
+ uInt prev_outlen, outlen;
+ int err;
+
+ outlen = sizeof(char) * (str_length * 1.001 + 12);
+ buffer = (Bytef *) emalloc(outlen+10+8); /* 10+8 for the header and trailer */
+
+ ZLIBG(stream).next_out = buffer+10;
+ ZLIBG(stream).avail_out = outlen;
+
+ err = deflate(&ZLIBG(stream), Z_NO_FLUSH);
+ while (err == Z_OK && !ZLIBG(stream).avail_out) {
+ prev_outlen = outlen;
+ outlen *= 3;
+ buffer = realloc(buffer, outlen+10+8);
+
+ ZLIBG(stream).next_out = buffer+10 + prev_outlen;
+ ZLIBG(stream).avail_out = prev_outlen * 2;
+
+ err = deflate(&ZLIBG(stream), Z_NO_FLUSH);
+ }
+
+ err = deflate(&ZLIBG(stream), Z_FINISH);
+
+ *p_buffer = buffer;
+ *p_buf_used = outlen - ZLIBG(stream).avail_out;
+ return err;
+}
+
+
+int php_deflate_string(const char *str, uint str_length, char **newstr, uint *new_length, int coding)
+{
+ Bytef *buffer;
+ uInt buf_used;
+ int err;
+ Bytef header_buffer[11];
+ Bytef trailer_buffer[9];
+ ZLIBLS_FETCH();
+
+ ZLIBG(compression_coding) = coding;
+
+ ZLIBG(stream).zalloc = Z_NULL;
+ ZLIBG(stream).zfree = Z_NULL;
+ ZLIBG(stream).opaque = Z_NULL;
+
+ switch (coding) {
+ case CODING_GZIP:
+ /* windowBits is passed < 0 to suppress zlib header & trailer */
+ if (deflateInit2(&ZLIBG(stream), Z_DEFAULT_COMPRESSION, Z_DEFLATED,
+ -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)
+ != Z_OK) {
+ /* TODO: print out error */
+ return FAILURE;
+ }
+
+ /*
+ sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1);
+ sapi_send_headers();
+ */
+
+ /* Write a very simple .gz header: */
+ sprintf(header_buffer, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0],
+ gz_magic[1], Z_DEFLATED, 0 /*flags*/,
+ 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+ ZLIBG(crc) = crc32(0L, Z_NULL, 0);
+ break;
+ case CODING_DEFLATE:
+ if (deflateInit(&ZLIBG(stream), Z_DEFAULT_COMPRESSION) != Z_OK) {
+ /* TODO: print out error */
+ return FAILURE;
+ }
+ /*
+ sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1);
+ */
+ break;
+ }
+
+
+ ZLIBG(stream).next_in = (Bytef*) str;
+ ZLIBG(stream).avail_in = (uInt) str_length;
+
+ if (ZLIBG(compression_coding) == 1) {
+ ZLIBG(crc) = crc32(ZLIBG(crc), (const Bytef *)str, str_length);
+ }
+
+ err = php_do_deflate(str_length, &buffer, &buf_used ZLIBLS_CC);
+ /* TODO: error handling (err may be Z_STREAM_ERROR, Z_BUF_ERROR, ?) */
+
+
+ if (ZLIBG(compression_coding) == 1) {
+ /* write crc & stream.total_in in LSB order */
+ sprintf(trailer_buffer, "%c%c%c%c%c%c%c%c",
+ (char) ZLIBG(crc) & 0xFF,
+ (char) (ZLIBG(crc) >> 8) & 0xFF,
+ (char) (ZLIBG(crc) >> 16) & 0xFF,
+ (char) (ZLIBG(crc) >> 24) & 0xFF,
+ (char) ZLIBG(stream).total_in & 0xFF,
+ (char) (ZLIBG(stream).total_in >> 8) & 0xFF,
+ (char) (ZLIBG(stream).total_in >> 16) & 0xFF,
+ (char) (ZLIBG(stream).total_in >> 24) & 0xFF);
+ }
+
+
+ memcpy(buffer, header_buffer, 10);
+ memcpy(buffer+10+buf_used, trailer_buffer, 8);
+
+ *new_length = buf_used + 10 + 8;
+ *newstr = buffer;
+
+ return SUCCESS;
+}
+
+
+PHP_FUNCTION(gzencode)
+{
+ zval **zv_coding, **zv_string;
+ int coding;
+
+ switch(ZEND_NUM_ARGS()) {
+ case CODING_GZIP:
+ if (zend_get_parameters_ex(1, &zv_string)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string_ex(zv_string);
+ coding = 1;
+ break;
+ case CODING_DEFLATE:
+ if (zend_get_parameters_ex(2, &zv_string, &zv_coding)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string_ex(zv_string);
+ convert_to_long_ex(zv_coding);
+ coding = Z_LVAL_PP(zv_coding);
+ break;
+ default:
+ ZEND_WRONG_PARAM_COUNT();
+ break;
+ }
+ if (php_deflate_string(Z_STRVAL_PP(zv_string), Z_STRLEN_PP(zv_string), &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), coding)==SUCCESS) {
+ Z_TYPE_P(return_value) = IS_STRING;
+ } else {
+ RETURN_FALSE;
+ }
+}
+
+
+PHP_FUNCTION(ob_gzhandler)
+{
+ int coding;
+ zval **zv_string;
+ zval **data, **a_encoding;
+
+ if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &zv_string)==FAILURE) {
+ ZEND_WRONG_PARAM_COUNT();
+ }
+
+ if (zend_hash_find(&EG(symbol_table), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), (void **) &data)==FAILURE
+ || Z_TYPE_PP(data)!=IS_ARRAY
+ || zend_hash_find(Z_ARRVAL_PP(data), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding)==FAILURE) {
+ /* return the original string */
+ *return_value = **zv_string;
+ zval_copy_ctor(return_value);
+ return;
+ }
+ convert_to_string_ex(a_encoding);
+ if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
+ coding = CODING_GZIP;
+ } else if(php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
+ coding = CODING_DEFLATE;
+ } else {
+ RETURN_FALSE;
+ }
+ if (php_deflate_string(Z_STRVAL_PP(zv_string), Z_STRLEN_PP(zv_string), &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), coding)==SUCCESS) {
+ Z_TYPE_P(return_value) = IS_STRING;
+ switch (coding) {
+ case CODING_GZIP:
+ sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1);
+ break;
+ case CODING_DEFLATE:
+ sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1);
+ break;
+ }
+ } else {
+ /* return the original string */
+ *return_value = **zv_string;
+ zval_copy_ctor(return_value);
+ }
+}
+
-#endif /* HAVE_ZLIB */
/*
* Local variables:
* tab-width: 4
diff --git a/main/SAPI.c b/main/SAPI.c
index 563f1cd072..67bd8019de 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -271,6 +271,7 @@ SAPI_API void sapi_activate(SLS_D)
SG(request_info).post_data = NULL;
SG(request_info).current_user = NULL;
SG(request_info).current_user_length = 0;
+ SG(request_info).no_headers = 0;
/* It's possible to override this general case in the activate() callback, if
* necessary.
@@ -363,7 +364,7 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo
char *colon_offset;
SLS_FETCH();
- if (SG(headers_sent)) {
+ if (SG(headers_sent) && !SG(request_info).no_headers) {
char *output_start_filename = php_get_output_start_filename();
int output_start_lineno = php_get_output_start_lineno();
@@ -457,7 +458,7 @@ SAPI_API int sapi_send_headers()
int ret = FAILURE;
SLS_FETCH();
- if (SG(headers_sent)) {
+ if (SG(headers_sent) || SG(request_info).no_headers) {
return SUCCESS;
}
diff --git a/main/SAPI.h b/main/SAPI.h
index 86eb356104..9c2f06abe3 100644
--- a/main/SAPI.h
+++ b/main/SAPI.h
@@ -73,7 +73,8 @@ typedef struct {
const char *content_type;
- unsigned char headers_only;
+ zend_bool headers_only;
+ zend_bool no_headers;
sapi_post_entry *post_entry;
diff --git a/main/main.c b/main/main.c
index 2ef64e9af1..325a9802b5 100644
--- a/main/main.c
+++ b/main/main.c
@@ -223,6 +223,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("magic_quotes_runtime", "0", PHP_INI_ALL, OnUpdateBool, magic_quotes_runtime, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("magic_quotes_sybase", "0", PHP_INI_ALL, OnUpdateBool, magic_quotes_sybase, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("output_buffering", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM,OnUpdateBool, output_buffering, php_core_globals, core_globals)
+ STD_PHP_INI_ENTRY("output_handler", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM,OnUpdateString, output_handler, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("register_argc_argv", "1", PHP_INI_ALL, OnUpdateBool, register_argc_argv, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("register_globals", "1", PHP_INI_ALL, OnUpdateBool, register_globals, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("safe_mode", "0", PHP_INI_SYSTEM, OnUpdateBool, safe_mode, php_core_globals, core_globals)
@@ -623,7 +624,15 @@ int php_request_startup(CLS_D ELS_DC PLS_DC SLS_DC)
sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
}
- if (PG(output_buffering)) {
+ if (PG(output_handler)) {
+ zval *output_handler;
+
+ ALLOC_INIT_ZVAL(output_handler);
+ Z_STRLEN_P(output_handler) = strlen(PG(output_handler)); /* this can be optimized */
+ Z_STRVAL_P(output_handler) = estrndup(PG(output_handler), Z_STRLEN_P(output_handler));
+ Z_TYPE_P(output_handler) = IS_STRING;
+ php_start_ob_buffer(output_handler);
+ } else if (PG(output_buffering)) {
php_start_ob_buffer(NULL);
} else if (PG(implicit_flush)) {
php_start_implicit_flush();
@@ -656,11 +665,11 @@ void php_request_shutdown(void *dummy)
PLS_FETCH();
if (setjmp(EG(bailout))==0) {
- sapi_send_headers();
+ php_end_ob_buffers(SG(request_info).headers_only?0:1);
}
if (setjmp(EG(bailout))==0) {
- php_end_ob_buffers(SG(request_info).headers_only?0:1);
+ sapi_send_headers();
}
if (PG(modules_activated) && setjmp(EG(bailout))==0) {
diff --git a/main/php_globals.h b/main/php_globals.h
index 97461c1e0a..aa313a4075 100644
--- a/main/php_globals.h
+++ b/main/php_globals.h
@@ -65,6 +65,9 @@ struct _php_core_globals {
zend_bool safe_mode;
zend_bool sql_safe_mode;
zend_bool enable_dl;
+
+ char *output_handler;
+
char *safe_mode_exec_dir;
long memory_limit;
diff --git a/php.ini-dist b/php.ini-dist
index 8d098e7d97..43b5032271 100644
--- a/php.ini-dist
+++ b/php.ini-dist
@@ -64,6 +64,12 @@ output_buffering = Off ; Output buffering allows you to send header lines (inclu
; You can enable output buffering by in runtime by calling the output
; buffering functions, or enable output buffering for all files
; by setting this directive to On.
+output_handler = ; You can redirect all of the output of your scripts to a function,
+ ; that can be responsible to process or log it. For example,
+ ; if you set the output_handler to "ob_gzhandler", than output
+ ; will be transparently compressed for browsers that support gzip or
+ ; deflate encoding. Setting an output handler automatically turns on
+ ; output buffering.
implicit_flush = Off ; Implicit flush tells PHP to tell the output layer to flush itself
; automatically after every output block. This is equivalent to
; calling the PHP function flush() after each and every call to print()
diff --git a/php.ini-optimized b/php.ini-optimized
index f0d4ca6ae5..1bdd0060aa 100644
--- a/php.ini-optimized
+++ b/php.ini-optimized
@@ -51,6 +51,12 @@ output_buffering = Off ; Output buffering allows you to send header lines (inclu
; You can enable output buffering by in runtime by calling the output
; buffering functions, or enable output buffering for all files
; by setting this directive to On.
+output_handler = ; You can redirect all of the output of your scripts to a function,
+ ; that can be responsible to process or log it. For example,
+ ; if you set the output_handler to "ob_gzhandler", than output
+ ; will be transparently compressed for browsers that support gzip or
+ ; deflate encoding. Setting an output handler automatically turns on
+ ; output buffering.
implicit_flush = Off ; Implicit flush tells PHP to tell the output layer to flush itself
; automatically after every output block. This is equivalent to
; calling the PHP function flush() after each and every call to print()
diff --git a/php.ini-recommended b/php.ini-recommended
index f0d4ca6ae5..1bdd0060aa 100644
--- a/php.ini-recommended
+++ b/php.ini-recommended
@@ -51,6 +51,12 @@ output_buffering = Off ; Output buffering allows you to send header lines (inclu
; You can enable output buffering by in runtime by calling the output
; buffering functions, or enable output buffering for all files
; by setting this directive to On.
+output_handler = ; You can redirect all of the output of your scripts to a function,
+ ; that can be responsible to process or log it. For example,
+ ; if you set the output_handler to "ob_gzhandler", than output
+ ; will be transparently compressed for browsers that support gzip or
+ ; deflate encoding. Setting an output handler automatically turns on
+ ; output buffering.
implicit_flush = Off ; Implicit flush tells PHP to tell the output layer to flush itself
; automatically after every output block. This is equivalent to
; calling the PHP function flush() after each and every call to print()
diff --git a/sapi/apache/sapi_apache.c b/sapi/apache/sapi_apache.c
index e2cb151c37..f6139a9dc8 100644
--- a/sapi/apache/sapi_apache.c
+++ b/sapi/apache/sapi_apache.c
@@ -92,8 +92,8 @@ int apache_php_module_main(request_rec *r, int display_source_mode CLS_DC ELS_DC
if (setjmp(EG(bailout))!=0) {
return OK;
}
- php_header(); /* Make sure headers have been sent */
php_end_ob_buffers(1);
+ php_header(); /* Make sure headers have been sent */
return (OK);
}
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index 67ed3b80b5..d966527c26 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -548,6 +548,7 @@ any .htaccess restrictions anywhere on your site you can leave doc_root undefine
}
}
if (no_headers) {
+ SG(request_info).no_headers = 1;
SG(headers_sent) = 1;
}
cgi_started=1;
@@ -582,6 +583,7 @@ any .htaccess restrictions anywhere on your site you can leave doc_root undefine
}
if (no_headers) {
SG(headers_sent) = 1;
+ SG(request_info).no_headers = 1;
}
cgi_started=1;
php_print_info(0xFFFFFFFF);
@@ -630,6 +632,7 @@ any .htaccess restrictions anywhere on your site you can leave doc_root undefine
}
if (no_headers) {
SG(headers_sent) = 1;
+ SG(request_info).no_headers = 1;
}
php_printf("%s\n", PHP_VERSION);
php_end_ob_buffers(1);
@@ -677,6 +680,7 @@ any .htaccess restrictions anywhere on your site you can leave doc_root undefine
}
if (no_headers) {
SG(headers_sent) = 1;
+ SG(request_info).no_headers = 1;
}
file_handle.filename = "-";
file_handle.type = ZEND_HANDLE_FP;
@@ -766,9 +770,6 @@ any .htaccess restrictions anywhere on your site you can leave doc_root undefine
#endif
}
- php_header(); /* Make sure headers have been sent */
-
-
if (SG(request_info).path_translated) {
persist_alloc(SG(request_info).path_translated);