diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/locales.js b/packages/node_modules/@node-red/editor-api/lib/editor/locales.js index a7f300cd3..ebe3e3281 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/locales.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/locales.js @@ -39,9 +39,12 @@ module.exports = { }, get: function(req,res) { var namespace = req.params[0]; - var lngs = req.query.lng; namespace = namespace.replace(/\.json$/,""); var lang = req.query.lng || i18n.defaultLang; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []); + if (/[^a-z\-]/i.test(lang)) { + res.json({}); + return; + } var prevLang = i18n.i.language; // Trigger a load from disk of the language if it is not the default i18n.i.changeLanguage(lang, function(){ diff --git a/packages/node_modules/@node-red/runtime/lib/api/nodes.js b/packages/node_modules/@node-red/runtime/lib/api/nodes.js index a06cbed96..aa5eca100 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/nodes.js +++ b/packages/node_modules/@node-red/runtime/lib/api/nodes.js @@ -99,6 +99,10 @@ var api = module.exports = { return new Promise(function(resolve,reject) { var id = opts.id; var lang = opts.lang; + if (/[^a-z\-]/i.test(opts.lang)) { + reject(new Error("Invalid language: "+opts.lang)); + return + } var result = runtime.nodes.getNodeConfig(id,lang); if (result) { runtime.log.audit({event: "nodes.config.get",id:id}, opts.req); @@ -124,6 +128,10 @@ var api = module.exports = { getNodeConfigs: function(opts) { return new Promise(function(resolve,reject) { runtime.log.audit({event: "nodes.configs.get"}, opts.req); + if (/[^a-z\-]/i.test(opts.lang)) { + reject(new Error("Invalid language: "+opts.lang)); + return + } return resolve(runtime.nodes.getNodeConfigs(opts.lang)); }); }, @@ -398,6 +406,10 @@ var api = module.exports = { var namespace = opts.module; var lang = opts.lang; var prevLang = runtime.i18n.i.language; + if (/[^a-z\-]/i.test(lang)) { + reject(new Error("Invalid language: "+lang)); + return + } // Trigger a load from disk of the language if it is not the default runtime.i18n.i.changeLanguage(lang, function(){ var nodeList = runtime.nodes.getNodeList(); @@ -427,6 +439,10 @@ var api = module.exports = { return new Promise(function(resolve,reject) { var namespace = opts.module; var lang = opts.lang; + if (/[^a-z\-]/i.test(lang)) { + reject(new Error("Invalid language: "+lang)); + return + } var prevLang = runtime.i18n.i.language; // Trigger a load from disk of the language if it is not the default runtime.i18n.i.changeLanguage(lang, function(){ diff --git a/packages/node_modules/@node-red/util/lib/i18n.js b/packages/node_modules/@node-red/util/lib/i18n.js index d95f4bec6..5d5a18887 100644 --- a/packages/node_modules/@node-red/util/lib/i18n.js +++ b/packages/node_modules/@node-red/util/lib/i18n.js @@ -24,7 +24,7 @@ var i18n = require("i18next"); var when = require("when"); var path = require("path"); -var fs = require("fs"); +var fs = require("fs-extra"); var defaultLang = "en-US"; @@ -82,36 +82,28 @@ function mergeCatalog(fallback,catalog) { } -function readFile(lng, ns) { - return new Promise((resolve, reject) => { - if (resourceCache[ns] && resourceCache[ns][lng]) { - resolve(resourceCache[ns][lng]); - } else if (resourceMap[ns]) { - var file = path.join(resourceMap[ns].basedir, lng, resourceMap[ns].file); - fs.readFile(file, "utf8", function (err, content) { - if (err) { - reject(err); - } else { - try { - resourceCache[ns] = resourceCache[ns] || {}; - resourceCache[ns][lng] = JSON.parse(content.replace(/^\uFEFF/, '')); - var baseLng = lng.split('-')[0]; - if (baseLng !== lng && resourceCache[ns][baseLng]) { - mergeCatalog(resourceCache[ns][baseLng], resourceCache[ns][lng]); - } - if (lng !== defaultLang) { - mergeCatalog(resourceCache[ns][defaultLang], resourceCache[ns][lng]); - } - resolve(resourceCache[ns][lng]); - } catch (e) { - reject(e); - } - } - }); - } else { - reject(new Error("Unrecognised namespace")); +async function readFile(lng, ns) { + if (/[^a-z\-]/i.test(lng)) { + throw new Error("Invalid language: "+lng) + } + if (resourceCache[ns] && resourceCache[ns][lng]) { + return resourceCache[ns][lng]; + } else if (resourceMap[ns]) { + const file = path.join(resourceMap[ns].basedir, lng, resourceMap[ns].file); + const content = await fs.readFile(file, "utf8"); + resourceCache[ns] = resourceCache[ns] || {}; + resourceCache[ns][lng] = JSON.parse(content.replace(/^\uFEFF/, '')); + var baseLng = lng.split('-')[0]; + if (baseLng !== lng && resourceCache[ns][baseLng]) { + mergeCatalog(resourceCache[ns][baseLng], resourceCache[ns][lng]); } - }); + if (lng !== defaultLang) { + mergeCatalog(resourceCache[ns][defaultLang], resourceCache[ns][lng]); + } + return resourceCache[ns][lng]; + } else { + throw new Error("Unrecognised namespace"); + } } var MessageFileLoader = { @@ -182,6 +174,10 @@ function init() { function getCatalog(namespace,lang) { var result = null; lang = lang || defaultLang; + if (/[^a-z\-]/i.test(lang)) { + throw new Error("Invalid language: "+lng) + } + if (resourceCache.hasOwnProperty(namespace)) { result = resourceCache[namespace][lang]; if (!result) {