diff --git a/.htaccess.disabled b/.htaccess.disabled new file mode 100644 index 00000000..5a3abe46 --- /dev/null +++ b/.htaccess.disabled @@ -0,0 +1,12 @@ +RewriteEngine on +RewriteCond !%{HTTP_USER_AGENT} "Let's Encrypt validation server" [NC] +RewriteCond %{HTTP_USER_AGENT} ^.*(bot|spider|crawl|https?://|WhatsApp|SkypeUriPreview|facebookexternalhit) [NC] +RewriteRule .* - [R=403,L] + + +php_value max_execution_time 30 +php_value post_max_size 10M +php_value upload_max_size 10M +php_value upload_max_filesize 10M +php_value max_file_uploads 100 + diff --git a/CHANGELOG.md b/CHANGELOG.md index 085c9a5c..608716f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # PrivateBin version history * **1.4 (not yet released)** + * CHANGED: Upgrading libraries to: DOMpurify 2.0.8 + * CHANGED: Several translations got updated with missing messages + * CHANGED: Introduce HTML entity encoding on server side (#581) + * FIXED: HTML entity double encoding issues introduced in 1.3.2 (#560) * **1.3.2 (2020-01-11)** * ADDED: Translation for Ukrainian (#533) * ADDED: Option to send a mail with the link, when creating a paste (#398) diff --git a/INSTALL.md b/INSTALL.md index eb2c8ea3..2f3900c6 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -187,7 +187,7 @@ CREATE INDEX parent ON prefix_comment(pasteid); CREATE TABLE prefix_config ( id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id) ); -INSERT INTO prefix_config VALUES('VERSION', '1.3.2'); +INSERT INTO prefix_config VALUES('VERSION', '1.3.3'); ``` In **PostgreSQL**, the data, attachment, nickname and vizhash columns needs to be TEXT and not BLOB or MEDIUMBLOB. diff --git a/README.md b/README.md index ff86e973..d05a8654 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/) -*Current version: 1.3.2* +*Current version: 1.3.3* **PrivateBin** is a minimalist, open source online [pastebin](https://en.wikipedia.org/wiki/Pastebin) where the server has zero knowledge of pasted data. @@ -95,9 +95,9 @@ file](https://github.com/PrivateBin/PrivateBin/wiki/Configuration): ## Further resources -* [Installation guide](https://github.com/PrivateBin/PrivateBin/blob/master/INSTALL.md#installation) +* [FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ) -* [Upgrading from ZeroBin 0.19 Alpha](https://github.com/PrivateBin/PrivateBin/wiki/Upgrading-from-ZeroBin-0.19-Alpha) +* [Installation guide](https://github.com/PrivateBin/PrivateBin/blob/master/INSTALL.md#installation) * [Configuration guide](https://github.com/PrivateBin/PrivateBin/wiki/Configuration) diff --git a/SECURITY.md b/SECURITY.md index 300f6eea..f3b02da2 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,8 +4,8 @@ | Version | Supported | | ------- | ------------------ | -| 1.3.2 | :heavy_check_mark: | -| < 1.3.2 | :x: | +| 1.3.3 | :heavy_check_mark: | +| < 1.3.3 | :x: | ## Reporting a Vulnerability diff --git a/css/bootstrap/privatebin.css b/css/bootstrap/privatebin.css index 392966f6..7bd85f55 100644 --- a/css/bootstrap/privatebin.css +++ b/css/bootstrap/privatebin.css @@ -6,7 +6,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ body { diff --git a/css/noscript.css b/css/noscript.css index 6d71476d..3679c279 100644 --- a/css/noscript.css +++ b/css/noscript.css @@ -6,7 +6,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ /* When there is no script at all other */ diff --git a/css/privatebin.css b/css/privatebin.css index ae32f2e1..350d6217 100644 --- a/css/privatebin.css +++ b/css/privatebin.css @@ -6,7 +6,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ /* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved. diff --git a/i18n/bg.json b/i18n/bg.json index 63666060..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": @@ -168,5 +168,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/cs.json b/i18n/cs.json index 02b599d7..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": @@ -168,5 +168,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/de.json b/i18n/de.json index 1d6678ab..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": @@ -168,5 +168,21 @@ "Retry": "Wiederholen", "Showing raw text…": - "Zeige reinen Text an…" + "Zeige reinen Text an…", + "Notice:": + "Hinweis:", + "This link will expire after %s.": + "Dieser Link wird in %s ablaufen.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "Dieser Link kann nur einmal geöffnet werden, verwende nicht den \"Zurück\" oder \"Neu laden\" Knopf Deines Browsers.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Der Empfänger könnte Deine Zeitzone erfahren, möchtest Du die Zeit in UTC umwandeln?", + "Use Current Timezone": + "Aktuelle Zeitzone verwenden", + "Convert To UTC": + "In UTC Umwandeln", + "Close": + "Schliessen" } diff --git a/i18n/es.json b/i18n/es.json index 564dd72e..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": @@ -168,5 +168,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/fr.json b/i18n/fr.json index 90eabf1d..525f04a3 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": @@ -137,12 +137,12 @@ "Cloned: '%s'": "Cloner '%s'", "The cloned file '%s' was attached to this paste.": "Le fichier cloné '%s' a été attaché à ce paste.", "Attach a file": "Attacher un fichier ", - "alternatively drag & drop a file or paste an image from the clipboard": "alternativement, glisser & déposer un fichier ou coller une image à partir du presse-papiers", + "alternatively drag & drop a file or paste an image from the clipboard": "au choix, glisser & déposer un fichier ou coller une image à partir du presse-papiers", "File too large, to display a preview. Please download the attachment.": "Fichier trop volumineux, pour afficher un aperçu. Veuillez télécharger la pièce jointe.", - "Remove attachment": "Enlever l'attachement", + "Remove attachment": "Enlever la pièce jointe", "Your browser does not support uploading encrypted files. Please use a newer browser.": "Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.", - "Invalid attachment.": "Attachement invalide.", + "Invalid attachment.": "Pièce jointe invalide.", "Options": "Options", "Shorten URL": "Raccourcir URL", "Editor": "Éditer", @@ -158,7 +158,7 @@ "Preparing new paste…": "Préparation du paste…", "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "Si ce message ne disparaîssait pas, jetez un oeil à cette FAQ pour des idées de résolution (en Anglais).", - "+++ no paste text +++": "+++ pas de paste-text +++", + "+++ no paste text +++": "+++ pas de texte copié +++", "Could not get paste data: %s": "Impossible d'obtenir les données du paste: %s", "QR code": "QR code", @@ -169,13 +169,29 @@ "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Votre navigateur peut nécessiter une connexion HTTPS pour prendre en charge l’API WebCrypto. Essayez de passer en HTTPS.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", + "Votre navigateur ne prend pas en charge WebAssembly, utilisé pour la compression zlib. Vous pouvez créer des documents non compressés, mais vous ne pouvez pas lire les documents compressés.", "waiting on user to provide a password": - "waiting on user to provide a password", + "en attendant que l'utilisateur fournisse un mot de passe", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Impossible de décrypter les données. Vous avez saisi un mot de passe incorrect ? Réessayez avec le bouton en haut.", "Retry": - "Retry", + "Réessayer", "Showing raw text…": - "Showing raw text…" + "Affichage du texte brut…", + "Notice:": + "Avertissement :", + "This link will expire after %s.": + "Ce lien expire après le %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "Vous ne pouvez accéder à ce lien qu'une seule fois, n'utilisez pas le bouton précédent ou rafraîchir de votre navigateur.", + "Link:": + "Lien :", + "Recipient may become aware of your timezone, convert time to UTC?": + "Le destinataire peut connaître votre fuseau horaire, convertir l'heure au format UTC ?", + "Use Current Timezone": + "Conserver l'actuel", + "Convert To UTC": + "Convertir en UTC", + "Close": + "Fermer" } diff --git a/i18n/hu.json b/i18n/hu.json index c3e11a7b..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.", @@ -168,5 +168,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/it.json b/i18n/it.json index 07af891b..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": @@ -168,5 +168,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/nl.json b/i18n/nl.json index 29554d85..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": @@ -168,5 +168,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/no.json b/i18n/no.json index a2ad2c1a..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": @@ -168,5 +168,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/oc.json b/i18n/oc.json index 43a0db71..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": @@ -169,13 +169,29 @@ "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Se pòt que vòstre navigator faga besonh d’una connexion HTTPS per èsser compatible amb l’API WebCrypto. Ensajatz de passar al HTTPS.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", + "Vòstre navigator es pas compatible amb WebAssembly, utilizat per la compression zlib. Podètz crear de documents pas compressat, mas ne podètz pas legir de compressats.", "waiting on user to provide a password": - "waiting on user to provide a password", + "en espèra que l’utilizaire fornisca un senhal", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Deschiframent de las donadas impossible. Avètz picat un marrit senhal ? Tornatz ensajar amb lo boton ennaut.", "Retry": - "Retry", + "Tornar ensajar", "Showing raw text…": - "Showing raw text…" + "Afichatge del tèxte brut…", + "Notice:": + "Avertiment :", + "This link will expire after %s.": + "Aqueste ligam expirarà aprèp %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "Òm pòt pas qu’accedir a aqueste ligam qu’un còp, utilizetz pas lo boton precedent o actualizar del navigator.", + "Link:": + "Ligam :", + "Recipient may become aware of your timezone, convert time to UTC?": + "Lo destinatari pòt s’avisar de vòstre fus orari, convertir en UTC ?", + "Use Current Timezone": + "Utilizar l’actual", + "Convert To UTC": + "Convertir en UTC", + "Close": + "Tampar" } diff --git a/i18n/pl.json b/i18n/pl.json index 6b5cbb57..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.", @@ -168,5 +168,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/pt.json b/i18n/pt.json index 253a45ee..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": @@ -151,22 +151,38 @@ "Caso essa mensagem nunca desapareça, por favor veja este FAQ para saber como resolver os problemas.", "+++ no paste text +++": "+++ sem texto de cópia +++", "Could not get paste data: %s": - "Could not get paste data: %s", - "QR code": "QR code", + "Não foi possível obter dados de cópia: %s", + "QR code": "Código QR", "This website is using an insecure HTTP connection! Please use it only for testing.": - "This website is using an insecure HTTP connection! Please use it only for testing.", + "Esse site usa uma conexão HTTP insegura! Use-o apenas para testes.", "For more information see this FAQ entry.": - "For more information see this FAQ entry.", + "Para mais informações veja esse item do FAQ.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", + "Seu navegador pode exigir uma conexão HTTPS para dar suporte à API WebCrypto. Tente mudar para HTTPS.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", + "Seu navagador não suporta WebAssembly, usado para compressão zlib. Você pode criar documentos não compactados, mas não pode lê-los.", "waiting on user to provide a password": - "waiting on user to provide a password", + "esperando que o usuário digite uma senha", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Não foi possível decifrar os dados. Você digitou a senha corretamente? Tente novamente com o botão ao topo.", "Retry": - "Retry", + "Tentar Novamente", "Showing raw text…": - "Showing raw text…" + "Mostrando texto bruto…", + "Notice:": + "Aviso:", + "This link will expire after %s.": + "Esse link vai expirar após %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "Esse link só pode ser acessado uma vez, não utilize o botão de voltar ou atualizar do seu navegador.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "O recipiente pode ter ciência de seu fuso horário, converter hora para UTC?", + "Use Current Timezone": + "Usar Fuso Horário Atual", + "Convert To UTC": + "Converter para UTC", + "Close": + "Fechar" } diff --git a/i18n/ru.json b/i18n/ru.json index 77a03f61..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": @@ -178,5 +178,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/sl.json b/i18n/sl.json index f93d475c..15e57289 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -1,7 +1,7 @@ { "PrivateBin": "PrivateBin", "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": - "%s je minimalističen, odprtokodni spletni 'pastebin', kjer server ne ve ničesar o prilepljenih podatkih. Podatki so zakodirani/odkodirani v brskalniku z uporabo 256 bitnega AES. Več informacij na < href=\"https://privatebin.info/\">spletni strani projekta..", + "%s je minimalističen, odprtokodni spletni 'pastebin', kjer server ne ve ničesar o prilepljenih podatkih. Podatki so zakodirani/odkodirani v brskalniku z uporabo 256 bitnega AES. Več informacij na spletni strani projekta..", "Because ignorance is bliss": "Ker kar ne veš ne boli.", "en": "sl", @@ -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": @@ -177,5 +177,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/uk.json b/i18n/uk.json index 6fa2ee2c..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": @@ -178,5 +178,21 @@ "Retry": "Retry", "Showing raw text…": - "Showing raw text…" + "Showing raw text…", + "Notice:": + "Notice:", + "This link will expire after %s.": + "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": + "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": + "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": + "Use Current Timezone", + "Convert To UTC": + "Convert To UTC", + "Close": + "Close" } diff --git a/i18n/zh.json b/i18n/zh.json index b4bccbde..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": @@ -168,5 +168,21 @@ "Retry": "重试", "Showing raw text…": - "显示原始文字…" + "显示原始文字…", + "Notice:": + "注意:", + "This link will expire after %s.": + "这个链接将会在 %s 过期。", + "This link can only be accessed once, do not use back or refresh button in your browser.": + "这个链接只能被访问一次,请勿使用浏览器中的返回和刷新按钮。", + "Link:": + "链接地址:", + "Recipient may become aware of your timezone, convert time to UTC?": + "收件人可能会知道您的时区,将时间转换为UTC?", + "Use Current Timezone": + "使用当前时区", + "Convert To UTC": + "转换为UTC", + "Close": + "关闭" } diff --git a/index.php b/index.php index 09e5e684..f346a598 100644 --- a/index.php +++ b/index.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ // change this, if your php files and data is outside of your webservers document root diff --git a/js/privatebin.js b/js/privatebin.js index dc02e8fd..e76bf98c 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -6,7 +6,7 @@ * @see {@link https://github.com/PrivateBin/PrivateBin} * @copyright 2012 Sébastien SAUVAGE ({@link http://sebsauvage.net}) * @license {@link https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License} - * @version 1.3.2 + * @version 1.3.3 * @name PrivateBin * @namespace */ @@ -189,6 +189,26 @@ jQuery.PrivateBin = (function($, RawDeflate) { const Helper = (function () { const me = {}; + /** + * character to HTML entity lookup table + * + * @see {@link https://github.com/janl/mustache.js/blob/master/mustache.js#L60} + * @name Helper.entityMap + * @private + * @enum {Object} + * @readonly + */ + const entityMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`', + '=': '=' + }; + /** * cache for script location * @@ -302,19 +322,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { let format = args[0], i = 1; return format.replace(/%(s|d)/g, function (m) { - // m is the matched format, e.g. %s, %d let val = args[i]; - // A switch statement so that the formatter can be extended. - switch (m) - { - case '%d': - val = parseFloat(val); - if (isNaN(val)) { - val = 0; - } - break; - default: - // Default is %s + if (m === '%d') { + val = parseFloat(val); + if (isNaN(val)) { + val = 0; + } } ++i; return val; @@ -393,15 +406,21 @@ jQuery.PrivateBin = (function($, RawDeflate) { }; /** - * resets state, used for unit testing + * convert all applicable characters to HTML entities * - * @name Helper.reset + * @see {@link https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html} + * @name Helper.htmlEntities * @function + * @param {string} str + * @return {string} escaped HTML */ - me.reset = function() - { - baseUri = null; - }; + me.htmlEntities = function(str) { + return String(str).replace( + /[&<>"'`=\/]/g, function(s) { + return entityMap[s]; + } + ); + } /** * calculate expiration date given initial date and expiration period @@ -443,29 +462,14 @@ jQuery.PrivateBin = (function($, RawDeflate) { }; /** - * encode all applicable characters to HTML entities + * resets state, used for unit testing * - * @see {@link https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html} - * - * @name Helper.htmlEntities + * @name Helper.reset * @function - * @param string str - * @return string escaped HTML */ - me.htmlEntities = function(str) { - // using textarea, since other tags may allow and execute scripts, even when detached from DOM - let holder = document.createElement('textarea'); - holder.textContent = str; - // as per OWASP recommendation, also encoding quotes and slash - return holder.innerHTML.replace( - /["'\/]/g, - function(s) { - return { - '"': '"', - "'": ''', - '/': '/' - }[s]; - }); + me.reset = function() + { + baseUri = null; }; return me; @@ -538,10 +542,14 @@ jQuery.PrivateBin = (function($, RawDeflate) { * * Optionally pass a jQuery element as the first parameter, to automatically * let the text of this element be replaced. In case the (asynchronously - * loaded) language is not downloadet yet, this will make sure the string - * is replaced when it is actually loaded. - * So for easy translations passing the jQuery object to apply it to is - * more save, especially when they are loaded in the beginning. + * loaded) language is not downloaded yet, this will make sure the string + * is replaced when it eventually gets loaded. Using this is both simpler + * and more secure, as it avoids potential XSS when inserting text. + * The next parameter is the message ID, matching the ones found in + * the translation files under the i18n directory. + * Any additional parameters will get inserted into the message ID in + * place of %s (strings) or %d (digits), applying the appropriate plural + * in case of digits. See also Helper.sprintf(). * * @name I18n.translate * @function @@ -619,31 +627,39 @@ jQuery.PrivateBin = (function($, RawDeflate) { } // messageID may contain links, but should be from a trusted source (code or translation JSON files) - let containsNoLinks = args[0].indexOf(' 0) may never contain HTML as they may come from untrusted parties - if (i > 0 || containsNoLinks) { - args[i] = Helper.htmlEntities(args[i]); + let containsLinks = args[0].indexOf(' 0) may never contain HTML as they may come from untrusted parties + if ((containsLinks ? i > 1 : i > 0) || !containsLinks) { + args[i] = Helper.htmlEntities(args[i]); + } } } - // format string let output = Helper.sprintf.apply(this, args); - // if $element is given, apply text to element + if (containsLinks) { + // only allow tags/attributes we actually use in translations + output = DOMPurify.sanitize( + output, { + ALLOWED_TAGS: ['a', 'i', 'span'], + ALLOWED_ATTR: ['href', 'id'] + } + ); + } + + // if $element is given, insert translation if ($element !== null) { - if (containsNoLinks) { - // avoid HTML entity encoding if translation contains links - $element.text(output); + if (containsLinks) { + $element.html(output); } else { - // only allow tags/attributes we actually use in our translations - $element.html( - DOMPurify.sanitize(output, { - ALLOWED_TAGS: ['a', 'br', 'i', 'span'], - ALLOWED_ATTR: ['href', 'id'] - }) - ); + // text node takes care of entity encoding + $element.text(output); } + return ''; } return output; @@ -1876,11 +1892,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { return a.length - b.length; })[0]; if (typeof shortUrl === 'string' && shortUrl.length > 0) { - $('#pastelink').html( - I18n._( - 'Your paste is %s (Hit [Ctrl]+[c] to copy)', - shortUrl, shortUrl - ) + I18n._( + $('#pastelink'), + 'Your paste is %s (Hit [Ctrl]+[c] to copy)', + shortUrl, shortUrl ); // we disable the button to avoid calling shortener again $shortenButton.addClass('buttondisabled'); @@ -1935,11 +1950,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ me.createPasteNotification = function(url, deleteUrl) { - $('#pastelink').html( - I18n._( - 'Your paste is %s (Hit [Ctrl]+[c] to copy)', - url, url - ) + I18n._( + $('#pastelink'), + 'Your paste is %s (Hit [Ctrl]+[c] to copy)', + url, url ); // save newly created element $pasteUrl = $('#pasteurl'); @@ -1947,7 +1961,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { $pasteUrl.click(pasteLinkClick); // delete link - $('#deletelink').html('' + I18n._('Delete data') + ''); + $('#deletelink').html(''); + I18n._($('#deletelink a').first(), 'Delete data'); // enable shortener button $shortenButton.removeClass('buttondisabled'); @@ -2205,6 +2220,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { $messageEdit.addClass('active'); $messagePreview.removeClass('active'); + $('#messageedit').attr('aria-selected','true'); + $('#messagepreview').attr('aria-selected','false'); + PasteViewer.hide(); // reshow input @@ -2234,6 +2252,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { $messageEdit.removeClass('active'); $messagePreview.addClass('active'); + $('#messageedit').attr('aria-selected','false'); + $('#messagepreview').attr('aria-selected','true'); + // hide input as now preview is shown $message.addClass('hidden'); @@ -2402,10 +2423,13 @@ jQuery.PrivateBin = (function($, RawDeflate) { } // escape HTML entities, link URLs, sanitize - const escapedLinkedText = Helper.urls2links( - Helper.htmlEntities(text) - ), - sanitizedLinkedText = DOMPurify.sanitize(escapedLinkedText); + const escapedLinkedText = Helper.urls2links(text), + sanitizedLinkedText = DOMPurify.sanitize( + escapedLinkedText, { + ALLOWED_TAGS: ['a'], + ALLOWED_ATTR: ['href', 'rel'] + } + ); $plainText.html(sanitizedLinkedText); $prettyPrint.html(sanitizedLinkedText); @@ -3219,7 +3243,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { // set & parse text $commentEntryData.html( DOMPurify.sanitize( - Helper.urls2links(commentText) + Helper.urls2links(commentText), { + ALLOWED_TAGS: ['a'], + ALLOWED_ATTR: ['href', 'rel'] + } ) ); @@ -3704,8 +3731,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { const $emailconfirmmodal = $('#emailconfirmmodal'); if ($emailconfirmmodal.length > 0) { if (expirationDate !== null) { - $emailconfirmmodal.find('#emailconfirm-display').text( - I18n._('Recipient may become aware of your timezone, convert time to UTC?') + I18n._( + $emailconfirmmodal.find('#emailconfirm-display'), + 'Recipient may become aware of your timezone, convert time to UTC?' ); const $emailconfirmTimezoneCurrent = $emailconfirmmodal.find('#emailconfirm-timezone-current'); const $emailconfirmTimezoneUtc = $emailconfirmmodal.find('#emailconfirm-timezone-utc'); @@ -3905,9 +3933,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { }); } catch (error) { console.error(error); - Alert.showError( - I18n._('Cannot calculate expiration date.') - ); + Alert.showError('Cannot calculate expiration date.'); } } @@ -5197,7 +5223,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { // first load translations I18n.loadTranslations(); - DOMPurify.setConfig({SAFE_FOR_JQUERY: true}); + DOMPurify.setConfig({ + ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i, + SAFE_FOR_JQUERY: true + }); // center all modals $('.modal').on('show.bs.modal', function(e) { diff --git a/js/purify-2.0.7.js b/js/purify-2.0.7.js deleted file mode 100644 index 815d4b89..00000000 --- a/js/purify-2.0.7.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.DOMPurify=t()}(this,function(){"use strict";function e(e,t){y&&y(e,null);for(var n=t.length;n--;){var r=t[n];if("string"==typeof r){var o=r.toLowerCase();o!==r&&(Object.isFrozen(t)||(t[n]=o),r=o)}e[r]=!0}return e}function t(e){var t={},n=void 0;for(n in e)g(h,e,[n])&&(t[n]=e[n]);return t}function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t0&&void 0!==arguments[0]?arguments[0]:O(),u=function(e){return r(e)};if(u.version="2.0.7",u.removed=[],!o||!o.document||9!==o.document.nodeType)return u.isSupported=!1,u;var h=o.document,y=!1,g=!1,v=o.document,R=o.DocumentFragment,D=o.HTMLTemplateElement,C=o.Node,H=o.NodeFilter,F=o.NamedNodeMap,z=void 0===F?o.NamedNodeMap||o.MozNamedAttrMap:F,I=o.Text,j=o.Comment,U=o.DOMParser,P=o.TrustedTypes;if("function"==typeof D){var W=v.createElement("template");W.content&&W.content.ownerDocument&&(v=W.content.ownerDocument)}var B=N(P,h),q=B?B.createHTML(""):"",G=v,V=G.implementation,Y=G.createNodeIterator,K=G.getElementsByTagName,X=G.createDocumentFragment,$=h.importNode,J={};u.isSupported=V&&void 0!==V.createHTMLDocument&&9!==v.documentMode;var Q=b,Z=T,ee=A,te=x,ne=L,re=E,oe=S,ie=null,ae=e({},[].concat(n(i),n(a),n(l),n(s),n(c))),le=null,se=e({},[].concat(n(d),n(f),n(m),n(p))),ce=null,ue=null,de=!0,fe=!0,me=!1,pe=!1,he=!1,ye=!1,ge=!1,ve=!1,be=!1,Te=!1,Ae=!1,xe=!1,Se=!0,Le=!0,Ee=!1,Me={},ke=e({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","plaintext","script","style","svg","template","thead","title","video","xmp"]),we=e({},["audio","video","img","source","image"]),_e=null,Oe=e({},["alt","class","for","id","label","name","pattern","placeholder","summary","title","value","style","xmlns"]),Ne=null,Re=v.createElement("form"),De=function(r){Ne&&Ne===r||(r&&"object"===(void 0===r?"undefined":M(r))||(r={}),ie="ALLOWED_TAGS"in r?e({},r.ALLOWED_TAGS):ae,le="ALLOWED_ATTR"in r?e({},r.ALLOWED_ATTR):se,_e="ADD_URI_SAFE_ATTR"in r?e(t(Oe),r.ADD_URI_SAFE_ATTR):Oe,ce="FORBID_TAGS"in r?e({},r.FORBID_TAGS):{},ue="FORBID_ATTR"in r?e({},r.FORBID_ATTR):{},Me="USE_PROFILES"in r&&r.USE_PROFILES,de=!1!==r.ALLOW_ARIA_ATTR,fe=!1!==r.ALLOW_DATA_ATTR,me=r.ALLOW_UNKNOWN_PROTOCOLS||!1,pe=r.SAFE_FOR_JQUERY||!1,he=r.SAFE_FOR_TEMPLATES||!1,ye=r.WHOLE_DOCUMENT||!1,be=r.RETURN_DOM||!1,Te=r.RETURN_DOM_FRAGMENT||!1,Ae=r.RETURN_DOM_IMPORT||!1,xe=r.RETURN_TRUSTED_TYPE||!1,ve=r.FORCE_BODY||!1,Se=!1!==r.SANITIZE_DOM,Le=!1!==r.KEEP_CONTENT,Ee=r.IN_PLACE||!1,oe=r.ALLOWED_URI_REGEXP||oe,he&&(fe=!1),Te&&(be=!0),Me&&(ie=e({},[].concat(n(c))),le=[],!0===Me.html&&(e(ie,i),e(le,d)),!0===Me.svg&&(e(ie,a),e(le,f),e(le,p)),!0===Me.svgFilters&&(e(ie,l),e(le,f),e(le,p)),!0===Me.mathMl&&(e(ie,s),e(le,m),e(le,p))),r.ADD_TAGS&&(ie===ae&&(ie=t(ie)),e(ie,r.ADD_TAGS)),r.ADD_ATTR&&(le===se&&(le=t(le)),e(le,r.ADD_ATTR)),r.ADD_URI_SAFE_ATTR&&e(_e,r.ADD_URI_SAFE_ATTR),Le&&(ie["#text"]=!0),ye&&e(ie,["html","head","body"]),ie.table&&(e(ie,["tbody"]),delete ce.tbody),_&&_(r),Ne=r)},Ce=function(e){u.removed.push({element:e});try{e.parentNode.removeChild(e)}catch(t){e.outerHTML=q}},He=function(e,t){try{u.removed.push({attribute:t.getAttributeNode(e),from:t})}catch(e){u.removed.push({attribute:null,from:t})}t.removeAttribute(e)},Fe=function(t){var n=void 0,r=void 0;if(ve)t=""+t;else{var o=t.match(/^[\s]+/);(r=o&&o[0])&&(t=t.slice(r.length))}if(y)try{n=(new U).parseFromString(t,"text/html")}catch(e){}if(g&&e(ce,["title"]),!n||!n.documentElement){var i=(n=V.createHTMLDocument("")).body;i.parentNode.removeChild(i.parentNode.firstElementChild),i.outerHTML=B?B.createHTML(t):t}return t&&r&&n.body.insertBefore(v.createTextNode(r),n.body.childNodes[0]||null),K.call(n,ye?"html":"body")[0]};u.isSupported&&(function(){try{Fe('

').querySelector("svg img")&&(y=!0)}catch(e){}}(),function(){try{var e=Fe("</title><img>");/<\/title/.test(e.querySelector("title").innerHTML)&&(g=!0)}catch(e){}}());var ze=function(e){return Y.call(e.ownerDocument||e,e,H.SHOW_ELEMENT|H.SHOW_COMMENT|H.SHOW_TEXT,function(){return H.FILTER_ACCEPT},!1)},Ie=function(e){return!(e instanceof I||e instanceof j)&&!("string"==typeof e.nodeName&&"string"==typeof e.textContent&&"function"==typeof e.removeChild&&e.attributes instanceof z&&"function"==typeof e.removeAttribute&&"function"==typeof e.setAttribute&&"string"==typeof e.namespaceURI)},je=function(e){return"object"===(void 0===C?"undefined":M(C))?e instanceof C:e&&"object"===(void 0===e?"undefined":M(e))&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName},Ue=function(e,t,n){J[e]&&J[e].forEach(function(e){e.call(u,t,n,Ne)})},Pe=function(e){var t=void 0;if(Ue("beforeSanitizeElements",e,null),Ie(e))return Ce(e),!0;var n=e.nodeName.toLowerCase();if(Ue("uponSanitizeElement",e,{tagName:n,allowedTags:ie}),("svg"===n||"math"===n)&&0!==e.querySelectorAll("p, br").length)return Ce(e),!0;if(!ie[n]||ce[n]){if(Le&&!ke[n]&&"function"==typeof e.insertAdjacentHTML)try{var r=e.innerHTML;e.insertAdjacentHTML("AfterEnd",B?B.createHTML(r):r)}catch(e){}return Ce(e),!0}return"noscript"===n&&/<\/noscript/i.test(e.innerHTML)?(Ce(e),!0):"noembed"===n&&/<\/noembed/i.test(e.innerHTML)?(Ce(e),!0):(!pe||e.firstElementChild||e.content&&e.content.firstElementChild||!/</g.test(e.textContent)||(u.removed.push({element:e.cloneNode()}),e.innerHTML?e.innerHTML=e.innerHTML.replace(/</g,"<"):e.innerHTML=e.textContent.replace(/</g,"<")),he&&3===e.nodeType&&(t=(t=(t=e.textContent).replace(Q," ")).replace(Z," "),e.textContent!==t&&(u.removed.push({element:e.cloneNode()}),e.textContent=t)),Ue("afterSanitizeElements",e,null),!1)},We=function(e,t,n){if(Se&&("id"===t||"name"===t)&&(n in v||n in Re))return!1;if(fe&&ee.test(t));else if(de&&te.test(t));else{if(!le[t]||ue[t])return!1;if(_e[t]);else if(oe.test(n.replace(re,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==n.indexOf("data:")||!we[e]){if(me&&!ne.test(n.replace(re,"")));else if(n)return!1}else;}return!0},Be=function(e){var t=void 0,n=void 0,r=void 0,o=void 0,i=void 0;Ue("beforeSanitizeAttributes",e,null);var a=e.attributes;if(a){var l={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:le};for(i=a.length;i--;){var s=t=a[i],c=s.name,d=s.namespaceURI;if(n=t.value.trim(),r=c.toLowerCase(),l.attrName=r,l.attrValue=n,l.keepAttr=!0,Ue("uponSanitizeAttribute",e,l),n=l.attrValue,"name"===r&&"IMG"===e.nodeName&&a.id)o=a.id,a=k(w,a,[]),He("id",e),He(c,e),a.indexOf(o)>i&&e.setAttribute("id",o.value);else{if("INPUT"===e.nodeName&&"type"===r&&"file"===n&&l.keepAttr&&(le[r]||!ue[r]))continue;"id"===c&&e.setAttribute(c,""),He(c,e)}if(l.keepAttr)if(/svg|math/i.test(e.namespaceURI)&&new RegExp("</("+Object.keys(ke).join("|")+")","i").test(n))He(c,e);else{he&&(n=(n=n.replace(Q," ")).replace(Z," "));var f=e.nodeName.toLowerCase();if(We(f,r,n))try{d?e.setAttributeNS(d,c,n):e.setAttribute(c,n),u.removed.pop()}catch(e){}}}Ue("afterSanitizeAttributes",e,null)}},qe=function e(t){var n=void 0,r=ze(t);for(Ue("beforeSanitizeShadowDOM",t,null);n=r.nextNode();)Ue("uponSanitizeShadowNode",n,null),Pe(n)||(n.content instanceof R&&e(n.content),Be(n));Ue("afterSanitizeShadowDOM",t,null)};return u.sanitize=function(e,t){var n=void 0,r=void 0,i=void 0,a=void 0,l=void 0;if(e||(e="\x3c!--\x3e"),"string"!=typeof e&&!je(e)){if("function"!=typeof e.toString)throw new TypeError("toString is not a function");if("string"!=typeof(e=e.toString()))throw new TypeError("dirty is not a string, aborting")}if(!u.isSupported){if("object"===M(o.toStaticHTML)||"function"==typeof o.toStaticHTML){if("string"==typeof e)return o.toStaticHTML(e);if(je(e))return o.toStaticHTML(e.outerHTML)}return e}if(ge||De(t),u.removed=[],Ee);else if(e instanceof C)1===(r=(n=Fe("\x3c!--\x3e")).ownerDocument.importNode(e,!0)).nodeType&&"BODY"===r.nodeName?n=r:"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!be&&!he&&!ye&&xe&&-1===e.indexOf("<"))return B?B.createHTML(e):e;if(!(n=Fe(e)))return be?null:q}n&&ve&&Ce(n.firstChild);for(var s=ze(Ee?e:n);i=s.nextNode();)3===i.nodeType&&i===a||Pe(i)||(i.content instanceof R&&qe(i.content),Be(i),a=i);if(a=null,Ee)return e;if(be){if(Te)for(l=X.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return Ae&&(l=$.call(h,l,!0)),l}var c=ye?n.outerHTML:n.innerHTML;return he&&(c=(c=c.replace(Q," ")).replace(Z," ")),B&&xe?B.createHTML(c):c},u.setConfig=function(e){De(e),ge=!0},u.clearConfig=function(){Ne=null,ge=!1},u.isValidAttribute=function(e,t,n){Ne||De({});var r=e.toLowerCase(),o=t.toLowerCase();return We(r,o,n)},u.addHook=function(e,t){"function"==typeof t&&(J[e]=J[e]||[],J[e].push(t))},u.removeHook=function(e){J[e]&&J[e].pop()},u.removeHooks=function(e){J[e]&&(J[e]=[])},u.removeAllHooks=function(){J={}},u}var o=Object.freeze||function(e){return e},i=o(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),a=o(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","audio","canvas","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","video","view","vkern"]),l=o(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),s=o(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover"]),c=o(["#text"]),u=Object.freeze||function(e){return e},d=u(["accept","action","align","alt","autocomplete","background","bgcolor","border","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","coords","crossorigin","datetime","default","dir","disabled","download","enctype","face","for","headers","height","hidden","high","href","hreflang","id","integrity","ismap","label","lang","list","loop","low","max","maxlength","media","method","min","minlength","multiple","name","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","type","usemap","valign","value","width","xmlns"]),f=u(["accent-height","accumulate","additive","alignment-baseline","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","specularconstant","specularexponent","spreadmethod","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","tabindex","targetx","targety","transform","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),m=u(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),p=u(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),h=Object.hasOwnProperty,y=Object.setPrototypeOf,g=("undefined"!=typeof Reflect&&Reflect).apply;g||(g=function(e,t,n){return e.apply(t,n)});var v=Object.seal||function(e){return e},b=v(/\{\{[\s\S]*|[\s\S]*\}\}/gm),T=v(/<%[\s\S]*|[\s\S]*%>/gm),A=v(/^data-[\-\w.\u00B7-\uFFFF]/),x=v(/^aria-[\-\w]+$/),S=v(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),L=v(/^(?:\w+script|data):/i),E=v(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g),M="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},k=("undefined"!=typeof Reflect&&Reflect).apply,w=Array.prototype.slice,_=Object.freeze,O=function(){return"undefined"==typeof window?null:window};k||(k=function(e,t,n){return e.apply(t,n)});var N=function(e,t){if("object"!==(void 0===e?"undefined":M(e))||"function"!=typeof e.createPolicy)return null;var n=null;t.currentScript&&t.currentScript.hasAttribute("data-tt-policy-suffix")&&(n=t.currentScript.getAttribute("data-tt-policy-suffix"));var r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:function(e){return e}})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}};return r()}); diff --git a/js/purify-2.0.8.js b/js/purify-2.0.8.js new file mode 100644 index 00000000..5efdbd67 --- /dev/null +++ b/js/purify-2.0.8.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.DOMPurify=t()}(this,function(){"use strict";function e(e){if(Array.isArray(e)){for(var t=0,r=Array(e.length);t<e.length;t++)r[t]=e[t];return r}return Array.from(e)}function t(e){return function(t){for(var r=arguments.length,n=Array(r>1?r-1:0),o=1;o<r;o++)n[o-1]=arguments[o];return m(e,t,n)}}function r(e){return function(){for(var t=arguments.length,r=Array(t),n=0;n<t;n++)r[n]=arguments[n];return y(e,r)}}function n(e,t){c&&c(e,null);for(var r=t.length;r--;){var n=t[r];if("string"==typeof n){var o=x(n);o!==n&&(s(t)||(t[r]=o),n=o)}e[n]=!0}return e}function o(e){var t={},r=void 0;for(r in e)m(l,e,[r])&&(t[r]=e[r]);return t}function i(e){if(Array.isArray(e)){for(var t=0,r=Array(e.length);t<e.length;t++)r[t]=e[t];return r}return Array.from(e)}function a(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:V(),t=function(e){return a(e)};if(t.version="2.0.8",t.removed=[],!e||!e.document||9!==e.document.nodeType)return t.isSupported=!1,t;var r=e.document,l=!1,c=!1,s=e.document,f=e.DocumentFragment,p=e.HTMLTemplateElement,m=e.Node,y=e.NodeFilter,X=e.NamedNodeMap,$=void 0===X?e.NamedNodeMap||e.MozNamedAttrMap:X,J=e.Text,Q=e.Comment,Z=e.DOMParser,ee=e.trustedTypes;if("function"==typeof p){var te=s.createElement("template");te.content&&te.content.ownerDocument&&(s=te.content.ownerDocument)}var re=Y(ee,r),ne=re?re.createHTML(""):"",oe=s,ie=oe.implementation,ae=oe.createNodeIterator,le=oe.getElementsByTagName,ce=oe.createDocumentFragment,se=r.importNode,ue={};t.isSupported=ie&&void 0!==ie.createHTMLDocument&&9!==s.documentMode;var de=j,fe=U,pe=P,me=W,ye=q,ge=G,he=B,ve=null,be=n({},[].concat(i(O),i(w),i(D),i(R),i(H))),Te=null,Ae=n({},[].concat(i(C),i(F),i(z),i(I))),xe=null,Se=null,Le=!0,Ee=!0,Me=!1,ke=!1,_e=!1,Ne=!1,Oe=!1,we=!1,De=!1,Re=!1,He=!1,Ce=!1,Fe=!0,ze=!0,Ie=!1,je={},Ue=n({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","plaintext","script","style","svg","template","thead","title","video","xmp"]),Pe=n({},["audio","video","img","source","image"]),We=null,Be=n({},["alt","class","for","id","label","name","pattern","placeholder","summary","title","value","style","xmlns"]),qe=null,Ge=s.createElement("form"),Ke=function(e){qe&&qe===e||(e&&"object"===(void 0===e?"undefined":K(e))||(e={}),ve="ALLOWED_TAGS"in e?n({},e.ALLOWED_TAGS):be,Te="ALLOWED_ATTR"in e?n({},e.ALLOWED_ATTR):Ae,We="ADD_URI_SAFE_ATTR"in e?n(o(Be),e.ADD_URI_SAFE_ATTR):Be,xe="FORBID_TAGS"in e?n({},e.FORBID_TAGS):{},Se="FORBID_ATTR"in e?n({},e.FORBID_ATTR):{},je="USE_PROFILES"in e&&e.USE_PROFILES,Le=!1!==e.ALLOW_ARIA_ATTR,Ee=!1!==e.ALLOW_DATA_ATTR,Me=e.ALLOW_UNKNOWN_PROTOCOLS||!1,ke=e.SAFE_FOR_JQUERY||!1,_e=e.SAFE_FOR_TEMPLATES||!1,Ne=e.WHOLE_DOCUMENT||!1,De=e.RETURN_DOM||!1,Re=e.RETURN_DOM_FRAGMENT||!1,He=e.RETURN_DOM_IMPORT||!1,Ce=e.RETURN_TRUSTED_TYPE||!1,we=e.FORCE_BODY||!1,Fe=!1!==e.SANITIZE_DOM,ze=!1!==e.KEEP_CONTENT,Ie=e.IN_PLACE||!1,he=e.ALLOWED_URI_REGEXP||he,_e&&(Ee=!1),Re&&(De=!0),je&&(ve=n({},[].concat(i(H))),Te=[],!0===je.html&&(n(ve,O),n(Te,C)),!0===je.svg&&(n(ve,w),n(Te,F),n(Te,I)),!0===je.svgFilters&&(n(ve,D),n(Te,F),n(Te,I)),!0===je.mathMl&&(n(ve,R),n(Te,z),n(Te,I))),e.ADD_TAGS&&(ve===be&&(ve=o(ve)),n(ve,e.ADD_TAGS)),e.ADD_ATTR&&(Te===Ae&&(Te=o(Te)),n(Te,e.ADD_ATTR)),e.ADD_URI_SAFE_ATTR&&n(We,e.ADD_URI_SAFE_ATTR),ze&&(ve["#text"]=!0),Ne&&n(ve,["html","head","body"]),ve.table&&(n(ve,["tbody"]),delete xe.tbody),d&&d(e),qe=e)},Ve=function(e){T(t.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){e.outerHTML=ne}},Ye=function(e,r){try{T(t.removed,{attribute:r.getAttributeNode(e),from:r})}catch(e){T(t.removed,{attribute:null,from:r})}r.removeAttribute(e)},Xe=function(e){var t=void 0,r=void 0;if(we)e="<remove></remove>"+e;else{var o=S(e,/^[\s]+/);r=o&&o[0]}var i=re?re.createHTML(e):e;if(l)try{t=(new Z).parseFromString(i,"text/html")}catch(e){}if(c&&n(xe,["title"]),!t||!t.documentElement){var a=(t=ie.createHTMLDocument("")).body;a.parentNode.removeChild(a.parentNode.firstElementChild),a.outerHTML=i}return e&&r&&t.body.insertBefore(s.createTextNode(r),t.body.childNodes[0]||null),le.call(t,Ne?"html":"body")[0]};t.isSupported&&(function(){try{Xe('<svg><p><textarea><img src="</textarea><img src=x abc=1//">').querySelector("svg img")&&(l=!0)}catch(e){}}(),function(){try{var e=Xe("<x/><title></title><img>");k(/<\/title/,e.querySelector("title").innerHTML)&&(c=!0)}catch(e){}}());var $e=function(e){return ae.call(e.ownerDocument||e,e,y.SHOW_ELEMENT|y.SHOW_COMMENT|y.SHOW_TEXT,function(){return y.FILTER_ACCEPT},!1)},Je=function(e){return!(e instanceof J||e instanceof Q)&&!("string"==typeof e.nodeName&&"string"==typeof e.textContent&&"function"==typeof e.removeChild&&e.attributes instanceof $&&"function"==typeof e.removeAttribute&&"function"==typeof e.setAttribute&&"string"==typeof e.namespaceURI)},Qe=function(e){return"object"===(void 0===m?"undefined":K(m))?e instanceof m:e&&"object"===(void 0===e?"undefined":K(e))&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName},Ze=function(e,r,n){ue[e]&&g(ue[e],function(e){e.call(t,r,n,qe)})},et=function(e){var r=void 0;if(Ze("beforeSanitizeElements",e,null),Je(e))return Ve(e),!0;var n=x(e.nodeName);if(Ze("uponSanitizeElement",e,{tagName:n,allowedTags:ve}),("svg"===n||"math"===n)&&0!==e.querySelectorAll("p, br").length)return Ve(e),!0;if(!ve[n]||xe[n]){if(ze&&!Ue[n]&&"function"==typeof e.insertAdjacentHTML)try{var o=e.innerHTML;e.insertAdjacentHTML("AfterEnd",re?re.createHTML(o):o)}catch(e){}return Ve(e),!0}return"noscript"===n&&k(/<\/noscript/i,e.innerHTML)?(Ve(e),!0):"noembed"===n&&k(/<\/noembed/i,e.innerHTML)?(Ve(e),!0):(!ke||e.firstElementChild||e.content&&e.content.firstElementChild||!k(/</g,e.textContent)||(T(t.removed,{element:e.cloneNode()}),e.innerHTML?e.innerHTML=L(e.innerHTML,/</g,"<"):e.innerHTML=L(e.textContent,/</g,"<")),_e&&3===e.nodeType&&(r=e.textContent,r=L(r,de," "),r=L(r,fe," "),e.textContent!==r&&(T(t.removed,{element:e.cloneNode()}),e.textContent=r)),Ze("afterSanitizeElements",e,null),!1)},tt=function(e,t,r){if(Fe&&("id"===t||"name"===t)&&(r in s||r in Ge))return!1;if(Ee&&k(pe,t));else if(Le&&k(me,t));else{if(!Te[t]||Se[t])return!1;if(We[t]);else if(k(he,L(r,ge,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==E(r,"data:")||!Pe[e]){if(Me&&!k(ye,L(r,ge,"")));else if(r)return!1}else;}return!0},rt=function(e){var r=void 0,n=void 0,o=void 0,i=void 0,a=void 0;Ze("beforeSanitizeAttributes",e,null);var l=e.attributes;if(l){var c={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Te};for(a=l.length;a--;){var s=r=l[a],d=s.name,f=s.namespaceURI;if(n=M(r.value),o=x(d),c.attrName=o,c.attrValue=n,c.keepAttr=!0,c.forceKeepAttr=void 0,Ze("uponSanitizeAttribute",e,c),n=c.attrValue,!c.forceKeepAttr){if("name"===o&&"IMG"===e.nodeName&&l.id)i=l.id,l=A(l,[]),Ye("id",e),Ye(d,e),h(l,i)>a&&e.setAttribute("id",i.value);else{if("INPUT"===e.nodeName&&"type"===o&&"file"===n&&c.keepAttr&&(Te[o]||!Se[o]))continue;"id"===d&&e.setAttribute(d,""),Ye(d,e)}if(c.keepAttr)if(ke&&k(/\/>/i,n))Ye(d,e);else if(k(/svg|math/i,e.namespaceURI)&&k(_("</("+v(u(Ue),"|")+")","i"),n))Ye(d,e);else{_e&&(n=L(n,de," "),n=L(n,fe," "));var p=e.nodeName.toLowerCase();if(tt(p,o,n))try{f?e.setAttributeNS(f,d,n):e.setAttribute(d,n),b(t.removed)}catch(e){}}}}Ze("afterSanitizeAttributes",e,null)}},nt=function e(t){var r=void 0,n=$e(t);for(Ze("beforeSanitizeShadowDOM",t,null);r=n.nextNode();)Ze("uponSanitizeShadowNode",r,null),et(r)||(r.content instanceof f&&e(r.content),rt(r));Ze("afterSanitizeShadowDOM",t,null)};return t.sanitize=function(n,o){var i=void 0,a=void 0,l=void 0,c=void 0,s=void 0;if(n||(n="\x3c!--\x3e"),"string"!=typeof n&&!Qe(n)){if("function"!=typeof n.toString)throw N("toString is not a function");if("string"!=typeof(n=n.toString()))throw N("dirty is not a string, aborting")}if(!t.isSupported){if("object"===K(e.toStaticHTML)||"function"==typeof e.toStaticHTML){if("string"==typeof n)return e.toStaticHTML(n);if(Qe(n))return e.toStaticHTML(n.outerHTML)}return n}if(Oe||Ke(o),t.removed=[],"string"==typeof n&&(Ie=!1),Ie);else if(n instanceof m)1===(a=(i=Xe("\x3c!--\x3e")).ownerDocument.importNode(n,!0)).nodeType&&"BODY"===a.nodeName?i=a:"HTML"===a.nodeName?i=a:i.appendChild(a);else{if(!De&&!_e&&!Ne&&Ce&&-1===n.indexOf("<"))return re?re.createHTML(n):n;if(!(i=Xe(n)))return De?null:ne}i&&we&&Ve(i.firstChild);for(var u=$e(Ie?n:i);l=u.nextNode();)3===l.nodeType&&l===c||et(l)||(l.content instanceof f&&nt(l.content),rt(l),c=l);if(c=null,Ie)return n;if(De){if(Re)for(s=ce.call(i.ownerDocument);i.firstChild;)s.appendChild(i.firstChild);else s=i;return He&&(s=se.call(r,s,!0)),s}var d=Ne?i.outerHTML:i.innerHTML;return _e&&(d=L(d,de," "),d=L(d,fe," ")),re&&Ce?re.createHTML(d):d},t.setConfig=function(e){Ke(e),Oe=!0},t.clearConfig=function(){qe=null,Oe=!1},t.isValidAttribute=function(e,t,r){qe||Ke({});var n=x(e),o=x(t);return tt(n,o,r)},t.addHook=function(e,t){"function"==typeof t&&(ue[e]=ue[e]||[],T(ue[e],t))},t.removeHook=function(e){ue[e]&&b(ue[e])},t.removeHooks=function(e){ue[e]&&(ue[e]=[])},t.removeAllHooks=function(){ue={}},t}var l=Object.hasOwnProperty,c=Object.setPrototypeOf,s=Object.isFrozen,u=Object.keys,d=Object.freeze,f=Object.seal,p="undefined"!=typeof Reflect&&Reflect,m=p.apply,y=p.construct;m||(m=function(e,t,r){return e.apply(t,r)}),d||(d=function(e){return e}),f||(f=function(e){return e}),y||(y=function(t,r){return new(Function.prototype.bind.apply(t,[null].concat(e(r))))});var g=t(Array.prototype.forEach),h=t(Array.prototype.indexOf),v=t(Array.prototype.join),b=t(Array.prototype.pop),T=t(Array.prototype.push),A=t(Array.prototype.slice),x=t(String.prototype.toLowerCase),S=t(String.prototype.match),L=t(String.prototype.replace),E=t(String.prototype.indexOf),M=t(String.prototype.trim),k=t(RegExp.prototype.test),_=r(RegExp),N=r(TypeError),O=d(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),w=d(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","audio","canvas","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","video","view","vkern"]),D=d(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),R=d(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover"]),H=d(["#text"]),C=d(["accept","action","align","alt","autocomplete","background","bgcolor","border","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","coords","crossorigin","datetime","default","dir","disabled","download","enctype","face","for","headers","height","hidden","high","href","hreflang","id","integrity","ismap","label","lang","list","loop","low","max","maxlength","media","method","min","minlength","multiple","name","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","type","usemap","valign","value","width","xmlns"]),F=d(["accent-height","accumulate","additive","alignment-baseline","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","specularconstant","specularexponent","spreadmethod","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","tabindex","targetx","targety","transform","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),z=d(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),I=d(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),j=f(/\{\{[\s\S]*|[\s\S]*\}\}/gm),U=f(/<%[\s\S]*|[\s\S]*%>/gm),P=f(/^data-[\-\w.\u00B7-\uFFFF]/),W=f(/^aria-[\-\w]+$/),B=f(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),q=f(/^(?:\w+script|data):/i),G=f(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g),K="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},V=function(){return"undefined"==typeof window?null:window},Y=function(e,t){if("object"!==(void 0===e?"undefined":K(e))||"function"!=typeof e.createPolicy)return null;var r=null;t.currentScript&&t.currentScript.hasAttribute("data-tt-policy-suffix")&&(r=t.currentScript.getAttribute("data-tt-policy-suffix"));var n="dompurify"+(r?"#"+r:"");try{return e.createPolicy(n,{createHTML:function(e){return e}})}catch(e){return console.warn("TrustedTypes policy "+n+" could not be created."),null}};return a()}); diff --git a/lib/Configuration.php b/lib/Configuration.php index 58442fbf..d7877e21 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; diff --git a/lib/Controller.php b/lib/Controller.php index 18e58522..a10ffb47 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; @@ -28,7 +28,7 @@ class Controller * * @const string */ - const VERSION = '1.3.2'; + const VERSION = '1.3.3'; /** * minimal required PHP version diff --git a/lib/Data/AbstractData.php b/lib/Data/AbstractData.php index 85325f04..f0572ac0 100644 --- a/lib/Data/AbstractData.php +++ b/lib/Data/AbstractData.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Data; diff --git a/lib/Data/Database.php b/lib/Data/Database.php index 9e18acd4..ed52a63a 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Data; diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index 458bfd3b..1fe0319c 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Data; diff --git a/lib/Filter.php b/lib/Filter.php index 19aeb38d..fd0e11ec 100644 --- a/lib/Filter.php +++ b/lib/Filter.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; diff --git a/lib/FormatV2.php b/lib/FormatV2.php index 3e98c4e6..127b6a88 100644 --- a/lib/FormatV2.php +++ b/lib/FormatV2.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; diff --git a/lib/I18n.php b/lib/I18n.php index ed1a1d98..ffb781f1 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; @@ -125,9 +125,31 @@ 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], '<a') === false) { + $args[$i] = self::encode($args[$i]); + } + } + } return call_user_func_array('sprintf', $args); } + /** + * encode HTML entities for output into an HTML5 document + * + * @access public + * @static + * @param string $string + * @return string + */ + public static function encode($string) + { + return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5 | ENT_DISALLOWED, 'UTF-8', false); + } + /** * loads translations * diff --git a/lib/Json.php b/lib/Json.php index c7ce68ec..b00d2c58 100644 --- a/lib/Json.php +++ b/lib/Json.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; diff --git a/lib/Model.php b/lib/Model.php index cd86695e..b3c66a30 100644 --- a/lib/Model.php +++ b/lib/Model.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; diff --git a/lib/Model/AbstractModel.php b/lib/Model/AbstractModel.php index 1fd36e84..9e1ac61e 100644 --- a/lib/Model/AbstractModel.php +++ b/lib/Model/AbstractModel.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Model; diff --git a/lib/Model/Comment.php b/lib/Model/Comment.php index 960934da..2e45a034 100644 --- a/lib/Model/Comment.php +++ b/lib/Model/Comment.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Model; diff --git a/lib/Model/Paste.php b/lib/Model/Paste.php index 8d6dfaf5..263a06f3 100644 --- a/lib/Model/Paste.php +++ b/lib/Model/Paste.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Model; diff --git a/lib/Persistence/AbstractPersistence.php b/lib/Persistence/AbstractPersistence.php index 62ed6659..7d5a4b22 100644 --- a/lib/Persistence/AbstractPersistence.php +++ b/lib/Persistence/AbstractPersistence.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Persistence; diff --git a/lib/Persistence/PurgeLimiter.php b/lib/Persistence/PurgeLimiter.php index 8c28116f..22e2e1ad 100644 --- a/lib/Persistence/PurgeLimiter.php +++ b/lib/Persistence/PurgeLimiter.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Persistence; diff --git a/lib/Persistence/ServerSalt.php b/lib/Persistence/ServerSalt.php index d440a780..3e8a290b 100644 --- a/lib/Persistence/ServerSalt.php +++ b/lib/Persistence/ServerSalt.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Persistence; diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index e07ae8c1..b5c0de6c 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin\Persistence; diff --git a/lib/Request.php b/lib/Request.php index b0880ce8..636a0f01 100644 --- a/lib/Request.php +++ b/lib/Request.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; diff --git a/lib/View.php b/lib/View.php index 34af280b..d0993dd5 100644 --- a/lib/View.php +++ b/lib/View.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.3.2 + * @version 1.3.3 */ namespace PrivateBin; diff --git a/lib/Vizhash16x16.php b/lib/Vizhash16x16.php index f0ab26ab..14d8d49e 100644 --- a/lib/Vizhash16x16.php +++ b/lib/Vizhash16x16.php @@ -8,7 +8,7 @@ * @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 0.0.5 beta PrivateBin 1.3.2 + * @version 0.0.5 beta PrivateBin 1.3.3 */ namespace PrivateBin; diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index a74e767b..faaa9779 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -4,7 +4,7 @@ $isCpct = substr($template, 9, 8) === '-compact'; $isDark = substr($template, 9, 5) === '-dark'; $isPage = substr($template, -5) === '-page'; ?><!DOCTYPE html> -<html> +<html lang="<?php echo I18n::_('en'); ?>"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> @@ -70,9 +70,9 @@ if ($MARKDOWN): <?php 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.8.js" integrity="sha512-QwcEKGuEmKtMguCO9pqNtUtZqq9b/tJ8gNr5qhY8hykq3zKTlDOvpZAmf6Rs8yH35Bz1ZdctUjj2qEWxT5aXCg==" 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-wizOnILU1zHsTf7zI5sUykY0+hYrw0b43LaJv16fudk4K7t+nx2u3jRuGdjwhMZVSLQKb0dgiJ/IpXTaOCZslQ==" crossorigin="anonymous"></script> + <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-enOoc3FEmX00nbC+28Qrhjc2shbso/DWmeHVbLDy+a0jvXXweYXCr/B1PRqnXJzTBdPqVBYLVM1u6peVlTwNxg==" crossorigin="anonymous"></script> <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-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" /> @@ -440,7 +440,7 @@ if (strlen($NOTICE)): ?> <div role="alert" class="alert alert-info"> <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> - <?php echo htmlspecialchars($NOTICE), PHP_EOL; ?> + <?php echo I18n::encode($NOTICE), PHP_EOL; ?> </div> <?php endif; @@ -460,16 +460,16 @@ endif; ?> <div id="status" role="alert" class="alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>"> <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> - <?php echo htmlspecialchars($STATUS), PHP_EOL; ?> + <?php echo I18n::encode($STATUS), PHP_EOL; ?> </div> <div id="errormessage" role="alert" class="<?php echo empty($ERROR) ? 'hidden' : '' ?> alert alert-danger"> <span class="glyphicon glyphicon-alert" aria-hidden="true"></span> - <?php echo htmlspecialchars($ERROR), PHP_EOL; ?> + <?php echo I18n::encode($ERROR), PHP_EOL; ?> </div> <noscript> <div id="noscript" role="alert" class="alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>"> <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> </noscript> <div id="oldnotice" role="alert" class="hidden alert alert-danger"> @@ -477,7 +477,8 @@ endif; <?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.opera.com/">Opera</a>, - <a href="https://www.google.com/chrome">Chrome</a>… + <a href="https://www.google.com/chrome">Chrome</a>…<br /> + <span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-the-error-privatebin-requires-a-modern-browser-to-work'); ?></span> </div> <?php if ($HTTPWARNING): @@ -504,7 +505,7 @@ endif; if (strlen($URLSHORTENER)): ?> <p> - <button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> btn-block"> + <button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> btn-block"> <span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?> </button> </p> @@ -517,8 +518,8 @@ endif; ?> </div> <ul id="editorTabs" class="nav nav-tabs hidden"> - <li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li> - <li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li> + <li role="presentation" class="active"><a role="tab" aria-selected="true" aria-controls="editorTabs" id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li> + <li role="presentation"><a role="tab" aria-selected="false" aria-controls="editorTabs" id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li> <li role="presentation" class="pull-right"> <?php if ($isPage): @@ -556,7 +557,7 @@ endif; <div id="noscript" role="alert" class="alert alert-info noscript-hide"> <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Loading…'); ?><br /> - <span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away'); ?></span> + <span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-the-loading-message-not-go-away'); ?></span> </div> </section> <footer class="container"> @@ -590,4 +591,4 @@ if ($FILEUPLOAD): endif; ?> </body> -</html> \ No newline at end of file +</html> diff --git a/tpl/page.php b/tpl/page.php index 865b0295..8dc9c0d9 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -1,7 +1,7 @@ <?php use PrivateBin\I18n; ?><!DOCTYPE html> -<html lang="en"> +<html lang="<?php echo I18n::_('en'); ?>"> <head> <meta charset="utf-8" /> <meta name="robots" content="noindex" /> @@ -48,9 +48,9 @@ if ($MARKDOWN): <?php 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.8.js" integrity="sha512-QwcEKGuEmKtMguCO9pqNtUtZqq9b/tJ8gNr5qhY8hykq3zKTlDOvpZAmf6Rs8yH35Bz1ZdctUjj2qEWxT5aXCg==" 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-wizOnILU1zHsTf7zI5sUykY0+hYrw0b43LaJv16fudk4K7t+nx2u3jRuGdjwhMZVSLQKb0dgiJ/IpXTaOCZslQ==" crossorigin="anonymous"></script> + <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-enOoc3FEmX00nbC+28Qrhjc2shbso/DWmeHVbLDy+a0jvXXweYXCr/B1PRqnXJzTBdPqVBYLVM1u6peVlTwNxg==" crossorigin="anonymous"></script> <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-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" /> @@ -67,24 +67,26 @@ endif; <?php if (strlen($NOTICE)): ?> - <span class="blink">▶</span> <?php echo htmlspecialchars($NOTICE); + <span class="blink">▶</span> <?php echo I18n::encode($NOTICE); endif; ?> </div> <h1 class="title reloadlink"><?php echo I18n::_($NAME); ?></h1><br /> <h2 class="title"><?php echo I18n::_('Because ignorance is bliss'); ?></h2><br /> <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> - <div id="oldnotice" class="nonworking hidden"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?> + <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; ?> <a href="https://www.mozilla.org/firefox/">Firefox</a>, <a href="https://www.opera.com/">Opera</a>, - <a href="https://www.google.com/chrome">Chrome</a>… + <a href="https://www.google.com/chrome">Chrome</a>…<br /> + <span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-the-error-privatebin-requires-a-modern-browser-to-work'); ?></span> </div> <?php if ($HTTPWARNING): ?> <div id="httpnotice" class="errorMessage hidden"> - <?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'); ?> + <?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'); ?><br /> <span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection'); ?></span> </div> <div id="insecurecontextnotice" class="errorMessage hidden"> @@ -97,8 +99,8 @@ endif; <section> <article> <div id="loadingindicator" class="hidden"><?php echo I18n::_('Loading…'); ?></div> - <div id="status"><?php echo htmlspecialchars($STATUS); ?></div> - <div id="errormessage" class="hidden"><?php echo htmlspecialchars($ERROR); ?></div> + <div id="status"><?php echo I18n::encode($STATUS); ?></div> + <div id="errormessage" class="hidden"><?php echo I18n::encode($ERROR); ?></div> <div id="toolbar"> <button id="newbutton" class="reloadlink hidden"><img src="img/icon_new.png" width="11" height="15" alt="" /><?php echo I18n::_('New'); ?></button> <button id="retrybutton" class="reloadlink hidden"><?php echo I18n::_('Retry'), PHP_EOL; ?></button> @@ -207,7 +209,7 @@ endif; <?php if (strlen($URLSHORTENER)): ?> - <button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>"><img src="img/icon_shorten.png" width="13" height="15" /><?php echo I18n::_('Shorten URL'); ?></button> + <button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>"><img src="img/icon_shorten.png" width="13" height="15" /><?php echo I18n::_('Shorten URL'); ?></button> <?php endif; ?> @@ -266,7 +268,7 @@ endif; <section class="container"> <div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"> <span> <?php echo I18n::_('Loading…'); ?></span><br> - <span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away">this FAQ for information to troubleshoot</a>.'); ?></span> + <span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-the-loading-message-not-go-away'); ?></span> </div> </section> </body>