Skip to content

Commit

Permalink
php_cli_server: ensure single date header is present
Browse files Browse the repository at this point in the history
Currently the PHP Development Server appends a Date header in the
response, despite already set from user code.

Added a check condition before append the header, and a test file.

Closes GH-12363.
  • Loading branch information
coppolafab authored and nielsdos committed Oct 6, 2023
1 parent 36a87e6 commit f6ac08c
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
3 changes: 3 additions & 0 deletions NEWS
Expand Up @@ -10,6 +10,9 @@ PHP NEWS
. Fixed bug GH-12273 (__builtin_cpu_init check). (Freaky)
. Fixed bug #80092 (ZTS + preload = segfault on shutdown). (nielsdos)

- CLI:
. Ensure a single Date header is present. (coppolafab)

- CType:
. Fixed bug GH-11997 (ctype_alnum 5 times slower in PHP 8.1 or greater).
(nielsdos)
Expand Down
25 changes: 20 additions & 5 deletions sapi/cli/php_cli_server.c
Expand Up @@ -348,18 +348,33 @@ static void append_http_status_line(smart_str *buffer, int protocol_version, int
smart_str_appendl_ex(buffer, "\r\n", 2, persistent);
} /* }}} */

static void append_essential_headers(smart_str* buffer, php_cli_server_client *client, int persistent) /* {{{ */
static void append_essential_headers(smart_str* buffer, php_cli_server_client *client, int persistent, sapi_headers_struct *sapi_headers) /* {{{ */
{
char *val;
struct timeval tv = {0};
bool append_date_header = true;

if (sapi_headers != NULL) {
zend_llist_position pos;
sapi_header_struct *h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
while (h) {
if (h->header_len > strlen("Date:")) {
if (strncasecmp(h->header, "Date:", strlen("Date:")) == 0) {
append_date_header = false;
break;
}
}
h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
}
}

if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "host", sizeof("host")-1))) {
smart_str_appends_ex(buffer, "Host: ", persistent);
smart_str_appends_ex(buffer, val, persistent);
smart_str_appends_ex(buffer, "\r\n", persistent);
}

if (!gettimeofday(&tv, NULL)) {
if (append_date_header && !gettimeofday(&tv, NULL)) {
zend_string *dt = php_format_date("D, d M Y H:i:s", sizeof("D, d M Y H:i:s") - 1, tv.tv_sec, 0);
smart_str_appends_ex(buffer, "Date: ", persistent);
smart_str_appends_ex(buffer, dt->val, persistent);
Expand Down Expand Up @@ -552,7 +567,7 @@ static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers) /* {{
append_http_status_line(&buffer, client->request.protocol_version, SG(sapi_headers).http_response_code, 0);
}

append_essential_headers(&buffer, client, 0);
append_essential_headers(&buffer, client, 0, sapi_headers);

h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
while (h) {
Expand Down Expand Up @@ -1997,7 +2012,7 @@ static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server
/* out of memory */
goto fail;
}
append_essential_headers(&buffer, client, 1);
append_essential_headers(&buffer, client, 1, NULL);
smart_str_appends_ex(&buffer, "Content-Type: text/html; charset=UTF-8\r\n", 1);
smart_str_appends_ex(&buffer, "Content-Length: ", 1);
smart_str_append_unsigned_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1);
Expand Down Expand Up @@ -2093,7 +2108,7 @@ static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_serv
php_cli_server_log_response(client, 500, NULL);
return FAILURE;
}
append_essential_headers(&buffer, client, 1);
append_essential_headers(&buffer, client, 1, NULL);
if (mime_type) {
smart_str_appendl_ex(&buffer, "Content-Type: ", sizeof("Content-Type: ") - 1, 1);
smart_str_appends_ex(&buffer, mime_type, 1);
Expand Down
39 changes: 39 additions & 0 deletions sapi/cli/tests/gh12363.phpt
@@ -0,0 +1,39 @@
--TEST--
Ensure a single Date header is present
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
include "php_cli_server.inc";
php_cli_server_start(<<<'PHP'
header('Date: Mon, 25 Mar 1985 00:20:00 GMT');
PHP
);

$host = PHP_CLI_SERVER_HOSTNAME;
$fp = php_cli_server_connect();

if(fwrite($fp, <<<HEADER
GET / HTTP/1.1
Host: {$host}
HEADER
)) {
while (!feof($fp)) {
echo fgets($fp);
}
}

fclose($fp);
?>
--EXPECTF--
HTTP/1.1 200 OK
Host: %s
Connection: close
X-Powered-By: %s
Date: Mon, 25 Mar 1985 00:20:00 GMT
Content-type: text/html; charset=UTF-8

0 comments on commit f6ac08c

Please sign in to comment.