in case of redirects and positive cache hits (instead, standard output will be discarded)
[http]
; enable if you want to transform all errors to exceptions (PHP >= 5 only)
-http.only_exceptions = 0
+;http.only_exceptions = 1
+
+; disable if you want php not to exit in case of redirects and cache hits
+;http.force_exit = 0
; the hashing algorithm with wich ETags are generated
; you can use mhash constants if ext/mhash is enabled, or their
HTTP_PHP_INI_ENTRY("http.redirect_log", "", PHP_INI_ALL, OnUpdateString, log.redirect)
HTTP_PHP_INI_ENTRY("http.allowed_methods_log", "", PHP_INI_ALL, OnUpdateString, log.allowed_methods)
HTTP_PHP_INI_ENTRY("http.composite_log", "", PHP_INI_ALL, OnUpdateString, log.composite)
+ HTTP_PHP_INI_ENTRY_EX("http.etag_mode", "-2", PHP_INI_ALL, OnUpdateLong, http_etag_mode_displayer, etag.mode)
#ifdef ZEND_ENGINE_2
HTTP_PHP_INI_ENTRY("http.only_exceptions", "0", PHP_INI_ALL, OnUpdateBool, only_exceptions)
#endif
- HTTP_PHP_INI_ENTRY_EX("http.etag_mode", "-2", PHP_INI_ALL, OnUpdateLong, http_etag_mode_displayer, etag.mode)
+ HTTP_PHP_INI_ENTRY("http.force_exit", "1", PHP_INI_ALL, OnUpdateBool, force_exit)
PHP_INI_END()
/* }}} */
}
/* }}} */
+static void http_ob_blackhole(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
+{
+ *handled_output = ecalloc(1,1);
+ *handled_output_len = 0;
+}
+
/* {{{ STATUS http_exit(int, char*, char*) */
STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC)
{
return FAILURE;
}
+ php_end_ob_buffers(0 TSRMLS_CC);
if (php_header(TSRMLS_C) && body) {
PHPWRITE(body, strlen(body));
}
STR_FREE(header);
STR_FREE(body);
- zend_bailout();
- /* fake */
+ if (HTTP_G(force_exit)) {
+ zend_bailout();
+ } else {
+ php_ob_set_internal_handler(http_ob_blackhole, 4096, "blackhole", 0 TSRMLS_CC);
+ }
+
return SUCCESS;
}
/* }}} */
{
char *sent_header = NULL;
+ if (SG(headers_sent)) {
+ return FAILURE;
+ }
+
if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) {
return FAILURE;
}
{
char *sent_header = NULL;
+ if (SG(headers_sent)) {
+ return FAILURE;
+ }
+
if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) {
return FAILURE;
}
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) {
RETURN_FALSE;
}
+
+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
t = (long) time(NULL);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) {
RETURN_FALSE;
}
+
+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
}
if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) {
RETURN_FALSE;
}
- if (SG(headers_sent)) {
- http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, headers have already been sent");
- RETURN_FALSE;
- }
+
+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
sent = GET_STATIC_PROP(sent);
- if (zval_is_true(sent)) {
+ if (Z_LVAL_P(sent)) {
http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, response has already been sent");
RETURN_FALSE;
} else {
if (etag_p) zval_ptr_dtor(&etag_p);
if (lmod_p) zval_ptr_dtor(&lmod_p);
if (cctl_p) zval_ptr_dtor(&cctl_p);
+
+ if (php_ob_handler_used("blackhole" TSRMLS_CC)) {
+ RETURN_TRUE;
+ }
}
/* content type */
PHP_METHOD(HttpResponse, capture)
{
NO_ARGS;
+
+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
UPD_STATIC_PROP(long, catch, 1);
</stability>
<license>BSD, revised</license>
<notes><![CDATA[
++ Added INI setting http.force_exit which can be used to disable script termination
+ in case of redirects and positive cache hits (instead, standard output will be discarded)
+ Classes HttpMessage and HttpRequestPool implement Countable if PHP >= 5.1 with SPL is available
+ Class HttpMessage implements Serializable if PHP >= 5.1 is available
zend_bool only_exceptions;
#endif
+ zend_bool force_exit;
+
ZEND_END_MODULE_GLOBALS(http)
#ifdef ZTS
action; \
}
+#define HTTP_CHECK_HEADERS_SENT(action) \
+ if (SG(headers_sent) && !SG(request_info).no_headers) { \
+ char *output_start_filename = php_get_output_start_filename(TSRMLS_C); \
+ int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); \
+ \
+ if (output_start_filename) { \
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent by (output started at %s:%d)", \
+ output_start_filename, output_start_lineno); \
+ } else { \
+ http_error(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent"); \
+ } \
+ action; \
+ }
+
+
#define http_log(f, i, m) _http_log_ex((f), (i), (m) TSRMLS_CC)
extern void http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC);