Comparing version 1.1.0 to 1.1.1
126
lib/jsftp.js
@@ -131,12 +131,12 @@ /* vim:set ts=2 sw=2 sts=2 expandtab */ | ||
var nextCmd = this.cmdBuffer_[0][1]; | ||
var next = this.cmdBuffer_[0][1]; | ||
if (Utils.isMark(data.code)) { | ||
// If we receive a Mark and it is not expected, we ignore | ||
// that command | ||
if (!nextCmd.expectsMark || nextCmd.expectsMark.marks.indexOf(data.code) === -1) | ||
if (!next.expectsMark || next.expectsMark.marks.indexOf(data.code) === -1) | ||
return; | ||
// We might have to ignore the command that comes after the | ||
// mark. | ||
if (nextCmd.expectsMark.ignore) | ||
this.ignoreCmdCode = nextCmd.expectsMark.ignore; | ||
if (next.expectsMark.ignore) | ||
this.ignoreCmdCode = next.expectsMark.ignore; | ||
} | ||
@@ -167,4 +167,6 @@ | ||
Ftp.prototype.nextCmd = function() { | ||
if (this.cmdBuffer_[0]) | ||
if (!this.inProgress && this.cmdBuffer_[0]) { | ||
this.send(this.cmdBuffer_[0][0]); | ||
this.inProgress = true; | ||
} | ||
}; | ||
@@ -191,4 +193,3 @@ | ||
this._executeCommand(action, callback); | ||
} | ||
else { | ||
} else { | ||
var self = this; | ||
@@ -212,4 +213,3 @@ this.authenticated = false; | ||
executeCmd(); | ||
} | ||
else { | ||
} else { | ||
this.getFeatures(function() { | ||
@@ -242,2 +242,4 @@ self.auth(self.user, self.pass, executeCmd); | ||
command[1](err, response); | ||
this.inProgress = false; | ||
this.nextCmd(); | ||
}; | ||
@@ -325,10 +327,10 @@ | ||
self.pass = pass; | ||
self.raw.type("I", function() { notifyAll(null, res); }); | ||
} | ||
else if (res.code === 332) { | ||
self.raw.type("I", function() { | ||
notifyAll(null, res); | ||
}); | ||
} else if (res.code === 332) { | ||
self.raw.acct(""); // ACCT not really supported | ||
} | ||
}); | ||
} | ||
else { | ||
} else { | ||
self.authenticating = false; | ||
@@ -370,3 +372,6 @@ notifyAll(new Error("Login not accepted")); | ||
}; | ||
cb.expectsMark = { marks: [125, 150], ignore: 226 }; | ||
cb.expectsMark = { | ||
marks: [125, 150], | ||
ignore: 226 | ||
}; | ||
@@ -376,4 +381,8 @@ var listing = ""; | ||
self.getPasvSocket(function(err, socket) { | ||
socket.on("data", function(data) { listing += data; }); | ||
socket.on("close", function(err) { cb(err || null, listing); }); | ||
socket.on("data", function(data) { | ||
listing += data; | ||
}); | ||
socket.on("close", function(err) { | ||
cb(err || null, listing); | ||
}); | ||
socket.on("error", cb); | ||
@@ -411,7 +420,8 @@ | ||
this.getGetSocket(remotePath, callback); | ||
} | ||
else { | ||
} else { | ||
callback = once(callback || function() {}); | ||
this.getGetSocket(remotePath, function(err, socket) { | ||
if (err) { callback(err); } | ||
if (err) { | ||
callback(err); | ||
} | ||
@@ -460,3 +470,6 @@ var writeStream = fs.createWriteStream(localPath); | ||
cmdCallback.expectsMark = { marks: [125, 150], ignore: 226 }; | ||
cmdCallback.expectsMark = { | ||
marks: [125, 150], | ||
ignore: 226 | ||
}; | ||
self.execute("retr " + path, cmdCallback); | ||
@@ -479,4 +492,3 @@ }); | ||
}, callback); | ||
} | ||
else { | ||
} else { | ||
var self = this; | ||
@@ -488,17 +500,19 @@ fs.exists(from, function(exists) { | ||
self.getPutSocket(to, function(err, socket) { | ||
if (err) return; | ||
if (err) return; | ||
fs.stat(from, function(err, stats) { | ||
var totalSize = err ? 0 : stats.size; | ||
var read = fs.createReadStream(from, { bufferSize: 4 * 1024 }); | ||
read.pipe(socket); | ||
read.on('readable', function() { | ||
self.emitProgress({ | ||
filename: to, | ||
action: 'put', | ||
socket: read, | ||
totalSize: totalSize | ||
}); | ||
fs.stat(from, function(err, stats) { | ||
var totalSize = err ? 0 : stats.size; | ||
var read = fs.createReadStream(from, { | ||
bufferSize: 4 * 1024 | ||
}); | ||
read.pipe(socket); | ||
read.on('readable', function() { | ||
self.emitProgress({ | ||
filename: to, | ||
action: 'put', | ||
socket: read, | ||
totalSize: totalSize | ||
}); | ||
}); | ||
}); | ||
}, callback); | ||
@@ -534,8 +548,10 @@ }); | ||
_callback(null, socket); | ||
} | ||
else { | ||
} else { | ||
return _callback(new Error("Unexpected command " + res.text)); | ||
} | ||
}); | ||
putCallback.expectsMark = { marks: [125, 150], ignore: 226 }; | ||
putCallback.expectsMark = { | ||
marks: [125, 150], | ||
ignore: 226 | ||
}; | ||
self.execute("stor " + path, putCallback); | ||
@@ -573,12 +589,12 @@ }); | ||
* { | ||
* name: 'README.txt', | ||
* type: 0, | ||
* time: 996052680000, | ||
* size: '2582', | ||
* owner: 'sergi', | ||
* group: 'staff', | ||
* userPermissions: { read: true, write: true, exec: false }, | ||
* groupPermissions: { read: true, write: false, exec: false }, | ||
* otherPermissions: { read: true, write: false, exec: false } | ||
* } | ||
* name: 'README.txt', | ||
* type: 0, | ||
* time: 996052680000, | ||
* size: '2582', | ||
* owner: 'sergi', | ||
* group: 'staff', | ||
* userPermissions: { read: true, write: true, exec: false }, | ||
* groupPermissions: { read: true, write: false, exec: false }, | ||
* otherPermissions: { read: true, write: false, exec: false } | ||
* } | ||
* | ||
@@ -593,3 +609,5 @@ * The constants used in the object are defined in ftpParser.js | ||
function entriesToList(err, entries) { | ||
if (err) { return callback(err); } | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, Utils.parseEntry(entries.text || entries)); | ||
@@ -600,4 +618,3 @@ } | ||
this.list(filePath, entriesToList); | ||
} | ||
else { | ||
} else { | ||
var self = this; | ||
@@ -617,4 +634,3 @@ this.raw.stat(filePath, function(err, data) { | ||
self.list(filePath, entriesToList); | ||
} | ||
else { | ||
} else { | ||
entriesToList(err, data); | ||
@@ -630,3 +646,5 @@ } | ||
if (err) return callback(err); | ||
self.raw.rnto(to, function(err, res) { callback(err, res); }); | ||
self.raw.rnto(to, function(err, res) { | ||
callback(err, res); | ||
}); | ||
}); | ||
@@ -633,0 +651,0 @@ }; |
{ | ||
"name": "jsftp", | ||
"id": "jsftp", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "A sane FTP client implementation for NodeJS", | ||
@@ -6,0 +6,0 @@ "keywords": [ "ftp", "protocol", "files", "server", "client", "async" ], |
jsftp <a href="http://flattr.com/thing/1452098/" target="_blank"><img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a> | ||
===== | ||
jsftp is a client FTP library for NodeJS that focuses on correctness, clarity | ||
A client FTP library for NodeJS that focuses on correctness, clarity | ||
and conciseness. It doesn't get in the way and plays nice with streaming APIs. | ||
**BIG Warning: The latest version (1.0.0) of jsftp breaks API compatibility with previous | ||
[![NPM](https://nodei.co/npm/jsftp.png)](https://nodei.co/npm/jsftp/) | ||
**Warning: The latest version (1.0.0) of jsftp breaks API compatibility with previous | ||
versions, it is NOT a drop-in replacement. Please be careful when upgrading. The | ||
@@ -17,8 +19,7 @@ API changes are not drastic at all and it is all documented below. If you do not | ||
```javascript | ||
var Ftp = require("jsftp"); | ||
var JSFtp = require("jsftp"); | ||
// The constructor accepts the parameters `host`, `port`, `user` and `pass`. | ||
// `port` defaults to `21`. | ||
var myFtp = new Ftp({ | ||
var Ftp = new JSFtp({ | ||
host: "myserver.com", | ||
port: 3331, // defaults to 21 | ||
user: "user", // defaults to "anonymous" | ||
@@ -32,3 +33,3 @@ pass: "1234" // defaults to "@anonymous" | ||
actions that require complex chains of commands (e.g. uploading and retrieving | ||
files, passive operations). | ||
files, passive operations), as shown below. | ||
@@ -40,3 +41,3 @@ When raw commands succeed they always pass the response of the server to the | ||
Raw (or native) commands are accessible in the form `Ftp.raw["desired_command"](params, callback)` | ||
Raw (or native) commands are accessible in the form `Ftp.raw["command"](params, callback)` | ||
@@ -59,14 +60,24 @@ Thus, a command like `QUIT` will be called like this: | ||
console.log(data.text); // Presenting the FTP response text to the user | ||
console.log(data.code); // Presenting the FTP response code to the user | ||
console.log(data.text); // Show the FTP response text to the user | ||
console.log(data.code); // Show the FTP response code to the user | ||
}); | ||
``` | ||
API and examples | ||
---------------- | ||
#### new Ftp(options) | ||
- `options` is an object with the following properties: | ||
```javascript | ||
{ | ||
host: 'localhost', // Host name for the current FTP server. | ||
port: 3333, // Port number for the current FTP server (defaults to 21). | ||
user: 'user', // Username | ||
pass: 'pass', // Password | ||
} | ||
``` | ||
API and examples | ||
---------------- | ||
Creates a new Ftp instance. | ||
### Properties | ||
@@ -147,3 +158,3 @@ #### Ftp.host | ||
```javascript | ||
var str = ""; // We will store the contents of the file in this string | ||
var str = ""; // Will store the contents of the file | ||
ftp.get('remote/path/file.txt', function(err, socket) { | ||
@@ -213,5 +224,5 @@ if (err) return; | ||
Current overall coverage rate: | ||
lines......: 92.1% (316 of 343 lines) | ||
functions..: 91.0% (71 of 78 functions) | ||
Current overall coverage rate: | ||
lines......: 92.1% (316 of 343 lines) | ||
functions..: 91.0% (71 of 78 functions) | ||
@@ -222,3 +233,3 @@ | ||
To run the tests: | ||
To run tests: | ||
@@ -225,0 +236,0 @@ npm install --dev |
@@ -23,3 +23,4 @@ /* | ||
var concat = function(bufs) { | ||
var buffer, length = 0, index = 0; | ||
var buffer, length = 0, | ||
index = 0; | ||
@@ -48,3 +49,5 @@ if (!Array.isArray(bufs)) | ||
var pieces = []; | ||
socket.on("data", function(p) { pieces.push(p); }); | ||
socket.on("data", function(p) { | ||
pieces.push(p); | ||
}); | ||
socket.on("close", function(hadError) { | ||
@@ -142,3 +145,5 @@ if (hadError) | ||
var cb = sinon.spy(); | ||
cb.expectsMark = { marks: [150] }; | ||
cb.expectsMark = { | ||
marks: [150] | ||
}; | ||
var data = { | ||
@@ -178,3 +183,5 @@ code: 150, | ||
it("test send function", function(next) { | ||
ftp.pipeline = { write: sinon.spy() }; | ||
ftp.pipeline = { | ||
write: sinon.spy() | ||
}; | ||
ftp.send(); | ||
@@ -189,3 +196,6 @@ ftp.send("list /"); | ||
var cb = sinon.spy(); | ||
cb.expectsMark = { marks: [150], ignore: 226 }; | ||
cb.expectsMark = { | ||
marks: [150], | ||
ignore: 226 | ||
}; | ||
var data1 = { | ||
@@ -273,3 +283,3 @@ code: 150, | ||
var code = parseInt(res.code, 10); | ||
assert.ok(!!err); | ||
assert.ok( !! err); | ||
assert.equal(code, 550, "A (wrong) CWD command was successful. It should have failed"); | ||
@@ -425,3 +435,5 @@ next(); | ||
assert.ok(arguments.length === 2); | ||
socket.on("data", function(d) { str += d; }) | ||
socket.on("data", function(d) { | ||
str += d; | ||
}) | ||
socket.on("close", function(hadErr) { | ||
@@ -515,6 +527,6 @@ assert.equal(realContents, str); | ||
ftp.getPutSocket(remotePath, function(err, socket, res) { | ||
assert.ok(!!err, err); | ||
assert.ok( !! err, err); | ||
assert.equal(err.code, 550, err); | ||
}, function(err, res) { | ||
assert.ok(!!err); | ||
assert.ok( !! err); | ||
next(); | ||
@@ -559,119 +571,137 @@ }); | ||
it("test attach event handlers: connect", function(_next) { | ||
var clientOnConnect = function() { | ||
client.auth(FTPCredentials.user, FTPCredentials.pass, next); | ||
}; | ||
it("test attach event handlers: connect", function(_next) { | ||
var clientOnConnect = function() { | ||
client.auth(FTPCredentials.user, FTPCredentials.pass, next); | ||
}; | ||
var next = function(err) { | ||
assert.ok(!err); | ||
client.destroy(); | ||
_next(); | ||
}; | ||
var next = function(err) { | ||
assert.ok(!err); | ||
client.destroy(); | ||
_next(); | ||
}; | ||
var client = new Ftp({ | ||
host: "localhost", | ||
user: "user", | ||
port: 3334, | ||
pass: "12345" | ||
}); | ||
client.on("connect", clientOnConnect); | ||
var client = new Ftp({ | ||
host: "localhost", | ||
user: "user", | ||
port: 3334, | ||
pass: "12345" | ||
}); | ||
client.on("connect", clientOnConnect); | ||
}); | ||
it("test PASV streaming: Copy file using piping", function(next) { | ||
var filePath = getRemotePath("testfile.txt"); | ||
var originalData = Fs.readFileSync(getLocalPath("testfile.txt")); | ||
ftp.getGetSocket(filePath, function(err, readable) { | ||
assert(!err, err); | ||
assert.ok(readable); | ||
it("test PASV streaming: Copy file using piping", function(next) { | ||
var filePath = getRemotePath("testfile.txt"); | ||
var originalData = Fs.readFileSync(getLocalPath("testfile.txt")); | ||
ftp.getGetSocket(filePath, function(err, readable) { | ||
assert(!err, err); | ||
assert.ok(readable); | ||
readable.on("error", error); | ||
readable.on("error", error); | ||
function error(err) { | ||
assert.ok(!err, err); | ||
if (readable.destroy) readable.destroy(); | ||
next(); | ||
} | ||
function error(err) { | ||
assert.ok(!err, err); | ||
if (readable.destroy) readable.destroy(); | ||
next(); | ||
} | ||
var remoteCopy = filePath + ".bak"; | ||
ftp.getPutSocket(remoteCopy, function(err, socket) { | ||
assert.ok(!err, err); | ||
readable.pipe(socket); | ||
readable.resume(); | ||
}, | ||
var remoteCopy = filePath + ".bak"; | ||
ftp.getPutSocket(remoteCopy, function(err, socket) { | ||
assert.ok(!err, err); | ||
readable.pipe(socket); | ||
readable.resume(); | ||
}, | ||
function(hadError) { | ||
assert.ok(!hadError); | ||
function(hadError) { | ||
assert.ok(!hadError); | ||
var str = ""; | ||
ftp.getGetSocket(remoteCopy, function(err, socket) { | ||
assert.ok(!err, err); | ||
socket.on("data", function(d) { str += d; }); | ||
socket.on("close", function(hadErr) { | ||
assert.equal(originalData.toString("utf8"), str); | ||
next(); | ||
}); | ||
socket.resume(); | ||
}); | ||
var str = ""; | ||
ftp.getGetSocket(remoteCopy, function(err, socket) { | ||
assert.ok(!err, err); | ||
socket.on("data", function(d) { | ||
str += d; | ||
}); | ||
socket.on("close", function(hadErr) { | ||
assert.equal(originalData.toString("utf8"), str); | ||
next(); | ||
}); | ||
socket.resume(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it("Test that streaming GET (RETR) retrieves a file properly", function(next) { | ||
var path = getLocalPath("testfile.txt"); | ||
var originalData = Fs.readFileSync(path); | ||
ftp.getGetSocket(getRemotePath("testfile.txt"), function(err, readable) { | ||
it("Test that streaming GET (RETR) retrieves a file properly", function(next) { | ||
var path = getLocalPath("testfile.txt"); | ||
var originalData = Fs.readFileSync(path); | ||
ftp.getGetSocket(getRemotePath("testfile.txt"), function(err, readable) { | ||
assert.ok(!err); | ||
concatStream(err, readable, function(err, buffer) { | ||
assert.ok(!err); | ||
concatStream(err, readable, function(err, buffer) { | ||
assert.ok(!err); | ||
assert.equal(buffer.toString(), originalData.toString()); | ||
next(); | ||
}); | ||
assert.equal(buffer.toString(), originalData.toString()); | ||
next(); | ||
}); | ||
}); | ||
}); | ||
it("Test that streaming GET (RETR) fails when a file is not present", function(next) { | ||
ftp.getGetSocket("unexisting/file/path", function(err, readable) { | ||
assert.ok(err); | ||
assert.equal(550, err.code); | ||
next(); | ||
}); | ||
it("Test that streaming GET (RETR) fails when a file is not present", function(next) { | ||
ftp.getGetSocket("unexisting/file/path", function(err, readable) { | ||
assert.ok(err); | ||
assert.equal(550, err.code); | ||
next(); | ||
}); | ||
}); | ||
it("Test that streaming PUT (STOR) stores a file properly", function(next) { | ||
var path = getLocalPath("testfile.txt"); | ||
var originalData = Fs.createReadStream(getLocalPath("testfile.txt")); | ||
originalData.pause(); | ||
it("Test that streaming PUT (STOR) stores a file properly", function(next) { | ||
var path = getLocalPath("testfile.txt"); | ||
var originalData = Fs.createReadStream(getLocalPath("testfile.txt")); | ||
originalData.pause(); | ||
ftp.getPutSocket(getRemotePath("testfile.txt.bak"), function(err, socket) { | ||
ftp.getPutSocket(getRemotePath("testfile.txt.bak"), function(err, socket) { | ||
assert.ok(!err); | ||
originalData.pipe(socket); | ||
originalData.resume(); | ||
concatStream(err, originalData, function(err, buffer) { | ||
assert.ok(!err); | ||
originalData.pipe(socket); | ||
originalData.resume(); | ||
concatStream(err, originalData, function(err, buffer) { | ||
assert.ok(!err); | ||
Fs.readFile(path, "utf8", function(err, original) { | ||
assert.equal(buffer.toString("utf8"), original); | ||
next(); | ||
}); | ||
Fs.readFile(path, "utf8", function(err, original) { | ||
assert.equal(buffer.toString("utf8"), original); | ||
next(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it("Test that streaming PUT (STOR) fails when a file is not present", function(next) { | ||
ftp.getPutSocket("unexisting/file/path", function(err, socket) { | ||
assert.ok(err); | ||
next(); | ||
}); | ||
it("Test that streaming PUT (STOR) fails when a file is not present", function(next) { | ||
ftp.getPutSocket("unexisting/file/path", function(err, socket) { | ||
assert.ok(err); | ||
next(); | ||
}); | ||
}); | ||
it("Test that onConnect is called", function(next) { | ||
var FTPCredentials = { | ||
host: "localhost", | ||
user: "user", | ||
port: 3334, | ||
pass: "12345" | ||
}; | ||
it("Test that onConnect is called", function(next) { | ||
var ftp2 = new Ftp(FTPCredentials); | ||
ftp2.on("connect", function() { | ||
next(); | ||
}); | ||
}); | ||
var ftp2 = new Ftp(FTPCredentials); | ||
ftp2.on("connect", function() { next(); }); | ||
it("Test for correct data on ls 1", function(next) { | ||
var paths = ['test/test_c9/testfile.txt', 'work/test/main.css']; | ||
ftp.auth(FTPCredentials.user, FTPCredentials.pass, function(err, data) { | ||
if (err) return console.log(err); | ||
var processed = 0; | ||
ftp.ls(paths[0], function showFile(err, res) { | ||
assert.ok(!err); | ||
assert.strictEqual(res[0].name, 'testfile.txt'); | ||
processed += 1; | ||
if (processed === 2) next(); | ||
}); | ||
ftp.ls(paths[1], function showFile(err, res1) { | ||
assert.ok(!!err); | ||
processed += 1; | ||
if (processed === 2) next(); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
204748
1741
236