Browse Source

Add sapi_header_op interface which supersedes the sapi_add_header and _ex

calls.

Revert the change to the sapi_add_header_ex interface.

Fix various bugs:

1.  header("HTTP/1.0 306 foo");
    header("Location: absolute-uri");

    did not work in combination with several SAPI modules, because
    http_status_line was never properly reset.  And thus, all SAPI
    modules which looked at http_status_line ignored the changed
    http_response_code.

2.  The CGI SAPI did not send out the HTTP status line at all, if
    http_status_line had not been set explicitly by calling
    header("HTTP/1.0 200 foo");
experimental/new_apache_hooks
Sascha Schumann 24 years ago
parent
commit
9c876ea01a
  1. 22
      ext/standard/head.c
  2. 88
      main/SAPI.c
  3. 34
      main/SAPI.h
  4. 12
      sapi/pi3web/pi3web_sapi.c
  5. 8
      sapi/tux/php_tux.c
  6. 18
      sapi/webjames/webjames.c

22
ext/standard/head.c

@ -39,16 +39,14 @@
Sends a raw HTTP header */
PHP_FUNCTION(header)
{
char *header;
int header_len;
zend_bool replace = 1;
int http_code = 0;
zend_bool rep = 1;
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, &rep, &ctr.response_code) == FAILURE)
return;
}
sapi_add_header_ex(header, header_len, 1, replace, http_code TSRMLS_CC);
sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
}
/* }}} */
@ -70,7 +68,8 @@ PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, t
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 +121,10 @@ PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, t
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);
}

88
main/SAPI.c

@ -385,41 +385,83 @@ static int sapi_extract_response_code(const char *header_line)
return code;
}
static void sapi_update_response_code(int ncode TSRMLS_CC)
{
if (SG(sapi_headers).http_status_line) {
efree(SG(sapi_headers).http_status_line);
SG(sapi_headers).http_status_line = NULL;
}
SG(sapi_headers).http_response_code = ncode;
}
static int sapi_find_matching_header(void *element1, void *element2)
{
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;
}
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:
sapi_update_response_code((int) arg TSRMLS_CC);
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';
@ -433,7 +475,7 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo
if (header_line_len>=5
&& !strncasecmp(header_line, "HTTP/", 5)) {
/* filter out the response code */
SG(sapi_headers).http_response_code = sapi_extract_response_code(header_line);
sapi_update_response_code(sapi_extract_response_code(header_line) TSRMLS_CC);
SG(sapi_headers).http_status_line = header_line;
return SUCCESS;
} else {
@ -465,7 +507,7 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo
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;
sapi_update_response_code(302 TSRMLS_CC);
}
} else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
int newlen;
@ -476,7 +518,7 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo
int ptr_len=0, result_len = 0;
#endif
SG(sapi_headers).http_response_code = 401; /* authentication-required */
sapi_update_response_code(401 TSRMLS_CC); /* authentication-required */
#if HAVE_PCRE || HAVE_BUNDLED_PCRE
if(PG(safe_mode)) {
myuid = php_getuid();
@ -546,9 +588,8 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo
}
}
}
if (http_response_code) {
SG(sapi_headers).http_response_code = http_response_code;
sapi_update_response_code(http_response_code TSRMLS_CC);
}
if (sapi_module.header_handler) {
retval = sapi_module.header_handler(&sapi_header, &SG(sapi_headers) TSRMLS_CC);
@ -602,12 +643,17 @@ SAPI_API int sapi_send_headers(TSRMLS_D)
case SAPI_HEADER_SENT_SUCCESSFULLY:
ret = SUCCESS;
break;
case SAPI_HEADER_DO_SEND:
if (SG(sapi_headers).http_status_line) {
case SAPI_HEADER_DO_SEND: {
sapi_header_struct http_status_line;
char buf[255];
http_status_line.header = SG(sapi_headers).http_status_line;
http_status_line.header_len = strlen(SG(sapi_headers).http_status_line);
if (SG(sapi_headers).http_status_line) {
http_status_line.header = SG(sapi_headers).http_status_line;
http_status_line.header_len = strlen(SG(sapi_headers).http_status_line);
} else {
http_status_line.header = buf;
http_status_line.header_len = sprintf(buf, "HTTP/1.0 %d X", SG(sapi_headers).http_response_code);
}
sapi_module.send_header(&http_status_line, SG(server_context) TSRMLS_CC);
}
zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context) TSRMLS_CC);

34
main/SAPI.h

@ -133,9 +133,37 @@ SAPI_API void sapi_activate(TSRMLS_D);
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.
*/
/*
* Always specify a sapi_header_line this way:
*
* sapi_header_line ctr = {0};
*/
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);

12
sapi/pi3web/pi3web_sapi.c

@ -422,9 +422,14 @@ DWORD PHP4_wrapper(LPCONTROL_BLOCK lpCB)
};
};
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 @@ DWORD PHP4_wrapper(LPCONTROL_BLOCK lpCB)
{
iRet = PIAPI_ERROR;
};
efree(header_line);
break;
case PHP_MODE_LINT:
iRet = (php_lint_script(&file_handle TSRMLS_CC) == SUCCESS) ?

8
sapi/tux/php_tux.c

@ -192,10 +192,12 @@ static void sapi_tux_register_variables(zval *track_vars_array TSRMLS_DC)
{
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);

18
sapi/webjames/webjames.c

@ -54,22 +54,6 @@ static int sapi_webjames_ub_write(const char *str, uint str_length TSRMLS_DC)
return bytes;
}
static int sapi_webjames_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
/*send the HTTP response line*/
{
char buf[256];
if (WG(conn)->flags.outputheaders) {
if (!SG(sapi_headers).http_status_line) {
int code=SG(sapi_headers).http_response_code;
snprintf(buf, 255, "HTTP/1.0 %d %s\r\n", code, code==200 ? "OK" : code==302 ? "Moved temporarily" : "Something");
webjames_writestring(WG(conn), buf);
}
}
return SAPI_HEADER_DO_SEND;
}
static void sapi_webjames_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC)
/*send an HTTP header*/
{
@ -286,7 +270,7 @@ static sapi_module_struct sapi_module = {
php_error, /* error handler */
NULL, /* header handler */
sapi_webjames_send_headers, /* send headers handler */
NULL, /* send headers handler */
sapi_webjames_send_header, /* send header handler */
sapi_webjames_read_post, /* read POST data */
sapi_webjames_read_cookies, /* read Cookies */

Loading…
Cancel
Save