Skip to content

Commit

Permalink
Fix bug #77680: Correctly implement recursive mkdir on FTP stream
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vtemian authored and nikic committed Mar 25, 2019
1 parent 85095df commit ec2ecb7
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 28 deletions.
6 changes: 5 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2019, PHP 7.2.18

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

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

- Standard:
. Fixed bug #77680 (recursive mkdir on ftp stream wrapper is incorrect).
(Vlad Temian)

04 Apr 2019, PHP 7.2.17

- Core:
Expand Down
12 changes: 10 additions & 2 deletions ext/ftp/tests/server.inc
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,13 @@ if ($pid) {
}

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

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

Expand Down Expand Up @@ -332,6 +337,9 @@ if ($pid) {
if (isset($bug7216)) {
fputs($s, "257 OK.\r\n");
} else {
if (isset($bug77680)) {
var_dump($buf);
}
fputs($s, "257 \"/path/to/ftproot$cwd$m[1]\" created.\r\n");
}

Expand Down
49 changes: 24 additions & 25 deletions ext/standard/ftp_fopen_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1070,41 +1070,40 @@ static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, in

/* find a top level directory we need to create */
while ((p = strrchr(buf, '/'))) {
*p = '\0';
php_stream_printf(stream, "CWD %s\r\n", buf);
*p = '\0';
php_stream_printf(stream, "CWD %s\r\n", strlen(buf) ? buf : "/");
result = GET_FTP_RESULT(stream);
if (result >= 200 && result <= 299) {
*p = '/';
break;
}
}
if (p == buf) {
php_stream_printf(stream, "MKD %s\r\n", resource->path);
result = GET_FTP_RESULT(stream);
} else {
php_stream_printf(stream, "MKD %s\r\n", buf);
result = GET_FTP_RESULT(stream);
if (result >= 200 && result <= 299) {
if (!p) {
p = buf;
}
/* create any needed directories if the creation of the 1st directory worked */
while (++p != e) {
if (*p == '\0' && *(p + 1) != '\0') {
*p = '/';
php_stream_printf(stream, "MKD %s\r\n", buf);
result = GET_FTP_RESULT(stream);
if (result < 200 || result > 299) {
if (options & REPORT_ERRORS) {
php_error_docref(NULL, E_WARNING, "%s", tmp_line);
}
break;
}

php_stream_printf(stream, "MKD %s\r\n", strlen(buf) ? buf : "/");
result = GET_FTP_RESULT(stream);

if (result >= 200 && result <= 299) {
if (!p) {
p = buf;
}
/* create any needed directories if the creation of the 1st directory worked */
while (p != e) {
if (*p == '\0' && *(p + 1) != '\0') {
*p = '/';
php_stream_printf(stream, "MKD %s\r\n", buf);
result = GET_FTP_RESULT(stream);
if (result < 200 || result > 299) {
if (options & REPORT_ERRORS) {
php_error_docref(NULL, E_WARNING, "%s", tmp_line);
}
break;
}
}
++p;
}
}
efree(buf);

efree(buf);
}

php_url_free(resource);
Expand Down
36 changes: 36 additions & 0 deletions ext/standard/tests/streams/bug77680.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
Recursive mkdir() on ftp should create missing directories.
--SKIPIF--
<?php
if (array_search('ftp',stream_get_wrappers()) === FALSE) die("skip ftp wrapper not available.");
if (!function_exists('pcntl_fork')) die("skip pcntl_fork() not available.");
?>
--FILE--
<?php
$bug77680=1;

require __DIR__ . "/../../../ftp/tests/server.inc";

$path = "ftp://localhost:" . $port."/one/two/three/";
mkdir($path, 0755, true);

?>
==DONE==
--EXPECTF--
string(20) "CWD /one/two/three
"
string(14) "CWD /one/two
"
string(10) "CWD /one
"
string(7) "CWD /
"
string(7) "MKD /
"
string(10) "MKD /one
"
string(14) "MKD /one/two
"
string(20) "MKD /one/two/three
"
==DONE==

0 comments on commit ec2ecb7

Please sign in to comment.