From 428ea2f34ebc1f76780e049c969f22ad9355bdd6 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 1 Feb 2020 08:09:30 +0100 Subject: [PATCH 1/4] adding test that expects parameters of php translation to get HTML entities to get encoded --- tst/I18nTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tst/I18nTest.php b/tst/I18nTest.php index f366720a..658ceb18 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -155,6 +155,13 @@ class I18nTest extends PHPUnit_Framework_TestCase $this->assertEquals('some string + 1', I18n::_('some %s + %d', 'string', 1), 'browser language en'); } + public function testHtmlEntityEncoding() + { + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'foobar'; + I18n::loadTranslations(); + $this->assertEquals('some ' . htmlentities('&<>"\'/`=', ENT_QUOTES | ENT_XHTML | ENT_DISALLOWED, 'UTF-8') . ' + 1', I18n::_('some %s + %d', '&<>"\'/`=', 1), 'browser language en'); + } + public function testMessageIdsExistInAllLanguages() { $messageIds = array(); From cc0920fc09b43803bc5323724e555f3b400fc32d Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 1 Feb 2020 08:46:59 +0100 Subject: [PATCH 2/4] add HTML entity encoding to PHP translation logic, remove exception to allow
tags in DOMpurify by eliminating the single case that made use of it --- i18n/bg.json | 4 ++-- i18n/cs.json | 4 ++-- i18n/de.json | 4 ++-- i18n/es.json | 4 ++-- i18n/fr.json | 4 ++-- i18n/hu.json | 2 +- i18n/it.json | 4 ++-- i18n/nl.json | 4 ++-- i18n/no.json | 4 ++-- i18n/oc.json | 4 ++-- i18n/pl.json | 2 +- i18n/pt.json | 4 ++-- i18n/ru.json | 4 ++-- i18n/sl.json | 4 ++-- i18n/uk.json | 4 ++-- i18n/zh.json | 4 ++-- js/privatebin.js | 2 +- js/test/I18n.js | 6 +++--- lib/I18n.php | 9 +++++++++ tpl/bootstrap.php | 4 ++-- tpl/page.php | 4 ++-- 21 files changed, 47 insertions(+), 38 deletions(-) diff --git a/i18n/bg.json b/i18n/bg.json index 632bedb3..c87c1afd 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -31,8 +31,8 @@ "Невалиден код за изтриване. Информацията Ви не беше изтрита.", "Paste was properly deleted.": "Информацията Ви е изтрита.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "Услугата %s се нуждае от JavaScript, за да работи.
Съжаляваме за неудобството.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "Услугата %s се нуждае от JavaScript, за да работи. Съжаляваме за неудобството.", "%s requires a modern browser to work.": "%s се нуждае от съвременен браузър за да работи.", "New": diff --git a/i18n/cs.json b/i18n/cs.json index 02a55513..a199bc56 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -31,8 +31,8 @@ "Wrong deletion token. Paste was not deleted.", "Paste was properly deleted.": "Paste was properly deleted.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "JavaScript is required for %s to work.
Sorry for the inconvenience.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "JavaScript is required for %s to work. Sorry for the inconvenience.", "%s requires a modern browser to work.": "%%s requires a modern browser to work.", "New": diff --git a/i18n/de.json b/i18n/de.json index 2c883dfe..31eec787 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -31,8 +31,8 @@ "Falscher Lösch-Code. Text wurde nicht gelöscht.", "Paste was properly deleted.": "Text wurde erfolgreich gelöscht.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "JavaScript ist eine Voraussetzung, um %s zu nutzen.
Bitte entschuldige die Unannehmlichkeiten.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "JavaScript ist eine Voraussetzung, um %s zu nutzen. Bitte entschuldige die Unannehmlichkeiten.", "%s requires a modern browser to work.": "%s setzt einen modernen Browser voraus, um funktionieren zu können.", "New": diff --git a/i18n/es.json b/i18n/es.json index 93509874..df1e054f 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -31,8 +31,8 @@ "Token de eliminación erróneo. El \"paste\" no fue eliminado.", "Paste was properly deleted.": "El \"paste\" se ha eliminado correctamente.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "JavaScript es necesario para que %s funcione.
Sentimos los inconvenientes ocasionados.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "JavaScript es necesario para que %s funcione. Sentimos los inconvenientes ocasionados.", "%s requires a modern browser to work.": "%s requiere un navegador moderno para funcionar.", "New": diff --git a/i18n/fr.json b/i18n/fr.json index 9af77fb1..5cb87976 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -31,8 +31,8 @@ "Jeton de suppression incorrect. Le paste n'a pas été supprimé.", "Paste was properly deleted.": "Le paste a été correctement supprimé.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "JavaScript est requis pour faire fonctionner %s.
Désolé pour cet inconvénient.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "JavaScript est requis pour faire fonctionner %s. Désolé pour cet inconvénient.", "%s requires a modern browser to work.": "%s nécessite un navigateur moderne pour fonctionner.", "New": diff --git a/i18n/hu.json b/i18n/hu.json index 57076d9c..f55efdcb 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -31,7 +31,7 @@ "Hibás törlési azonosító. A bejegyzés nem lett törölve.", "Paste was properly deleted.": "A bejegyzés sikeresen törölve.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": + "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript szükséges a %s működéséhez. Elnézést a fennakadásért.", "%s requires a modern browser to work.": "A %s működéséhez a jelenleginél újabb böngészőre van szükség.", diff --git a/i18n/it.json b/i18n/it.json index 26b11c6c..2a2bff50 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -31,8 +31,8 @@ "Codice cancellazione errato. Il messaggio NON è stato cancellato.", "Paste was properly deleted.": "Il messaggio è stato correttamente cancellato.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "%s funziona solo con JavaScript attivo.
Ci dispiace per l'inconveniente.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "%s funziona solo con JavaScript attivo. Ci dispiace per l'inconveniente.", "%s requires a modern browser to work.": "%s richiede un browser moderno e aggiornato per funzionare.", "New": diff --git a/i18n/nl.json b/i18n/nl.json index d6780c39..d3bdb720 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -31,8 +31,8 @@ "Foutieve verwijdercode. Geplakte tekst is niet verwijderd.", "Paste was properly deleted.": "Geplakte tekst is correct verwijderd.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "JavaScript vereist om %s te laten werken.
Sorry voor het ongemak.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "JavaScript vereist om %s te laten werken. Sorry voor het ongemak.", "%s requires a modern browser to work.": "%s vereist een moderne browser om te kunnen werken ", "New": diff --git a/i18n/no.json b/i18n/no.json index ccb5f2c7..f43ef6e4 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -31,8 +31,8 @@ "Feil slettingsnøkkel. Innlegg ble ikke fjernet.", "Paste was properly deleted.": "Innlegget er slettet.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "Javascript kreves for at %s skal fungere
Beklager.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "Javascript kreves for at %s skal fungere. Beklager.", "%s requires a modern browser to work.": "%s krever en moderne nettleser for å fungere.", "New": diff --git a/i18n/oc.json b/i18n/oc.json index 7f9ad2a0..c078faed 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -31,8 +31,8 @@ "Geton de supression incorrècte. Lo tèxte es pas estat suprimit.", "Paste was properly deleted.": "Lo tèxte es estat corrèctament suprimit.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "JavaScript es requesit per far foncionar %s.
O planhèm per l’inconvenient.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "JavaScript es requesit per far foncionar %s. O planhèm per l’inconvenient.", "%s requires a modern browser to work.": "%s necessita un navigator modèrn per foncionar.", "New": diff --git a/i18n/pl.json b/i18n/pl.json index ff27c473..3517b076 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -31,7 +31,7 @@ "Nieprawidłowy token usuwania. Wklejka nie została usunięta.", "Paste was properly deleted.": "Wklejka usunięta poprawnie.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": + "JavaScript is required for %s to work. Sorry for the inconvenience.": "Do działania %sa jest wymagany JavaScript. Przepraszamy za tę niedogodność.", "%s requires a modern browser to work.": "%s wymaga do działania nowoczesnej przeglądarki.", diff --git a/i18n/pt.json b/i18n/pt.json index 6ccd9d39..6dc1f405 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -31,8 +31,8 @@ "Token de remoção inválido. A cópia não foi excluída.", "Paste was properly deleted.": "A cópia foi devidamente excluída.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "JavaScript é necessário para que %s funcione.
Pedimos desculpas pela inconveniência.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "JavaScript é necessário para que %s funcione. Pedimos desculpas pela inconveniência.", "%s requires a modern browser to work.": "%s requer um navegador moderno para funcionar.", "New": diff --git a/i18n/ru.json b/i18n/ru.json index c65d5e9d..8973f24c 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -31,8 +31,8 @@ "Неверный ключ удаления записи. Запись не удалена.", "Paste was properly deleted.": "Запись была успешно удалена.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "Для работы %s требуется включенный JavaScript.
Приносим извинения за неудобства.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "Для работы %s требуется включенный JavaScript. Приносим извинения за неудобства.", "%s requires a modern browser to work.": "Для работы %s требуется более современный браузер.", "New": diff --git a/i18n/sl.json b/i18n/sl.json index 804e5fb8..15e57289 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -31,8 +31,8 @@ "Napačen token za izbris. Prilepek ni bil izbrisan..", "Paste was properly deleted.": "Prilepek je uspešno izbrisan.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "Da %s deluje, moraš vklopiti JavaScript.
Oprosti za povročene nevšečnosti.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "Da %s deluje, moraš vklopiti JavaScript. Oprosti za povročene nevšečnosti.", "%s requires a modern browser to work.": "%s za svoje delovanje potrebuje moderen brskalnik.", "New": diff --git a/i18n/uk.json b/i18n/uk.json index fd53982d..635495d3 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -31,8 +31,8 @@ "Неправильний ключ вилучення допису. Допис не вилучено.", "Paste was properly deleted.": "Допис був вилучений повністю.", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "Для роботи %s потрібен увімкнутий JavaScript.
Вибачте.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "Для роботи %s потрібен увімкнутий JavaScript. Вибачте.", "%s requires a modern browser to work.": "Для роботи %s потрібен більш сучасний переглядач.", "New": diff --git a/i18n/zh.json b/i18n/zh.json index d5e55fb0..749d611a 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -31,8 +31,8 @@ "错误的删除token,粘贴内容没有被删除。", "Paste was properly deleted.": "粘贴内容已被正确删除。", - "JavaScript is required for %s to work.
Sorry for the inconvenience.": - "%s需要JavaScript来进行加解密。
给你带来的不便敬请谅解。", + "JavaScript is required for %s to work. Sorry for the inconvenience.": + "%s需要JavaScript来进行加解密。 给你带来的不便敬请谅解。", "%s requires a modern browser to work.": "%s需要在现代浏览器上工作。", "New": diff --git a/js/privatebin.js b/js/privatebin.js index c1b016b6..4729128b 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -645,7 +645,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // only allow tags/attributes we actually use in translations output = DOMPurify.sanitize( output, { - ALLOWED_TAGS: ['a', 'br', 'i', 'span'], + ALLOWED_TAGS: ['a', 'i', 'span'], ALLOWED_ATTR: ['href', 'id'] } ); diff --git a/js/test/I18n.js b/js/test/I18n.js index 6d82b63b..585ee3e5 100644 --- a/js/test/I18n.js +++ b/js/test/I18n.js @@ -38,7 +38,7 @@ describe('I18n', function () { } else { messageId = DOMPurify.sanitize( messageId, { - ALLOWED_TAGS: ['a', 'br', 'i', 'span'], + ALLOWED_TAGS: ['a', 'i', 'span'], ALLOWED_ATTR: ['href', 'id'] } ); @@ -77,7 +77,7 @@ describe('I18n', function () { postfix = postfix.replace(/%(s|d)/g, '%%'); const translation = DOMPurify.sanitize( prefix + $.PrivateBin.Helper.htmlEntities(params[0]) + '' + postfix, { - ALLOWED_TAGS: ['a', 'br', 'i', 'span'], + ALLOWED_TAGS: ['a', 'i', 'span'], ALLOWED_ATTR: ['href', 'id'] } ); @@ -129,7 +129,7 @@ describe('I18n', function () { postfix = postfix.replace(/%(s|d)/g, '%%').trim(); const translation = DOMPurify.sanitize( prefix + $.PrivateBin.Helper.htmlEntities(params[0]) + '' + postfix, { - ALLOWED_TAGS: ['a', 'br', 'i', 'span'], + ALLOWED_TAGS: ['a', 'i', 'span'], ALLOWED_ATTR: ['href', 'id'] } ); diff --git a/lib/I18n.php b/lib/I18n.php index ed1a1d98..c44b67ed 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -125,6 +125,15 @@ class I18n } else { $args[0] = self::$_translations[$messageId]; } + // encode any non-integer arguments and the message ID, if it doesn't contain a link + $argsCount = count($args); + if ($argsCount > 1) { + for ($i = 0; $i < $argsCount; ++$i) { + if (($i > 0 && !is_int($args[$i])) || strpos($args[0], ' - + @@ -469,7 +469,7 @@ endif;