]> granicus.if.org Git - php/commitdiff
Add header_register_callback(), allows a userland function
authorScott MacVicar <scottmac@php.net>
Thu, 3 Feb 2011 16:47:28 +0000 (16:47 +0000)
committerScott MacVicar <scottmac@php.net>
Thu, 3 Feb 2011 16:47:28 +0000 (16:47 +0000)
to be called as all the headers are being sent and after all
of the default headers have been merged.

headers_list(), header_remove() and header() can all be used
inside the callback.

<?php

header('Content-Type: text/plain');
header('X-Test: foo');

function foo() {
  foreach (headers_list() as $header) {
    if (strpos($header, 'X-Powered') !== false) {
      header_remove('X-Powered-By');
    }
    header_remove('X-Test');
  }
}

$result = header_register_callback('foo');
echo "a";

NEWS
ext/standard/basic_functions.c
ext/standard/basic_functions.h
main/SAPI.c
main/SAPI.h

diff --git a/NEWS b/NEWS
index 8ab552fcb87cf0d2382254a7bf388201d0f137cb..898b701b79587a07bd27d21493bfc8d7e57d5f32 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,9 @@ PHP                                                                        NEWS
   . Added support for object references in recursive serialize() calls.
     FR #36424. (Mike)
   . Added http_response_code() function. FR #52555. (Paul Dragoonis, Kalle)
+  . Added header_register_callback() which is invoked immediately
+    prior to the sending of headers and after default headers have
+    been added. (Scott)
   . Added DTrace support. (David Soria Parra)
   . Improved output layer, see README.NEW-OUTPUT-API for internals. (Mike)
   . Improved unserialize() performance.
index 7f7eefe46c7e913bf7fc7bfb15b41768e7820e24..53bbef4443054ef38ffefb9f6c90ba1c01e60e09 100644 (file)
@@ -141,6 +141,13 @@ ZEND_BEGIN_ARG_INFO(arginfo_set_time_limit, 0)
        ZEND_ARG_INFO(0, seconds)
 ZEND_END_ARG_INFO()
 /* }}} */
+
+/* {{{ main/sapi.c */
+ZEND_BEGIN_ARG_INFO(arginfo_header_register_callback, 0)
+       ZEND_ARG_INFO(0, callback)
+ZEND_END_ARG_INFO()
+/* }}} */
+
 /* {{{ main/output.c */
 ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_start, 0, 0, 0)
        ZEND_ARG_INFO(0, user_function)
@@ -2940,6 +2947,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */
        PHP_FE(convert_cyr_string,                                                                                              arginfo_convert_cyr_string)
        PHP_FE(get_current_user,                                                                                                arginfo_get_current_user)
        PHP_FE(set_time_limit,                                                                                                  arginfo_set_time_limit)
+       PHP_FE(header_register_callback,                                                                                arginfo_header_register_callback)
        PHP_FE(get_cfg_var,                                                                                                             arginfo_get_cfg_var)
 
        PHP_DEP_FALIAS(magic_quotes_runtime,    set_magic_quotes_runtime,               arginfo_set_magic_quotes_runtime)
index ec993a50a317c36bce8e7eaa60ac938a85ee4c74..9427b6c9fbe25ca44ec9024d4960d88d2d6a6b60 100644 (file)
@@ -69,6 +69,8 @@ PHP_FUNCTION(getopt);
 PHP_FUNCTION(get_current_user);
 PHP_FUNCTION(set_time_limit);
 
+PHP_FUNCTION(header_register_callback);
+
 PHP_FUNCTION(get_cfg_var);
 PHP_FUNCTION(set_magic_quotes_runtime);
 PHP_FUNCTION(get_magic_quotes_runtime);
index 2e95eea3201a23385189a53c48ef6be233aaa4da..619f00ae195c3ea7d984836a2f3cd532b7c766e2 100644 (file)
@@ -116,6 +116,58 @@ SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
        efree(sapi_header->header);
 }
 
+/* {{{ proto bool header_register_callback(mixed callback)
+   call a header function */
+PHP_FUNCTION(header_register_callback)
+{
+       zval *callback_func;
+       char *callback_name;
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callback_func) == FAILURE) {
+               return;
+       }
+       
+       if (!zend_is_callable(callback_func, 0, &callback_name TSRMLS_CC)) {
+               efree(callback_name);
+               RETURN_FALSE;
+       }
+       efree(callback_name);
+
+       if (SG(callback_func)) {
+               zval_ptr_dtor(&SG(callback_func));
+               SG(fci_cache) = empty_fcall_info_cache;
+       }
+
+       Z_ADDREF_P(callback_func);
+
+       SG(callback_func) = callback_func;
+       
+       RETURN_TRUE;
+}
+/* }}} */
+
+static void sapi_run_header_callback()
+{
+       int   error;
+       zend_fcall_info fci;
+       zval *retval_ptr = NULL;
+
+       fci.size = sizeof(fci);
+       fci.function_table = EG(function_table);
+       fci.object_ptr = NULL;
+       fci.function_name = SG(callback_func);
+       fci.retval_ptr_ptr = &retval_ptr;
+       fci.param_count = 0;
+       fci.params = NULL;
+       fci.no_separation = 0;
+       fci.symbol_table = NULL;
+
+       error = zend_call_function(&fci, &SG(fci_cache) TSRMLS_CC);
+       if (error == FAILURE) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the sapi_header_callback");
+       } else if (retval_ptr) {
+               zval_ptr_dtor(&retval_ptr);
+       }
+}
 
 SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
 {
@@ -433,6 +485,9 @@ static void sapi_send_headers_free(TSRMLS_D)
 SAPI_API void sapi_deactivate(TSRMLS_D)
 {
        zend_llist_destroy(&SG(sapi_headers).headers);
+       if (SG(callback_func)) {
+               zval_ptr_dtor(&SG(callback_func));
+       }
        if (SG(request_info).post_data) {
                efree(SG(request_info).post_data);
        }  else         if (SG(server_context)) {
@@ -574,7 +629,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
        char *header_line;
        uint header_line_len;
        int http_response_code;
-       
+
        if (SG(headers_sent) && !SG(request_info).no_headers) {
                char *output_start_filename = php_output_get_start_filename(TSRMLS_C);
                int output_start_lineno = php_output_get_start_lineno(TSRMLS_C);
@@ -774,6 +829,11 @@ SAPI_API int sapi_send_headers(TSRMLS_D)
                SG(sapi_headers).send_default_content_type = 0;
        }
 
+       if (SG(callback_func) && !SG(callback_run)) {
+               SG(callback_run) = 1;
+               sapi_run_header_callback();
+       }
+
        SG(headers_sent) = 1;
 
        if (sapi_module.send_headers) {
index 3fea6b8814a07040fdedc1abf91239f7c85e6b9d..3966b2d5aa7082363ade4db1761e417125e46426 100644 (file)
@@ -131,6 +131,9 @@ typedef struct _sapi_globals_struct {
        zend_bool sapi_started;
        double global_request_time;
        HashTable known_post_content_types;
+       zval *callback_func;
+       zend_fcall_info_cache fci_cache;
+       zend_bool callback_run;
 } sapi_globals_struct;