Skip to content

Commit a8fd90c

Browse files
committed
LIST command misbehaves when file or directory doesn't exist. Fixes #95.
1 parent f8d9e31 commit a8fd90c

File tree

3 files changed

+34
-23
lines changed

3 files changed

+34
-23
lines changed

lib/jsftp.js

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ Ftp.prototype.reemit = function(event) {
107107
if (self.debugMode) {
108108
self.emit('jsftp_debug', 'event:' + event, data || {});
109109
}
110-
}
110+
};
111111
};
112112

113113
Ftp.prototype._createSocket = function(port, host, firstAction) {
@@ -143,12 +143,10 @@ Ftp.prototype.parseResponse = function(data) {
143143

144144
var next = this.cmdBuffer_[0][1];
145145
if (data.isMark) {
146-
// If we receive a Mark and it is not expected, we ignore
147-
// that command
146+
// If we receive a Mark and it is not expected, we ignore that command
148147
if (!next.expectsMark || next.expectsMark.marks.indexOf(data.code) === -1)
149148
return;
150-
// We might have to ignore the command that comes after the
151-
// mark.
149+
// We might have to ignore the command that comes after the mark.
152150
if (next.expectsMark.ignore)
153151
this.ignoreCmdCode = next.expectsMark.ignore;
154152
}
@@ -353,7 +351,7 @@ Ftp.prototype.setType = function(type, callback) {
353351
/**
354352
* Lists a folder's contents using a passive connection.
355353
*
356-
* @param {String} [path] Remote path for the file/folder to retrieve
354+
* @param {String} path Remote path for the file/folder to retrieve
357355
* @param {Function} callback Function to call with errors or results
358356
*/
359357
Ftp.prototype.list = function(path, callback) {
@@ -363,30 +361,35 @@ Ftp.prototype.list = function(path, callback) {
363361
}
364362

365363
var self = this;
366-
var cb = function(err, listing) {
364+
var cb = once(function(err, listing) {
367365
self.setType("I", once(function() {
368366
callback(err, listing);
369367
}));
370-
};
371-
cb.expectsMark = {
372-
marks: [125, 150],
373-
ignore: 226
374-
};
368+
});
375369

376370
var listing = "";
377371
this.setType("A", function() {
378372
self.getPasvSocket(function(err, socket) {
379-
self.pasvTimeout.bind(self, socket, cb);
373+
self.pasvTimeout.call(self, socket, cb);
380374

381-
socket.on("data", function(data) {
382-
listing += data;
383-
});
384-
socket.on("close", function(err) {
385-
cb(err || null, listing);
386-
});
375+
socket.on("data", function(data) { listing += data; });
376+
socket.on("close", function(err) { cb(err, listing); });
387377
socket.on("error", cb);
388378

389-
self.send("list " + (path || ""));
379+
function cmdCallback(err, res) {
380+
if (err) return cb(err);
381+
382+
if (res.code !== 125 && res.code !== 150) {
383+
cb(new Error("Unexpected command " + res.text));
384+
}
385+
}
386+
387+
cmdCallback.expectsMark = {
388+
marks: [125, 150],
389+
ignore: 226
390+
};
391+
392+
self.execute("list " + (path || ""), cmdCallback);
390393
});
391394
});
392395
};
@@ -454,7 +457,7 @@ Ftp.prototype.getGetSocket = function(path, callback) {
454457
this.getPasvSocket(function(err, socket) {
455458
if (err) return cmdCallback(err);
456459

457-
self.pasvTimeout.bind(self, socket, cmdCallback);
460+
self.pasvTimeout.call(self, socket, cmdCallback);
458461
socket.pause();
459462

460463
function cmdCallback(err, res) {
@@ -547,7 +550,7 @@ Ftp.prototype.getPutSocket = function(path, callback, doneCallback) {
547550
if (res.code === 125 || res.code === 150) {
548551
socket.on('close', doneCallback);
549552
socket.on('error', doneCallback);
550-
self.pasvTimeout.bind(self, socket, doneCallback);
553+
self.pasvTimeout.call(self, socket, doneCallback);
551554
_callback(null, socket);
552555
} else {
553556
return _callback(new Error("Unexpected command " + res.text));

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "jsftp",
33
"id": "jsftp",
4-
"version": "1.3.3",
4+
"version": "1.3.4",
55
"description": "A sane FTP client implementation for NodeJS",
66
"keywords": [ "ftp", "protocol", "files", "server", "client", "async" ],
77
"author": "Sergi Mansilla <sergi.mansilla@gmail.com> (http://sergimansilla.com)",

test/jsftp_test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,14 @@ describe("jsftp test suite", function() {
304304
});
305305
});
306306

307+
it("test passive listing of nonexisting directory", function(next) {
308+
ftp.list('does-not-exist/', function(err, res) {
309+
assert.equal(typeof err, 'object');
310+
assert.ok(err.code === 450 || err.code === 550);
311+
next();
312+
});
313+
});
314+
307315
it("test ftp node stat", function(next) {
308316
ftp.raw.pwd(function(err, res) {
309317
var parent = new RegExp('.*"(.*)".*').exec(res.text)[1];

0 commit comments

Comments
 (0)