mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
ftp_mlsd(): Parse the MLSD response
This commit is contained in:
parent
efefb5276b
commit
5b1300b6c9
6 changed files with 159 additions and 11 deletions
|
@ -707,6 +707,50 @@ ftp_mlsd(ftpbuf_t *ftp, const char *path, const size_t path_len)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ftp_mlsd_parse_line
|
||||
*/
|
||||
int
|
||||
ftp_mlsd_parse_line(HashTable *ht, const char *input) {
|
||||
|
||||
zval zstr;
|
||||
const char *end = input + strlen(input);
|
||||
|
||||
const char *sp = memchr(input, ' ', end - input);
|
||||
if (!sp) {
|
||||
php_error_docref(NULL, E_WARNING, "Missing pathname in MLSD response");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Extract pathname */
|
||||
ZVAL_STRINGL(&zstr, sp + 1, end - sp - 1);
|
||||
zend_hash_str_update(ht, "name", sizeof("name")-1, &zstr);
|
||||
end = sp;
|
||||
|
||||
while (input < end) {
|
||||
const char *semi, *eq;
|
||||
|
||||
/* Find end of fact */
|
||||
semi = memchr(input, ';', end - input);
|
||||
if (!semi) {
|
||||
php_error_docref(NULL, E_WARNING, "Malformed fact in MLSD response");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Separate fact key and value */
|
||||
eq = memchr(input, '=', semi - input);
|
||||
if (!eq) {
|
||||
php_error_docref(NULL, E_WARNING, "Malformed fact in MLSD response");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
ZVAL_STRINGL(&zstr, eq + 1, semi - eq - 1);
|
||||
zend_hash_str_update(ht, input, eq - input, &zstr);
|
||||
input = semi + 1;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ftp_type
|
||||
*/
|
||||
|
|
|
@ -163,6 +163,11 @@ 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);
|
||||
|
||||
/* populates a hashtable with the facts contained in one line of
|
||||
* an MLSD response.
|
||||
*/
|
||||
int ftp_mlsd_parse_line(HashTable *ht, const char *input);
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -755,13 +755,14 @@ 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 */
|
||||
Returns a detailed listing of a directory as an array of parsed output lines */
|
||||
PHP_FUNCTION(ftp_mlsd)
|
||||
{
|
||||
zval *z_ftp;
|
||||
ftpbuf_t *ftp;
|
||||
char **llist, **ptr, *dir;
|
||||
size_t dir_len;
|
||||
zval entry;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
|
||||
return;
|
||||
|
@ -778,8 +779,14 @@ PHP_FUNCTION(ftp_mlsd)
|
|||
|
||||
array_init(return_value);
|
||||
for (ptr = llist; *ptr; ptr++) {
|
||||
add_next_index_string(return_value, *ptr);
|
||||
array_init(&entry);
|
||||
if (ftp_mlsd_parse_line(Z_ARRVAL_P(&entry), *ptr) == SUCCESS) {
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &entry);
|
||||
} else {
|
||||
zval_ptr_dtor(&entry);
|
||||
}
|
||||
}
|
||||
|
||||
efree(llist);
|
||||
}
|
||||
/* }}} */
|
||||
|
|
97
ext/ftp/tests/ftp_mlsd.phpt
Normal file
97
ext/ftp/tests/ftp_mlsd.phpt
Normal file
|
@ -0,0 +1,97 @@
|
|||
--TEST--
|
||||
ftp_mlsd() return parsed lines
|
||||
--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, '.'));
|
||||
|
||||
ftp_close($ftp);
|
||||
?>
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
|
||||
Warning: ftp_mlsd(): Missing pathname in MLSD response in %s on line %d
|
||||
|
||||
Warning: ftp_mlsd(): Malformed fact in MLSD response in %s on line %d
|
||||
|
||||
Warning: ftp_mlsd(): Malformed fact in MLSD response in %s on line %d
|
||||
array(4) {
|
||||
[0]=>
|
||||
array(8) {
|
||||
["name"]=>
|
||||
string(1) "."
|
||||
["modify"]=>
|
||||
string(14) "20170127230002"
|
||||
["perm"]=>
|
||||
string(7) "flcdmpe"
|
||||
["type"]=>
|
||||
string(4) "cdir"
|
||||
["unique"]=>
|
||||
string(11) "811U4340002"
|
||||
["UNIX.group"]=>
|
||||
string(2) "33"
|
||||
["UNIX.mode"]=>
|
||||
string(4) "0755"
|
||||
["UNIX.owner"]=>
|
||||
string(2) "33"
|
||||
}
|
||||
[1]=>
|
||||
array(8) {
|
||||
["name"]=>
|
||||
string(2) ".."
|
||||
["modify"]=>
|
||||
string(14) "20170127230002"
|
||||
["perm"]=>
|
||||
string(7) "flcdmpe"
|
||||
["type"]=>
|
||||
string(4) "pdir"
|
||||
["unique"]=>
|
||||
string(11) "811U4340002"
|
||||
["UNIX.group"]=>
|
||||
string(2) "33"
|
||||
["UNIX.mode"]=>
|
||||
string(4) "0755"
|
||||
["UNIX.owner"]=>
|
||||
string(2) "33"
|
||||
}
|
||||
[2]=>
|
||||
array(9) {
|
||||
["name"]=>
|
||||
string(6) "foobar"
|
||||
["modify"]=>
|
||||
string(14) "20170126121225"
|
||||
["perm"]=>
|
||||
string(5) "adfrw"
|
||||
["size"]=>
|
||||
string(4) "4729"
|
||||
["type"]=>
|
||||
string(4) "file"
|
||||
["unique"]=>
|
||||
string(11) "811U4340CB9"
|
||||
["UNIX.group"]=>
|
||||
string(2) "33"
|
||||
["UNIX.mode"]=>
|
||||
string(4) "0644"
|
||||
["UNIX.owner"]=>
|
||||
string(2) "33"
|
||||
}
|
||||
[3]=>
|
||||
array(3) {
|
||||
["name"]=>
|
||||
string(9) "path;name"
|
||||
["fact"]=>
|
||||
string(6) "val=ue"
|
||||
["empty"]=>
|
||||
string(0) ""
|
||||
}
|
||||
}
|
|
@ -13,7 +13,6 @@ 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'));
|
||||
|
||||
|
@ -21,14 +20,6 @@ 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)
|
||||
|
|
|
@ -489,6 +489,10 @@ if ($pid) {
|
|||
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($fs, "fact=val=ue;empty=; path;name\r\n");
|
||||
fputs($fs, "no_space\r\n");
|
||||
fputs($fs, "no_semi pathname\r\n");
|
||||
fputs($fs, "no_eq; pathname\r\n");
|
||||
}
|
||||
|
||||
fputs($s, "226 Closing data Connection.\r\n");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue