Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions frontend/express/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ var versionInfo = require('./version.info'),
{ validateCreate } = require('../../api/utils/rights.js'),
tracker = require('../../api/parts/mgmt/tracker.js');

//Language codes as the dashboard uses them, e.g. "en", "pt-br", "zh_CN". Anything
//else is refused rather than sanitized, so a bad value never reaches storage.
var LANG_CODE_RE = /^[A-Za-z]{2,3}(?:[-_][A-Za-z0-9]{2,8})?$/;

console.log("Starting Countly", "version", versionInfo.version, "package", pack.version);

var COUNTLY_NAMED_TYPE = "Countly Lite v" + COUNTLY_VERSION;
Expand Down Expand Up @@ -1796,8 +1800,12 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_

var updatedUser = {};

if (req.body.lang) {
updatedUser.lang = req.body.lang;
//The stored lang reaches file paths in several places, for example
//api/utils/localization.js and the plugin localization lookups, so keep it to a
//language code here rather than relying on every reader to sanitize it. The
//dashboard only ever sends codes from its own localization list.
if (req.body.lang && LANG_CODE_RE.test(req.body.lang + "")) {
updatedUser.lang = req.body.lang + "";

countlyDb.collection('members').update({"_id": countlyDb.ObjectID(req.session.uid + "")}, {'$set': updatedUser}, {safe: true}, function(err, member) {
if (member && !err) {
Expand Down
6 changes: 4 additions & 2 deletions plugins/plugins/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ var plugin = {},
if (!resultObj.enabled) {
var local_path = fullpath + "/frontend/public/localization/" + resultObj.code + ".properties";
if (params.member.lang && params.member.lang !== "en") {
local_path = fullpath + "/frontend/public/localization/" + resultObj.code + "_" + params.member.lang + ".properties";
//sanitized the same way api/utils/localization.js does it
local_path = fullpath + "/frontend/public/localization/" + resultObj.code + "_" + common.sanitizeFilename(params.member.lang) + ".properties";
}
if (fs.existsSync(local_path)) {
var local_properties = fs.readFileSync(local_path);
Expand Down Expand Up @@ -379,7 +380,8 @@ var plugin = {},
var fullpath = path.resolve(__dirname, "../");
var local_path = fullpath + "/frontend/public/localization/plugins.properties";
if (params.member.lang && params.member.lang !== "en") {
path = fullpath + "/frontend/public/localization/plugins" + "_" + params.member.lang + ".properties";
//sanitized the same way api/utils/localization.js does it
path = fullpath + "/frontend/public/localization/plugins" + "_" + common.sanitizeFilename(params.member.lang) + ".properties";
if (fs.existsSync(path)) {
local_path = path;
}
Expand Down
Loading