Skip to content

Commit

Permalink
Add debug mode and some style changes. Fixes #87.
Browse files Browse the repository at this point in the history
  • Loading branch information
sergi committed May 5, 2014
1 parent a78fb8f commit 0a0d263
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 22 deletions.
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,54 @@ Refreshes the interval thats keep the server connection active. `wait` is an opt
You can find more usage examples in the [unit tests](https://github.com/sergi/jsftp/blob/master/test/jsftp_test.js). This documentation
will grow as jsftp evolves.


Debugging
---------

In order to enable debug mode in a FTP connection, a `debugMode` parameter can
be used in the constructors's config object:

```javascript
var Ftp = new JSFtp({
host: "myserver.com",
port: 3331,
user: "user",
pass: "1234",
debugMode: true
});
```

It can also be activated or deactivated by calling the `setDebugMode` method:

```javascript
Ftp.setDebugMode(true); // Debug Mode on
Ftp.setDebugMode(false; // Debug mode off
```
If the debug mode is on, the jsftp instance will emit `jsftp_debug` events with
two parameters: the first is the type of the event and the second and object
including data related to the event. There are 3 possible types of events:
- `response` events: These are response from the FTP server to the user's FTP
commands
- `user_command` events: These are commands that the user issuendss to the
FTP server.
- `event:{event name}` events: These are other events mostly related to the server
connection, such as `timeout`, `connect` or `disconnect`. For example,
a timeout event will have the name `event:timeout`.
In order to react to print all debug events (for example), we would listen to the
debug messages like this:
```javascript
Ftp.on('jsftp_debug', function(eventType, data) {
console.log('DEBUG: ', eventType);
console.log(JSON.stringify(data, null, 2));
});
```
Installation
------------
Expand Down
64 changes: 42 additions & 22 deletions lib/jsftp.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ var fs = require("fs");
var once = require("once");

var FTP_PORT = 21;
var DEBUG_MODE = false;
var TIMEOUT = 10 * 60 * 1000;
var IDLE_TIME = 30000;
var NOOP = function() {};
Expand All @@ -31,14 +30,17 @@ var COMMANDS = [
"chmod", "size"
];

function getPasvPort(text) {
function getPasvPort(text, cb) {
var RE_PASV = /([-\d]+,[-\d]+,[-\d]+,[-\d]+),([-\d]+),([-\d]+)/;
var match = RE_PASV.exec(text);
if (!match) return false;
if (!match) {
return cb(new Error("Bad passive host/port combination"));
}

// Array containing the passive host and the port number
return [match[1].replace(/,/g, "."),
(parseInt(match[2], 10) & 255) * 256 + (parseInt(match[3], 10) & 255)];
cb(null, {
host: match[1].replace(/,/g, "."),
port: (parseInt(match[2], 10) & 255) * 256 + (parseInt(match[3], 10) & 255)
});
}

function runCmd(cmd) {
Expand Down Expand Up @@ -75,21 +77,37 @@ var Ftp = module.exports = function(cfg) {
// Generate generic methods from parameter names. they can easily be
// overriden if we need special behavior. they accept any parameters given,
// it is the responsability of the user to validate the parameters.
this.raw = function () {
this.raw = function() {
return runCmd.apply(this, arguments);
}.bind(this);
COMMANDS.forEach(function(cmd) {
this.raw[cmd] = runCmd.bind(this, cmd);
}, this);

var self = this;
this.on('data', function(data) {
if (self.debugMode) {
self.emit('jsftp_debug', 'response', data || {});
}
});

this.socket = this._createSocket(this.port, this.host);
};

util.inherits(Ftp, EventEmitter);

Ftp.prototype.setDebugMode = function(debugOn) {
this.debugMode = (debugOn !== false);
};

Ftp.prototype.reemit = function(event) {
var self = this;
return function(data) { self.emit(event, data); }
return function(data) {
self.emit(event, data);
if (self.debugMode) {
self.emit('jsftp_debug', 'event:' + event, data || {});
}
}
};

Ftp.prototype._createSocket = function(port, host, firstAction) {
Expand Down Expand Up @@ -155,6 +173,10 @@ Ftp.prototype.send = function(command) {

this.emit("cmdSend", command);
this.pipeline.write(command + "\r\n");

if (this.debugMode) {
this.emit('jsftp_debug', 'user_command', command || {});
}
};

Ftp.prototype.nextCmd = function() {
Expand Down Expand Up @@ -489,11 +511,11 @@ Ftp.prototype.put = function(from, to, callback) {
return callback(new Error("Local file doesn't exist."));

fs.stat(from, function(err, stats) {
var totalSize = err ? 0 : stats.size;
var read = fs.createReadStream(from, {
bufferSize: 4 * 1024
});
putReadable(read, to, totalSize, callback);
var totalSize = err ? 0 : stats.size;
var read = fs.createReadStream(from, {
bufferSize: 4 * 1024
});
putReadable(read, to, totalSize, callback);
});
});
} else {
Expand Down Expand Up @@ -546,23 +568,21 @@ Ftp.prototype.pasvTimeout = function(socket, cb) {
socket.destroy();
cb(new Error("Passive socket timeout"));
});
}
};

Ftp.prototype.getPasvSocket = function(callback) {
var timeout = this.timeout;
callback = once(callback || NOOP);
this.execute("pasv", function(err, res) {
if (err) return callback(err);

var pasvRes = getPasvPort(res.text);
if (pasvRes === false)
return callback(new Error("PASV: Bad host/port combination"));
getPasvPort(res.text, function(err, res) {
if (err) return callback(err);

var host = pasvRes[0];
var port = pasvRes[1];
var socket = Net.createConnection(port, host);
socket.setTimeout(timeout || TIMEOUT);
callback(null, socket);
var socket = Net.createConnection(res.port, res.host);
socket.setTimeout(timeout || TIMEOUT);
callback(null, socket);
});
});
};

Expand Down
17 changes: 17 additions & 0 deletions test/jsftp_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -743,4 +743,21 @@ describe("jsftp test suite", function() {
next();
}, 5000);
});

it("Test debug mode", function(next) {
var debugCredentials = JSON.parse(JSON.stringify(FTPCredentials));
debugCredentials.debugMode = true;

var ftp2 = new Ftp(debugCredentials);
ftp2.once('jsftp_debug', function(type, data) {
next();
});
});

it("Test debug mode `setDebugMode`", function(next) {
ftp.setDebugMode(true);
ftp.once('jsftp_debug', function(type, data) {
next();
});
});
});

0 comments on commit 0a0d263

Please sign in to comment.