From c6264e80407021a45baaedff4c2f44d233b716ac Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sun, 22 Dec 2013 22:22:47 +0000 Subject: [PATCH 1/8] Add newline when wrapping function to allow comments Fixes #122 --- nodes/core/core/80-function.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes/core/core/80-function.js b/nodes/core/core/80-function.js index 2766dc49b..c02af92fa 100644 --- a/nodes/core/core/80-function.js +++ b/nodes/core/core/80-function.js @@ -25,7 +25,7 @@ function FunctionNode(n) { RED.nodes.createNode(this,n); this.name = n.name; this.func = n.func; - var functionText = "var results = (function(msg){"+this.func+"})(msg);"; + var functionText = "var results = (function(msg){"+this.func+"\n})(msg);"; this.topic = n.topic; this.context = {global:RED.settings.functionGlobalContext || {}}; try { From a9668a1999e66ebc5159f21dae7e04e9ce0f9ee1 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 23 Dec 2013 14:44:35 +0000 Subject: [PATCH 2/8] Better error message if twitter auth flow fails Closes #123 --- nodes/core/social/27-twitter.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/nodes/core/social/27-twitter.js b/nodes/core/social/27-twitter.js index f8c493812..120f70e81 100644 --- a/nodes/core/social/27-twitter.js +++ b/nodes/core/social/27-twitter.js @@ -283,10 +283,12 @@ RED.app.get('/twitter/:id/auth', function(req, res){ oauth_callback: req.query.callback },function(error, oauth_token, oauth_token_secret, results){ if (error) { - console.log(error); - res.send("yeah no. didn't work.") - } - else { + var resp = '

Oh no!

'+ + '

Something went wrong with the authentication process. The following error was returned:

'+ + '

'+error.statusCode+': '+error.data+'

'+ + '

One known cause of this type of failure is if the clock is wrong on system running Node-RED.'; + res.send(resp) + } else { credentials.oauth_token = oauth_token; credentials.oauth_token_secret = oauth_token_secret; res.redirect('https://twitter.com/oauth/authorize?oauth_token='+oauth_token) From 2ba5e0fe3e1df3207c8be2a7a4b51b8511f559ff Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Tue, 24 Dec 2013 13:12:17 +0000 Subject: [PATCH 3/8] Add socketTimeout to settings.js for TCP server sockets Fixes #125 adds an optional socketTimeout param to settings.js file to add a TCP server socket timeout. Default is no timeout. --- nodes/core/io/31-tcpin.js | 263 +++++++++++++++++++------------------- settings.js | 20 +-- 2 files changed, 143 insertions(+), 140 deletions(-) diff --git a/nodes/core/io/31-tcpin.js b/nodes/core/io/31-tcpin.js index fdfac98c0..100f41fbc 100644 --- a/nodes/core/io/31-tcpin.js +++ b/nodes/core/io/31-tcpin.js @@ -16,12 +16,11 @@ var RED = require(process.env.NODE_RED_HOME+"/red/red"); var reconnectTime = RED.settings.socketReconnectTime||10000; +var socketTimeout = RED.settings.socketTimeout||null; var net = require('net'); var connectionPool = {}; - - function TcpIn(n) { RED.nodes.createNode(this,n); this.host = n.host; @@ -43,55 +42,53 @@ function TcpIn(n) { node.log("connecting to "+node.host+":"+node.port); var id = (1+Math.random()*4294967295).toString(16); client = net.connect(node.port, node.host, function() { - buffer = (node.datatype == 'buffer')? new Buffer(0):""; - node.log("connected to "+node.host+":"+node.port); + buffer = (node.datatype == 'buffer')? new Buffer(0):""; + node.log("connected to "+node.host+":"+node.port); }); connectionPool[id] = client; - + client.on('data', function (data) { - if (node.datatype != 'buffer') { - data = data.toString(node.datatype); - } - if (node.stream) { - if ((node.datatype) === "utf8" && node.newline != "") { - buffer = buffer+data; - var parts = buffer.split(node.newline); - for (var i = 0;i 0)) { - var msg = {topic:node.topic,payload:buffer}; + var msg = {topic:node.topic, payload:data}; msg._session = {type:"tcp",id:id}; node.send(msg); - buffer = null; } + } else { + if ((typeof data) === "string") { + buffer = buffer+data; + } else { + buffer = Buffer.concat([buffer,data],buffer.length+data.length); + } + } + }); + client.on('end', function() { + if (!node.stream || (node.datatype == "utf8" && node.newline != "" && buffer.length > 0)) { + var msg = {topic:node.topic,payload:buffer}; + msg._session = {type:"tcp",id:id}; + node.send(msg); + buffer = null; + } }); - client.on('close', function() { - delete connectionPool[id]; - node.log("connection lost to "+node.host+":"+node.port); - if (!node.closing) { - reconnectTimeout = setTimeout(setupTcpClient, reconnectTime); - } + delete connectionPool[id]; + node.log("connection lost to "+node.host+":"+node.port); + if (!node.closing) { + reconnectTimeout = setTimeout(setupTcpClient, reconnectTime); + } }); - client.on('error', function(err) { node.log(err); }); @@ -105,52 +102,57 @@ function TcpIn(n) { }); } else { var server = net.createServer(function (socket) { - var id = (1+Math.random()*4294967295).toString(16); - connectionPool[id] = socket; - - var buffer = (node.datatype == 'buffer')? new Buffer(0):""; - socket.on('data', function (data) { - if (node.datatype != 'buffer') { - data = data.toString(node.datatype); - } + if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } + var id = (1+Math.random()*4294967295).toString(16); + connectionPool[id] = socket; - if (node.stream) { - if ((typeof data) === "string" && node.newline != "") { - buffer = buffer+data; - var parts = buffer.split(node.newline); - for (var i = 0;i 0)) { - var msg = {topic:node.topic,payload:buffer}; + var buffer = (node.datatype == 'buffer')? new Buffer(0):""; + socket.on('data', function (data) { + if (node.datatype != 'buffer') { + data = data.toString(node.datatype); + } + + if (node.stream) { + if ((typeof data) === "string" && node.newline != "") { + buffer = buffer+data; + var parts = buffer.split(node.newline); + for (var i = 0;i 0)) { + var msg = {topic:node.topic,payload:buffer}; + msg._session = {type:"tcp",id:id}; + node.send(msg); + buffer = null; + } + }); + socket.on('timeout', function() { + node.log('timeout closed socket port '+node.port); + socket.end(); + }); + socket.on('close', function() { + delete connectionPool[id]; + }); + socket.on('error',function(err) { + node.log(err); + }); }); server.listen(node.port); node.log('listening on port '+node.port); @@ -163,7 +165,6 @@ function TcpIn(n) { } } - RED.nodes.registerType("tcp in",TcpIn); function TcpOut(n) { @@ -180,51 +181,47 @@ function TcpOut(n) { var reconnectTimeout; var client = null; var connected = false; - + function setupTcpClient() { node.log("connecting to "+node.host+":"+node.port); client = net.connect(node.port, node.host, function() { - connected = true; - node.log("connected to "+node.host+":"+node.port); + connected = true; + node.log("connected to "+node.host+":"+node.port); }); - client.on('error', function (err) { - node.log('error : '+err); + node.log('error : '+err); }); - client.on('end', function (err) { }); - client.on('close', function() { - node.log("connection lost to "+node.host+":"+node.port); - connected = false; - client.destroy(); - if (!node.closing) { - reconnectTimeout = setTimeout(setupTcpClient,reconnectTime); - } + node.log("connection lost to "+node.host+":"+node.port); + connected = false; + client.destroy(); + if (!node.closing) { + reconnectTimeout = setTimeout(setupTcpClient,reconnectTime); + } }); } setupTcpClient(); - - + node.on("input", function(msg) { - if (connected && msg.payload != null) { - if (Buffer.isBuffer(msg.payload)) { - client.write(msg.payload); - } else if (typeof msg.payload === "string" && node.base64) { - client.write(new Buffer(msg.payload,'base64')); - } else { - client.write(new Buffer(""+msg.payload)); - } + if (connected && msg.payload != null) { + if (Buffer.isBuffer(msg.payload)) { + client.write(msg.payload); + } else if (typeof msg.payload === "string" && node.base64) { + client.write(new Buffer(msg.payload,'base64')); + } else { + client.write(new Buffer(""+msg.payload)); } + } }); - + node.on("close", function() { this.closing = true; client.end(); clearTimeout(reconnectTimeout); }); - + } else if (node.beserver == "reply") { node.on("input",function(msg) { if (msg._session && msg._session.type == "tcp") { @@ -243,33 +240,37 @@ function TcpOut(n) { } else { var connectedSockets = []; var server = net.createServer(function (socket) { - var remoteDetails = socket.remoteAddress+":"+socket.remotePort; - node.log("connection from "+remoteDetails); - connectedSockets.push(socket); - socket.on('close',function() { - node.log("connection closed from "+remoteDetails); - connectedSockets.splice(connectedSockets.indexOf(socket),1); - }); - socket.on('error',function() { - node.log("socket error from "+remoteDetails); - connectedSockets.splice(connectedSockets.indexOf(socket),1); - }); - + if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } + var remoteDetails = socket.remoteAddress+":"+socket.remotePort; + node.log("connection from "+remoteDetails); + connectedSockets.push(socket); + socket.on('timeout', function() { + node.log('timeout closed socket port '+node.port); + socket.end(); + }); + socket.on('close',function() { + node.log("connection closed from "+remoteDetails); + connectedSockets.splice(connectedSockets.indexOf(socket),1); + }); + socket.on('error',function() { + node.log("socket error from "+remoteDetails); + connectedSockets.splice(connectedSockets.indexOf(socket),1); + }); }); node.on("input", function(msg) { - if (msg.payload != null) { - var buffer; - if (Buffer.isBuffer(msg.payload)) { - buffer = msg.payload; - } else if (typeof msg.payload === "string" && node.base64) { - buffer = new Buffer(msg.payload,'base64'); - } else { - buffer = new Buffer(""+msg.payload); - } - for (var i = 0; i.json //flowFile: 'flows.json', - + // By default, all user data is stored in the Node-RED install directory. To // use a different location, the following property can be used //userDir: '/home/nol/.node-red/', - + // Node-RED scans the `nodes` directory in the install directory to find nodes. // The following property can be used to specify an additional directory to scan. //nodesDir: '/home/nol/.node-red/nodes', - + // You can protect the user interface with a userid and password by using the following property // the password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') //httpAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, @@ -53,11 +57,11 @@ module.exports = { // The following property can be used to specifiy a different root path. //httpRoot: '/admin', - // When httpRoot is used to move the UI to a different root path, the + // When httpRoot is used to move the UI to a different root path, the // following property can be used to identify a directory of static content // that should be served at http://localhost:1880/. //httpStatic: '/home/nol/node-red-dashboard/', - + // The following property can be used to enable HTTPS // See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener // for details on its contents. From b7531bae4d2595a1885f19c036cf7273d5d30d64 Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Tue, 24 Dec 2013 16:18:18 +0000 Subject: [PATCH 4/8] Added proper choice for regex support to change node (and better error catching) Addresses Issue #121 --- nodes/core/logic/15-change.html | 11 ++++++++++- nodes/core/logic/15-change.js | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/nodes/core/logic/15-change.html b/nodes/core/logic/15-change.html index ea360908f..c2a2f0420 100644 --- a/nodes/core/logic/15-change.html +++ b/nodes/core/logic/15-change.html @@ -34,6 +34,11 @@ +

+ + + +

@@ -58,6 +63,7 @@ property: {value:"payload"}, from: {value:""}, to: {value:""}, + reg: {value:false}, name: {value:""} }, inputs: 1, @@ -78,6 +84,7 @@ $("#node-input-t").html("with value"); $("#node-from-row").hide(); $("#node-to-row").show(); + $("#node-reg-row").hide(); $("#node-tip").html("Tip: expects a new property name and either a fixed value OR the full name of another msg.property eg: msg.sentiment.score"); } if (a === "delete") { @@ -86,6 +93,7 @@ //$("#node-input-t").html("to"); $("#node-from-row").hide(); $("#node-to-row").hide(); + $("#node-reg-row").hide(); $("#node-tip").html("Tip: deletes the named property and all sub-properties"); } if (a === "change") { @@ -94,7 +102,8 @@ $("#node-input-t").html("replace with"); $("#node-from-row").show(); $("#node-to-row").show(); - $("#node-tip").html("Tip: if it contains can be a regex, likewise replace with can accept regex results. Only works on strings."); + $("#node-reg-row").show(); + $("#node-tip").html("Tip: If contains is a regex, you must escape any special characters. Likewise replace with can accept regex results. Only works on strings."); } //if (a === "replace") { // $("#node-input-todo").html("called"); diff --git a/nodes/core/logic/15-change.js b/nodes/core/logic/15-change.js index 4866239c0..0a8b53ef6 100644 --- a/nodes/core/logic/15-change.js +++ b/nodes/core/logic/15-change.js @@ -22,6 +22,8 @@ function ChangeNode(n) { this.property = n.property || ""; this.from = n.from || " "; this.to = n.to || " "; + this.reg = n.reg; + console.log("Type=",this.reg); var node = this; var makeNew = function( stem, path, value ) { @@ -35,7 +37,15 @@ function ChangeNode(n) { this.on('input', function (msg) { if (node.action == "change") { - node.re = new RegExp(this.from, "g"); + if (node.reg === false) { + this.from = this.from.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + } + //console.log("Regex is:",this.from); + try { + node.re = new RegExp(this.from, "g"); + } catch (e) { + node.error("Invalid regex: "+this.from); + } if (typeof msg[node.property] === "string") { msg[node.property] = (msg[node.property]).replace(node.re, node.to); } From 6b2e666600f1182fce2eaae9d9e9205b29b3c632 Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Tue, 24 Dec 2013 16:24:31 +0000 Subject: [PATCH 5/8] Make sure old flows with change node - work as-is/was. Signed-off-by: Dave C-J --- nodes/core/logic/15-change.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes/core/logic/15-change.js b/nodes/core/logic/15-change.js index 0a8b53ef6..6d1a8911b 100644 --- a/nodes/core/logic/15-change.js +++ b/nodes/core/logic/15-change.js @@ -22,7 +22,7 @@ function ChangeNode(n) { this.property = n.property || ""; this.from = n.from || " "; this.to = n.to || " "; - this.reg = n.reg; + this.reg = n.reg || true; console.log("Type=",this.reg); var node = this; From dafb2f1d38eabe06d1e3cd60218bde066a935345 Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Tue, 24 Dec 2013 16:54:19 +0000 Subject: [PATCH 6/8] Removed excess debugging from change node (sorry) --- nodes/core/logic/15-change.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/nodes/core/logic/15-change.js b/nodes/core/logic/15-change.js index 6d1a8911b..2d7a24770 100644 --- a/nodes/core/logic/15-change.js +++ b/nodes/core/logic/15-change.js @@ -22,8 +22,7 @@ function ChangeNode(n) { this.property = n.property || ""; this.from = n.from || " "; this.to = n.to || " "; - this.reg = n.reg || true; - console.log("Type=",this.reg); + this.reg = n.reg; var node = this; var makeNew = function( stem, path, value ) { @@ -37,14 +36,14 @@ function ChangeNode(n) { this.on('input', function (msg) { if (node.action == "change") { + var from = node.from; if (node.reg === false) { - this.from = this.from.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + from = from.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); } - //console.log("Regex is:",this.from); try { - node.re = new RegExp(this.from, "g"); + node.re = new RegExp(from, "g"); } catch (e) { - node.error("Invalid regex: "+this.from); + node.error("Invalid regex: "+from); } if (typeof msg[node.property] === "string") { msg[node.property] = (msg[node.property]).replace(node.re, node.to); From e0921f84c4769f5ed694b40916c053528f260171 Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Tue, 24 Dec 2013 17:01:53 +0000 Subject: [PATCH 7/8] still flattening wrinkles in change node... (I blame the Xmas "spirit" ;-) --- nodes/core/logic/15-change.html | 1 + nodes/core/logic/15-change.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/nodes/core/logic/15-change.html b/nodes/core/logic/15-change.html index c2a2f0420..9d6d2c344 100644 --- a/nodes/core/logic/15-change.html +++ b/nodes/core/logic/15-change.html @@ -76,6 +76,7 @@ return this.name ? "node_label_italic" : ""; }, oneditprepare: function() { + if (this.reg === null) { $("#node-input-reg").selected(true); } $("#node-input-action").change( function() { var a = $("#node-input-action").val(); if (a === "replace") { diff --git a/nodes/core/logic/15-change.js b/nodes/core/logic/15-change.js index 2d7a24770..8922bde20 100644 --- a/nodes/core/logic/15-change.js +++ b/nodes/core/logic/15-change.js @@ -22,7 +22,7 @@ function ChangeNode(n) { this.property = n.property || ""; this.from = n.from || " "; this.to = n.to || " "; - this.reg = n.reg; + this.reg = (n.reg === null || n.reg); var node = this; var makeNew = function( stem, path, value ) { From 00202a39303a44cc57ad8c77d86ac73f7491bc56 Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Tue, 24 Dec 2013 17:07:07 +0000 Subject: [PATCH 8/8] wrong syntax for checking check box... in change node --- nodes/core/logic/15-change.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes/core/logic/15-change.html b/nodes/core/logic/15-change.html index 9d6d2c344..9d8ad6652 100644 --- a/nodes/core/logic/15-change.html +++ b/nodes/core/logic/15-change.html @@ -76,7 +76,7 @@ return this.name ? "node_label_italic" : ""; }, oneditprepare: function() { - if (this.reg === null) { $("#node-input-reg").selected(true); } + if (this.reg === null) { $("#node-input-reg").prop('checked', true); } $("#node-input-action").change( function() { var a = $("#node-input-action").val(); if (a === "replace") {