}
/* }}} */
+/* {{{ 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
*/
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
*/
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()
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)
}
/* }}} */
+/* {{{ 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)
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);
var_dump(ftp_site($ftp));
var_dump(ftp_set_option($ftp));
var_dump(ftp_get_option($ftp));
+var_dump(ftp_mlsd($ftp));
?>
--EXPECTF--
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
--- /dev/null
+--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)
--- /dev/null
+--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)
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);