diff --git a/app/main/request.ts b/app/main/request.ts index 7931d715..f6254855 100644 --- a/app/main/request.ts +++ b/app/main/request.ts @@ -4,7 +4,6 @@ import path from 'path'; import stream from 'stream'; import util from 'util'; -import escape from 'escape-html'; import getStream from 'get-stream'; import {ServerConf} from '../renderer/js/utils/domain-util'; @@ -73,7 +72,7 @@ export const _getServerSettings = async (domain: string, session: Electron.sessi // Following check handles both the cases icon: realm_icon.startsWith('/') ? realm_uri + realm_icon : realm_icon, url: realm_uri, - alias: escape(realm_name) + alias: realm_name }; }; diff --git a/app/renderer/about.html b/app/renderer/about.html index eae9d709..b0324ef6 100644 --- a/app/renderer/about.html +++ b/app/renderer/about.html @@ -26,7 +26,7 @@ const { app } = require('electron').remote; const version_tag = document.querySelector('#version'); - version_tag.innerHTML = 'v' + app.getVersion(); + version_tag.textContent = 'v' + app.getVersion(); diff --git a/app/renderer/js/components/base.ts b/app/renderer/js/components/base.ts index abe796e0..bdb7475c 100644 --- a/app/renderer/js/components/base.ts +++ b/app/renderer/js/components/base.ts @@ -1,7 +1,7 @@ export default class BaseComponent { - generateNodeFromTemplate(template: string): Element | null { + generateNodeFromHTML(html: string): Element | null { const wrapper = document.createElement('div'); - wrapper.innerHTML = template; + wrapper.innerHTML = html; return wrapper.firstElementChild; } } diff --git a/app/renderer/js/components/functional-tab.ts b/app/renderer/js/components/functional-tab.ts index 5b507ec5..1e4465d1 100644 --- a/app/renderer/js/components/functional-tab.ts +++ b/app/renderer/js/components/functional-tab.ts @@ -1,3 +1,5 @@ +import {htmlEscape} from 'escape-goat'; + import Tab, {TabProps} from './tab'; export default class FunctionalTab extends Tab { @@ -8,19 +10,21 @@ export default class FunctionalTab extends Tab { this.init(); } - template(): string { - return `
-
- close -
-
- ${this.props.materialIcon} -
-
`; + templateHTML(): string { + return htmlEscape` +
+
+ close +
+
+ ${this.props.materialIcon} +
+
+ `; } init(): void { - this.$el = this.generateNodeFromTemplate(this.template()); + this.$el = this.generateNodeFromHTML(this.templateHTML()); if (this.props.name !== 'Settings') { this.props.$root.append(this.$el); this.$closeButton = this.$el.querySelectorAll('.server-tab-badge')[0]; diff --git a/app/renderer/js/components/server-tab.ts b/app/renderer/js/components/server-tab.ts index 786f5e81..76f3a744 100644 --- a/app/renderer/js/components/server-tab.ts +++ b/app/renderer/js/components/server-tab.ts @@ -1,5 +1,7 @@ import {ipcRenderer} from 'electron'; +import {htmlEscape} from 'escape-goat'; + import * as SystemUtil from '../utils/system-util'; import Tab, {TabProps} from './tab'; @@ -12,19 +14,21 @@ export default class ServerTab extends Tab { this.init(); } - template(): string { - return `
- -
-
- -
-
${this.generateShortcutText()}
-
`; + templateHTML(): string { + return htmlEscape` +
+ +
+
+ +
+
${this.generateShortcutText()}
+
+ `; } init(): void { - this.$el = this.generateNodeFromTemplate(this.template()); + this.$el = this.generateNodeFromHTML(this.templateHTML()); this.props.$root.append(this.$el); this.registerListeners(); this.$badge = this.$el.querySelectorAll('.server-tab-badge')[0]; @@ -33,7 +37,7 @@ export default class ServerTab extends Tab { updateBadge(count: number): void { if (count > 0) { const formattedCount = count > 999 ? '1K+' : count.toString(); - this.$badge.innerHTML = formattedCount; + this.$badge.textContent = formattedCount; this.$badge.classList.add('active'); } else { this.$badge.classList.remove('active'); diff --git a/app/renderer/js/components/webview.ts b/app/renderer/js/components/webview.ts index ea0c09cd..cefb8f7b 100644 --- a/app/renderer/js/components/webview.ts +++ b/app/renderer/js/components/webview.ts @@ -2,6 +2,8 @@ import {ipcRenderer, remote} from 'electron'; import fs from 'fs'; import path from 'path'; +import {htmlEscape} from 'escape-goat'; + import * as ConfigUtil from '../utils/config-util'; import * as SystemUtil from '../utils/system-util'; @@ -50,25 +52,27 @@ export default class WebView extends BaseComponent { this.$webviewsContainer = document.querySelector('#webviews-container').classList; } - template(): string { - return ` - `; + templateHTML(): string { + return htmlEscape` + + + `; } init(): void { - this.$el = this.generateNodeFromTemplate(this.template()) as Electron.WebviewTag; + this.$el = this.generateNodeFromHTML(this.templateHTML()) as Electron.WebviewTag; this.domReady = new Promise(resolve => { this.$el.addEventListener('dom-ready', () => resolve(), true); }); diff --git a/app/renderer/js/main.ts b/app/renderer/js/main.ts index 375cf32e..a2642596 100644 --- a/app/renderer/js/main.ts +++ b/app/renderer/js/main.ts @@ -2,7 +2,6 @@ import {ipcRenderer, remote, clipboard} from 'electron'; import path from 'path'; import isDev from 'electron-is-dev'; -import escape from 'escape-html'; import * as Messages from '../../resources/messages'; @@ -10,7 +9,6 @@ import FunctionalTab from './components/functional-tab'; import ServerTab from './components/server-tab'; import WebView from './components/webview'; import {feedbackHolder} from './feedback'; -import * as CommonUtil from './utils/common-util'; import * as ConfigUtil from './utils/config-util'; import * as DNDUtil from './utils/dnd-util'; import type {DNDSettings} from './utils/dnd-util'; @@ -125,7 +123,7 @@ class ServerManagerView { this.$fullscreenPopup = document.querySelector('#fullscreen-popup'); this.$fullscreenEscapeKey = process.platform === 'darwin' ? '^⌘F' : 'F11'; - this.$fullscreenPopup.innerHTML = `Press ${this.$fullscreenEscapeKey} to exit full screen`; + this.$fullscreenPopup.textContent = `Press ${this.$fullscreenEscapeKey} to exit full screen`; this.loading = new Set(); this.activeTabIndex = -1; @@ -358,7 +356,7 @@ class ServerManagerView { this.tabs.push(new ServerTab({ role: 'server', icon: server.icon, - name: CommonUtil.decodeString(server.alias), + name: server.alias, $root: this.$tabsContainer, onClick: this.activateLastTab.bind(this, index), index, @@ -371,7 +369,7 @@ class ServerManagerView { tabIndex, url: server.url, role: 'server', - name: CommonUtil.decodeString(server.alias), + name: server.alias, hasPermission: (origin: string, permission: string) => origin === server.url && permission === 'notifications', isActive: () => index === this.activeTabIndex, @@ -499,7 +497,7 @@ class ServerManagerView { } onHover(index: number): void { - // `this.$serverIconTooltip[index].innerHTML` already has realm name, so we are just + // `this.$serverIconTooltip[index].textContent` already has realm name, so we are just // removing the style. this.$serverIconTooltip[index].removeAttribute('style'); // To handle position of servers' tooltip due to scrolling of list of organizations @@ -684,8 +682,8 @@ class ServerManagerView { this.functionalTabs.clear(); // Clear DOM elements - this.$tabsContainer.innerHTML = ''; - this.$webviewsContainer.innerHTML = ''; + this.$tabsContainer.textContent = ''; + this.$webviewsContainer.textContent = ''; } async reloadView(): Promise { @@ -929,11 +927,11 @@ class ServerManagerView { if (domain.url.includes(serverURL)) { const serverTooltipSelector = '.tab .server-tooltip'; const serverTooltips = document.querySelectorAll(serverTooltipSelector); - serverTooltips[index].innerHTML = escape(realmName); - this.tabs[index].props.name = escape(realmName); + serverTooltips[index].textContent = realmName; + this.tabs[index].props.name = realmName; this.tabs[index].webview.props.name = realmName; - domain.alias = escape(realmName); + domain.alias = realmName; DomainUtil.updateDomain(index, domain); // Update the realm name also on the Window menu ipcRenderer.send('update-menu', { diff --git a/app/renderer/js/pages/preference/add-certificate.ts b/app/renderer/js/pages/preference/add-certificate.ts index 12c00e39..80a1bc10 100644 --- a/app/renderer/js/pages/preference/add-certificate.ts +++ b/app/renderer/js/pages/preference/add-certificate.ts @@ -1,6 +1,8 @@ import {remote, OpenDialogOptions} from 'electron'; import path from 'path'; +import {htmlEscape} from 'escape-goat'; + import BaseComponent from '../../components/base'; import * as CertificateUtil from '../../utils/certificate-util'; import * as DomainUtil from '../../utils/domain-util'; @@ -24,8 +26,8 @@ export default class AddCertificate extends BaseComponent { this._certFile = ''; } - template(): string { - return ` + templateHTML(): string { + return htmlEscape`
${t.__('Organization URL')}
@@ -40,7 +42,7 @@ export default class AddCertificate extends BaseComponent { } init(): void { - this.$addCertificate = this.generateNodeFromTemplate(this.template()); + this.$addCertificate = this.generateNodeFromHTML(this.templateHTML()); this.props.$root.append(this.$addCertificate); this.addCertificateButton = this.$addCertificate.querySelector('#add-certificate-button'); this.serverUrl = this.$addCertificate.querySelectorAll('input.setting-input-value')[0] as HTMLInputElement; diff --git a/app/renderer/js/pages/preference/base-section.ts b/app/renderer/js/pages/preference/base-section.ts index 8276b82d..1d76ed5d 100644 --- a/app/renderer/js/pages/preference/base-section.ts +++ b/app/renderer/js/pages/preference/base-section.ts @@ -1,6 +1,6 @@ import {ipcRenderer} from 'electron'; -import escape from 'escape-html'; +import {htmlEscape} from 'escape-goat'; import BaseComponent from '../../components/base'; @@ -15,9 +15,9 @@ export default class BaseSection extends BaseComponent { generateSettingOption(props: BaseSectionProps): void { const {$element, disabled, value, clickHandler} = props; - $element.innerHTML = ''; + $element.textContent = ''; - const $optionControl = this.generateNodeFromTemplate(this.generateOptionTemplate(value, disabled)); + const $optionControl = this.generateNodeFromHTML(this.generateOptionHTML(value, disabled)); $element.append($optionControl); if (!disabled) { @@ -25,39 +25,39 @@ export default class BaseSection extends BaseComponent { } } - generateOptionTemplate(settingOption: boolean, disabled?: boolean): string { - const label = disabled ? '