Skip to content

Commit ec2ecb7

Browse files
vtemiannikic
authored andcommitted
Fix bug #77680: Correctly implement recursive mkdir on FTP stream
If the root directory was missing, an extra CWD without arguments was made. Also, the MKD contained an empty string. Now the CWD will use / and MKDs will be issued starting from the root directory.
1 parent 85095df commit ec2ecb7

File tree

4 files changed

+75
-28
lines changed

4 files changed

+75
-28
lines changed

NEWS

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? 2019, PHP 7.2.18
44

5-
- interbase:
5+
- Interbase:
66
. Fixed bug #72175 (Impossibility of creating multiple connections to
77
Interbase with php 7.x). (Nikita)
88

@@ -12,6 +12,10 @@ PHP NEWS
1212
- Reflection:
1313
. Fixed bug #77772 (ReflectionClass::getMethods(null) doesn't work). (Nikita)
1414

15+
- Standard:
16+
. Fixed bug #77680 (recursive mkdir on ftp stream wrapper is incorrect).
17+
(Vlad Temian)
18+
1519
04 Apr 2019, PHP 7.2.17
1620

1721
- Core:

ext/ftp/tests/server.inc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,13 @@ if ($pid) {
289289
}
290290

291291
}elseif (preg_match("~^CWD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
292-
change_dir($m[1]);
293-
fputs($s, "250 CWD command successful.\r\n");
292+
if (isset($bug77680)) {
293+
fputs($s, "550 Directory change to $m[1] failed: file does not exist\r\n");
294+
var_dump($buf);
295+
} else {
296+
change_dir($m[1]);
297+
fputs($s, "250 CWD command successful.\r\n");
298+
}
294299

295300
} elseif (preg_match("~^NLST(?: ([A-Za-z./]+))?\r\n$~", $buf, $m)) {
296301

@@ -332,6 +337,9 @@ if ($pid) {
332337
if (isset($bug7216)) {
333338
fputs($s, "257 OK.\r\n");
334339
} else {
340+
if (isset($bug77680)) {
341+
var_dump($buf);
342+
}
335343
fputs($s, "257 \"/path/to/ftproot$cwd$m[1]\" created.\r\n");
336344
}
337345

ext/standard/ftp_fopen_wrapper.c

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,41 +1070,40 @@ static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, in
10701070

10711071
/* find a top level directory we need to create */
10721072
while ((p = strrchr(buf, '/'))) {
1073-
*p = '\0';
1074-
php_stream_printf(stream, "CWD %s\r\n", buf);
1073+
*p = '\0';
1074+
php_stream_printf(stream, "CWD %s\r\n", strlen(buf) ? buf : "/");
10751075
result = GET_FTP_RESULT(stream);
10761076
if (result >= 200 && result <= 299) {
10771077
*p = '/';
10781078
break;
10791079
}
1080-
}
1081-
if (p == buf) {
1082-
php_stream_printf(stream, "MKD %s\r\n", resource->path);
1083-
result = GET_FTP_RESULT(stream);
1084-
} else {
1085-
php_stream_printf(stream, "MKD %s\r\n", buf);
1086-
result = GET_FTP_RESULT(stream);
1087-
if (result >= 200 && result <= 299) {
1088-
if (!p) {
1089-
p = buf;
1090-
}
1091-
/* create any needed directories if the creation of the 1st directory worked */
1092-
while (++p != e) {
1093-
if (*p == '\0' && *(p + 1) != '\0') {
1094-
*p = '/';
1095-
php_stream_printf(stream, "MKD %s\r\n", buf);
1096-
result = GET_FTP_RESULT(stream);
1097-
if (result < 200 || result > 299) {
1098-
if (options & REPORT_ERRORS) {
1099-
php_error_docref(NULL, E_WARNING, "%s", tmp_line);
1100-
}
1101-
break;
1080+
}
1081+
1082+
php_stream_printf(stream, "MKD %s\r\n", strlen(buf) ? buf : "/");
1083+
result = GET_FTP_RESULT(stream);
1084+
1085+
if (result >= 200 && result <= 299) {
1086+
if (!p) {
1087+
p = buf;
1088+
}
1089+
/* create any needed directories if the creation of the 1st directory worked */
1090+
while (p != e) {
1091+
if (*p == '\0' && *(p + 1) != '\0') {
1092+
*p = '/';
1093+
php_stream_printf(stream, "MKD %s\r\n", buf);
1094+
result = GET_FTP_RESULT(stream);
1095+
if (result < 200 || result > 299) {
1096+
if (options & REPORT_ERRORS) {
1097+
php_error_docref(NULL, E_WARNING, "%s", tmp_line);
11021098
}
1099+
break;
11031100
}
11041101
}
1102+
++p;
11051103
}
11061104
}
1107-
efree(buf);
1105+
1106+
efree(buf);
11081107
}
11091108

11101109
php_url_free(resource);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Recursive mkdir() on ftp should create missing directories.
3+
--SKIPIF--
4+
<?php
5+
if (array_search('ftp',stream_get_wrappers()) === FALSE) die("skip ftp wrapper not available.");
6+
if (!function_exists('pcntl_fork')) die("skip pcntl_fork() not available.");
7+
?>
8+
--FILE--
9+
<?php
10+
$bug77680=1;
11+
12+
require __DIR__ . "/../../../ftp/tests/server.inc";
13+
14+
$path = "ftp://localhost:" . $port."/one/two/three/";
15+
mkdir($path, 0755, true);
16+
17+
?>
18+
==DONE==
19+
--EXPECTF--
20+
string(20) "CWD /one/two/three
21+
"
22+
string(14) "CWD /one/two
23+
"
24+
string(10) "CWD /one
25+
"
26+
string(7) "CWD /
27+
"
28+
string(7) "MKD /
29+
"
30+
string(10) "MKD /one
31+
"
32+
string(14) "MKD /one/two
33+
"
34+
string(20) "MKD /one/two/three
35+
"
36+
==DONE==

0 commit comments

Comments
 (0)