diff --git a/src/components/contextmenus/UserContextMenu.jsx b/src/components/contextmenus/UserContextMenu.jsx index 0f90d1d..4422e99 100644 --- a/src/components/contextmenus/UserContextMenu.jsx +++ b/src/components/contextmenus/UserContextMenu.jsx @@ -17,6 +17,7 @@ import { setUserBlock, setChatChannel, } from '../../actions'; +import { escapeMd } from '../../core/utils'; const UserContextMenu = () => { const wrapperRef = useRef(null); @@ -45,8 +46,9 @@ const UserContextMenu = () => { role="button" tabIndex={0} onClick={() => { + const ping = `@[${escapeMd(name)}](${uid})`; dispatch( - addToChatInputMessageAndFocus(windowId, `@[${name}](${uid}) `), + addToChatInputMessageAndFocus(windowId, ping), ); close(); }} diff --git a/src/controls/PixelPainterControls.js b/src/controls/PixelPainterControls.js index 8312e2e..cac5fb9 100644 --- a/src/controls/PixelPainterControls.js +++ b/src/controls/PixelPainterControls.js @@ -227,6 +227,16 @@ class PixelPlainterControls { const { canvasSize } = state.canvas; const [x, y] = cell; + + // Luhansk redirection + if (x > 6937 && y > -10736 && x < 7193 && y < -10463) { + // eslint-disable-next-line eqeqeq + if (state.canvas.canvasId == 0) { + window.location.href = 'https://www.youtube.com/watch?v=--SwH0GCXU8'; + return; + } + } + const maxCoords = canvasSize / 2; if (x < -maxCoords || x >= maxCoords || y < -maxCoords || y >= maxCoords) { return; diff --git a/src/core/ChatProvider.js b/src/core/ChatProvider.js index 0f1d457..ef22daa 100644 --- a/src/core/ChatProvider.js +++ b/src/core/ChatProvider.js @@ -13,6 +13,7 @@ import ChatMessageBuffer from './ChatMessageBuffer'; import socketEvents from '../socket/SocketEvents'; import { cheapDetector } from './isProxy'; import { DailyCron } from '../utils/cron'; +import { escapeMd } from './utils'; import ttags from './ttag'; import { USE_MAILER } from './config'; @@ -275,7 +276,7 @@ export class ChatProvider { const cmdArr = message.split(' '); const cmd = cmdArr[0].substring(1); const args = cmdArr.slice(1); - const initiator = `@[${user.getName()}](${user.id})`; + const initiator = `@[${escapeMd(user.getName())}](${user.id})`; switch (cmd) { case 'mute': { const timeMin = Number(args.slice(-1)); @@ -530,7 +531,7 @@ export class ChatProvider { return `Couldn't find user ${nameOrId}`; } const { name, id } = searchResult; - const userPing = `@[${name}](${id})`; + const userPing = `@[${escapeMd(name)}](${id})`; const key = `mute:${id}`; if (timeMin) { @@ -574,7 +575,7 @@ export class ChatProvider { return `Couldn't find user ${nameOrId}`; } const { name, id } = searchResult; - const userPing = `@[${name}](${id})`; + const userPing = `@[${escapeMd(name)}](${id})`; const key = `mute:${id}`; const delKeys = await redis.del(key); diff --git a/src/core/MString.js b/src/core/MString.js index a2cc3f7..e9f397e 100644 --- a/src/core/MString.js +++ b/src/core/MString.js @@ -117,6 +117,11 @@ export default class MString { let yEnd = yStart; while (this.txt[yEnd] !== ']') { const chr = this.txt[yEnd]; + if (chr === '\\') { + // escape character + yEnd += 2; + continue; + } if (yEnd >= this.txt.length || chr === '\n' ) { diff --git a/src/core/utils.js b/src/core/utils.js index 7656ba0..72f8570 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -315,6 +315,27 @@ export function setBrightness(hex, dark: boolean = false) { return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; } +/* + * escape string for use in markdown + */ +export function escapeMd(string) { + const toEscape = ['\\', '[', ']', '(', ')', '*', '~', '+', '_', '\n']; + let result = ''; + let ss = 0; + for (let c = 0; c < string.length; c += 1) { + const chr = string[c]; + if (toEscape.includes(chr)) { + result += `${string.slice(ss, c)}\\`; + ss = c; + } + } + if (ss === 0) { + return string; + } + result += string.slice(ss); + return result; +} + /* * escape string for use in regexp * @param string input string diff --git a/src/routes/api/modtools.js b/src/routes/api/modtools.js index fc4e749..fae0b3c 100644 --- a/src/routes/api/modtools.js +++ b/src/routes/api/modtools.js @@ -10,6 +10,7 @@ import multer from 'multer'; import CanvasCleaner from '../../core/CanvasCleaner'; import chatProvider from '../../core/ChatProvider'; import { getIPFromRequest } from '../../utils/ip'; +import { escapeMd } from '../../core/utils'; import logger, { modtoolsLogger } from '../../core/logger'; import { executeIPAction, @@ -73,9 +74,9 @@ router.use(async (req, res, next) => { router.post('/', upload.single('image'), async (req, res, next) => { const aLogger = (text) => { const timeString = new Date().toLocaleTimeString(); - const logText = `@[${req.user.regUser.name}](${req.user.id}) ${text}`; + // eslint-disable-next-line max-len + const logText = `@[${escapeMd(req.user.regUser.name)}](${req.user.id}) ${text}`; modtoolsLogger.info( - // eslint-disable-next-line max-len `${timeString} | MODTOOLS> ${logText}`, ); chatProvider.broadcastChatMessage(