From 0d215d4f181f34af40fad377570919dc978ff563 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 16 Feb 2005 16:25:47 +0000 Subject: [PATCH] * added ob_httpetaghandler() (has major limitations compared to http_cache_etag()) * smarter ob handling in http_cache_etag() - used buffers will be fetched, freed and piped through again, so that everything passes the etag ob handler --- http.c | 55 +++++++++++++++++++++++++++++++++++++------------- http_api.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ package.xml | 13 ++++-------- php_http.h | 4 +++- php_http_api.h | 3 +++ 5 files changed, 104 insertions(+), 24 deletions(-) diff --git a/http.c b/http.c index 0132ff9..535a5ae 100644 --- a/http.c +++ b/http.c @@ -110,6 +110,7 @@ function_entry http_functions[] = { #ifndef ZEND_ENGINE_2 PHP_FE(http_build_query, NULL) #endif + PHP_FE(ob_httpetaghandler, NULL) {NULL, NULL, NULL} }; /* }}} */ @@ -440,31 +441,57 @@ PHP_FUNCTION(http_cache_etag) RETURN_FALSE; } - php_end_ob_buffers(0 TSRMLS_CC); http_send_header("Cache-Control: private, must-revalidate, max-age=0"); if (etag_len) { - RETURN_SUCCESS(http_send_etag(etag, etag_len)); + http_send_etag(etag, etag_len); + if (http_etag_match("HTTP_IF_NONE_MATCH", etag)) { + if (SUCCESS == http_send_status(304)) { + zend_bailout(); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not send 304 Not Modified"); + RETURN_FALSE; + } + } } - /* if no etag is given and we didn't already - * start ob_etaghandler -- start it - */ + /* if no etag is given and we didn't already start ob_etaghandler -- start it */ if (!HTTP_G(etag_started)) { - php_ob_set_internal_handler(_http_ob_etaghandler, (uint) 4096, "etag output handler", 0 TSRMLS_CC); - HTTP_G(etag_started) = 1; - RETURN_BOOL(php_start_ob_buffer_named("etag output handler", (uint) 4096, 0 TSRMLS_CC)); + RETURN_BOOL(HTTP_G(etag_started) = (SUCCESS == http_start_ob_handler(_http_ob_etaghandler, "ob_etaghandler", 0, 1))); } + RETURN_TRUE; +} +/* }}} */ - if (http_etag_match("HTTP_IF_NONE_MATCH", etag)) { - if (SUCCESS == http_send_status(304)) { - zend_bailout(); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not send 304 Not Modified"); +/* {{{ proto string ob_httpetaghandler(string data, int mode) + * + * For use with ob_start(). Note that this has to be started as first output buffer. + */ +PHP_FUNCTION(ob_httpetaghandler) +{ + char *data; + int data_len; + long mode; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) { + RETURN_FALSE; + } + + if (mode & PHP_OUTPUT_HANDLER_START) { + if (HTTP_G(etag_started)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "ob_etaghandler can only be used once"); RETURN_FALSE; } + if (OG(ob_nesting_level)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "must be started prior to other output buffers"); + RETURN_FALSE; + } + http_send_header("Cache-Control: private, must-revalidate, max-age=0"); + HTTP_G(etag_started) = 1; } - + + Z_TYPE_P(return_value) = IS_STRING; + http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), mode); } /* }}} */ diff --git a/http_api.c b/http_api.c index c5f25cf..238dd5a 100644 --- a/http_api.c +++ b/http_api.c @@ -147,6 +147,8 @@ static int check_tzone(char *tzone); static char *pretty_key(char *key, int key_len, int uctitle, int xhyphen); +static int http_ob_stack_get(php_ob_buffer *, php_ob_buffer **); + /* {{{ HAVE_CURL */ #ifdef HTTP_HAVE_CURL #define http_curl_initbuf(m) _http_curl_initbuf((m) TSRMLS_CC) @@ -835,6 +837,20 @@ static char *pretty_key(char *key, int key_len, int uctitle, int xhyphen) } /* }}} */ +/* {{{ static STATUS http_ob_stack_get(php_ob_buffer *, php_ob_buffer **) */ +static STATUS http_ob_stack_get(php_ob_buffer *o, php_ob_buffer **s) +{ + static int i = 0; + php_ob_buffer *b = emalloc(sizeof(php_ob_buffer)); + b->handler_name = estrdup(o->handler_name); + b->buffer = estrndup(o->buffer, o->text_length); + b->chunk_size = o->chunk_size; + b->erase = o->erase; + s[i++] = b; + return SUCCESS; +} +/* }}} */ + /* }}} internals */ /* {{{ public API */ @@ -1095,6 +1111,43 @@ PHP_HTTP_API void _http_ob_etaghandler(char *output, uint output_len, } /* }}} */ +/* {{{ STATUS http_start_ob_handler(php_output_handler_func_t, char *, uint, zend_bool) */ +PHP_HTTP_API STATUS _http_start_ob_handler(php_output_handler_func_t handler_func, + char *handler_name, uint chunk_size, zend_bool erase TSRMLS_DC) +{ + php_ob_buffer **stack; + int count, i; + STATUS result; + + count = OG(ob_nesting_level); + stack = emalloc(sizeof(php_ob_buffer *) * count); + + if (count > 1) { + zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, + (int (*)(void *elem, void *)) http_ob_stack_get, stack); + } + + if (count > 0) { + http_ob_stack_get(&OG(active_ob_buffer), stack); + } + + while (OG(ob_nesting_level)) { + php_end_ob_buffer(0, 0 TSRMLS_CC); + } + + php_ob_set_internal_handler(handler_func, 0, handler_name, 0 TSRMLS_CC); + result = php_start_ob_buffer_named(handler_name, chunk_size, erase TSRMLS_CC); + + for (i = 0; i < count; i++) { + php_ob_buffer *s = stack[i]; + php_start_ob_buffer_named(s->handler_name, s->chunk_size, s->erase TSRMLS_CC); + php_body_write(s->buffer, s->text_length TSRMLS_CC); + } + + return result; +} +/* }}} */ + /* {{{ int http_modified_match(char *, int) */ PHP_HTTP_API int _http_modified_match(const char *entry, const time_t t TSRMLS_DC) { diff --git a/package.xml b/package.xml index 4d84dca..41dcd94 100644 --- a/package.xml +++ b/package.xml @@ -29,18 +29,13 @@ - 0.4.0 + 0.5.0 2005-02-16 alpha diff --git a/php_http.h b/php_http.h index 105e4b6..29d868c 100644 --- a/php_http.h +++ b/php_http.h @@ -18,7 +18,7 @@ #ifndef PHP_EXT_HTTP_H #define PHP_EXT_HTTP_H -#define PHP_EXT_HTTP_VERSION "0.4.0" +#define PHP_EXT_HTTP_VERSION "0.5.0-dev" /* make compile on Win32 */ #include "php_streams.h" @@ -67,6 +67,8 @@ PHP_FUNCTION(http_post_array); PHP_FUNCTION(http_auth_basic); PHP_FUNCTION(http_auth_basic_cb); +PHP_FUNCTION(ob_httpetaghandler); + PHP_MINIT_FUNCTION(http); PHP_MSHUTDOWN_FUNCTION(http); PHP_RSHUTDOWN_FUNCTION(http); diff --git a/php_http_api.h b/php_http_api.h index 9055e66..f28e30b 100644 --- a/php_http_api.h +++ b/php_http_api.h @@ -111,6 +111,9 @@ PHP_HTTP_API inline zval *_http_get_server_var(const char *key TSRMLS_DC); #define http_ob_etaghandler(o, l, ho, hl, m) _http_ob_etaghandler((o), (l), (ho), (hl), (m) TSRMLS_CC) PHP_HTTP_API void _http_ob_etaghandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC); +#define http_start_ob_handler(f, h, s, e) _http_start_ob_handler((f), (h), (s), (e) TSRMLS_CC) +PHP_HTTP_API STATUS _http_start_ob_handler(php_output_handler_func_t handler_func, char *handler_name, uint chunk_size, zend_bool erase TSRMLS_DC); + #define http_modified_match(entry, modified) _http_modified_match((entry), (modified) TSRMLS_CC) PHP_HTTP_API int _http_modified_match(const char *entry, const time_t t TSRMLS_DC); -- 2.30.2