Comparing version 0.3.6 to 0.3.7
@@ -254,17 +254,17 @@ /* | ||
Fs.readFile(localPath, "binary", function(err, data) { | ||
var buffer = new Buffer(data, "binary"); | ||
ftp.put(remotePath, buffer, function(err, res) { | ||
Fs.readFile(localPath, "binary", function(err, data) { | ||
var buffer = new Buffer(data, "binary"); | ||
ftp.put(remotePath, buffer, function(err, res) { | ||
assert.ok(!err, err); | ||
ftp.get(remotePath, function(err, data) { | ||
assert.ok(!err, err); | ||
ftp.get(remotePath, function(err, data) { | ||
assert.ok(!err, err); | ||
assert.equal(buffer.length, data.length); | ||
ftp.raw.dele(remotePath, function(err, data) { | ||
assert.ok(!err); | ||
next(); | ||
}); | ||
assert.equal(buffer.length, data.length); | ||
ftp.raw.dele(remotePath, function(err, data) { | ||
assert.ok(!err); | ||
next(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}, | ||
@@ -277,17 +277,17 @@ | ||
ftp.put(filePath, new Buffer("test"), handler); | ||
ftp.get(filePath, function(err, data) { | ||
assert.ok(!err, err); | ||
assert.ok(data); | ||
}); | ||
ftp.put(filePath, new Buffer("test"), handler); | ||
ftp.get(filePath, function(err, data) { | ||
assert.ok(!err, err); | ||
assert.ok(data); | ||
}); | ||
ftp.put(filePath, new Buffer("test"), handler); | ||
ftp.get(filePath, function(err, data) { | ||
assert.ok(!err, err); | ||
assert.ok(data); | ||
ftp.put(filePath, new Buffer("test"), handler); | ||
ftp.get(filePath, function(err, data) { | ||
assert.ok(!err, err); | ||
assert.ok(data); | ||
assert.equal(counter, 2); | ||
next(); | ||
}); | ||
}); | ||
function handler() { counter++; }; | ||
function handler() { counter++;}; | ||
}, | ||
@@ -294,0 +294,0 @@ |
222
jsftp.js
@@ -11,3 +11,2 @@ /* | ||
var EventEmitter = require("events").EventEmitter; | ||
var ftpPasv = require("./lib/ftpPasv"); | ||
var Parser = require('./lib/ftpParser'); | ||
@@ -26,3 +25,3 @@ var S = require("streamer"); | ||
var DEBUG_MODE = false; | ||
var TIMEOUT = 60000; | ||
var TIMEOUT = 10 * 60 * 1000; | ||
var IDLE_TIME = 30000; | ||
@@ -34,3 +33,3 @@ var COMMANDS = [ | ||
"CWD", "DELE", "LIST", "MDTM", "MKD", "MODE", "NLST", "PASS", "RETR", "RMD", | ||
"RNFR", "RNTO", "SITE", "STAT", "STOR", "TYPE", "USER", "PASS", | ||
"RNFR", "RNTO", "SITE", "STAT", "STOR", "TYPE", "USER", "PASS", "XRMD", | ||
// Extended features | ||
@@ -87,2 +86,3 @@ "SYST", "CHMOD", "SIZE" | ||
this.useList = false; | ||
this.pasvCallBuffer = []; | ||
@@ -97,7 +97,2 @@ if (cfg) { | ||
var cmdfn = function(action, callback) { | ||
clearInterval(self._keepAliveinterval); | ||
if (action.indexOf("quit") !== 0) { | ||
self.keepAlive(); | ||
} | ||
// check whether the ftp user is authenticated at the moment of the | ||
@@ -172,3 +167,3 @@ // enqueing. ideally this should happen in the `push` method, just | ||
// once that one is received | ||
this.push = function(command, callback, onWriteCallback) { | ||
this.push = function(command, callback) { | ||
if (!command || typeof command !== "string") | ||
@@ -179,5 +174,2 @@ return; | ||
self.emitter.emit("command", this._sanitize(command)); | ||
if (onWriteCallback) | ||
onWriteCallback(this.socket); | ||
}; | ||
@@ -201,3 +193,3 @@ | ||
cmd(obj, self.nextCmd); | ||
self.push(obj[0], obj[1], obj[2] || null); | ||
self.push(obj[0], obj[1] || function(){}); | ||
}); | ||
@@ -209,9 +201,11 @@ })(); | ||
// becomes available. | ||
var tasks = S.zip(S.filter(function(x) { | ||
// We ignore FTP marks for now. They don't convey useful | ||
// information. A more elegant solution should be found in the | ||
// future. | ||
return !isMark(x.code); | ||
}, | ||
self.serverResponse(input)), | ||
var tasks = S.zip( | ||
S.filter(function(x) { | ||
// We ignore FTP marks for now. They don't convey useful | ||
// information. A more elegant solution should be found in the | ||
// future. | ||
return !isMark(x.code); | ||
}, | ||
self.serverResponse(input) | ||
), | ||
S.append(S.list(null), function(next, stop) { | ||
@@ -339,3 +333,2 @@ // Stream of FTP commands from the client. | ||
var callback = command[1]; | ||
var err; | ||
if (callback) { | ||
@@ -346,3 +339,3 @@ // In FTP every response code above 399 means error in some way. | ||
if (ftpResponse && ftpResponse.code > 399) { | ||
err = new Error(ftpResponse.text || "Unknown FTP error."); | ||
var err = new Error(ftpResponse.text || "Unknown FTP error."); | ||
err.code = ftpResponse.code; | ||
@@ -361,7 +354,3 @@ callback(err); | ||
this.raw.feat(function(err, response) { | ||
if (err) | ||
self.features = []; | ||
else | ||
self.features = self._parseFeats(response.text); | ||
self.features = err ? [] : self._parseFeats(response.text); | ||
callback(); | ||
@@ -420,7 +409,6 @@ }); | ||
if (this.dataConn) | ||
this.dataConn.socket.destroy(); | ||
this.features = null; | ||
this.authenticated = false; | ||
this.currentPasv = null; | ||
this.pasvCallBuffer = []; | ||
}; | ||
@@ -494,37 +482,55 @@ | ||
* | ||
* @param data {Object} Object with the following properties: | ||
* | ||
* mode {String}, optional: "I" or "A", referring to binary or text format, respectively. Default is binary., | ||
* cmd {String}: String of the command to execute, | ||
* onCmdWrite {function}, optional: Function to execute just after writing the command to the socket. | ||
* pasvCallback {function}, optional: Function to execute when the data socket closes (either by success or by error). | ||
* @param callback {function}: Function to execute when the data socket closes (either by success or by error). | ||
*/ | ||
this.setPassive = function(data) { | ||
this.getPassiveSocket = function(callback) { | ||
var self = this; | ||
var callback = data.pasvCallback; | ||
var doPasv = function(err, res) { | ||
if (err || res.code !== 227) | ||
return callback(res.text); | ||
// `_getPassive` retrieves a passive connection and sends its socket to | ||
// the callback. | ||
var _getPassive = function _getPassive(callback) { | ||
var doPasv = function(err, res) { | ||
if (err || res.code !== 227) | ||
return callback(res.text); | ||
var match = RE_PASV.exec(res.text); | ||
if (!match) | ||
return callback("PASV: Bad port"); | ||
var match = RE_PASV.exec(res.text); | ||
if (!match) | ||
return callback("PASV: Bad port"); | ||
var port = (parseInt(match[1], 10) & 255) * 256 + (parseInt(match[2], 10) & 255); | ||
self.dataConn = new ftpPasv({ | ||
host: self.host, | ||
port: port, | ||
mode: data.mode, | ||
callback: callback, | ||
ftp: self | ||
var port = (parseInt(match[1], 10) & 255) * 256 + (parseInt(match[2], 10) & 255); | ||
// Executes the next passive call, if there are any. | ||
var nextPasv = function nextPasv(err) { | ||
self.currentPasv = null; | ||
if (self.pasvCallBuffer && self.pasvCallBuffer.length) { | ||
self.currentPasv = self.pasvCallBuffer.shift(); | ||
self.currentPasv(); | ||
} | ||
}; | ||
var socket = Net.createConnection(port, self.host); | ||
// On each one of the events below we want to move on to the | ||
// next passive call, if any. | ||
socket.on("close", nextPasv); | ||
socket.on("end", nextPasv); | ||
socket.on("error", nextPasv); | ||
// Send the passive socket to the callback. | ||
callback(null, socket); | ||
}; | ||
self.raw.type("I", function(err, res) { | ||
enqueue(self.cmdQueue, ["pasv", doPasv]); | ||
}); | ||
}; | ||
} | ||
// Make sure to set the desired mode before starting any passive | ||
// operation. | ||
this.raw.type(data.mode || "I", function(err, res) { | ||
enqueue(self.cmdQueue, ["pasv", doPasv]); | ||
enqueue(self.cmdQueue, [data.cmd, null, data.onCmdWrite]); | ||
}); | ||
// If there is a passive call happening, we put the requested passive | ||
// call in the passive call buffer, to be executed later. | ||
if (this.currentPasv) { | ||
this.pasvCallBuffer.push(function() { _getPassive(callback); }); | ||
} | ||
// otherwise, execute right away because there is no passive calls | ||
// occuring right now. | ||
else { | ||
this.currentPasv = function() { _getPassive(callback); }; | ||
this.currentPasv(); | ||
} | ||
}; | ||
@@ -543,40 +549,58 @@ | ||
this.setPassive({ | ||
cmd: "list " + filePath, | ||
pasvCallback: callback | ||
var cmdQueue = this.cmdQueue; | ||
this.getPassiveSocket(function(err, socket) { | ||
concatStream(err, socket, callback); | ||
enqueue(cmdQueue, ["list " + filePath]); | ||
}); | ||
}; | ||
/** | ||
* Downloads a file from FTP server, given a valid Path. It uses the RETR | ||
* command to retrieve the file. | ||
*/ | ||
this.get = function(filePath, callback) { | ||
var cmdQueue = this.cmdQueue; | ||
this.getPassiveSocket(function(err, socket) { | ||
concatStream(err, socket, callback); | ||
enqueue(cmdQueue, ["retr " + filePath]); | ||
}); | ||
}; | ||
this.getGetSocket = function(path, callback) { | ||
var self = this; | ||
self.setPassive({ | ||
mode: "I", | ||
cmd: "retr " + filePath, | ||
pasvCallback: callback | ||
this.getPassiveSocket(function(err, socket) { | ||
if (err) | ||
callback(err); | ||
// Pause the socket to avoid data streaming before there are any | ||
// listeners to it. We'll let the API consumer resume it. | ||
if (socket.pause) | ||
socket.pause(); | ||
callback(err, socket); | ||
enqueue(self.cmdQueue, ["retr " + path]); | ||
}); | ||
}; | ||
this.put = function(filePath, buffer, callback) { | ||
var self = this; | ||
this.setPassive({ | ||
mode: "I", | ||
cmd: "stor " + filePath, | ||
onCmdWrite: function() { | ||
if (self.dataConn) { | ||
var socket = self.dataConn.socket; | ||
if (socket.writable) | ||
socket.end(buffer); | ||
this.put = function(filepath, buffer, callback) { | ||
var cmdQueue = this.cmdQueue; | ||
this.getPassiveSocket(function(err, socket) { | ||
enqueue(cmdQueue, ["stor " + filepath]); | ||
setTimeout(function() { | ||
if (socket && socket.writable) { | ||
socket.end(buffer); | ||
callback(); | ||
} | ||
else { | ||
console.log("FTP error: Couldn't retrieve PASV connection for command 'stor " + filePath + "'."); | ||
console.log("ftp error: couldn't retrieve pasv connection for command 'stor " + filepath + "'."); | ||
} | ||
}, | ||
pasvCallback: callback | ||
}, 100); | ||
}); | ||
}; | ||
this.getPutSocket = function(filepath, callback) { | ||
var self = this; | ||
this.getPassiveSocket(function(err, socket) { | ||
enqueue(self.cmdQueue, ["stor " + filepath]); | ||
setTimeout(function() { | ||
callback(err, socket); | ||
}, 100); | ||
}); | ||
}; | ||
/** | ||
@@ -668,3 +692,35 @@ * Provides information about files. It lists a directory contents or | ||
}; | ||
}).call(Ftp.prototype); | ||
}).call(Ftp.prototype); | ||
function concat(bufs) { | ||
var buffer, length = 0, index = 0; | ||
if (!Array.isArray(bufs)) | ||
bufs = Array.prototype.slice.call(arguments); | ||
for (var i=0, l=bufs.length; i<l; i++) { | ||
buffer = bufs[i]; | ||
length += buffer.length; | ||
} | ||
buffer = new Buffer(length); | ||
bufs.forEach(function(buf, i) { | ||
buf.copy(buffer, index, 0, buf.length); | ||
index += buf.length; | ||
}); | ||
return buffer; | ||
} | ||
function concatStream(err, socket, callback) { | ||
if (err) | ||
return; | ||
var pieces = []; | ||
socket.on("data", function(p) { pieces.push(p); }); | ||
socket.on("end", function() { | ||
callback(null, concat(pieces)); | ||
}); | ||
socket.on("error", function(e) { callback(e); }); | ||
} |
{ | ||
"name": "jsftp", | ||
"id": "jsftp", | ||
"version": "0.3.6", | ||
"version": "0.3.7", | ||
"description": "A sane FTP client implementation for NodeJS", | ||
@@ -6,0 +6,0 @@ "keywords": [ "ftp", "protocol", "files", "server", "client", "async" ], |
17
test.js
@@ -1,16 +0,1 @@ | ||
// Initialize some common variables | ||
var user = "fjakobs"; | ||
var pass = "lecatoc"; | ||
var Ftp = require('./jsftp.js'); | ||
var ftp = new Ftp({ | ||
host: "sergimansilla.com", | ||
port: 21, // The port defaults to 21, but let's include it anyway. | ||
}); | ||
// First, we authenticate the user | ||
ftp.auth(user, pass, function(err, res) { | ||
if (err) throw err; | ||
console.log("auth ok"); | ||
}); | ||
var arr = [1, 2, 3, 33, 4, 52, 7, 110]; |
Sorry, the diff of this file is not supported yet
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
Non-existent author
Supply chain riskThe package was published by an npm account that no longer exists.
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
481314
2
1657
1