Skip to content

Commit d7d0d19

Browse files
committed
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
1 parent 8876639 commit d7d0d19

6 files changed

+35
-20
lines changed

UPGRADING

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ PHP 8.4 UPGRADE NOTES
1919
1. Backward Incompatible Changes
2020
========================================
2121

22+
- CLI:
23+
. The builtin server looks for an index file recursively by traversing parent
24+
directories in case the specified file cannot be located. This process was
25+
previously skipped if the path looked like it was referring to a file, i.e.
26+
if the last path component contained a period. In that case, a 404 error was
27+
returned. The behavior has been changed to look for an index file in all
28+
cases.
29+
2230
- Core:
2331
. The type of PHP_DEBUG and PHP_ZTS constants changed to bool.
2432

sapi/cli/php_cli_server.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,14 +1437,13 @@ static void php_cli_server_request_dtor(php_cli_server_request *req) /* {{{ */
14371437
}
14381438
} /* }}} */
14391439

1440-
static void php_cli_server_request_translate_vpath(php_cli_server_request *request, const char *document_root, size_t document_root_len) /* {{{ */
1440+
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) /* {{{ */
14411441
{
14421442
zend_stat_t sb = {0};
14431443
static const char *index_files[] = { "index.php", "index.html", NULL };
14441444
char *buf = safe_pemalloc(1, request->vpath_len, 1 + document_root_len + 1 + sizeof("index.html"), 1);
14451445
char *p = buf, *prev_path = NULL, *q, *vpath;
14461446
size_t prev_path_len = 0;
1447-
int is_static_file = 0;
14481447

14491448
memmove(p, document_root, document_root_len);
14501449
p += document_root_len;
@@ -1453,13 +1452,6 @@ static void php_cli_server_request_translate_vpath(php_cli_server_request *reque
14531452
if (request->vpath[0] != '/') {
14541453
*p++ = DEFAULT_SLASH;
14551454
}
1456-
q = request->vpath + request->vpath_len;
1457-
while (q > request->vpath) {
1458-
if (*q-- == '.') {
1459-
is_static_file = 1;
1460-
break;
1461-
}
1462-
}
14631455
memmove(p, request->vpath, request->vpath_len);
14641456
#ifdef PHP_WIN32
14651457
q = p + request->vpath_len;
@@ -1489,7 +1481,7 @@ static void php_cli_server_request_translate_vpath(php_cli_server_request *reque
14891481
}
14901482
file++;
14911483
}
1492-
if (!*file || is_static_file) {
1484+
if (!*file) {
14931485
if (prev_path) {
14941486
pefree(prev_path, 1);
14951487
}
@@ -1801,7 +1793,7 @@ static int php_cli_server_client_read_request_on_message_complete(php_http_parse
18011793
{
18021794
php_cli_server_client *client = parser->data;
18031795
client->request.protocol_version = parser->http_major * 100 + parser->http_minor;
1804-
php_cli_server_request_translate_vpath(&client->request, client->server->document_root, client->server->document_root_len);
1796+
php_cli_server_request_translate_vpath(client->server, &client->request, client->server->document_root, client->server->document_root_len);
18051797
if (client->request.vpath) {
18061798
const char *vpath = client->request.vpath;
18071799
const char *end = vpath + client->request.vpath_len;

sapi/cli/tests/php_cli_server.inc

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function php_cli_server_start(
1717
$error = null;
1818

1919
// Create dedicated doc root to avoid index.php clashes between tests.
20-
$doc_root = __DIR__ . '/' . basename($_SERVER['PHP_SELF'], '.php');
20+
$doc_root = __DIR__ . DIRECTORY_SEPARATOR . basename($_SERVER['PHP_SELF'], '.php');
2121
@mkdir($doc_root);
2222

2323
if ($code) {
@@ -103,7 +103,7 @@ function php_cli_server_start(
103103
printf("Server output:\n%s\n", file_get_contents($output_file));
104104
}
105105
@unlink(__DIR__ . "/{$router}");
106-
@rmdir($doc_root);
106+
remove_directory($doc_root);
107107
},
108108
$handle
109109
);
@@ -126,4 +126,19 @@ function php_cli_server_connect() {
126126
return $fp;
127127
}
128128

129+
function remove_directory($dir) {
130+
if (is_dir($dir) === false) {
131+
return;
132+
}
133+
$files = new RecursiveIteratorIterator(
134+
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
135+
RecursiveIteratorIterator::CHILD_FIRST
136+
);
137+
foreach ($files as $fileinfo) {
138+
$todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
139+
$todo($fileinfo->getRealPath());
140+
}
141+
@rmdir($dir);
142+
}
143+
129144
?>

sapi/cli/tests/php_cli_server_009.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,4 @@ X-Powered-By: PHP/%s
7979
Content-type: text/html; charset=UTF-8
8080

8181
string(9) "/foo/bar/"
82-
HTTP/1.0 404 Not Found
82+
HTTP/1.0 200 OK

sapi/cli/tests/php_cli_server_014.phpt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,11 @@ X-Powered-By: %s
6161
Content-type: %s
6262

6363
done
64-
HTTP/1.1 404 Not Found
64+
HTTP/1.1 200 OK
6565
Host: %s
6666
Date: %s
6767
Connection: close
6868
X-Powered-By: PHP/%s
69-
Content-Type: %s
70-
Content-Length: %d
69+
Content-type: %s
7170

72-
<!doctype html><html><head><title>404 Not Found</title><style>AAA</style>
73-
</head><body><h1>Not Found</h1><p>The requested resource <code class="url">/main/no-exists.php</code> was not found on this server.</p></body></html>
71+
done

sapi/cli/tests/php_cli_server_016.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ include "skipif.inc";
1010
--FILE--
1111
<?php
1212
include "php_cli_server.inc";
13-
php_cli_server_start(<<<'PHP'
13+
$info = php_cli_server_start(null, 'router.php');
14+
file_put_contents($info->docRoot . '/router.php', <<<'PHP'
15+
<?php
1416
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"]))
1517
return false; // serve the requested resource as-is.
1618
else {

0 commit comments

Comments
 (0)