mirror of
https://github.com/php/php-src.git
synced 2024-11-24 02:15:04 +08:00
Merge branch 'pull-request/2345'
* pull-request/2345: FTP: implement MLSD for structured listing of directories, decribed at https://tools.ietf.org/html/rfc3659
This commit is contained in:
commit
f007e9ff8c
3
NEWS
3
NEWS
@ -63,6 +63,9 @@ PHP NEWS
|
||||
. Fixed bug #69865 (php-fpm does not close stderr when using syslog).
|
||||
(Mike)
|
||||
|
||||
- FTP:
|
||||
. Implement MLSD for structured listing of directories. (blar)
|
||||
|
||||
- GD:
|
||||
. Implemented imageresolution as getter and setter (Christoph)
|
||||
|
||||
|
@ -698,6 +698,16 @@ ftp_list(ftpbuf_t *ftp, const char *path, const size_t path_len, int recursive)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ftp_mlsd
|
||||
*/
|
||||
char**
|
||||
ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len)
|
||||
{
|
||||
return ftp_genlist(ftp, "MLSD", sizeof("MLSD")-1, path, path_len);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ftp_type
|
||||
*/
|
||||
int
|
||||
|
@ -163,6 +163,13 @@ char** ftp_nlist(ftpbuf_t *ftp, const char *path, const size_t path_len);
|
||||
*/
|
||||
char** ftp_list(ftpbuf_t *ftp, const char *path, const size_t path_len, int recursive);
|
||||
|
||||
/* returns a NULL-terminated array of lines returned by the ftp
|
||||
* MLSD command for the given path or NULL on error. the return
|
||||
* array must be freed (but don't
|
||||
* free the array elements)
|
||||
*/
|
||||
char** ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len);
|
||||
|
||||
/* switches passive mode on or off
|
||||
* returns true on success, false on error
|
||||
*/
|
||||
|
@ -117,6 +117,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_rawlist, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, recursive)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_ftp_mlsd, 0)
|
||||
ZEND_ARG_INFO(0, ftp)
|
||||
ZEND_ARG_INFO(0, directory)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_ftp_systype, 0)
|
||||
ZEND_ARG_INFO(0, ftp)
|
||||
ZEND_END_ARG_INFO()
|
||||
@ -254,6 +259,7 @@ const zend_function_entry php_ftp_functions[] = {
|
||||
PHP_FE(ftp_alloc, arginfo_ftp_alloc)
|
||||
PHP_FE(ftp_nlist, arginfo_ftp_nlist)
|
||||
PHP_FE(ftp_rawlist, arginfo_ftp_rawlist)
|
||||
PHP_FE(ftp_mlsd, arginfo_ftp_mlsd)
|
||||
PHP_FE(ftp_systype, arginfo_ftp_systype)
|
||||
PHP_FE(ftp_pasv, arginfo_ftp_pasv)
|
||||
PHP_FE(ftp_get, arginfo_ftp_get)
|
||||
@ -748,6 +754,36 @@ PHP_FUNCTION(ftp_rawlist)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array ftp_mlsd(resource stream, string directory)
|
||||
Returns a detailed listing of a directory as an array of output lines */
|
||||
PHP_FUNCTION(ftp_mlsd)
|
||||
{
|
||||
zval *z_ftp;
|
||||
ftpbuf_t *ftp;
|
||||
char **llist, **ptr, *dir;
|
||||
size_t dir_len;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* get raw directory listing */
|
||||
if (NULL == (llist = ftp_mlsd(ftp, dir, dir_len))) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
array_init(return_value);
|
||||
for (ptr = llist; *ptr; ptr++) {
|
||||
add_next_index_string(return_value, *ptr);
|
||||
}
|
||||
efree(llist);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string ftp_systype(resource stream)
|
||||
Returns the system type identifier */
|
||||
PHP_FUNCTION(ftp_systype)
|
||||
|
@ -54,6 +54,7 @@ PHP_FUNCTION(ftp_chmod);
|
||||
PHP_FUNCTION(ftp_alloc);
|
||||
PHP_FUNCTION(ftp_nlist);
|
||||
PHP_FUNCTION(ftp_rawlist);
|
||||
PHP_FUNCTION(ftp_mlsd);
|
||||
PHP_FUNCTION(ftp_systype);
|
||||
PHP_FUNCTION(ftp_pasv);
|
||||
PHP_FUNCTION(ftp_get);
|
||||
|
@ -30,6 +30,7 @@ var_dump(ftp_rename($ftp));
|
||||
var_dump(ftp_site($ftp));
|
||||
var_dump(ftp_set_option($ftp));
|
||||
var_dump(ftp_get_option($ftp));
|
||||
var_dump(ftp_mlsd($ftp));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
@ -98,3 +99,6 @@ NULL
|
||||
|
||||
Warning: ftp_get_option() expects exactly 2 parameters, 1 given in %s006.php on line 25
|
||||
NULL
|
||||
|
||||
Warning: ftp_mlsd() expects exactly 2 parameters, 1 given in %s006.php on line 26
|
||||
NULL
|
||||
|
34
ext/ftp/tests/ftp_mlsd_empty_directory.phpt
Normal file
34
ext/ftp/tests/ftp_mlsd_empty_directory.phpt
Normal file
@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
ftp_mlsd() must not return false on empty directories
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require 'skipif.inc';
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'server.inc';
|
||||
|
||||
$ftp = ftp_connect('127.0.0.1', $port);
|
||||
if (!$ftp) die("Couldn't connect to the server");
|
||||
|
||||
var_dump(ftp_login($ftp, 'user', 'pass'));
|
||||
|
||||
var_dump(ftp_mlsd($ftp, ''));
|
||||
var_dump(ftp_mlsd($ftp, 'emptydir'));
|
||||
var_dump(ftp_mlsd($ftp, 'bogusdir'));
|
||||
|
||||
ftp_close($ftp);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(109) "modify=20170127230002;perm=flcdmpe;type=cdir;unique=811U4340002;UNIX.group=33;UNIX.mode=0755;UNIX.owner=33; ."
|
||||
[1]=>
|
||||
string(110) "modify=20170127230002;perm=flcdmpe;type=pdir;unique=811U4340002;UNIX.group=33;UNIX.mode=0755;UNIX.owner=33; .."
|
||||
[2]=>
|
||||
string(122) "modify=20170126121225;perm=adfrw;size=4729;type=file;unique=811U4340CB9;UNIX.group=33;UNIX.mode=0644;UNIX.owner=33; foobar"
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
bool(false)
|
20
ext/ftp/tests/ftp_mlsd_missing_directory.phpt
Normal file
20
ext/ftp/tests/ftp_mlsd_missing_directory.phpt
Normal file
@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Testing ftp_mlsd returns false on server error
|
||||
--CREDITS--
|
||||
Andreas Treichel <gmblar+github [at] gmail [dot] com>
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require 'skipif.inc';
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'server.inc';
|
||||
|
||||
$ftp = ftp_connect('127.0.0.1', $port);
|
||||
ftp_login($ftp, 'user', 'pass');
|
||||
if (!$ftp) die("Couldn't connect to the server");
|
||||
|
||||
var_dump(ftp_mlsd($ftp, 'no_exists/'));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(false)
|
@ -441,6 +441,44 @@ if ($pid) {
|
||||
fputs($s, "350 OK\r\n");
|
||||
}elseif (preg_match('/^SIZE largefile/', $buf)) {
|
||||
fputs($s, "213 5368709120\r\n");
|
||||
}elseif (preg_match('/^MLSD no_exists\//', $buf, $matches)) {
|
||||
fputs($s, "425 Error establishing connection\r\n");
|
||||
}elseif (preg_match("~^MLSD(?: ([A-Za-z./]+))?\r\n$~", $buf, $m)) {
|
||||
|
||||
if(isset($m[1]) && (($m[1] === 'bogusdir') || ($m[1] === '/bogusdir'))) {
|
||||
fputs($s, "250 $m[1]: No such file or directory\r\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// there are some servers that don't open the ftp-data socket if there's nothing to send
|
||||
if(isset($bug39458) && isset($m[1]) && $m[1] === 'emptydir') {
|
||||
fputs($s, "226 Transfer complete.\r\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(empty($pasv)) {
|
||||
fputs($s, "150 File status okay; about to open data connection\r\n");
|
||||
if(!$fs = stream_socket_client("tcp://$host:$port")) {
|
||||
fputs($s, "425 Can't open data connection\r\n");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
fputs($s, "125 Data connection already open; transfer starting.\r\n");
|
||||
$fs = $pasvs;
|
||||
}
|
||||
|
||||
if((!empty($ssl)) && (!stream_socket_enable_crypto($pasvs, TRUE, STREAM_CRYPTO_METHOD_SSLv23_SERVER))) {
|
||||
die("SSLv23 handshake failed.\n");
|
||||
}
|
||||
|
||||
if(empty($m[1]) || $m[1] !== 'emptydir') {
|
||||
fputs($fs, "modify=20170127230002;perm=flcdmpe;type=cdir;unique=811U4340002;UNIX.group=33;UNIX.mode=0755;UNIX.owner=33; .\r\n");
|
||||
fputs($fs, "modify=20170127230002;perm=flcdmpe;type=pdir;unique=811U4340002;UNIX.group=33;UNIX.mode=0755;UNIX.owner=33; ..\r\n");
|
||||
fputs($fs, "modify=20170126121225;perm=adfrw;size=4729;type=file;unique=811U4340CB9;UNIX.group=33;UNIX.mode=0644;UNIX.owner=33; foobar\r\n");
|
||||
}
|
||||
|
||||
fputs($s, "226 Closing data Connection.\r\n");
|
||||
fclose($fs);
|
||||
}else {
|
||||
fputs($s, "500 Syntax error, command unrecognized.\r\n");
|
||||
dump_and_exit($buf);
|
||||
|
Loading…
Reference in New Issue
Block a user