From b7783dca317e5738032bfb1aab9c904d98140af9 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 21 Dec 2023 15:09:27 +0100 Subject: [PATCH] Support index.php fallback for files in built-in server If no router script is used, the built-in webserver will now look for a fallback index file recursively in all cases, including URLs with a period. Fixes GH-12604 Closes GH-12992 --- UPGRADING | 8 ++++++++ sapi/cli/php_cli_server.c | 14 +++----------- sapi/cli/tests/php_cli_server.inc | 19 +++++++++++++++++-- sapi/cli/tests/php_cli_server_009.phpt | 2 +- sapi/cli/tests/php_cli_server_014.phpt | 9 ++++----- sapi/cli/tests/php_cli_server_016.phpt | 4 +++- 6 files changed, 36 insertions(+), 20 deletions(-) diff --git a/UPGRADING b/UPGRADING index 7ccc9751c0d0..0cd2dc3007ff 100644 --- a/UPGRADING +++ b/UPGRADING @@ -19,6 +19,14 @@ PHP 8.4 UPGRADE NOTES 1. Backward Incompatible Changes ======================================== +- CLI: + . The builtin server looks for an index file recursively by traversing parent + directories in case the specified file cannot be located. This process was + previously skipped if the path looked like it was referring to a file, i.e. + if the last path component contained a period. In that case, a 404 error was + returned. The behavior has been changed to look for an index file in all + cases. + - Core: . The type of PHP_DEBUG and PHP_ZTS constants changed to bool. diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index a09f273a7022..9dc266bb662f 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -1437,14 +1437,13 @@ static void php_cli_server_request_dtor(php_cli_server_request *req) /* {{{ */ } } /* }}} */ -static void php_cli_server_request_translate_vpath(php_cli_server_request *request, const char *document_root, size_t document_root_len) /* {{{ */ +static void php_cli_server_request_translate_vpath(const php_cli_server *server, php_cli_server_request *request, const char *document_root, size_t document_root_len) /* {{{ */ { zend_stat_t sb = {0}; static const char *index_files[] = { "index.php", "index.html", NULL }; char *buf = safe_pemalloc(1, request->vpath_len, 1 + document_root_len + 1 + sizeof("index.html"), 1); char *p = buf, *prev_path = NULL, *q, *vpath; size_t prev_path_len = 0; - int is_static_file = 0; memmove(p, document_root, document_root_len); p += document_root_len; @@ -1453,13 +1452,6 @@ static void php_cli_server_request_translate_vpath(php_cli_server_request *reque if (request->vpath[0] != '/') { *p++ = DEFAULT_SLASH; } - q = request->vpath + request->vpath_len; - while (q > request->vpath) { - if (*q-- == '.') { - is_static_file = 1; - break; - } - } memmove(p, request->vpath, request->vpath_len); #ifdef PHP_WIN32 q = p + request->vpath_len; @@ -1489,7 +1481,7 @@ static void php_cli_server_request_translate_vpath(php_cli_server_request *reque } file++; } - if (!*file || is_static_file) { + if (!*file) { if (prev_path) { pefree(prev_path, 1); } @@ -1801,7 +1793,7 @@ static int php_cli_server_client_read_request_on_message_complete(php_http_parse { php_cli_server_client *client = parser->data; client->request.protocol_version = parser->http_major * 100 + parser->http_minor; - php_cli_server_request_translate_vpath(&client->request, client->server->document_root, client->server->document_root_len); + php_cli_server_request_translate_vpath(client->server, &client->request, client->server->document_root, client->server->document_root_len); if (client->request.vpath) { const char *vpath = client->request.vpath; const char *end = vpath + client->request.vpath_len; diff --git a/sapi/cli/tests/php_cli_server.inc b/sapi/cli/tests/php_cli_server.inc index d4fca001e505..047537c815d5 100644 --- a/sapi/cli/tests/php_cli_server.inc +++ b/sapi/cli/tests/php_cli_server.inc @@ -17,7 +17,7 @@ function php_cli_server_start( $error = null; // Create dedicated doc root to avoid index.php clashes between tests. - $doc_root = __DIR__ . '/' . basename($_SERVER['PHP_SELF'], '.php'); + $doc_root = __DIR__ . DIRECTORY_SEPARATOR . basename($_SERVER['PHP_SELF'], '.php'); @mkdir($doc_root); if ($code) { @@ -103,7 +103,7 @@ function php_cli_server_start( printf("Server output:\n%s\n", file_get_contents($output_file)); } @unlink(__DIR__ . "/{$router}"); - @rmdir($doc_root); + remove_directory($doc_root); }, $handle ); @@ -126,4 +126,19 @@ function php_cli_server_connect() { return $fp; } +function remove_directory($dir) { + if (is_dir($dir) === false) { + return; + } + $files = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), + RecursiveIteratorIterator::CHILD_FIRST + ); + foreach ($files as $fileinfo) { + $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); + $todo($fileinfo->getRealPath()); + } + @rmdir($dir); +} + ?> diff --git a/sapi/cli/tests/php_cli_server_009.phpt b/sapi/cli/tests/php_cli_server_009.phpt index 07ba46e89c71..48f298e7f5ba 100644 --- a/sapi/cli/tests/php_cli_server_009.phpt +++ b/sapi/cli/tests/php_cli_server_009.phpt @@ -79,4 +79,4 @@ X-Powered-By: PHP/%s Content-type: text/html; charset=UTF-8 string(9) "/foo/bar/" -HTTP/1.0 404 Not Found +HTTP/1.0 200 OK diff --git a/sapi/cli/tests/php_cli_server_014.phpt b/sapi/cli/tests/php_cli_server_014.phpt index b29a01437399..cbe47d1ec690 100644 --- a/sapi/cli/tests/php_cli_server_014.phpt +++ b/sapi/cli/tests/php_cli_server_014.phpt @@ -61,12 +61,11 @@ X-Powered-By: %s Content-type: %s done -HTTP/1.1 404 Not Found +HTTP/1.1 200 OK Host: %s Date: %s Connection: close -Content-Type: %s -Content-Length: %d +X-Powered-By: PHP/%s +Content-type: %s -404 Not Found -

Not Found

The requested resource /main/no-exists.php was not found on this server.

+done diff --git a/sapi/cli/tests/php_cli_server_016.phpt b/sapi/cli/tests/php_cli_server_016.phpt index be8855fb9551..3a5ab328ec96 100644 --- a/sapi/cli/tests/php_cli_server_016.phpt +++ b/sapi/cli/tests/php_cli_server_016.phpt @@ -10,7 +10,9 @@ include "skipif.inc"; --FILE-- docRoot . '/router.php', <<<'PHP' +