add HTML entity encoding to PHP translation logic, remove exception to allow <br/> tags in DOMpurify by eliminating the single case that made use of it

This commit is contained in:
El RIDO 2020-02-01 08:46:59 +01:00
parent 428ea2f34e
commit cc0920fc09
No known key found for this signature in database
GPG Key ID: 0F5C940A6BD81F92
21 changed files with 47 additions and 38 deletions

View File

@ -31,8 +31,8 @@
"Невалиден код за изтриване. Информацията Ви не беше изтрита.", "Невалиден код за изтриване. Информацията Ви не беше изтрита.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Информацията Ви е изтрита.", "Информацията Ви е изтрита.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"Услугата %s се нуждае от JavaScript, за да работи.<br />Съжаляваме за неудобството.", "Услугата %s се нуждае от JavaScript, за да работи. Съжаляваме за неудобството.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s се нуждае от съвременен браузър за да работи.", "%s се нуждае от съвременен браузър за да работи.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Wrong deletion token. Paste was not deleted.", "Wrong deletion token. Paste was not deleted.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Paste was properly deleted.", "Paste was properly deleted.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript is required for %s to work.<br />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.":
"%%s requires a modern browser to work.", "%%s requires a modern browser to work.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Falscher Lösch-Code. Text wurde nicht gelöscht.", "Falscher Lösch-Code. Text wurde nicht gelöscht.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Text wurde erfolgreich gelöscht.", "Text wurde erfolgreich gelöscht.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript ist eine Voraussetzung, um %s zu nutzen.<br />Bitte entschuldige die Unannehmlichkeiten.", "JavaScript ist eine Voraussetzung, um %s zu nutzen. Bitte entschuldige die Unannehmlichkeiten.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s setzt einen modernen Browser voraus, um funktionieren zu können.", "%s setzt einen modernen Browser voraus, um funktionieren zu können.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Token de eliminación erróneo. El \"paste\" no fue eliminado.", "Token de eliminación erróneo. El \"paste\" no fue eliminado.",
"Paste was properly deleted.": "Paste was properly deleted.":
"El \"paste\" se ha eliminado correctamente.", "El \"paste\" se ha eliminado correctamente.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript es necesario para que %s funcione.<br />Sentimos los inconvenientes ocasionados.", "JavaScript es necesario para que %s funcione. Sentimos los inconvenientes ocasionados.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s requiere un navegador moderno para funcionar.", "%s requiere un navegador moderno para funcionar.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Jeton de suppression incorrect. Le paste n'a pas été supprimé.", "Jeton de suppression incorrect. Le paste n'a pas été supprimé.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Le paste a été correctement supprimé.", "Le paste a été correctement supprimé.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript est requis pour faire fonctionner %s. <br />Désolé pour cet inconvénient.", "JavaScript est requis pour faire fonctionner %s. Désolé pour cet inconvénient.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s nécessite un navigateur moderne pour fonctionner.", "%s nécessite un navigateur moderne pour fonctionner.",
"New": "New":

View File

@ -31,7 +31,7 @@
"Hibás törlési azonosító. A bejegyzés nem lett törölve.", "Hibás törlési azonosító. A bejegyzés nem lett törölve.",
"Paste was properly deleted.": "Paste was properly deleted.":
"A bejegyzés sikeresen törölve.", "A bejegyzés sikeresen törölve.",
"JavaScript is required for %s to work.<br />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.", "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.": "%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.", "A %s működéséhez a jelenleginél újabb böngészőre van szükség.",

View File

@ -31,8 +31,8 @@
"Codice cancellazione errato. Il messaggio NON è stato cancellato.", "Codice cancellazione errato. Il messaggio NON è stato cancellato.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Il messaggio è stato correttamente cancellato.", "Il messaggio è stato correttamente cancellato.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"%s funziona solo con JavaScript attivo.<br />Ci dispiace per l'inconveniente.", "%s funziona solo con JavaScript attivo. Ci dispiace per l'inconveniente.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s richiede un browser moderno e aggiornato per funzionare.", "%s richiede un browser moderno e aggiornato per funzionare.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Foutieve verwijdercode. Geplakte tekst is niet verwijderd.", "Foutieve verwijdercode. Geplakte tekst is niet verwijderd.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Geplakte tekst is correct verwijderd.", "Geplakte tekst is correct verwijderd.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript vereist om %s te laten werken.<br />Sorry voor het ongemak.", "JavaScript vereist om %s te laten werken. Sorry voor het ongemak.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s vereist een moderne browser om te kunnen werken ", "%s vereist een moderne browser om te kunnen werken ",
"New": "New":

View File

@ -31,8 +31,8 @@
"Feil slettingsnøkkel. Innlegg ble ikke fjernet.", "Feil slettingsnøkkel. Innlegg ble ikke fjernet.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Innlegget er slettet.", "Innlegget er slettet.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"Javascript kreves for at %s skal fungere<br />Beklager.", "Javascript kreves for at %s skal fungere. Beklager.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s krever en moderne nettleser for å fungere.", "%s krever en moderne nettleser for å fungere.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Geton de supression incorrècte. Lo tèxte es pas estat suprimit.", "Geton de supression incorrècte. Lo tèxte es pas estat suprimit.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Lo tèxte es estat corrèctament suprimit.", "Lo tèxte es estat corrèctament suprimit.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript es requesit per far foncionar %s. <br />O planhèm per linconvenient.", "JavaScript es requesit per far foncionar %s. O planhèm per linconvenient.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s necessita un navigator modèrn per foncionar.", "%s necessita un navigator modèrn per foncionar.",
"New": "New":

View File

@ -31,7 +31,7 @@
"Nieprawidłowy token usuwania. Wklejka nie została usunięta.", "Nieprawidłowy token usuwania. Wklejka nie została usunięta.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Wklejka usunięta poprawnie.", "Wklejka usunięta poprawnie.",
"JavaScript is required for %s to work.<br />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ść.", "Do działania %sa jest wymagany JavaScript. Przepraszamy za tę niedogodność.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s wymaga do działania nowoczesnej przeglądarki.", "%s wymaga do działania nowoczesnej przeglądarki.",

View File

@ -31,8 +31,8 @@
"Token de remoção inválido. A cópia não foi excluída.", "Token de remoção inválido. A cópia não foi excluída.",
"Paste was properly deleted.": "Paste was properly deleted.":
"A cópia foi devidamente excluída.", "A cópia foi devidamente excluída.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript é necessário para que %s funcione.<br />Pedimos desculpas pela inconveniência.", "JavaScript é necessário para que %s funcione. Pedimos desculpas pela inconveniência.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s requer um navegador moderno para funcionar.", "%s requer um navegador moderno para funcionar.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Неверный ключ удаления записи. Запись не удалена.", "Неверный ключ удаления записи. Запись не удалена.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Запись была успешно удалена.", "Запись была успешно удалена.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"Для работы %s требуется включенный JavaScript.<br />Приносим извинения за неудобства.", "Для работы %s требуется включенный JavaScript. Приносим извинения за неудобства.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"Для работы %s требуется более современный браузер.", "Для работы %s требуется более современный браузер.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Napačen token za izbris. Prilepek ni bil izbrisan..", "Napačen token za izbris. Prilepek ni bil izbrisan..",
"Paste was properly deleted.": "Paste was properly deleted.":
"Prilepek je uspešno izbrisan.", "Prilepek je uspešno izbrisan.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"Da %s deluje, moraš vklopiti JavaScript.<br />Oprosti za povročene nevšečnosti.", "Da %s deluje, moraš vklopiti JavaScript. Oprosti za povročene nevšečnosti.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s za svoje delovanje potrebuje moderen brskalnik.", "%s za svoje delovanje potrebuje moderen brskalnik.",
"New": "New":

View File

@ -31,8 +31,8 @@
"Неправильний ключ вилучення допису. Допис не вилучено.", "Неправильний ключ вилучення допису. Допис не вилучено.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Допис був вилучений повністю.", "Допис був вилучений повністю.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"Для роботи %s потрібен увімкнутий JavaScript.<br />Вибачте.", "Для роботи %s потрібен увімкнутий JavaScript. Вибачте.",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"Для роботи %s потрібен більш сучасний переглядач.", "Для роботи %s потрібен більш сучасний переглядач.",
"New": "New":

View File

@ -31,8 +31,8 @@
"错误的删除token粘贴内容没有被删除。", "错误的删除token粘贴内容没有被删除。",
"Paste was properly deleted.": "Paste was properly deleted.":
"粘贴内容已被正确删除。", "粘贴内容已被正确删除。",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.":
"%s需要JavaScript来进行加解密。<br />给你带来的不便敬请谅解。", "%s需要JavaScript来进行加解密。 给你带来的不便敬请谅解。",
"%s requires a modern browser to work.": "%s requires a modern browser to work.":
"%s需要在现代浏览器上工作。", "%s需要在现代浏览器上工作。",
"New": "New":

View File

@ -645,7 +645,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// only allow tags/attributes we actually use in translations // only allow tags/attributes we actually use in translations
output = DOMPurify.sanitize( output = DOMPurify.sanitize(
output, { output, {
ALLOWED_TAGS: ['a', 'br', 'i', 'span'], ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id'] ALLOWED_ATTR: ['href', 'id']
} }
); );

View File

@ -38,7 +38,7 @@ describe('I18n', function () {
} else { } else {
messageId = DOMPurify.sanitize( messageId = DOMPurify.sanitize(
messageId, { messageId, {
ALLOWED_TAGS: ['a', 'br', 'i', 'span'], ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id'] ALLOWED_ATTR: ['href', 'id']
} }
); );
@ -77,7 +77,7 @@ describe('I18n', function () {
postfix = postfix.replace(/%(s|d)/g, '%%'); postfix = postfix.replace(/%(s|d)/g, '%%');
const translation = DOMPurify.sanitize( const translation = DOMPurify.sanitize(
prefix + $.PrivateBin.Helper.htmlEntities(params[0]) + '<a></a>' + postfix, { prefix + $.PrivateBin.Helper.htmlEntities(params[0]) + '<a></a>' + postfix, {
ALLOWED_TAGS: ['a', 'br', 'i', 'span'], ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id'] ALLOWED_ATTR: ['href', 'id']
} }
); );
@ -129,7 +129,7 @@ describe('I18n', function () {
postfix = postfix.replace(/%(s|d)/g, '%%').trim(); postfix = postfix.replace(/%(s|d)/g, '%%').trim();
const translation = DOMPurify.sanitize( const translation = DOMPurify.sanitize(
prefix + $.PrivateBin.Helper.htmlEntities(params[0]) + '<a></a>' + postfix, { prefix + $.PrivateBin.Helper.htmlEntities(params[0]) + '<a></a>' + postfix, {
ALLOWED_TAGS: ['a', 'br', 'i', 'span'], ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id'] ALLOWED_ATTR: ['href', 'id']
} }
); );

View File

@ -125,6 +125,15 @@ class I18n
} else { } else {
$args[0] = self::$_translations[$messageId]; $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], '<a') === false) {
$args[$i] = htmlentities($args[$i], ENT_QUOTES | ENT_XHTML | ENT_DISALLOWED, 'UTF-8');
}
}
}
return call_user_func_array('sprintf', $args); return call_user_func_array('sprintf', $args);
} }

View File

@ -72,7 +72,7 @@ endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-Q7yHFlVuPYWw/SJFiMv83PPVwGKqBwoqZhNtHAwkTIxocS6Zpqyj1I0/nUCRWv15xuurctViB3lSVs6s+7f0jw==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-F6du+TJ3nokfL4mt94qSzqIXrf/dmwBMMfHwe3tDI86xE47VgwVHUC2tmbEpDQZkoydhXR+Lrnj/wCepoK144w==" crossorigin="anonymous"></script>
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" /> <link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" /> <link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" /> <link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
@ -469,7 +469,7 @@ endif;
<noscript> <noscript>
<div id="noscript" role="alert" class="alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>"> <div id="noscript" role="alert" class="alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)), PHP_EOL; ?> <?php echo I18n::_('JavaScript is required for %s to work. Sorry for the inconvenience.', I18n::_($NAME)), PHP_EOL; ?>
</div> </div>
</noscript> </noscript>
<div id="oldnotice" role="alert" class="hidden alert alert-danger"> <div id="oldnotice" role="alert" class="hidden alert alert-danger">

View File

@ -50,7 +50,7 @@ endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-Q7yHFlVuPYWw/SJFiMv83PPVwGKqBwoqZhNtHAwkTIxocS6Zpqyj1I0/nUCRWv15xuurctViB3lSVs6s+7f0jw==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-F6du+TJ3nokfL4mt94qSzqIXrf/dmwBMMfHwe3tDI86xE47VgwVHUC2tmbEpDQZkoydhXR+Lrnj/wCepoK144w==" crossorigin="anonymous"></script>
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" /> <link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" /> <link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" /> <link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
@ -74,7 +74,7 @@ endif;
<h1 class="title reloadlink"><?php echo I18n::_($NAME); ?></h1><br /> <h1 class="title reloadlink"><?php echo I18n::_($NAME); ?></h1><br />
<h2 class="title"><?php echo I18n::_('Because ignorance is bliss'); ?></h2><br /> <h2 class="title"><?php echo I18n::_('Because ignorance is bliss'); ?></h2><br />
<h3 class="title"><?php echo $VERSION; ?></h3> <h3 class="title"><?php echo $VERSION; ?></h3>
<noscript><div id="noscript" class="nonworking"><?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)); ?></div></noscript> <noscript><div id="noscript" class="nonworking"><?php echo I18n::_('JavaScript is required for %s to work. Sorry for the inconvenience.', I18n::_($NAME)); ?></div></noscript>
<div id="oldnotice" class="nonworking hidden"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?> <div id="oldnotice" class="nonworking hidden"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?>
<a href="https://www.mozilla.org/firefox/">Firefox</a>, <a href="https://www.mozilla.org/firefox/">Firefox</a>,
<a href="https://www.opera.com/">Opera</a>, <a href="https://www.opera.com/">Opera</a>,