@node-red/nodes 4.1.2 → 4.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/common/25-status.js +7 -5
- package/core/function/89-delay.js +8 -4
- package/core/function/90-exec.js +17 -9
- package/core/network/05-tls.html +3 -0
- package/core/network/10-mqtt.js +11 -6
- package/core/network/21-httprequest.js +83 -53
- package/core/network/22-websocket.js +5 -1
- package/core/network/31-tcpin.js +152 -140
- package/core/network/32-udp.js +12 -8
- package/core/storage/10-file.html +2 -2
- package/package.json +2 -2
package/core/common/25-status.js
CHANGED
|
@@ -20,13 +20,15 @@ module.exports = function(RED) {
|
|
|
20
20
|
function StatusNode(n) {
|
|
21
21
|
RED.nodes.createNode(this,n);
|
|
22
22
|
var node = this;
|
|
23
|
-
this.scope = n.scope
|
|
23
|
+
this.scope = n.scope;
|
|
24
24
|
|
|
25
25
|
// auto-filter out any directly connected nodes to avoid simple loopback
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.scope
|
|
26
|
+
if (Array.isArray(this.scope)) {
|
|
27
|
+
const w = this.wires.flat();
|
|
28
|
+
for (let i = 0; i < this.scope.length; i++) {
|
|
29
|
+
if (w.includes(this.scope[i])) {
|
|
30
|
+
this.scope.splice(i, 1);
|
|
31
|
+
}
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -159,7 +159,8 @@ module.exports = function(RED) {
|
|
|
159
159
|
if (node.pauseType === "delay") {
|
|
160
160
|
node.on("input", function(msg, send, done) {
|
|
161
161
|
var id = ourTimeout(function() {
|
|
162
|
-
node.idList.
|
|
162
|
+
var idx = node.idList.indexOf(id);
|
|
163
|
+
if (idx !== -1) { node.idList.splice(idx, 1); }
|
|
163
164
|
if (node.timeout > 1000) {
|
|
164
165
|
node.status({fill:"blue",shape:"dot",text:node.idList.length});
|
|
165
166
|
}
|
|
@@ -184,7 +185,8 @@ module.exports = function(RED) {
|
|
|
184
185
|
}
|
|
185
186
|
if (delayvar < 0) { delayvar = 0; }
|
|
186
187
|
var id = ourTimeout(function() {
|
|
187
|
-
node.idList.
|
|
188
|
+
var idx = node.idList.indexOf(id);
|
|
189
|
+
if (idx !== -1) { node.idList.splice(idx, 1); }
|
|
188
190
|
if (node.idList.length === 0) { node.status({}); }
|
|
189
191
|
send(msg);
|
|
190
192
|
if (delayvar >= 0) {
|
|
@@ -192,7 +194,8 @@ module.exports = function(RED) {
|
|
|
192
194
|
}
|
|
193
195
|
done();
|
|
194
196
|
}, delayvar, () => done());
|
|
195
|
-
|
|
197
|
+
if (Object.keys(msg).length === 2 && msg.hasOwnProperty("flush")) { id.clear(); }
|
|
198
|
+
else { node.idList.push(id); }
|
|
196
199
|
if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
|
|
197
200
|
if (msg.hasOwnProperty("flush")) { flushDelayList(msg.flush); done(); }
|
|
198
201
|
if (delayvar >= 0) {
|
|
@@ -206,7 +209,8 @@ module.exports = function(RED) {
|
|
|
206
209
|
node.on("input", function(msg, send, done) {
|
|
207
210
|
var wait = node.randomFirst + (node.diff * Math.random());
|
|
208
211
|
var id = ourTimeout(function() {
|
|
209
|
-
node.idList.
|
|
212
|
+
var idx = node.idList.indexOf(id);
|
|
213
|
+
if (idx !== -1) { node.idList.splice(idx, 1); }
|
|
210
214
|
send(msg);
|
|
211
215
|
if (node.timeout >= 1000) {
|
|
212
216
|
node.status({fill:"blue",shape:"dot",text:node.idList.length});
|
package/core/function/90-exec.js
CHANGED
|
@@ -105,18 +105,26 @@ module.exports = function(RED) {
|
|
|
105
105
|
}
|
|
106
106
|
node.activeProcesses[child.pid] = child;
|
|
107
107
|
child.stdout.on('data', function (data) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
try {
|
|
109
|
+
if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
|
|
110
|
+
// console.log('[exec] stdout: ' + data,child.pid);
|
|
111
|
+
if (isUtf8(data)) { msg.payload = data.toString(); }
|
|
112
|
+
else { msg.payload = data; }
|
|
113
|
+
nodeSend([RED.util.cloneMessage(msg),null,null]);
|
|
114
|
+
}
|
|
115
|
+
} catch (err) {
|
|
116
|
+
node.error(err.toString());
|
|
113
117
|
}
|
|
114
118
|
});
|
|
115
119
|
child.stderr.on('data', function (data) {
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
try {
|
|
121
|
+
if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
|
|
122
|
+
if (isUtf8(data)) { msg.payload = data.toString(); }
|
|
123
|
+
else { msg.payload = data; }
|
|
124
|
+
nodeSend([null,RED.util.cloneMessage(msg),null]);
|
|
125
|
+
}
|
|
126
|
+
} catch (err) {
|
|
127
|
+
node.error(err.toString());
|
|
120
128
|
}
|
|
121
129
|
});
|
|
122
130
|
child.on('close', function (code,signal) {
|
package/core/network/05-tls.html
CHANGED
|
@@ -167,12 +167,15 @@
|
|
|
167
167
|
$("#tls-config-button-cert-clear").on("click", function() {
|
|
168
168
|
clearNameData("cert");
|
|
169
169
|
});
|
|
170
|
+
RED.popover.tooltip($("#tls-config-button-cert-clear"), RED._("common.label.delete"));
|
|
170
171
|
$("#tls-config-button-key-clear").on("click", function() {
|
|
171
172
|
clearNameData("key");
|
|
172
173
|
});
|
|
174
|
+
RED.popover.tooltip($("#tls-config-button-key-clear"), RED._("common.label.delete"));
|
|
173
175
|
$("#tls-config-button-ca-clear").on("click", function() {
|
|
174
176
|
clearNameData("ca");
|
|
175
177
|
});
|
|
178
|
+
RED.popover.tooltip($("#tls-config-button-ca-clear"), RED._("common.label.delete"));
|
|
176
179
|
|
|
177
180
|
if (RED.settings.tlsConfigDisableLocalFiles) {
|
|
178
181
|
$("#node-config-row-uselocalfiles").hide();
|
package/core/network/10-mqtt.js
CHANGED
|
@@ -227,6 +227,7 @@ module.exports = function(RED) {
|
|
|
227
227
|
* Handle the payload / packet recieved in MQTT In and MQTT Sub nodes
|
|
228
228
|
*/
|
|
229
229
|
function subscriptionHandler(node, datatype ,topic, payload, packet) {
|
|
230
|
+
if (!packet) { packet = {}; }
|
|
230
231
|
const msg = {topic:topic, payload:null, qos:packet.qos, retain:packet.retain};
|
|
231
232
|
const v5 = (node && node.brokerConn)
|
|
232
233
|
? node.brokerConn.v5()
|
|
@@ -1074,12 +1075,16 @@ module.exports = function(RED) {
|
|
|
1074
1075
|
|
|
1075
1076
|
if (!subscription.handler) {
|
|
1076
1077
|
subscription.handler = function (mtopic, mpayload, mpacket) {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1078
|
+
try {
|
|
1079
|
+
const sops = subscription.options ? subscription.options.properties : {}
|
|
1080
|
+
const pops = (mpacket && mpacket.properties) || {}
|
|
1081
|
+
if (subIdsAvailable && pops.subscriptionIdentifier && sops.subscriptionIdentifier && (pops.subscriptionIdentifier !== sops.subscriptionIdentifier)) {
|
|
1082
|
+
//do nothing as subscriptionIdentifier does not match
|
|
1083
|
+
} else if (matchTopic(topic, mtopic)) {
|
|
1084
|
+
subscription.callback && subscription.callback(mtopic, mpayload, mpacket)
|
|
1085
|
+
}
|
|
1086
|
+
} catch (err) {
|
|
1087
|
+
node.error("MQTT subscription handler error: " + err.toString());
|
|
1083
1088
|
}
|
|
1084
1089
|
}
|
|
1085
1090
|
}
|
|
@@ -143,15 +143,6 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
|
-
/**
|
|
147
|
-
* @param {Object} headersObject
|
|
148
|
-
* @param {string} name
|
|
149
|
-
* @return {any} value
|
|
150
|
-
*/
|
|
151
|
-
const getHeaderValue = (headersObject, name) => {
|
|
152
|
-
const asLowercase = name.toLowercase();
|
|
153
|
-
return headersObject[Object.keys(headersObject).find(k => k.toLowerCase() === asLowercase)];
|
|
154
|
-
}
|
|
155
146
|
this.count = 0;
|
|
156
147
|
this.on("input",function(msg,nodeSend,nodeDone) {
|
|
157
148
|
node.count++;
|
|
@@ -256,34 +247,42 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
256
247
|
opts.hooks = {
|
|
257
248
|
beforeRequest: [
|
|
258
249
|
options => {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
250
|
+
try {
|
|
251
|
+
// Whilst HTTP headers are meant to be case-insensitive,
|
|
252
|
+
// in the real world, there are servers that aren't so compliant.
|
|
253
|
+
// GOT will lower case all headers given a chance, so we need
|
|
254
|
+
// to restore the case of any headers the user has set.
|
|
255
|
+
Object.keys(options.headers).forEach(h => {
|
|
256
|
+
if (originalHeaderMap[h] && originalHeaderMap[h] !== h) {
|
|
257
|
+
options.headers[originalHeaderMap[h]] = options.headers[h];
|
|
258
|
+
delete options.headers[h];
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
if (node.insecureHTTPParser) {
|
|
262
|
+
// Setting the property under _unixOptions as pretty
|
|
263
|
+
// much the only hack available to get got to apply
|
|
264
|
+
// a core http option it doesn't think we should be
|
|
265
|
+
// allowed to set
|
|
266
|
+
options._unixOptions = { ...options.unixOptions, insecureHTTPParser: true }
|
|
267
267
|
}
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
// Setting the property under _unixOptions as pretty
|
|
271
|
-
// much the only hack available to get got to apply
|
|
272
|
-
// a core http option it doesn't think we should be
|
|
273
|
-
// allowed to set
|
|
274
|
-
options._unixOptions = { ...options.unixOptions, insecureHTTPParser: true }
|
|
268
|
+
} catch (err) {
|
|
269
|
+
node.warn("Error in beforeRequest hook: " + err.message);
|
|
275
270
|
}
|
|
276
271
|
}
|
|
277
272
|
],
|
|
278
273
|
beforeRedirect: [
|
|
279
274
|
(options, response) => {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
275
|
+
try {
|
|
276
|
+
let redirectInfo = {
|
|
277
|
+
location: response.headers.location
|
|
278
|
+
}
|
|
279
|
+
if (response.headers.hasOwnProperty('set-cookie')) {
|
|
280
|
+
redirectInfo.cookies = extractCookies(response.headers['set-cookie']);
|
|
281
|
+
}
|
|
282
|
+
redirectList.push(redirectInfo)
|
|
283
|
+
} catch (err) {
|
|
284
|
+
node.warn("Error processing redirect: " + err.message);
|
|
285
285
|
}
|
|
286
|
-
redirectList.push(redirectInfo)
|
|
287
286
|
}
|
|
288
287
|
]
|
|
289
288
|
}
|
|
@@ -422,25 +421,30 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
422
421
|
let digestCreds = this.credentials;
|
|
423
422
|
let sentCreds = false;
|
|
424
423
|
opts.hooks.afterResponse = [(response, retry) => {
|
|
425
|
-
|
|
426
|
-
if (
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
424
|
+
try {
|
|
425
|
+
if (response.statusCode === 401) {
|
|
426
|
+
if (sentCreds) {
|
|
427
|
+
return response
|
|
428
|
+
}
|
|
429
|
+
const requestUrl = new URL(response.request.requestUrl);
|
|
430
|
+
const options = { headers: {} }
|
|
431
|
+
const normalisedHeaders = {};
|
|
432
|
+
Object.keys(response.headers).forEach(k => {
|
|
433
|
+
normalisedHeaders[k.toLowerCase()] = response.headers[k]
|
|
434
|
+
})
|
|
435
|
+
if (normalisedHeaders['www-authenticate']) {
|
|
436
|
+
let authHeader = buildDigestHeader(digestCreds.user,digestCreds.password, response.request.options.method, requestUrl.pathname + requestUrl.search, normalisedHeaders['www-authenticate'])
|
|
437
|
+
options.headers.Authorization = authHeader;
|
|
438
|
+
}
|
|
439
|
+
// response.request.options.merge(options)
|
|
440
|
+
sentCreds = true;
|
|
441
|
+
return retry(options);
|
|
438
442
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
443
|
+
return response
|
|
444
|
+
} catch (err) {
|
|
445
|
+
node.warn("Digest authentication failed: " + err.message);
|
|
446
|
+
return response;
|
|
442
447
|
}
|
|
443
|
-
return response
|
|
444
448
|
}];
|
|
445
449
|
} else if (this.authType === "bearer") {
|
|
446
450
|
opts.headers.Authorization = `Bearer ${this.credentials.password||""}`
|
|
@@ -688,6 +692,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
688
692
|
if (!sendErrorsToCatch) {
|
|
689
693
|
nodeSend(msg);
|
|
690
694
|
}
|
|
695
|
+
node.count--;
|
|
691
696
|
nodeDone();
|
|
692
697
|
});
|
|
693
698
|
});
|
|
@@ -720,13 +725,29 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
720
725
|
|
|
721
726
|
function extractCookies(setCookie) {
|
|
722
727
|
var cookies = {};
|
|
728
|
+
if (!Array.isArray(setCookie)) {
|
|
729
|
+
return cookies;
|
|
730
|
+
}
|
|
723
731
|
setCookie.forEach(function(c) {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
732
|
+
try {
|
|
733
|
+
if (typeof c !== 'string') {
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
var parsedCookie = cookie.parse(c);
|
|
737
|
+
var eq_idx = c.indexOf('=');
|
|
738
|
+
if (eq_idx === -1) {
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
var key = c.substr(0, eq_idx).trim()
|
|
742
|
+
if (!key) {
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
parsedCookie.value = parsedCookie[key];
|
|
746
|
+
delete parsedCookie[key];
|
|
747
|
+
cookies[key] = parsedCookie;
|
|
748
|
+
} catch (err) {
|
|
749
|
+
// Skip malformed cookies
|
|
750
|
+
}
|
|
730
751
|
});
|
|
731
752
|
return cookies;
|
|
732
753
|
}
|
|
@@ -778,6 +799,9 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
778
799
|
}
|
|
779
800
|
|
|
780
801
|
function buildDigestHeader(user, pass, method, path, authHeader) {
|
|
802
|
+
if (!authHeader || typeof authHeader !== 'string') {
|
|
803
|
+
throw new Error("Invalid or missing WWW-Authenticate header");
|
|
804
|
+
}
|
|
781
805
|
var challenge = {}
|
|
782
806
|
var re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi
|
|
783
807
|
for (;;) {
|
|
@@ -787,6 +811,12 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
787
811
|
}
|
|
788
812
|
challenge[match[1]] = match[2] || match[3]
|
|
789
813
|
}
|
|
814
|
+
if (!challenge.nonce) {
|
|
815
|
+
throw new Error("Invalid digest challenge: missing nonce");
|
|
816
|
+
}
|
|
817
|
+
if (!challenge.realm) {
|
|
818
|
+
throw new Error("Invalid digest challenge: missing realm");
|
|
819
|
+
}
|
|
790
820
|
var qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth'
|
|
791
821
|
var nc = qop && '00000001'
|
|
792
822
|
var cnonce = qop && uuid().replace(/-/g, '')
|
|
@@ -297,7 +297,11 @@ module.exports = function(RED) {
|
|
|
297
297
|
}
|
|
298
298
|
msg._session = {type:"websocket",id:id};
|
|
299
299
|
for (var i = 0; i < this._inputNodes.length; i++) {
|
|
300
|
-
|
|
300
|
+
try {
|
|
301
|
+
this._inputNodes[i].send(msg);
|
|
302
|
+
} catch (err) {
|
|
303
|
+
this.error(RED._("websocket.errors.send-error") + " " + err.toString());
|
|
304
|
+
}
|
|
301
305
|
}
|
|
302
306
|
}
|
|
303
307
|
|
package/core/network/31-tcpin.js
CHANGED
|
@@ -127,32 +127,36 @@ module.exports = function(RED) {
|
|
|
127
127
|
connectionPool[id] = client;
|
|
128
128
|
|
|
129
129
|
client.on('data', function (data) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
130
|
+
try {
|
|
131
|
+
if (node.datatype != 'buffer') {
|
|
132
|
+
data = data.toString(node.datatype);
|
|
133
|
+
}
|
|
134
|
+
if (node.stream) {
|
|
135
|
+
var msg;
|
|
136
|
+
if ((node.datatype) === "utf8" && node.newline !== "") {
|
|
137
|
+
buffer = buffer+data;
|
|
138
|
+
var parts = buffer.split(node.newline);
|
|
139
|
+
for (var i = 0; i<parts.length-1; i+=1) {
|
|
140
|
+
msg = {topic:node.topic, payload:parts[i]};
|
|
141
|
+
if (node.trim == true) { msg.payload += node.newline; }
|
|
142
|
+
msg._session = {type:"tcp",id:id};
|
|
143
|
+
node.send(msg);
|
|
144
|
+
}
|
|
145
|
+
buffer = parts[parts.length-1];
|
|
146
|
+
} else {
|
|
147
|
+
msg = {topic:node.topic, payload:data};
|
|
141
148
|
msg._session = {type:"tcp",id:id};
|
|
142
149
|
node.send(msg);
|
|
143
150
|
}
|
|
144
|
-
buffer = parts[parts.length-1];
|
|
145
151
|
} else {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if ((typeof data) === "string") {
|
|
152
|
-
buffer = buffer+data;
|
|
153
|
-
} else {
|
|
154
|
-
buffer = Buffer.concat([buffer,data],buffer.length+data.length);
|
|
152
|
+
if ((typeof data) === "string") {
|
|
153
|
+
buffer = buffer+data;
|
|
154
|
+
} else {
|
|
155
|
+
buffer = Buffer.concat([buffer,data],buffer.length+data.length);
|
|
156
|
+
}
|
|
155
157
|
}
|
|
158
|
+
} catch (err) {
|
|
159
|
+
node.error(RED._("tcpin.errors.error",{error:err.toString()}));
|
|
156
160
|
}
|
|
157
161
|
});
|
|
158
162
|
client.on('end', function() {
|
|
@@ -222,35 +226,39 @@ module.exports = function(RED) {
|
|
|
222
226
|
|
|
223
227
|
var buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
|
|
224
228
|
socket.on('data', function (data) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
229
|
+
try {
|
|
230
|
+
if (node.datatype != 'buffer') {
|
|
231
|
+
data = data.toString(node.datatype);
|
|
232
|
+
}
|
|
233
|
+
if (node.stream) {
|
|
234
|
+
var msg;
|
|
235
|
+
if ((typeof data) === "string" && node.newline !== "") {
|
|
236
|
+
buffer = buffer+data;
|
|
237
|
+
var parts = buffer.split(node.newline);
|
|
238
|
+
for (var i = 0; i<parts.length-1; i+=1) {
|
|
239
|
+
msg = {topic:node.topic, payload:parts[i], ip:socket.remoteAddress, port:socket.remotePort};
|
|
240
|
+
if (node.trim == true) { msg.payload += node.newline; }
|
|
241
|
+
msg._session = {type:"tcp",id:id};
|
|
242
|
+
node.send(msg);
|
|
243
|
+
}
|
|
244
|
+
buffer = parts[parts.length-1];
|
|
245
|
+
} else {
|
|
246
|
+
msg = {topic:node.topic, payload:data, ip:socket.remoteAddress, port:socket.remotePort};
|
|
236
247
|
msg._session = {type:"tcp",id:id};
|
|
237
248
|
node.send(msg);
|
|
238
249
|
}
|
|
239
|
-
buffer = parts[parts.length-1];
|
|
240
|
-
} else {
|
|
241
|
-
msg = {topic:node.topic, payload:data, ip:socket.remoteAddress, port:socket.remotePort};
|
|
242
|
-
msg._session = {type:"tcp",id:id};
|
|
243
|
-
node.send(msg);
|
|
244
250
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
+
else {
|
|
252
|
+
if ((typeof data) === "string") {
|
|
253
|
+
buffer = buffer+data;
|
|
254
|
+
} else {
|
|
255
|
+
buffer = Buffer.concat([buffer,data],buffer.length+data.length);
|
|
256
|
+
}
|
|
257
|
+
fromi = socket.remoteAddress;
|
|
258
|
+
fromp = socket.remotePort;
|
|
251
259
|
}
|
|
252
|
-
|
|
253
|
-
|
|
260
|
+
} catch (err) {
|
|
261
|
+
node.error(RED._("tcpin.errors.error",{error:err.toString()}));
|
|
254
262
|
}
|
|
255
263
|
});
|
|
256
264
|
socket.on('end', function() {
|
|
@@ -678,117 +686,121 @@ module.exports = function(RED) {
|
|
|
678
686
|
}
|
|
679
687
|
var chunk = "";
|
|
680
688
|
clients[connection_id].client.on('data', function(data) {
|
|
681
|
-
|
|
682
|
-
if (
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
689
|
+
try {
|
|
690
|
+
if (node.out === "sit") { // if we are staying connected just send the buffer
|
|
691
|
+
if (clients[connection_id]) {
|
|
692
|
+
const msg = clients[connection_id].lastMsg || {};
|
|
693
|
+
msg.payload = RED.util.cloneMessage(data);
|
|
694
|
+
if (node.ret === "string") {
|
|
695
|
+
try {
|
|
696
|
+
if (node.newline && node.newline !== "" ) {
|
|
697
|
+
chunk += msg.payload.toString();
|
|
698
|
+
let parts = chunk.split(node.newline);
|
|
699
|
+
for (var p=0; p<parts.length-1; p+=1) {
|
|
700
|
+
let m = RED.util.cloneMessage(msg);
|
|
701
|
+
m.payload = parts[p];
|
|
702
|
+
if (node.trim == true) { m.payload += node.newline; }
|
|
703
|
+
nodeSend(m);
|
|
704
|
+
}
|
|
705
|
+
chunk = parts[parts.length-1];
|
|
706
|
+
}
|
|
707
|
+
else {
|
|
708
|
+
msg.payload = msg.payload.toString();
|
|
709
|
+
nodeSend(msg);
|
|
695
710
|
}
|
|
696
|
-
chunk = parts[parts.length-1];
|
|
697
|
-
}
|
|
698
|
-
else {
|
|
699
|
-
msg.payload = msg.payload.toString();
|
|
700
|
-
nodeSend(msg);
|
|
701
711
|
}
|
|
712
|
+
catch(e) { node.error(RED._("tcpin.errors.bad-string"), msg); }
|
|
702
713
|
}
|
|
703
|
-
|
|
714
|
+
else { nodeSend(msg); }
|
|
704
715
|
}
|
|
705
|
-
else { nodeSend(msg); }
|
|
706
716
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
if (node.out === "time") {
|
|
715
|
-
if (clients[connection_id]) {
|
|
716
|
-
// do the timer thing
|
|
717
|
-
if (clients[connection_id].timeout) {
|
|
718
|
-
i += 1;
|
|
719
|
-
buf[i] = data[j];
|
|
720
|
-
}
|
|
721
|
-
else {
|
|
722
|
-
clients[connection_id].timeout = setTimeout(function () {
|
|
723
|
-
if (clients[connection_id]) {
|
|
724
|
-
clients[connection_id].timeout = null;
|
|
725
|
-
const msg = clients[connection_id].lastMsg || {};
|
|
726
|
-
msg.payload = Buffer.alloc(i+1);
|
|
727
|
-
buf.copy(msg.payload,0,0,i+1);
|
|
728
|
-
if (node.ret === "string") {
|
|
729
|
-
try { msg.payload = msg.payload.toString(); }
|
|
730
|
-
catch(e) { node.error("Failed to create string", msg); }
|
|
731
|
-
}
|
|
732
|
-
nodeSend(msg);
|
|
733
|
-
if (clients[connection_id].client) {
|
|
734
|
-
node.status({});
|
|
735
|
-
clients[connection_id].client.destroy();
|
|
736
|
-
delete clients[connection_id];
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
}, node.splitc);
|
|
740
|
-
i = 0;
|
|
741
|
-
buf[0] = data[j];
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
// count bytes into a buffer...
|
|
746
|
-
else if (node.out == "count") {
|
|
747
|
-
buf[i] = data[j];
|
|
748
|
-
i += 1;
|
|
749
|
-
if ( i >= node.splitc) {
|
|
717
|
+
// else if (node.splitc === 0) {
|
|
718
|
+
// clients[connection_id].msg.payload = data;
|
|
719
|
+
// node.send(clients[connection_id].msg);
|
|
720
|
+
// }
|
|
721
|
+
else {
|
|
722
|
+
for (var j = 0; j < data.length; j++ ) {
|
|
723
|
+
if (node.out === "time") {
|
|
750
724
|
if (clients[connection_id]) {
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
try { msg.payload = msg.payload.toString(); }
|
|
756
|
-
catch(e) { node.error("Failed to create string", msg); }
|
|
725
|
+
// do the timer thing
|
|
726
|
+
if (clients[connection_id].timeout) {
|
|
727
|
+
i += 1;
|
|
728
|
+
buf[i] = data[j];
|
|
757
729
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
730
|
+
else {
|
|
731
|
+
clients[connection_id].timeout = setTimeout(function () {
|
|
732
|
+
if (clients[connection_id]) {
|
|
733
|
+
clients[connection_id].timeout = null;
|
|
734
|
+
const msg = clients[connection_id].lastMsg || {};
|
|
735
|
+
msg.payload = Buffer.alloc(i+1);
|
|
736
|
+
buf.copy(msg.payload,0,0,i+1);
|
|
737
|
+
if (node.ret === "string") {
|
|
738
|
+
try { msg.payload = msg.payload.toString(); }
|
|
739
|
+
catch(e) { node.error("Failed to create string", msg); }
|
|
740
|
+
}
|
|
741
|
+
nodeSend(msg);
|
|
742
|
+
if (clients[connection_id].client) {
|
|
743
|
+
node.status({});
|
|
744
|
+
clients[connection_id].client.destroy();
|
|
745
|
+
delete clients[connection_id];
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}, node.splitc);
|
|
749
|
+
i = 0;
|
|
750
|
+
buf[0] = data[j];
|
|
763
751
|
}
|
|
764
|
-
i = 0;
|
|
765
752
|
}
|
|
766
753
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
754
|
+
// count bytes into a buffer...
|
|
755
|
+
else if (node.out == "count") {
|
|
756
|
+
buf[i] = data[j];
|
|
757
|
+
i += 1;
|
|
758
|
+
if ( i >= node.splitc) {
|
|
759
|
+
if (clients[connection_id]) {
|
|
760
|
+
const msg = clients[connection_id].lastMsg || {};
|
|
761
|
+
msg.payload = Buffer.alloc(i);
|
|
762
|
+
buf.copy(msg.payload,0,0,i);
|
|
763
|
+
if (node.ret === "string") {
|
|
764
|
+
try { msg.payload = msg.payload.toString(); }
|
|
765
|
+
catch(e) { node.error("Failed to create string", msg); }
|
|
766
|
+
}
|
|
767
|
+
nodeSend(msg);
|
|
768
|
+
if (clients[connection_id].client) {
|
|
769
|
+
node.status({});
|
|
770
|
+
clients[connection_id].client.destroy();
|
|
771
|
+
delete clients[connection_id];
|
|
772
|
+
}
|
|
773
|
+
i = 0;
|
|
780
774
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
// look for a char
|
|
778
|
+
else {
|
|
779
|
+
buf[i] = data[j];
|
|
780
|
+
i += 1;
|
|
781
|
+
if (data[j] == node.splitc) {
|
|
782
|
+
if (clients[connection_id]) {
|
|
783
|
+
const msg = clients[connection_id].lastMsg || {};
|
|
784
|
+
msg.payload = Buffer.alloc(i);
|
|
785
|
+
buf.copy(msg.payload,0,0,i);
|
|
786
|
+
if (node.ret === "string") {
|
|
787
|
+
try { msg.payload = msg.payload.toString(); }
|
|
788
|
+
catch(e) { node.error("Failed to create string", msg); }
|
|
789
|
+
}
|
|
790
|
+
nodeSend(msg);
|
|
791
|
+
if (clients[connection_id].client) {
|
|
792
|
+
node.status({});
|
|
793
|
+
clients[connection_id].client.destroy();
|
|
794
|
+
delete clients[connection_id];
|
|
795
|
+
}
|
|
796
|
+
i = 0;
|
|
786
797
|
}
|
|
787
|
-
i = 0;
|
|
788
798
|
}
|
|
789
799
|
}
|
|
790
800
|
}
|
|
791
801
|
}
|
|
802
|
+
} catch (err) {
|
|
803
|
+
node.error(RED._("tcpin.errors.error",{error:err.toString()}));
|
|
792
804
|
}
|
|
793
805
|
});
|
|
794
806
|
|
package/core/network/32-udp.js
CHANGED
|
@@ -98,15 +98,19 @@ module.exports = function(RED) {
|
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
server.on('message', function (message, remote) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
101
|
+
try {
|
|
102
|
+
var msg;
|
|
103
|
+
if (node.datatype =="base64") {
|
|
104
|
+
msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
|
|
105
|
+
} else if (node.datatype =="utf8") {
|
|
106
|
+
msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
|
|
107
|
+
} else {
|
|
108
|
+
msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
|
|
109
|
+
}
|
|
110
|
+
node.send(msg);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
node.error(RED._("udp.errors.error",{error:err.toString()}));
|
|
108
113
|
}
|
|
109
|
-
node.send(msg);
|
|
110
114
|
});
|
|
111
115
|
|
|
112
116
|
server.on('listening', function () {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<script type="text/html" data-template-name="file">
|
|
3
3
|
<div class="form-row node-input-filename">
|
|
4
4
|
<label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
|
|
5
|
-
<input id="node-input-filename" type="text">
|
|
5
|
+
<input id="node-input-filename" type="text" style="width: 100% !important;">
|
|
6
6
|
<input type="hidden" id="node-input-filenameType">
|
|
7
7
|
</div>
|
|
8
8
|
<div class="form-row">
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
<script type="text/html" data-template-name="file in">
|
|
39
39
|
<div class="form-row">
|
|
40
40
|
<label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
|
|
41
|
-
<input id="node-input-filename" type="text">
|
|
41
|
+
<input id="node-input-filename" type="text" style="width: 100% !important;">
|
|
42
42
|
<input type="hidden" id="node-input-filenameType">
|
|
43
43
|
</div>
|
|
44
44
|
<div class="form-row">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node-red/nodes",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.4",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"acorn": "8.15.0",
|
|
19
19
|
"acorn-walk": "8.3.4",
|
|
20
20
|
"ajv": "8.17.1",
|
|
21
|
-
"body-parser": "1.20.
|
|
21
|
+
"body-parser": "1.20.4",
|
|
22
22
|
"cheerio": "1.0.0-rc.10",
|
|
23
23
|
"content-type": "1.0.5",
|
|
24
24
|
"cookie-parser": "1.4.7",
|