From 3ef1e7ee00d7df90f7f7eda0f63edd06d5316e12 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Mon, 27 Feb 2017 13:09:55 +0100 Subject: [PATCH] Escape pasted text in compose area Sanitizing text would cause some non-HTML text to disappear (see #86). Instead, we escape HTML, so that it looks exactly like pasted. The applyFilters helper function has been removed, it's unclear what it does. Being explicit is better in this case. Pasting emoji tags still works, because tags are converted to their alt-text, which is in turn converted back to an tag by the emojify filter. --- src/directives/compose_area.ts | 29 ++++++++++++----------------- src/filters.ts | 3 +-- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/directives/compose_area.ts b/src/directives/compose_area.ts index 978df0881..67371ce7f 100644 --- a/src/directives/compose_area.ts +++ b/src/directives/compose_area.ts @@ -26,7 +26,6 @@ export default [ '$translate', '$mdDialog', '$filter', - '$sanitize', '$log', function(browserService: threema.BrowserService, stringService: threema.StringService, @@ -34,7 +33,6 @@ export default [ $translate: ng.translate.ITranslateService, $mdDialog: ng.material.IDialogService, $filter: ng.IFilterService, - $sanitize: ng.sanitize.ISanitizeService, $log: ng.ILogService) { return { restrict: 'EA', @@ -277,12 +275,6 @@ export default [ }); } - function applyFilters(text: string): string { - const emojify = $filter('emojify') as (a: string, b?: boolean) => string; - const parseNewLine = $filter('nlToBr') as (a: string, b?: boolean) => string; - return parseNewLine(emojify(text, true), true); - } - // Handle pasting function onPaste(ev: ClipboardEvent) { ev.preventDefault(); @@ -346,17 +338,20 @@ export default [ } else if (textIdx !== null) { const text = ev.clipboardData.getData('text/plain'); - // Apply filters (emojify, convert newline, etc) - const formatted = applyFilters(text); - - // Replace HTML formatting with ASCII counterparts + // Look up some filter functions const htmlToAsciiMarkup = $filter('htmlToAsciiMarkup') as (a: string) => string; + const escapeHtml = $filter('escapeHtml') as (a: string) => string; + const emojify = $filter('emojify') as (a: string, b?: boolean) => string; + const nlToBr = $filter('nlToBr') as (a: string, b?: boolean) => string; + + // Escape HTML markup + const escaped = escapeHtml(htmlToAsciiMarkup(text)); - // Sanitize - const sanitized = $sanitize(htmlToAsciiMarkup(formatted)); + // Apply filters (emojify, convert newline, etc) + const formatted = nlToBr(emojify(escaped, true), true); - // Insert HTML - document.execCommand('insertHTML', false, sanitized); + // Insert resulting HTML + document.execCommand('insertHTML', false, formatted); cleanupComposeContent(); updateView(); @@ -419,7 +414,7 @@ export default [ function onEmojiChosen(ev: MouseEvent): void { ev.stopPropagation(); const emoji = this.textContent; // Unicode character - const formatted = applyFilters(emoji); + const formatted = ($filter('emojify') as any)(emoji, true); // Firefox inserts a
after editing content editable fields. // Remove the last
to fix this. diff --git a/src/filters.ts b/src/filters.ts index 971cb5418..4364051a9 100644 --- a/src/filters.ts +++ b/src/filters.ts @@ -34,8 +34,7 @@ angular.module('3ema.filters', []) if (text === undefined || text === null) { text = ''; } - const escaped = text.replace(/[&<>"']/g, (m) => map[m]); - return escaped; + return text.replace(/[&<>"']/g, (m) => map[m]); }; })