I think it is time for deprecating sapi_add_header* in favor
    of a more general function, called sapi_header_op.

    Let me quickly recapitulate the history.

    The original function sapi_add_header added and sometimes
    replaced HTTP headers and changed HTTP response codes at
    will.  This was still a real black box.

    Then I added a parameter "replace" which turned the black box
    into something more deterministic.  The new function was
    called sapi_add_header_ex to retain source code
    compatibility.

    The recent extension for specifying the HTTP response code
    eliminated further black box symptoms, but at the cost of
    changing an established API.

    I therefore propose the addition of a saner sapi_header_op()
    and the removal of the API breaking change from a week ago.
    This will allow further extensions regarding parameters
    without the burden of creating new APIs at the same time.

    The appended patch also unbreaks the CGI SAPI which did not
    generate status codes at all -- http_status_line was NULL all
    the time.


typedef struct {
    char *line; /* If you allocated this, you need to free it yourself */
    uint line_len;
    long response_code; /* long due to zend_parse_parameters compatibility */
} sapi_header_line;

typedef enum {                  /* Parameter:           */
    SAPI_HEADER_REPLACE,        /* sapi_header_line*    */
    SAPI_HEADER_ADD,            /* sapi_header_line*    */
    SAPI_HEADER_SET_STATUS      /* int                  */
} sapi_header_op_enum;

SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC);


    - Sascha
? difx
Index: ext/standard/head.c
===================================================================
RCS file: /repository/php4/ext/standard/head.c,v
retrieving revision 1.57
diff -u -r1.57 head.c
--- ext/standard/head.c 21 Jun 2002 09:31:20 -0000      1.57
+++ ext/standard/head.c 30 Jun 2002 11:28:45 -0000
@@ -39,16 +39,18 @@
    Sends a raw HTTP header */
 PHP_FUNCTION(header)
 {
-       char *header;
-       int header_len;
        zend_bool replace = 1;
-       int http_code = 0;
+       sapi_header_line ctr = {0};
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &header,
-                                                         &header_len, &replace, 
&http_code) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
+                               &ctr.line_len, &replace, &ctr.response_code) == 
+FAILURE) {
                return;
        }
-       sapi_add_header_ex(header, header_len, 1, replace, http_code TSRMLS_CC);
+       
+       if (sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD,
+                       &ctr TSRMLS_CC) == SUCCESS)
+               RETURN_TRUE;
+       RETURN_FALSE;
 }
 /* }}} */
 
@@ -70,7 +72,8 @@
        int len=sizeof("Set-Cookie: ");
        time_t t;
        char *dt;
-
+       sapi_header_line ctr = {0};
+       
        len += name_len;
        if (value) {
                int encoded_value_len;
@@ -122,7 +125,10 @@
                strcat(cookie, "; secure");
        }
 
-       return sapi_add_header_ex(cookie, strlen(cookie), 0, 0, 0 TSRMLS_CC);
+       ctr.line = cookie;
+       ctr.line_len = strlen(cookie);
+
+       return sapi_header_op(SAPI_HEADER_ADD, &ctr TSRMLS_CC);
 }
 
 
Index: main/SAPI.c
===================================================================
RCS file: /repository/php4/main/SAPI.c,v
retrieving revision 1.133
diff -u -r1.133 SAPI.c
--- main/SAPI.c 21 Jun 2002 09:31:21 -0000      1.133
+++ main/SAPI.c 30 Jun 2002 11:28:49 -0000
@@ -283,7 +283,7 @@
        /*
        SG(sapi_headers).http_response_code = 200;
        */
-       SG(sapi_headers).http_status_line = NULL;
+       SG(sapi_headers).http_status_line = estrdup("HTTP/1.0 200 Ok");
        SG(headers_sent) = 0;
        SG(read_post_bytes) = 0;
        SG(request_info).post_data = NULL;
@@ -390,36 +390,78 @@
        return strncasecmp(((sapi_header_struct*)element1)->header, (char*)element2, 
strlen((char*)element2)) == 0;
 }
 
-/* This function expects a *duplicated* string, that was previously emalloc()'d.
- * Pointers sent to this functions will be automatically freed by the framework.
- */
-SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool 
duplicate, zend_bool replace, int http_response_code TSRMLS_DC)
+SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool 
+duplicate, zend_bool replace TSRMLS_DC)
+{
+       sapi_header_line ctr = {0};
+       int r;
+       
+       ctr.line = header_line;
+       ctr.line_len = header_line_len;
+
+       r = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD,
+                       &ctr TSRMLS_CC);
+
+       if (!duplicate)
+               efree(header_line);
+
+       return r;
+}
+
+static void update_http_response_code(int new_code TSRMLS_DC) {
+               char buf[256];
+               
+               SG(sapi_headers).http_response_code = new_code;
+               efree(SG(sapi_headers).http_status_line);
+               sprintf(buf, "HTTP/1.0 %d X", new_code);
+               SG(sapi_headers).http_status_line = estrdup(buf);
+}
+
+
+SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
 {
        int retval;
        sapi_header_struct sapi_header;
        char *colon_offset;
        long myuid = 0L;
-
+       char *header_line;
+       uint header_line_len;
+       zend_bool replace;
+       int http_response_code;
+       
        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) {
-                       sapi_module.sapi_error(E_WARNING, "Cannot add header 
information - headers already sent by (output started at %s:%d)",
+                       sapi_module.sapi_error(E_WARNING, "Cannot modify header 
+information - headers already sent by (output started at %s:%d)",
                                output_start_filename, output_start_lineno);
                } else {
-                       sapi_module.sapi_error(E_WARNING, "Cannot add header 
information - headers already sent");
-               }
-               if (!duplicate) {
-                       efree(header_line);
+                       sapi_module.sapi_error(E_WARNING, "Cannot modify header 
+information - headers already sent");
                }
                return FAILURE;
        }
 
-       if (duplicate) {
-               header_line = estrndup(header_line, header_line_len);
+       switch (op) {
+       case SAPI_HEADER_SET_STATUS:
+               SG(sapi_headers).http_response_code = (int) arg;
+               return SUCCESS;
+
+       case SAPI_HEADER_REPLACE:
+       case SAPI_HEADER_ADD: {
+               sapi_header_line *p = arg;
+               header_line = p->line;
+               header_line_len = p->line_len;
+               http_response_code = p->response_code;
+               replace = (op == SAPI_HEADER_REPLACE);
+               break;
+               }
+       
+       default:
+               return FAILURE;
        }
 
+       header_line = estrndup(header_line, header_line_len);
+
        /* cut of trailing spaces, linefeeds and carriage-returns */
        while(isspace(header_line[header_line_len-1])) 
                  header_line[--header_line_len]='\0';
@@ -465,7 +507,7 @@
                                if (SG(sapi_headers).http_response_code < 300 ||
                                        SG(sapi_headers).http_response_code > 307) {
                                        /* Return a Found Redirect if one is not 
already specified */
-                                       SG(sapi_headers).http_response_code = 302;
+                                       update_http_response_code(302 TSRMLS_CC);
                                }
                        } else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* 
HTTP Authentication */
                                int newlen;
@@ -476,7 +518,7 @@
                                int ptr_len=0, result_len = 0;
 #endif
 
-                               SG(sapi_headers).http_response_code = 401; /* 
authentication-required */
+                               update_http_response_code(401 TSRMLS_CC); /* 
+authentication-required */
 #if HAVE_PCRE || HAVE_BUNDLED_PCRE
                                if(PG(safe_mode)) {
                                        myuid = php_getuid();
@@ -546,9 +588,8 @@
                        }
                }
        }
-
        if (http_response_code) {
-               SG(sapi_headers).http_response_code = http_response_code;
+               update_http_response_code(http_response_code TSRMLS_C);
        }
        if (sapi_module.header_handler) {
                retval = sapi_module.header_handler(&sapi_header, &SG(sapi_headers) 
TSRMLS_CC);
Index: main/SAPI.h
===================================================================
RCS file: /repository/php4/main/SAPI.h,v
retrieving revision 1.82
diff -u -r1.82 SAPI.h
--- main/SAPI.h 21 Jun 2002 09:31:21 -0000      1.82
+++ main/SAPI.h 30 Jun 2002 11:28:49 -0000
@@ -133,9 +133,31 @@
 SAPI_API void sapi_deactivate(TSRMLS_D);
 SAPI_API void sapi_initialize_empty_request(TSRMLS_D);
 
-SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool 
duplicate, zend_bool replace, int http_response_code TSRMLS_DC);
-#define sapi_add_header(header_line, header_line_len, duplicate) \
-       sapi_add_header_ex((header_line), (header_line_len), (duplicate), 1, 0 
TSRMLS_CC)
+/*
+ * This is the preferred and maintained API for 
+ * operating on HTTP headers.
+ */
+
+typedef struct {
+       char *line; /* If you allocated this, you need to free it yourself */
+       uint line_len;
+       long response_code; /* long due to zend_parse_parameters compatibility */
+} sapi_header_line;
+
+typedef enum {                                 /* Parameter:                   */
+       SAPI_HEADER_REPLACE,            /* sapi_header_line*    */
+       SAPI_HEADER_ADD,                        /* sapi_header_line*    */
+       SAPI_HEADER_SET_STATUS          /* int                                  */
+} sapi_header_op_enum;
+
+SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC);
+
+
+/* Deprecated functions. Use sapi_header_op instead. */
+SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool 
+duplicate, zend_bool replace TSRMLS_DC);
+#define sapi_add_header(a, b, c) sapi_add_header_ex((a),(b),(c),1 TSRMLS_CC)
+
+
 SAPI_API int sapi_send_headers(TSRMLS_D);
 SAPI_API void sapi_free_header(sapi_header_struct *sapi_header);
 SAPI_API void sapi_handle_post(void *arg TSRMLS_DC);
Index: sapi/pi3web/pi3web_sapi.c
===================================================================
RCS file: /repository/php4/sapi/pi3web/pi3web_sapi.c,v
retrieving revision 1.41
diff -u -r1.41 pi3web_sapi.c
--- sapi/pi3web/pi3web_sapi.c   21 Jun 2002 09:31:21 -0000      1.41
+++ sapi/pi3web/pi3web_sapi.c   30 Jun 2002 11:28:57 -0000
@@ -422,9 +422,14 @@
                                        };
                                };
                                break;
-                       case PHP_MODE_INDENT:
-                               header_line = (char *)estrdup("Content-Type: 
text/plain");
-                               sapi_add_header_ex(header_line, strlen(header_line), 
1, 1, 0 TSRMLS_CC);
+                       case PHP_MODE_INDENT: {
+                               sapi_header_line ctr = {0};
+
+                               ctr.line = "Content-Type: text/plain";
+                               ctr.line_len = strlen(ctr.line);
+                               
+                               sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
+                         }
                                if ( open_file_for_scanning( &file_handle TSRMLS_CC ) 
== SUCCESS )
                                        {
                                        zend_indent();
@@ -433,7 +438,6 @@
                                        {
                                        iRet = PIAPI_ERROR;
                                        };
-                               efree(header_line);
                                break;
                        case PHP_MODE_LINT:
                                iRet = (php_lint_script(&file_handle TSRMLS_CC) == 
SUCCESS) ?
Index: sapi/tux/php_tux.c
===================================================================
RCS file: /repository/php4/sapi/tux/php_tux.c,v
retrieving revision 1.16
diff -u -r1.16 php_tux.c
--- sapi/tux/php_tux.c  21 Jun 2002 09:31:21 -0000      1.16
+++ sapi/tux/php_tux.c  30 Jun 2002 11:28:57 -0000
@@ -192,10 +192,12 @@
 {
        char buf[BUF_SIZE + 1];
        char *p;
-
+       sapi_header_line ctr = {0};
+       
+       ctr.line = buf;
+       ctr.line_len = sprintf(buf, "Server: %s", TUXAPI_version);
+       sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
        
-       sprintf(buf, "Server: %s", TUXAPI_version);
-       sapi_add_header_ex(buf, strlen(buf), 1, 0, 0 TSRMLS_CC);
        php_register_variable("PHP_SELF", SG(request_info).request_uri, 
track_vars_array TSRMLS_CC);
        php_register_variable("SERVER_SOFTWARE", TUXAPI_version, track_vars_array 
TSRMLS_CC);
        php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array 
TSRMLS_CC);
-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to