Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions sapi/cli/php.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,13 @@ Start built-in web server on the given local address and port
Specify the document root to be used by the built-in web server
.TP
.PD 0
.B \-\-redirect
.TP
.PD 1
.B \-P
Redirect not found files to index.php and set PATH_INFO
.TP
.PD 0
.B \-\-version
.TP
.PD 1
Expand Down
2 changes: 2 additions & 0 deletions sapi/cli/php_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ const opt_struct OPTIONS[] = {
{'l', 0, "syntax-check"},
{'m', 0, "modules"},
{'n', 0, "no-php-ini"},
{'P', 0, "redirect"},
{'q', 0, "no-header"}, /* for compatibility with CGI (do not generate HTTP headers) */
{'R', 1, "process-code"},
{'H', 0, "hide-args"},
Expand Down Expand Up @@ -541,6 +542,7 @@ static void php_cli_usage(char *argv0)
" -H Hide any passed arguments from external tools.\n"
" -S <addr>:<port> Run with built-in web server.\n"
" -t <docroot> Specify document root <docroot> for built-in web server.\n"
" -P Redirect not found files to index.php and set PATH_INFO.\n"
" -s Output HTML syntax highlighted source.\n"
" -v Version number\n"
" -w Output source with stripped comments and whitespace.\n"
Expand Down
32 changes: 20 additions & 12 deletions sapi/cli/php_cli_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ typedef struct php_cli_server {
size_t document_root_len;
char *router;
size_t router_len;
int redirect;
socklen_t socklen;
HashTable clients;
HashTable extension_mime_types;
Expand Down Expand Up @@ -1361,11 +1362,11 @@ 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(php_cli_server_request *request, struct php_cli_server *server) /* {{{ */
{
zend_stat_t sb;
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 *buf = safe_pemalloc(1, request->vpath_len, 1 + server->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;
Expand All @@ -1374,17 +1375,19 @@ static void php_cli_server_request_translate_vpath(php_cli_server_request *reque
return;
}

memmove(p, document_root, document_root_len);
p += document_root_len;
memmove(p, server->document_root, server->document_root_len);
p += server->document_root_len;
vpath = p;
if (request->vpath_len > 0 && request->vpath[0] != '/') {
*p++ = DEFAULT_SLASH;
}
q = request->vpath + request->vpath_len;
while (q > request->vpath) {
if (*q-- == '.') {
is_static_file = 1;
break;
if (!server->redirect) {
q = request->vpath + request->vpath_len;
while (q > request->vpath) {
if (*q-- == '.') {
is_static_file = 1;
break;
}
}
}
memmove(p, request->vpath, request->vpath_len);
Expand Down Expand Up @@ -1657,7 +1660,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->request, client->server);
{
const char *vpath = client->request.vpath, *end = vpath + client->request.vpath_len, *p = end;
client->request.ext = end;
Expand Down Expand Up @@ -2202,7 +2205,7 @@ static void php_cli_server_client_dtor_wrapper(zval *zv) /* {{{ */
pefree(p, 1);
} /* }}} */

static int php_cli_server_ctor(php_cli_server *server, const char *addr, const char *document_root, const char *router) /* {{{ */
static int php_cli_server_ctor(php_cli_server *server, const char *addr, const char *document_root, const char *router, int redirect) /* {{{ */
{
int retval = SUCCESS;
char *host = NULL;
Expand Down Expand Up @@ -2304,6 +2307,7 @@ static int php_cli_server_ctor(php_cli_server *server, const char *addr, const c
goto out;
}

server->redirect = redirect;
server->is_running = 1;
out:
if (retval != SUCCESS) {
Expand Down Expand Up @@ -2482,6 +2486,7 @@ int do_cli_server(int argc, char **argv) /* {{{ */
char *php_optarg = NULL;
int php_optind = 1;
int c;
int redirect = 0;
const char *server_bind_address = NULL;
extern const opt_struct OPTIONS[];
const char *document_root = NULL;
Expand All @@ -2496,6 +2501,9 @@ int do_cli_server(int argc, char **argv) /* {{{ */
case 't':
document_root = php_optarg;
break;
case 'P':
redirect = 1;
break;
}
}

Expand Down Expand Up @@ -2528,7 +2536,7 @@ int do_cli_server(int argc, char **argv) /* {{{ */
router = argv[php_optind];
}

if (FAILURE == php_cli_server_ctor(&server, server_bind_address, document_root, router)) {
if (FAILURE == php_cli_server_ctor(&server, server_bind_address, document_root, router, redirect)) {
return 1;
}
sapi_module.phpinfo_as_text = 0;
Expand Down
44 changes: 44 additions & 0 deletions sapi/cli/tests/php_cli_server_021.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
--TEST--
PATH_INFO test with -P / --redirect
--INI--
allow_url_fopen=1
--SKIPIF--
<?php
include "skipif.inc";
?>
--FILE--
<?php
include "php_cli_server.inc";
echo "-- Without redirect\n";
$proc_handle = php_cli_server_start('var_dump($_SERVER["PATH_INFO"]);', false);
echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS);
echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . '/foo/bar');
echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . '/foo-1.1/bar');
echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . '/foo/bar.png');
php_cli_server_stop($proc_handle);

echo "-- With redirect\n";
$proc_handle = php_cli_server_start('var_dump($_SERVER["PATH_INFO"]);', false, '--redirect');
echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS);
echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . '/foo/bar');
echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . '/foo-1.1/bar');
echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . '/foo/bar.png');
php_cli_server_stop($proc_handle);
?>
Done
--EXPECTF--
-- Without redirect
NULL
string(8) "/foo/bar"

Warning: file_get_contents(%s/foo-1.1/bar): failed to open stream: HTTP request failed! HTTP/1.0 404 Not Found
in %s on line %d

Warning: file_get_contents(%s/foo/bar.png): failed to open stream: HTTP request failed! HTTP/1.0 404 Not Found
in %s on line %d
-- With redirect
NULL
string(8) "/foo/bar"
string(12) "/foo-1.1/bar"
string(12) "/foo/bar.png"
Done