diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index a7c91aaffb..deace2b263 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -229,22 +229,25 @@ ajaxify = window.ajaxify || {}; .forEach(function (el) { document.head.removeChild(el); }); - - // Add new meta tags - ajaxify.data._header.tags.meta - .filter(function (tagObj) { - var name = tagObj.name || tagObj.property; - return metaWhitelist.some(function (exp) { - return !!exp.test(name); + require(['translator'], function (translator) { + // Add new meta tags + ajaxify.data._header.tags.meta + .filter(function (tagObj) { + var name = tagObj.name || tagObj.property; + return metaWhitelist.some(function (exp) { + return !!exp.test(name); + }); + }).forEach(async function (tagObj) { + if (tagObj.content) { + tagObj.content = await translator.translate(tagObj.content); + } + var metaEl = document.createElement('meta'); + Object.keys(tagObj).forEach(function (prop) { + metaEl.setAttribute(prop, tagObj[prop]); + }); + document.head.appendChild(metaEl); }); - }) - .forEach(function (tagObj) { - var metaEl = document.createElement('meta'); - Object.keys(tagObj).forEach(function (prop) { - metaEl.setAttribute(prop, tagObj[prop]); - }); - document.head.appendChild(metaEl); - }); + }); // Delete the old link tags Array.prototype.slice diff --git a/public/src/client/chats.js b/public/src/client/chats.js index bdbe71b86a..3f38a118e9 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -416,7 +416,7 @@ define('forum/chats', [ roomid = ''; } - var url = 'user/' + ajaxify.data.userslug + '/chats/' + roomid; + var url = 'user/' + ajaxify.data.userslug + '/chats/' + roomid + window.location.search; if (self.fetch) { fetch(config.relative_path + '/api/' + url, { credentials: 'include' }) .then(function (response) { diff --git a/src/api/helpers.js b/src/api/helpers.js index 2e82cd2399..648bb8c35d 100644 --- a/src/api/helpers.js +++ b/src/api/helpers.js @@ -10,6 +10,13 @@ const socketHelpers = require('../socket.io/helpers'); const websockets = require('../socket.io'); const events = require('../events'); +exports.setDefaultPostData = function (reqOrSocket, data) { + data.uid = reqOrSocket.uid; + data.req = exports.buildReqObject(reqOrSocket, { ...data }); + data.timestamp = Date.now(); + data.fromQueue = false; +}; + // creates a slimmed down version of the request object exports.buildReqObject = (req, payload) => { req = req || {}; diff --git a/src/api/topics.js b/src/api/topics.js index de62942370..3b5d367eb5 100644 --- a/src/api/topics.js +++ b/src/api/topics.js @@ -33,10 +33,7 @@ topicsAPI.create = async function (caller, data) { const payload = { ...data }; payload.tags = payload.tags || []; - payload.uid = caller.uid; - payload.req = apiHelpers.buildReqObject(caller); - payload.timestamp = Date.now(); - payload.fromQueue = false; + apiHelpers.setDefaultPostData(caller, payload); // Blacklist & Post Queue await meta.blacklist.test(caller.ip); @@ -57,16 +54,8 @@ topicsAPI.create = async function (caller, data) { }; topicsAPI.reply = async function (caller, data) { - var payload = { - tid: data.tid, - uid: caller.uid, - req: apiHelpers.buildReqObject(caller), // For IP recording - content: data.content, - timestamp: Date.now(), - fromQueue: false, - }; - - if (data.toPid) { payload.toPid = data.toPid; } + const payload = { ...data }; + apiHelpers.setDefaultPostData(caller, payload); // Blacklist & Post Queue await meta.blacklist.test(caller.ip); diff --git a/src/controllers/errors.js b/src/controllers/errors.js index bb8951b038..671f3beccb 100644 --- a/src/controllers/errors.js +++ b/src/controllers/errors.js @@ -1,10 +1,11 @@ 'use strict'; -var nconf = require('nconf'); -var winston = require('winston'); -var validator = require('validator'); -var plugins = require('../plugins'); -var middleware = require('../middleware'); +const nconf = require('nconf'); +const winston = require('winston'); +const validator = require('validator'); +const plugins = require('../plugins'); +const middleware = require('../middleware'); +const helpers = require('../middleware/helpers'); exports.handleURIErrors = async function handleURIErrors(err, req, res, next) { // Handle cases where malformed URIs are passed in @@ -56,12 +57,17 @@ exports.handleErrors = function handleErrors(err, req, res, next) { // eslint-di res.status(status || 500); - var path = String(req.path || ''); + const path = String(req.path || ''); + const data = { + path: validator.escape(path), + error: validator.escape(String(err.message)), + bodyClass: helpers.buildBodyClass(req, res), + }; if (res.locals.isAPI) { - res.json({ path: validator.escape(path), error: err.message }); + res.json(data); } else { await middleware.buildHeaderAsync(req, res); - res.render('500', { path: validator.escape(path), error: validator.escape(String(err.message)) }); + res.render('500', data); } }; diff --git a/src/middleware/render.js b/src/middleware/render.js index 647c734276..1b4b2a5931 100644 --- a/src/middleware/render.js +++ b/src/middleware/render.js @@ -16,74 +16,82 @@ const relative_path = nconf.get('relative_path'); module.exports = function (middleware) { middleware.processRender = function processRender(req, res, next) { // res.render post-processing, modified from here: https://gist.github.com/mrlannigan/5051687 - const render = res.render; + const { render } = res; + res.render = async function renderOverride(template, options, fn) { const self = this; - const req = this.req; - - options = options || {}; - if (typeof options === 'function') { - fn = options; - options = {}; - } - - options.loggedIn = req.uid > 0; - options.relative_path = relative_path; - options.template = { name: template, [template]: true }; - options.url = (req.baseUrl + req.path.replace(/^\/api/, '')); - options.bodyClass = helpers.buildBodyClass(req, res, options); - - const buildResult = await plugins.hooks.fire(`filter:${template}.build`, { req: req, res: res, templateData: options }); - if (res.headersSent) { - return; - } - const templateToRender = buildResult.templateData.templateToRender || template; - - const renderResult = await plugins.hooks.fire('filter:middleware.render', { req: req, res: res, templateData: buildResult.templateData }); - if (res.headersSent) { - return; - } - options = renderResult.templateData; - options._header = { - tags: await meta.tags.parse(req, renderResult, res.locals.metaTags, res.locals.linkTags), - }; - options.widgets = await widgets.render(req.uid, { - template: template + '.tpl', - url: options.url, - templateData: options, - req: req, - res: res, - }); - res.locals.template = template; - options._locals = undefined; - - if (res.locals.isAPI) { - if (req.route && req.route.path === '/api/') { - options.title = '[[pages:home]]'; + const { req } = this; + async function renderMethod(template, options, fn) { + options = options || {}; + if (typeof options === 'function') { + fn = options; + options = {}; + } + + options.loggedIn = req.uid > 0; + options.relative_path = relative_path; + options.template = { name: template, [template]: true }; + options.url = (req.baseUrl + req.path.replace(/^\/api/, '')); + options.bodyClass = helpers.buildBodyClass(req, res, options); + + const buildResult = await plugins.hooks.fire(`filter:${template}.build`, { req: req, res: res, templateData: options }); + if (res.headersSent) { + return; + } + const templateToRender = buildResult.templateData.templateToRender || template; + + const renderResult = await plugins.hooks.fire('filter:middleware.render', { req: req, res: res, templateData: buildResult.templateData }); + if (res.headersSent) { + return; + } + options = renderResult.templateData; + options._header = { + tags: await meta.tags.parse(req, renderResult, res.locals.metaTags, res.locals.linkTags), + }; + options.widgets = await widgets.render(req.uid, { + template: `${template}.tpl`, + url: options.url, + templateData: options, + req: req, + res: res, + }); + res.locals.template = template; + options._locals = undefined; + + if (res.locals.isAPI) { + if (req.route && req.route.path === '/api/') { + options.title = '[[pages:home]]'; + } + req.app.set('json spaces', global.env === 'development' || req.query.pretty ? 4 : 0); + return res.json(options); + } + + const results = await utils.promiseParallel({ + header: renderHeaderFooter('renderHeader', req, res, options), + content: renderContent(render, templateToRender, req, res, options), + footer: renderHeaderFooter('renderFooter', req, res, options), + }); + + const str = `${results.header + + (res.locals.postHeader || '') + + results.content + }${ + res.locals.preFooter || '' + }${results.footer}`; + + if (typeof fn !== 'function') { + self.send(str); + } else { + fn(null, str); } - req.app.set('json spaces', global.env === 'development' || req.query.pretty ? 4 : 0); - return res.json(options); } - const results = await utils.promiseParallel({ - header: renderHeaderFooter('renderHeader', req, res, options), - content: renderContent(render, templateToRender, req, res, options), - footer: renderHeaderFooter('renderFooter', req, res, options), - }); - - const str = results.header + - (res.locals.postHeader || '') + - results.content + - '' + - (res.locals.preFooter || '') + - results.footer; - - if (typeof fn !== 'function') { - self.send(str); - } else { - fn(null, str); + try { + await renderMethod(template, options, fn); + } catch (err) { + next(err); } }; diff --git a/src/socket.io/helpers.js b/src/socket.io/helpers.js index 08545b9093..fc6030c242 100644 --- a/src/socket.io/helpers.js +++ b/src/socket.io/helpers.js @@ -18,10 +18,8 @@ const apiHelpers = require('../api/helpers'); const SocketHelpers = module.exports; SocketHelpers.setDefaultPostData = function (data, socket) { - data.uid = socket.uid; - data.req = apiHelpers.buildReqObject(socket); - data.timestamp = Date.now(); - data.fromQueue = false; + websockets.warnDeprecated(socket, 'apiHelpers.setDefaultPostData'); + apiHelpers.setDefaultPostData(socket, data); }; SocketHelpers.notifyNew = async function (uid, type, result) { diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index afe02ce91f..867b02f654 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -10,6 +10,7 @@ const user = require('../user'); const socketHelpers = require('./helpers'); const utils = require('../utils'); const api = require('../api'); +const apiHelpers = require('../api/helpers'); const sockets = require('.'); const SocketPosts = module.exports; @@ -28,7 +29,7 @@ SocketPosts.reply = async function (socket, data) { throw new Error('[[error:invalid-data]]'); } - socketHelpers.setDefaultPostData(data, socket); + apiHelpers.setDefaultPostData(socket, data); await meta.blacklist.test(data.req.ip); const shouldQueue = await posts.shouldQueue(socket.uid, data); if (shouldQueue) {