Skip to content

Commit 1c328ee

Browse files
committed
Add populate_post_data() function
This function allows populating the $_POST and $_FILES globals for non-post requests. This avoids manual parsing of RFC1867 requests. Fixes #55815
1 parent 1518443 commit 1c328ee

File tree

7 files changed

+117
-5
lines changed

7 files changed

+117
-5
lines changed

ext/standard/basic_functions.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,6 +2262,8 @@ function htmlentities(string $string, int $flags = ENT_QUOTES | ENT_SUBSTITUTE |
22622262
*/
22632263
function get_html_translation_table(int $table = HTML_SPECIALCHARS, int $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, string $encoding = "UTF-8"): array {}
22642264

2265+
function populate_post_data(): void {}
2266+
22652267
/* }}} */
22662268

22672269
/* assert.c */

ext/standard/basic_functions_arginfo.h

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/html.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,3 +1559,19 @@ PHP_FUNCTION(get_html_translation_table)
15591559
}
15601560
}
15611561
/* }}} */
1562+
1563+
PHP_FUNCTION(populate_post_data)
1564+
{
1565+
ZEND_PARSE_PARAMETERS_NONE();
1566+
1567+
zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_POST]);
1568+
zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_FILES]);
1569+
array_init(&PG(http_globals)[TRACK_VARS_POST]);
1570+
array_init(&PG(http_globals)[TRACK_VARS_FILES]);
1571+
sapi_read_post_data();
1572+
sapi_handle_post(&PG(http_globals)[TRACK_VARS_POST]);
1573+
zend_hash_update(&EG(symbol_table), zend_string_init_interned(ZEND_STRL("_POST"), 1), &PG(http_globals)[TRACK_VARS_POST]);
1574+
zend_hash_update(&EG(symbol_table), zend_string_init_interned(ZEND_STRL("_FILES"), 1), &PG(http_globals)[TRACK_VARS_FILES]);
1575+
Z_ADDREF(PG(http_globals)[TRACK_VARS_POST]);
1576+
Z_ADDREF(PG(http_globals)[TRACK_VARS_FILES]);
1577+
}

main/SAPI.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ SAPI_API void sapi_handle_post(void *arg)
169169
}
170170
}
171171

172-
static void sapi_read_post_data(void)
172+
SAPI_API void sapi_read_post_data(void)
173173
{
174174
sapi_post_entry *post_entry;
175175
uint32_t content_type_length = (uint32_t)strlen(SG(request_info).content_type);

main/SAPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ SAPI_API int sapi_add_header_ex(const char *header_line, size_t header_line_len,
186186
SAPI_API int sapi_send_headers(void);
187187
SAPI_API void sapi_free_header(sapi_header_struct *sapi_header);
188188
SAPI_API void sapi_handle_post(void *arg);
189+
SAPI_API void sapi_read_post_data(void);
189190
SAPI_API size_t sapi_read_post_block(char *buffer, size_t buflen);
190191
SAPI_API int sapi_register_post_entries(const sapi_post_entry *post_entry);
191192
SAPI_API int sapi_register_post_entry(const sapi_post_entry *post_entry);

sapi/fpm/tests/put_multipart.phpt

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
--TEST--
2+
PUT multipart
3+
--EXTENSIONS--
4+
zend_test
5+
--SKIPIF--
6+
<?php include "skipif.inc"; ?>
7+
--FILE--
8+
<?php
9+
10+
require_once "tester.inc";
11+
12+
$cfg = <<<EOT
13+
[global]
14+
error_log = {{FILE:LOG}}
15+
[unconfined]
16+
listen = {{ADDR}}
17+
pm = dynamic
18+
pm.max_children = 5
19+
pm.start_servers = 1
20+
pm.min_spare_servers = 1
21+
pm.max_spare_servers = 3
22+
EOT;
23+
24+
$code = <<<'EOT'
25+
<?php
26+
populate_post_data();
27+
$file_path = __DIR__ . '/put_multipart_uploaded_file.txt';
28+
move_uploaded_file($_FILES[0]['tmp_name'], $file_path);
29+
$file_content = file_get_contents($file_path);
30+
unlink($file_path);
31+
echo json_encode([
32+
'post' => $_POST,
33+
'files' => $_FILES,
34+
'file_content' => $file_content,
35+
], JSON_PRETTY_PRINT);
36+
EOT;
37+
38+
$tester = new FPM\Tester($cfg, $code);
39+
$tester->start();
40+
$tester->expectLogStartNotices();
41+
echo $tester
42+
->request(method: 'PUT', stdin: [
43+
'parts' => [
44+
[
45+
"disposition" => "form-data",
46+
"param" => "name",
47+
"name" => "get_parameter",
48+
"value" => "foo",
49+
],
50+
[
51+
"disposition" => "form-data",
52+
"param" => "filename",
53+
"name" => "uploaded_file",
54+
"value" => "bar",
55+
],
56+
],
57+
])
58+
->getBody();
59+
$tester->terminate();
60+
$tester->expectLogTerminatingNotices();
61+
$tester->close();
62+
63+
?>
64+
--EXPECTF--
65+
{
66+
"post": {
67+
"get_parameter": "foo"
68+
},
69+
"files": [
70+
{
71+
"name": "uploaded_file",
72+
"full_path": "uploaded_file",
73+
"type": "",
74+
"tmp_name": "%s",
75+
"error": 0,
76+
"size": 3
77+
}
78+
],
79+
"file_content": "bar"
80+
}
81+
--CLEAN--
82+
<?php
83+
require_once "tester.inc";
84+
FPM\Tester::clean();
85+
$file_path = __DIR__ . '/put_multipart_uploaded_file.txt';
86+
@unlink($file_path);
87+
?>

sapi/fpm/tests/tester.inc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,8 @@ class Tester
615615
string $uri = null,
616616
string $scriptFilename = null,
617617
string $scriptName = null,
618-
?string $stdin = null
618+
?string $stdin = null,
619+
?string $method = null,
619620
): array {
620621
if (is_null($scriptFilename)) {
621622
$scriptFilename = $this->makeSourceFile();
@@ -630,7 +631,7 @@ class Tester
630631
$params = array_merge(
631632
[
632633
'GATEWAY_INTERFACE' => 'FastCGI/1.0',
633-
'REQUEST_METHOD' => is_null($stdin) ? 'GET' : 'POST',
634+
'REQUEST_METHOD' => $method ?? (is_null($stdin) ? 'GET' : 'POST'),
634635
'SCRIPT_FILENAME' => $scriptFilename === '' ? null : $scriptFilename,
635636
'SCRIPT_NAME' => $scriptName,
636637
'QUERY_STRING' => $query,
@@ -750,6 +751,7 @@ class Tester
750751
string|array $stdin = null,
751752
bool $expectError = false,
752753
int $readLimit = -1,
754+
?string $method = null,
753755
): Response {
754756
if ($this->hasError()) {
755757
return new Response(null, true);
@@ -759,7 +761,7 @@ class Tester
759761
$stdin = $this->parseStdin($stdin, $headers);
760762
}
761763

762-
$params = $this->getRequestParams($query, $headers, $uri, $scriptFilename, $scriptName, $stdin);
764+
$params = $this->getRequestParams($query, $headers, $uri, $scriptFilename, $scriptName, $stdin, $method);
763765
$this->trace('Request params', $params);
764766

765767
try {

0 commit comments

Comments
 (0)