diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 7c69fdef1749e..486c929407b1d 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -202,6 +202,7 @@ typedef struct php_cli_server_http_response_status_code_pair {
static php_cli_server_http_response_status_code_pair template_map[] = {
{ 400, "
%s
Your browser sent a request that this server could not understand.
" },
{ 404, "%s
The requested resource %s
was not found on this server.
" },
+ { 405, "%s
Requested method not allowed.
" },
{ 500, "%s
The server is temporarily unavailable.
" },
{ 501, "%s
Request method not supported.
" }
};
@@ -1980,49 +1981,51 @@ static zend_result php_cli_server_send_error_page(php_cli_server *server, php_cl
php_cli_server_content_sender_ctor(&client->content_sender);
client->content_sender_initialized = true;
- escaped_request_uri = php_escape_html_entities_ex((const unsigned char *) ZSTR_VAL(client->request.request_uri), ZSTR_LEN(client->request.request_uri), 0, ENT_QUOTES, NULL, /* double_encode */ 0, /* quiet */ 0);
+ if (client->request.request_method != PHP_HTTP_HEAD) {
+ escaped_request_uri = php_escape_html_entities_ex((const unsigned char *) ZSTR_VAL(client->request.request_uri), ZSTR_LEN(client->request.request_uri), 0, ENT_QUOTES, NULL, /* double_encode */ 0, /* quiet */ 0);
- {
- static const char prologue_template[] = "%d %s";
- php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(prologue_template) + 3 + strlen(status_string) + 1);
- if (!chunk) {
- goto fail;
+ {
+ static const char prologue_template[] = "%d %s";
+ php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(prologue_template) + 3 + strlen(status_string) + 1);
+ if (!chunk) {
+ goto fail;
+ }
+ snprintf(chunk->data.heap.p, chunk->data.heap.len, prologue_template, status, status_string);
+ chunk->data.heap.len = strlen(chunk->data.heap.p);
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
}
- snprintf(chunk->data.heap.p, chunk->data.heap.len, prologue_template, status, status_string);
- chunk->data.heap.len = strlen(chunk->data.heap.p);
- php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
- }
- {
- php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(php_cli_server_css, sizeof(php_cli_server_css) - 1);
- if (!chunk) {
- goto fail;
+ {
+ php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(php_cli_server_css, sizeof(php_cli_server_css) - 1);
+ if (!chunk) {
+ goto fail;
+ }
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
}
- php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
- }
- {
- static const char template[] = "";
- php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(template, sizeof(template) - 1);
- if (!chunk) {
- goto fail;
+ {
+ static const char template[] = "";
+ php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(template, sizeof(template) - 1);
+ if (!chunk) {
+ goto fail;
+ }
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
}
- php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
- }
- {
- php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(content_template) + ZSTR_LEN(escaped_request_uri) + 3 + strlen(status_string) + 1);
- if (!chunk) {
- goto fail;
+ {
+ php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(content_template) + ZSTR_LEN(escaped_request_uri) + 3 + strlen(status_string) + 1);
+ if (!chunk) {
+ goto fail;
+ }
+ snprintf(chunk->data.heap.p, chunk->data.heap.len, content_template, status_string, ZSTR_VAL(escaped_request_uri));
+ chunk->data.heap.len = strlen(chunk->data.heap.p);
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
}
- snprintf(chunk->data.heap.p, chunk->data.heap.len, content_template, status_string, ZSTR_VAL(escaped_request_uri));
- chunk->data.heap.len = strlen(chunk->data.heap.p);
- php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
- }
- {
- static const char epilogue_template[] = "";
- php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(epilogue_template, sizeof(epilogue_template) - 1);
- if (!chunk) {
- goto fail;
+ {
+ static const char epilogue_template[] = "";
+ php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(epilogue_template, sizeof(epilogue_template) - 1);
+ if (!chunk) {
+ goto fail;
+ }
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
}
- php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
}
{
@@ -2038,6 +2041,15 @@ static zend_result php_cli_server_send_error_page(php_cli_server *server, php_cl
smart_str_appends_ex(&buffer, "Content-Length: ", 1);
smart_str_append_unsigned_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1);
smart_str_appendl_ex(&buffer, "\r\n", 2, 1);
+ if (status == 405) {
+ smart_str_appends_ex(&buffer, "Allow: ", 1);
+ smart_str_appends_ex(&buffer, php_http_method_str(PHP_HTTP_GET), 1);
+ smart_str_appends_ex(&buffer, ", ", 1);
+ smart_str_appends_ex(&buffer, php_http_method_str(PHP_HTTP_HEAD), 1);
+ smart_str_appends_ex(&buffer, ", ", 1);
+ smart_str_appends_ex(&buffer, php_http_method_str(PHP_HTTP_POST), 1);
+ smart_str_appendl_ex(&buffer, "\r\n", 2, 1);
+ }
smart_str_appendl_ex(&buffer, "\r\n", 2, 1);
chunk = php_cli_server_chunk_heap_new(buffer.s, ZSTR_VAL(buffer.s), ZSTR_LEN(buffer.s));
@@ -2053,14 +2065,18 @@ static zend_result php_cli_server_send_error_page(php_cli_server *server, php_cl
if (errstr) {
pefree(errstr, 1);
}
- zend_string_free(escaped_request_uri);
+ if (escaped_request_uri) {
+ zend_string_free(escaped_request_uri);
+ }
return SUCCESS;
fail:
if (errstr) {
pefree(errstr, 1);
}
- zend_string_free(escaped_request_uri);
+ if (escaped_request_uri) {
+ zend_string_free(escaped_request_uri);
+ }
return FAILURE;
} /* }}} */
@@ -2088,6 +2104,12 @@ static zend_result php_cli_server_begin_send_static(php_cli_server *server, php_
int fd;
int status = 200;
+ if (client->request.request_method == PHP_HTTP_DELETE
+ || client->request.request_method == PHP_HTTP_PUT
+ || client->request.request_method == PHP_HTTP_PATCH) {
+ return php_cli_server_send_error_page(server, client, 405);
+ }
+
if (client->request.path_translated && strlen(client->request.path_translated) != client->request.path_translated_len) {
/* can't handle paths that contain nul bytes */
return php_cli_server_send_error_page(server, client, 400);
@@ -2115,7 +2137,9 @@ static zend_result php_cli_server_begin_send_static(php_cli_server *server, php_
php_cli_server_content_sender_ctor(&client->content_sender);
client->content_sender_initialized = true;
- client->file_fd = fd;
+ if (client->request.request_method != PHP_HTTP_HEAD) {
+ client->file_fd = fd;
+ }
{
php_cli_server_chunk *chunk;
diff --git a/sapi/cli/tests/php_cli_server_013.phpt b/sapi/cli/tests/php_cli_server_013.phpt
index 8042219afe316..11e3fdf065b1f 100644
--- a/sapi/cli/tests/php_cli_server_013.phpt
+++ b/sapi/cli/tests/php_cli_server_013.phpt
@@ -58,6 +58,60 @@ HEAD /main/foo/bar HTTP/1.1
Host: {$host}
+HEADER
+)) {
+ while (!feof($fp)) {
+ $output .= fgets($fp);
+ }
+}
+
+echo preg_replace("/", $output), "\n";
+fclose($fp);
+
+$output = '';
+$fp = php_cli_server_connect();
+
+if(fwrite($fp, <<(.*?)<\/style>/s", "", $output), "\n";
+fclose($fp);
+
+$output = '';
+$fp = php_cli_server_connect();
+
+if(fwrite($fp, <<