Skip to content

Commit

Permalink
Add MLSD
Browse files Browse the repository at this point in the history
  • Loading branch information
icetee committed Jul 25, 2017
1 parent 3cb3674 commit 0e0a944
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 12 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Methods
* group - _string_ - An empty string or any combination of 'r', 'w', 'x'.

* other - _string_ - An empty string or any combination of 'r', 'w', 'x'.

* owner - _string_ - The user name or ID that this entry belongs to **(*NIX only)**.

* group - _string_ - The group name or ID that this entry belongs to **(*NIX only)**.
Expand Down Expand Up @@ -193,3 +193,5 @@ Methods
* **lastMod**(< _string_ >path, < _function_ >callback) - _(void)_ - Retrieves the last modified date and time for `path`. `callback` has 2 parameters: < _Error_ >err, < _Date_ >lastModified.

* **restart**(< _integer_ >byteOffset, < _function_ >callback) - _(void)_ - Sets the file byte offset for the next file transfer action (get/put) to `byteOffset`. `callback` has 1 parameter: < _Error_ >err.

* **mlsd**([< _string_ >path, ][< _boolean_ >useCompression, ]< _function_ >callback) - _(void)_ - Retrieves the directory listing of `path`. `path` defaults to the current working directory. `useCompression` defaults to false. `callback` has 2 parameters: < _Error_ >err, < _array_ >list. See the `list` command for a list of properties. Also see https://tools.ietf.org/html/rfc3659 7.2.
21 changes: 14 additions & 7 deletions lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,28 +416,27 @@ FTP.prototype.listSafe = function(path, zcomp, cb) {
this.list(path, zcomp, cb);
};

FTP.prototype.list = function(path, zcomp, cb) {
var self = this, cmd;
FTP.prototype.listCmd = function(path, zcomp, cmd, cb) {
var self = this;
var parse = cmd === 'MLSD' ? Parser.parseMlsdEntry : Parser.parseListEntry;

if (typeof path === 'function') {
// list(function() {})
cb = path;
path = undefined;
cmd = 'LIST';
zcomp = false;
} else if (typeof path === 'boolean') {
// list(true, function() {})
cb = zcomp;
zcomp = path;
path = undefined;
cmd = 'LIST';
} else if (typeof zcomp === 'function') {
// list('/foo', function() {})
cb = zcomp;
cmd = 'LIST ' + path;
cmd += ' ' + path;
zcomp = false;
} else
cmd = 'LIST ' + path;
cmd += ' ' + path;

this._pasv(function(err, sock) {
if (err)
Expand Down Expand Up @@ -487,7 +486,7 @@ FTP.prototype.list = function(path, zcomp, cb) {
entries.pop(); // ending EOL
var parsed = [];
for (var i = 0, len = entries.length; i < len; ++i) {
var parsedVal = Parser.parseListEntry(entries[i]);
var parsedVal = parse(entries[i]);
if (parsedVal !== null)
parsed.push(parsedVal);
}
Expand Down Expand Up @@ -540,6 +539,14 @@ FTP.prototype.list = function(path, zcomp, cb) {
});
};

FTP.prototype.list = function(path, zcomp, cb) {
return this.listCmd(path, zcomp, 'LIST', cb);
};

FTP.prototype.mlsd = function(path, zcomp, cb) {
return this.listCmd(path, zcomp, 'MLSD', cb);
};

FTP.prototype.get = function(path, zcomp, cb) {
var self = this;
if (typeof zcomp === 'function') {
Expand Down
36 changes: 32 additions & 4 deletions lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ var REX_LISTUNIX = XRegExp.cache('^(?<type>[\\-ld])(?<permission>([\\-r][\\-w][\
RE_ENTRY_TOTAL = /^total/,
RE_RES_END = /(?:^|\r?\n)(\d{3}) [^\r\n]*\r?\n/,
RE_EOL = /\r?\n/g,
RE_DASH = /\-/g;
RE_DASH = /\-/g,
RE_SEP = /;/g,
RE_EQ = /=/;

var MONTHS = {
jan: 1, feb: 2, mar: 3, apr: 4, may: 5, jun: 6,
Expand Down Expand Up @@ -129,13 +131,13 @@ Parser.parseListEntry = function(line) {
+ mins);
// If the date is in the past but no more than 6 months old, year
// isn't displayed and doesn't have to be the current year.
//
//
// If the date is in the future (less than an hour from now), year
// isn't displayed and doesn't have to be the current year.
// That second case is much more rare than the first and less annoying.
// It's impossible to fix without knowing about the server's timezone,
// so we just don't do anything about it.
//
//
// If we're here with a time that is more than 28 hours into the
// future (1 hour + maximum timezone offset which is 27 hours),
// there is a problem -- we should be in the second conditional block
Expand All @@ -153,7 +155,7 @@ Parser.parseListEntry = function(line) {
// ahead of local)
// For instance, remote is in 2014 while local is still in 2013. In
// this case, a date like 01/01/13 02:23 could be detected instead of
// 01/01/14 02:23
// 01/01/14 02:23
// Our trigger point will be 3600*24*31*6 (since we already use 31
// as an upper bound, no need to add the 27 hours timezone offset)
if (Date.now() - info.date.getTime() > 16070400000) {
Expand Down Expand Up @@ -213,4 +215,30 @@ Parser.parseListEntry = function(line) {
return ret;
};

Parser.parseMlsdEntry = function(entry) {
var kvs = entry.split(RE_SEP);
var obj = { name: kvs.pop().substring(1) };
kvs.forEach(function(kv) {
kv = kv.split( RE_EQ );
obj[kv[0].toLowerCase()] = kv[1];
});

obj.size = parseInt(obj.size, 10);

var modify = obj.modify;
if (modify) {
var year = modify.substr(0, 4);
var month = modify.substr(4, 2);
var date = modify.substr(6, 2);
var hour = modify.substr(8, 2);
var minute = modify.substr(10, 2);
var second = modify.substr(12, 2);
obj.date = new Date(
year + '-' + month + '-' + date + 'T' + hour + ':' +minute + ':' + second
);
}

return obj;
};

module.exports = Parser;

0 comments on commit 0e0a944

Please sign in to comment.