diff --git a/app/ssh.js b/app/ssh.js new file mode 100644 index 00000000..9f23f6d5 --- /dev/null +++ b/app/ssh.js @@ -0,0 +1,62 @@ +var ssh2 = require('ssh2'); + +exports.publish = function(req, res) { + var done; + function sendResult(result) { + if(!done) { + res.json(result); + } + done = true; + } + function sendError(error) { + sendResult({error: error}); + } + + var conn = new ssh2(); + conn.on('ready', function() { + conn.sftp(function(err, sftp) { + if(err) { + return sendError('Unable to establish SFTP connection'); + } + + var writeStream = sftp.createWriteStream(req.query.path); + + writeStream.on('close', function() { + sftp.end(); + conn.end(); + }); + + writeStream.on('error', function() { + sendError('Unable to write "' + req.query.path + '"'); + sftp.end(); + conn.end(); + }); + + req.pipe(writeStream); + }); + }); + + conn.on('error', function(err) { + if(err.level == "authentication") { + return sendError('Authentication failure'); + } + if(err.code == "ENOTFOUND") { + return sendError('Host not found'); + } + if(err.code == "ETIMEDOUT") { + return sendError('Connection timeout'); + } + sendError(err); + }); + + conn.on('end', function() { + sendResult({}); + }); + + conn.connect({ + host: req.query.host, + port: req.query.port || 22, + username: req.query.username, + password: req.query.password + }); +}; \ No newline at end of file diff --git a/doc/developer-guide.md b/doc/developer-guide.md index e2e143a0..5b02d18a 100644 --- a/doc/developer-guide.md +++ b/doc/developer-guide.md @@ -25,8 +25,6 @@ Getting started (export PORT=80 && node server.js) - > **NOTE:** StackEdit project itself has no back end. It can run on any apache server. - - Run Chrome without application cache: chrome --disable-application-cache diff --git a/public/res/helpers/sshHelper.js b/public/res/helpers/sshHelper.js index 826be9f7..ef6df323 100644 --- a/public/res/helpers/sshHelper.js +++ b/public/res/helpers/sshHelper.js @@ -1,93 +1,88 @@ define([ - "jquery", - "constants", - "core", - "logger", - "eventMgr", - "settings", - "classes/AsyncTask" + "jquery", + "constants", + "core", + "logger", + "eventMgr", + "settings", + "classes/AsyncTask" ], function($, constants, core, logger, eventMgr, settings, AsyncTask) { - var sshHelper = {}; + var sshHelper = {}; - // Listen to offline status changes - var isOffline = false; - eventMgr.addListener("onOfflineChanged", function(isOfflineParam) { - isOffline = isOfflineParam; - }); + // Listen to offline status changes + var isOffline = false; + eventMgr.addListener("onOfflineChanged", function(isOfflineParam) { + isOffline = isOfflineParam; + }); - // Only used to check the offline status - function connect(task) { - task.onRun(function() { - if(isOffline === true) { - task.error(new Error("Operation not available in offline mode.|stopPublish")); - return; - } - task.chain(); - }); - } + // Only used to check the offline status + function connect(task) { + task.onRun(function() { + if(isOffline === true) { + return task.error(new Error("Operation not available in offline mode.|stopPublish")); + } + task.chain(); + }); + } - sshHelper.upload = function(host, port, username, password, path, title, content, callback) { - var task = new AsyncTask(); - connect(task); - task.onRun(function() { - var url = settings.sshProxy + "upload"; - var data = { - host: host, - port: port, - username: username, - password: password, - path: path, - title: title, - content: content - }; - $.ajax({ - url: url, - data: data, - type: "POST", - dataType: "json", - timeout: constants.AJAX_TIMEOUT - }).done(function(response) { - if(response.error === undefined) { - task.chain(); - return; - } - handleError(response.error, task); - }).fail(function(jqXHR) { - var error = { - code: jqXHR.status, - message: jqXHR.statusText - }; - handleError(error, task); - }); - }); - task.onSuccess(function() { - callback(); - }); - task.onError(function(error) { - callback(error); - }); - task.enqueue(); - }; + sshHelper.upload = function(host, port, username, password, path, title, content, callback) { + var task = new AsyncTask(); + connect(task); + task.onRun(function() { + var url = constants.SSH_PUBLISH_URL + '?' + $.param({ + host: host, + port: port, + username: username, + password: password, + path: path, + title: title + }); + $.ajax({ + url: url, + data: content, + type: "POST", + timeout: constants.AJAX_TIMEOUT + }).done(function(response) { + if(response.error === undefined) { + return task.chain(); + } + handleError(response.error, task); + }).fail(function(jqXHR) { + var error = { + code: jqXHR.status, + message: jqXHR.statusText + }; + handleError(error, task); + }); + }); + task.onSuccess(function() { + callback(); + }); + task.onError(function(error) { + callback(error); + }); + task.enqueue(); + }; - function handleError(error, task) { - var errorMsg; - if(error) { - logger.error(error); - // Try to analyze the error - if(typeof error === "string") { - errorMsg = "SSH error: " + error + "."; - } - else { - errorMsg = "Could not publish on SSH server."; - if(error.code <= 0) { - core.setOffline(); - errorMsg = "|stopPublish"; - } - } - } - task.error(new Error(errorMsg)); - } + function handleError(error, task) { + var errorMsg; + if(error) { + logger.error(error); + // Try to analyze the error + if(typeof error === "string") { + errorMsg = "SSH error: " + error + "."; + } + else { + errorMsg = "Could not publish on SSH server."; + if(error.code <= 0) { + core.setOffline(); + errorMsg = "|stopPublish"; + } + } + } + task.error(new Error(errorMsg)); + } - return sshHelper; + return sshHelper; }); diff --git a/public/res/html/bodyIndex.html b/public/res/html/bodyIndex.html index bc0d3e52..4d27e979 100644 --- a/public/res/html/bodyIndex.html +++ b/public/res/html/bodyIndex.html @@ -590,11 +590,9 @@
Host must be accessible publicly, - unless you are hosting your own SSH - proxy. + unless you're hosting your own StackEdit instance.
@@ -1310,7 +1308,7 @@ diff --git a/public/res/settings.js b/public/res/settings.js index 03f5feea..3d41c3fb 100644 --- a/public/res/settings.js +++ b/public/res/settings.js @@ -56,7 +56,6 @@ define([ ' "pageSize": "A4"', '}' ].join('\n'), - sshProxy: constants.SSH_PROXY_URL, extensionSettings: {} };