diff --git a/.eslintrc b/.eslintrc index 1c90b8e..8275c96 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,3 +1,4 @@ +--- parserOptions: ecmaVersion: 2017 @@ -11,17 +12,16 @@ env: es6: true jquery: true node: true + mocha: true globals: - DOMPurify: false - after: true - before: true - cleanup: true - describe: false - it: false - jsc: false - jsdom: true - kjua: true + DOMPurify: readonly + cleanup: writable + describe: readonly + jsc: readonly + jsdom: writable + kjua: writable + WebCrypto: writable # http://eslint.org/docs/rules/ rules: diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index 3decc5c..0f2d50d 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -68,8 +68,17 @@ languageselection = false ; custom scripts from third-party domains to your templates, e.g. tracking ; scripts or run your site behind certain DDoS-protection services. ; Check the documentation at https://content-security-policy.com/ -; Note: If you use a bootstrap theme, you can remove the allow-popups from the sandbox restrictions. -; By default this disallows to load images from third-party servers, e.g. when they are embedded in pastes. If you wish to allow that, you can adjust the policy here. See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-it-load-embedded-images for details. +; Notes: +; - If you use a bootstrap theme, you can remove the allow-popups from the +; sandbox restrictions. +; - By default this disallows to load images from third-party servers, e.g. when +; they are embedded in pastes. If you wish to allow that, you can adjust the +; policy here. See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-it-load-embedded-images +; for details. +; - The 'unsafe-eval' is used in two cases; to check if the browser supports +; async functions and display an error if not and for Chrome to enable +; webassembly support (used for zlib compression). You can remove it if Chrome +; doesn't need to be supported and old browsers don't need to be warned. ; cspheader = "default-src 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval'; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals" ; stay compatible with PrivateBin Alpha 0.19, less secure diff --git a/i18n/bg.json b/i18n/bg.json index c51ab0f..e11f213 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -35,8 +35,6 @@ "Услугата %s се нуждае от JavaScript, за да работи.
Съжаляваме за неудобството.", "%s requires a modern browser to work.": "%s се нуждае от съвременен браузър за да работи.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Все още използваш Internet Explorer? Направи си услуга и го смени с модерен браузър:", "New": "Създаване", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Взимането на информацията беше неуспешно: %s", "QR code": "QR код", - "I love you too, bot…": "И аз те обичам, бот…", "This website is using an insecure HTTP connection! Please use it only for testing.": "Този сайт използва несигурна HTTP връзка. Моля използвайте само за проби.", "For more information see this FAQ entry.": "Вижте тази страница за повече информация.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": - "Браузъра ви може да се нуждае от HTTPS връзка за да използва WebCrypto API. Пробвай да минеш на HTTPS." + "Браузъра ви може да се нуждае от HTTPS връзка за да използва WebCrypto API. Пробвай да минеш на 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." } diff --git a/i18n/cs.json b/i18n/cs.json index a36ef8b..92d606f 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:", "New": "Nový", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Could not get paste data: %s", "QR code": "QR code", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/i18n/de.json b/i18n/de.json index 3f99404..d53b8b9 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Du benutzt immer noch den Internet Explorer? Tu Dir einen Gefallen und wechsle zu einem moderneren Browser:", "New": "Neu", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Text konnte nicht geladen werden: %s", "QR code": "QR code", - "I love you too, bot…": "Ich mag Dich auch, bot…", "This website is using an insecure HTTP connection! Please use it only for testing.": "Diese Webseite verwendet eine unsichere HTTP Verbindung! Bitte benutze sie nur zum Testen.", "For more information see this FAQ entry.": "Besuche diesen FAQ Eintrag für weitere Informationen dazu.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": - "Dein Browser benötigt möglicherweise eine HTTPS Verbindung um das WebCrypto API nutzen zu können. Versuche auf HTTPS zu wechseln." + "Dein Browser benötigt möglicherweise eine HTTPS Verbindung um das WebCrypto API nutzen zu können. Versuche auf HTTPS zu wechseln.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": + "Dein Browser unterstützt WebAssembly nicht, welches für zlib Komprimierung benötigt wird. Du kannst unkomprimierte Dokumente erzeugen, aber keine komprimierten lesen." } diff --git a/i18n/es.json b/i18n/es.json index 6dd9e91..205a18e 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "¿Sigues usando Internet Explorer? Hazte un favor, cambia a un navegador moderno:", "New": "Nuevo", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "No se pudieron obtener los datos: %s", "QR code": "Código QR", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/i18n/fr.json b/i18n/fr.json index fabb1d2..99ff78c 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Encore sur Internet Explorer ? Faites-vous une faveur, passez à un navigateur moderne :", "New": "Nouveau", "Send": @@ -164,11 +162,12 @@ "Could not get paste data: %s": "Impossible d'obtenir les données du paste: %s", "QR code": "QR code", - "I love you too, bot…": "Je t’aime aussi, bot…", "This website is using an insecure HTTP connection! Please use it only for testing.": "Ce site web utilise une connexion HTTP non sécurisée ! Veuillez l’utiliser uniquement pour des tests.", "For more information see this FAQ entry.": "Pour plus d'informations consultez cette rubrique de la FAQ.", "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." + "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." } diff --git a/i18n/hu.json b/i18n/hu.json index da2dd52..b0f0b8f 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Még mindig Internet Explorert használsz? Ideje váltani:", "New": "Új", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Could not get paste data: %s", "QR code": "QR code", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/i18n/it.json b/i18n/it.json index 125812f..15f1257 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -35,8 +35,6 @@ "%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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Usi ancora Internet Explorer? Ti consigliamo di passare ad un browser più sicuro:", "New": "Nuovo", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Could not get paste data: %s", "QR code": "QR code", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/i18n/nl.json b/i18n/nl.json index 4c93d78..5af40a1 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -35,8 +35,6 @@ "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 ", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Gebruik je nog steeds Internet explorer? Doe jezelf een plezier en maak gebruik van een moderne browser:", "New": "Nieuw", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Could not get paste data: %s", "QR code": "QR code", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/i18n/no.json b/i18n/no.json index db49704..0212852 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -35,8 +35,6 @@ "Javascript kreves for at %s skal fungere
Beklager.", "%s requires a modern browser to work.": "%s krever en moderne nettleser for å fungere.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Fortsatt bruker av Internet Explorer? Gjør deg selv en tjeneste og bytt til en moderne nettleser:", "New": "Ny", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Kunne ikke hente utklippsdata: %s", "QR code": "QR kode", - "I love you too, bot…": "Jeg elsker deg også, bot…", "This website is using an insecure HTTP connection! Please use it only for testing.": "Denne websiden bruker usikker HTTP tilkobling! Bruk den kun for testing.", "For more information see this FAQ entry.": "For mer informasjon se ofte stilte spørsmål.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": - "Din nettleser har behov for HTTPS tilkobling for å støtte WebCrypto biblioteket. Prøv å bytt til HTTPS." + "Din nettleser har behov for HTTPS tilkobling for å støtte WebCrypto biblioteket. Prøv å bytt til 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." } diff --git a/i18n/oc.json b/i18n/oc.json index ec81c89..ccfe3f6 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Encora sus Internet Explorer ? Fasètz-vos una favor, passatz a un navigator modèrn :", "New": "Nòu", "Send": @@ -164,11 +162,12 @@ "Could not get paste data: %s": "Recuperacion impossibla de las donadas copiadas : %s", "QR code": "Còdi QR", - "I love you too, bot…": "T’aimi tanben, robòt…", "This website is using an insecure HTTP connection! Please use it only for testing.": "Aqueste site utiliza una connexion HTTP pas segura ! Mercés de l’utilizar pas que per d’ensages.", "For more information see this FAQ entry.": "Per mai d’informacions vejatz aqueste article de FAQ.", "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." + "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." } diff --git a/i18n/pl.json b/i18n/pl.json index f1ae43f..fa87a3c 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Cały czas używasz Internet Explorera? Zrób sobie przysługę, przesiądź się na nowoczesną przeglądarkę:", "New": "Nowa", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Nie można było pobrać danych wklejki: %s", "QR code": "Kod QR", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/i18n/pt.json b/i18n/pt.json index f7b7e0b..ed84640 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Ainda usando Internet Explorer? Faça-se um favor, mude para um navegador moderno:", "New": "Novo", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "Could not get paste data: %s", "QR code": "QR code", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/i18n/ru.json b/i18n/ru.json index d25b346..5612f50 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -35,8 +35,6 @@ "Для работы %s требуется включенный JavaScript.
Приносим извинения за неудобства.", "%s requires a modern browser to work.": "Для работы %s требуется более современный браузер.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "До сих пор используете Internet Explorer? Пожалейте себя, перейдите на более современный браузер:", "New": "Новая запись", "Send": @@ -165,11 +163,12 @@ "Could not get paste data: %s": "Не удалось получить данные записи: %s", "QR code": "QR код", - "I love you too, bot…": "Я тоже люблю тебя, бот…", "This website is using an insecure HTTP connection! Please use it only for testing.": "Данный сайт использует незащищенное HTTP подключение! Пожалуйста используйте его только для тестирования.", "For more information see this FAQ entry.": "Для продробностей прочтите информацию в FAQ.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": - "Ваш браузер требует использования HTTPS подключения для поддержки WebCrypto API. Попробуйте переключиться на HTTPS." + "Ваш браузер требует использования HTTPS подключения для поддержки WebCrypto API. Попробуйте переключиться на 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." } diff --git a/i18n/sl.json b/i18n/sl.json index e88961d..68d7cc5 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -35,8 +35,6 @@ "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.", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "Še vedno uporabljaš Internet Explorer? Naredi si uslugo, preklopi na moderen brskalnik:", "New": "Nov prilepek", "Send": @@ -164,11 +162,12 @@ "Could not get paste data: %s": "Could not get paste data: %s", "QR code": "QR code", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/i18n/zh.json b/i18n/zh.json index 2e2c7de..a2a50af 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -35,8 +35,6 @@ "%s需要JavaScript来进行加解密。
给你带来的不便敬请谅解。", "%s requires a modern browser to work.": "%s需要在现代浏览器上工作。", - "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": - "还在使用Internet Explorer?对自己好点,换一个现代浏览器:", "New": "新建", "Send": @@ -155,11 +153,12 @@ "Could not get paste data: %s": "无法获取粘贴数据:%s", "QR code": "二维码", - "I love you too, bot…": "I love you too, bot…", "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.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "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." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to 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." } diff --git a/js/common.js b/js/common.js index 40e29a7..25659c8 100644 --- a/js/common.js +++ b/js/common.js @@ -19,6 +19,7 @@ global.prettyPrintOne = window.PR.prettyPrintOne; global.showdown = require('./showdown-1.9.1'); global.DOMPurify = require('./purify-2.0.1'); global.baseX = require('./base-x-3.0.5.1').baseX; +global.Legacy = require('./legacy').Legacy; require('./bootstrap-3.3.7'); require('./privatebin'); diff --git a/js/legacy.js b/js/legacy.js new file mode 100644 index 0000000..f1c9026 --- /dev/null +++ b/js/legacy.js @@ -0,0 +1,309 @@ +/** + * PrivateBin + * + * a zero-knowledge paste bin + * + * @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 + * @name Legacy + * @namespace + * + * IMPORTANT NOTICE FOR DEVELOPERS: + * The logic in this file is intended to run in legacy browsers. Avoid any use of: + * - jQuery (doesn't work in older browsers) + * - ES5 or newer in general + * - const/let, use the traditional var declarations instead + * - async/await or Promises, use traditional callbacks + * - shorthand function notation "() => output", use the full "function() {return output;}" style + * - IE doesn't support: + * - URL(), use the traditional window.location object + * - endsWith(), use indexof() + * - yes, this logic needs to support IE 6, to at least display the error message + */ + +'use strict'; +(function() { + /** + * compatibility check + * + * @name Check + * @class + */ + var Check = (function () { + var me = {}; + + /** + * Status of the initial check, true means it passed + * + * @private + * @prop {bool} + */ + var status = false; + + /** + * Initialization check did run + * + * @private + * @prop {bool} + */ + var init = false; + + /** + * blacklist of UserAgents (parts) known to belong to a bot + * + * @private + * @enum {Array} + * @readonly + */ + var badBotUA = [ + 'Bot', + 'bot' + ]; + + /** + * whitelist of top level domains to consider a secure context, + * regardless of protocol + * + * @private + * @enum {Array} + * @readonly + */ + var tld = [ + '.onion', + '.i2p' + ]; + + /** + * whitelist of hostnames to consider a secure context, + * regardless of protocol + * + * @private + * @enum {Array} + * @readonly + */ + // whitelists of TLDs & local hostnames + var hostname = [ + 'localhost', + '127.0.0.1', + '[::1]' + ]; + + /** + * check if the context is secure + * + * @private + * @name Check.isSecureContext + * @function + * @return {bool} + */ + function isSecureContext() + { + // use .isSecureContext if available + if (window.isSecureContext === true || window.isSecureContext === false) { + return window.isSecureContext; + } + + // HTTP is obviously insecure + if (window.location.protocol !== 'http:') { + return true; + } + + // filter out actually secure connections over HTTP + for (var i = 0; i < tld.length; i++) { + if ( + window.location.hostname.indexOf( + tld[i], + window.location.hostname.length - tld[i].length + ) !== -1 + ) { + return true; + } + } + + // whitelist localhost for development + for (var j = 0; j < hostname.length; j++) { + if (window.location.hostname === hostname[j]) { + return true; + } + } + + // totally INSECURE http protocol! + return false; + } + + /** + * checks whether this is a bot we dislike + * + * @private + * @name Check.isBadBot + * @function + * @return {bool} + */ + function isBadBot() { + // check whether a bot user agent part can be found in the current + // user agent + for (var i = 0; i < badBotUA.length; i++) { + if (navigator.userAgent.indexOf(badBotUA[i]) !== -1) { + return true; + } + } + return false; + } + + /** + * checks whether this is an unsupported browser, via feature detection + * + * @private + * @name Check.isOldBrowser + * @function + * @return {bool} + */ + function isOldBrowser() { + // webcrypto support + if (!( + 'crypto' in window && + 'getRandomValues' in window.crypto && + 'subtle' in window.crypto && + 'encrypt' in window.crypto.subtle && + 'decrypt' in window.crypto.subtle && + 'Uint8Array' in window && + 'Uint32Array' in window + )) { + return true; + } + + // async & ES6 support + try { + eval('async () => {}'); + } catch (e) { + if (e instanceof SyntaxError) { + return true; + } else { + throw e; // throws CSP error + } + } + + return false; + } + + /** + * shows an error message + * + * @private + * @name Check.showError + * @param {string} message + * @function + */ + function showError(message) + { + var element = document.getElementById('errormessage'); + if (message.indexOf(' 1) { - content[content.length - 1].nodeValue = ' ' + output; - } else { + // avoid HTML entity encoding if translation contains link + if (output.indexOf(' ('00' + x.toString(16)).slice(-2) @@ -903,7 +904,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { {name: 'PBKDF2'}, // we use PBKDF2 for key derivation false, // the key may not be exported ['deriveKey'] // we may only use it for key derivation - ); + ).catch(Alert.showError); // derive a stronger key for use with AES return window.crypto.subtle.deriveKey( @@ -920,7 +921,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { }, false, // the key may not be exported ['encrypt', 'decrypt'] // we may only use it for en- and decryption - ); + ).catch(Alert.showError); } /** @@ -957,18 +958,24 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ me.cipher = async function(key, password, message, adata) { + let zlib = (await z); // AES in Galois Counter Mode, keysize 256 bit, // authentication tag 128 bit, 10000 iterations in key derivation - const spec = [ - getRandomBytes(16), // initialization vector - getRandomBytes(8), // salt - 100000, // iterations - 256, // key size - 128, // tag size - 'aes', // algorithm - 'gcm', // algorithm mode - $('body').data('compression') || 'zlib' // compression - ], encodedSpec = []; + const compression = ( + typeof zlib === 'undefined' ? + 'none' : // client lacks support for WASM + ($('body').data('compression') || 'zlib') + ), + spec = [ + getRandomBytes(16), // initialization vector + getRandomBytes(8), // salt + 100000, // iterations + 256, // key size + 128, // tag size + 'aes', // algorithm + 'gcm', // algorithm mode + compression // compression + ], encodedSpec = []; for (let i = 0; i < spec.length; ++i) { encodedSpec[i] = i < 2 ? btoa(spec[i]) : spec[i]; } @@ -987,8 +994,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { await window.crypto.subtle.encrypt( cryptoSettings(JSON.stringify(adata), spec), await deriveKey(key, password, spec), - await compress(message, spec[7]) - ) + await compress(message, compression, zlib) + ).catch(Alert.showError) ) ), adata @@ -1008,7 +1015,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ me.decipher = async function(key, password, data) { - let adataString, spec, cipherMessage; + let adataString, spec, cipherMessage, plaintext; + let zlib = (await z); if (data instanceof Array) { // version 2 adataString = JSON.stringify(data[1]); @@ -1035,20 +1043,29 @@ jQuery.PrivateBin = (function($, RawDeflate) { } spec[0] = atob(spec[0]); spec[1] = atob(spec[1]); + if (spec[7] === 'zlib') { + if (typeof zlib === 'undefined') { + throw 'Error decompressing paste, due to missing WebAssembly support.' + } + } try { - return await decompress( - await window.crypto.subtle.decrypt( - cryptoSettings(adataString, spec), - await deriveKey(key, password, spec), - stringToArraybuffer( - atob(cipherMessage) - ) - ), - spec[7] + plaintext = await window.crypto.subtle.decrypt( + cryptoSettings(adataString, spec), + await deriveKey(key, password, spec), + stringToArraybuffer( + atob(cipherMessage) + ) ); } catch(err) { + console.error(err); return ''; } + try { + return await decompress(plaintext, spec[7], zlib); + } catch(err) { + Alert.showError(err); + return err; + } }; /** @@ -1194,7 +1211,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.getPasteId = function() { const idRegEx = /^[a-z0-9]{16}$/; - const idRegExFind = /[a-z0-9]{16}/; // return cached value if (id !== null) { @@ -1483,7 +1499,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { const alertType = [ 'loading', // not in bootstrap CSS, but using a plausible value here 'info', // status icon - 'warning', // not used yet + 'warning', // warning icon 'danger' // error icon ]; @@ -1527,28 +1543,35 @@ jQuery.PrivateBin = (function($, RawDeflate) { icon = null; // icons not supported in this case } } + let $translationTarget = $element; - // handle icon - if (icon !== null && // icon was passed - icon !== currentIcon[id] // and it differs from current icon - ) { - let $glyphIcon = $element.find(':first'); + // handle icon, if template uses one + const $glyphIcon = $element.find(':first'); + if ($glyphIcon.length) { + // if there is an icon, we need to provide an inner element + // to translate the message into, instead of the parent + $translationTarget = $(''); + $element.html(' ').prepend($glyphIcon).append($translationTarget); - // remove (previous) icon - $glyphIcon.removeClass(currentIcon[id]); + if (icon !== null && // icon was passed + icon !== currentIcon[id] // and it differs from current icon + ) { + // remove (previous) icon + $glyphIcon.removeClass(currentIcon[id]); - // any other thing as a string (e.g. 'null') (only) removes the icon - if (typeof icon === 'string') { - // set new icon - currentIcon[id] = 'glyphicon-' + icon; - $glyphIcon.addClass(currentIcon[id]); + // any other thing as a string (e.g. 'null') (only) removes the icon + if (typeof icon === 'string') { + // set new icon + currentIcon[id] = 'glyphicon-' + icon; + $glyphIcon.addClass(currentIcon[id]); + } } } // show text if (args !== null) { // add jQuery object to it as first parameter - args.unshift($element); + args.unshift($translationTarget); // pass it to I18n I18n._.apply(this, args); } @@ -1573,6 +1596,25 @@ jQuery.PrivateBin = (function($, RawDeflate) { handleNotification(1, $statusMessage, message, icon); }; + /** + * display a warning message + * + * This automatically passes the text to I18n for translation. + * + * @name Alert.showWarning + * @function + * @param {string|array} message string, use an array for %s/%d options + * @param {string|null} icon optional, the icon to show, default: + * leave previous icon + */ + me.showWarning = function(message, icon) + { + $errorMessage.find(':first') + .removeClass(currentIcon[3]) + .addClass(currentIcon[2]); + handleNotification(2, $errorMessage, message, icon); + }; + /** * display an error message * @@ -1699,7 +1741,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { currentIcon = [ 'glyphicon-time', // loading icon 'glyphicon-info-sign', // status icon - '', // reserved for warning, not used yet + 'glyphicon-warning-sign', // warning icon 'glyphicon-alert' // error icon ]; }; @@ -1768,14 +1810,14 @@ jQuery.PrivateBin = (function($, RawDeflate) { return; } } - Alert.showError( - I18n._('Cannot parse response from URL shortener.') - ); + Alert.showError('Cannot parse response from URL shortener.'); } }) .fail(function(data, textStatus, errorThrown) { console.error(textStatus, errorThrown); - // we don't know why it failed, could be CORS of the external server not setup properly, in which case we follow old behavior to open it in new tab + // we don't know why it failed, could be CORS of the external + // server not setup properly, in which case we follow old + // behavior to open it in new tab window.open( `${$shortenButton.data('shortener')}${encodeURIComponent($pasteUrl.attr('href'))}`, '_blank', @@ -2731,9 +2773,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // revert loading status… me.hideAttachment(); me.hideAttachmentPreview(); - Alert.showError( - I18n._('Your browser does not support uploading encrypted files. Please use a newer browser.') - ); + Alert.showWarning('Your browser does not support uploading encrypted files. Please use a newer browser.'); return; } @@ -2965,11 +3005,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.init = function() { $attachment = $('#attachment'); - if($attachment.length){ + $dragAndDropFileName = $('#dragAndDropFileName'); + $dropzone = $('#dropzone'); + if($attachment.length) { $attachmentLink = $('#attachment a'); $attachmentPreview = $('#attachmentPreview'); - $dragAndDropFileName = $('#dragAndDropFileName'); - $dropzone = $('#dropzone'); $fileInput = $('#file'); addDragDropHandler(); @@ -4194,8 +4234,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { const PasteEncrypter = (function () { const me = {}; - let requirementsChecked = false; - /** * called after successful paste upload * @@ -4428,16 +4466,13 @@ jQuery.PrivateBin = (function($, RawDeflate) { }); cipherMessage['attachment'] = await fileReading; } else { - Alert.showError( - I18n._('Cannot process attachment data.') - ); - throw new TypeError('Cannot process attachment data.'); + const error = 'Cannot process attachment data.'; + Alert.showError(error); + throw new TypeError(error); } } catch (error) { console.error(error); - Alert.showError( - I18n._('Cannot retrieve attachment.') - ); + Alert.showError('Cannot retrieve attachment.'); throw error; } } @@ -4494,7 +4529,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // if all tries failed, we can only return an error if (plaindata.length === 0) { - throw 'failed to decipher data'; + return false; } return plaindata; @@ -4523,13 +4558,14 @@ jQuery.PrivateBin = (function($, RawDeflate) { if (password.length === 0) { throw 'waiting on user to provide a password'; } else { - displayDecryptionError('failed to decipher paste text: Incorrect password?'); - throw 'waiting on user to provide correct password'; + Alert.hideLoading(); + // reset password, so it can be re-entered + Prompt.reset(); + TopNav.showRetryButton(); + throw 'Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.'; } } - let format = '', - text = ''; if (paste.v > 1) { // version 2 paste const pasteMessage = JSON.parse(pastePlain); @@ -4616,29 +4652,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { }); } - /** - * displays and logs decryption errors - * - * @name PasteDecrypter.displayDecryptionError - * @private - * @function - * @param {string} message - */ - function displayDecryptionError(message) - { - Alert.hideLoading(); - - // log detailed error, but display generic translation - console.error(message); - Alert.showError( - I18n._('Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.') - ); - - // reset password, so it can be re-entered - Prompt.reset(); - TopNav.showRetryButton(); - } - /** * show decrypted text in the display area, including discussion (if open) * @@ -4690,170 +4703,13 @@ jQuery.PrivateBin = (function($, RawDeflate) { .catch((err) => { // wait for the user to type in the password, // then PasteDecrypter.run will be called again - console.error(err); + Alert.showError(err); }); }; return me; })(); - - /** - * initial (security) check - * - * @name InitialCheck - * @param {object} window - * @param {object} document - * @class - */ - const InitialCheck = (function () { - const me = {}; - - /** - * blacklist of UserAgents (parts) known to belong to a bot - * - * @private - * @enum {Array} - * @readonly - */ - const badBotUA = [ - 'Bot', - 'bot' - ]; - - /** - * check if the connection is insecure - * - * @private - * @name InitialCheck.isInsecureConnection - * @function - * @return {bool} - */ - function isInsecureConnection() - { - // use .isSecureContext if available - if (window.isSecureContext === true || window.isSecureContext === false) { - return !window.isSecureContext; - } - - const url = new URL(window.location); - - // HTTP is obviously insecure - if (url.protocol !== 'http:') { - return false; - } - - // filter out actually secure connections over HTTP - for (const tld of ['.onion', '.i2p']) { - if (url.hostname.endsWith(tld)) { - return false; - } - } - - // whitelist localhost for development - for (const hostname of ['localhost', '127.0.0.1', '[::1]']) { - if (url.hostname === hostname) { - return false; - } - } - - // totally INSECURE http protocol! - return true; - } - - /** - * checks whether this is a bot we dislike - * - * @private - * @name InitialCheck.isBadBot - * @function - * @return {bool} - */ - function isBadBot() { - // check whether a bot user agent part can be found in the current - // user agent - for (const UAfragment of badBotUA) { - if (navigator.userAgent.indexOf(UAfragment) >= 0) { - return true; - } - } - return false; - } - - /** - * checks whether this is an unsupported browser, via feature detection - * - * @private - * @name InitialCheck.isOldBrowser - * @function - * @return {bool} - */ - function isOldBrowser() { - // webcrypto support - if (typeof window.crypto !== 'object') { - return true; - } - - if (typeof WebAssembly !== 'object' && typeof WebAssembly.instantiate !== 'function') { - return true; - } - try { - // [\0, 'a', 's', 'm', (uint_32) 1] - smallest valid wasm module - const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)); - if ( - !( - module instanceof WebAssembly.Module && - new WebAssembly.Instance(module) instanceof WebAssembly.Instance - ) - ) { - return true; - } - } catch (e) { - return true; - } - - // not checking for async/await, ES6, Promise or Uint8Array support, - // as most browsers introduced these earlier then webassembly and webcrypto: - // https://github.com/PrivateBin/PrivateBin/pull/431#issuecomment-493129359 - - return false; - } - - /** - * init on application start, returns an all-clear signal - * - * @name InitialCheck.init - * @function - * @return {bool} - */ - me.init = function() - { - // prevent bots from viewing a paste and potentially deleting data - // when burn-after-reading is set - if (isBadBot()) { - Alert.showError('I love you too, bot…'); - return false; - } - - if (isOldBrowser()) { - // some browsers (Chrome based ones) would have webcrypto support if using HTTPS - if (isInsecureConnection()) { - Alert.showError(['Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.', 'https' + window.location.href.slice(4)]); - } - $('#oldnotice').removeClass('hidden'); - return false; - } - - if (isInsecureConnection()) { - $('#httpnotice').removeClass('hidden'); - } - - return true; - } - - return me; - })(); - /** * (controller) main PrivateBin logic * @@ -4926,9 +4782,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // missing decryption key (or paste ID) in URL? if (window.location.hash.length === 0) { - Alert.showError( - I18n._('Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)') - ); + Alert.showError('Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)'); return; } } @@ -5030,13 +4884,29 @@ jQuery.PrivateBin = (function($, RawDeflate) { DiscussionViewer.prepareNewDiscussion(); }; + /** + * try initializing zlib or display a warning if it fails, + * extracted from main init to allow unit testing + * + * @name Controller.initZ + * @function + */ + me.initZ = function() + { + z = zlib.catch(function () { + if ($('body').data('compression') !== 'none') { + Alert.showWarning('Your browser doesn\'t support WebAssembly, used for zlib compression. You can create uncompressed documents, but can\'t read compressed ones.'); + } + }); + } + /** * application start * * @name Controller.init * @function */ - me.init = async function() + me.init = function() { // first load translations I18n.loadTranslations(); @@ -5054,11 +4924,18 @@ jQuery.PrivateBin = (function($, RawDeflate) { Prompt.init(); TopNav.init(); UiHelper.init(); - z = (await zlib); - if (!InitialCheck.init()) { + + // check for legacy browsers before going any further + if (!Legacy.Check.getInit()) { + // Legacy check didn't complete, wait and try again + setTimeout(init, 500); + return; + } + if (!Legacy.Check.getStatus()) { // something major is wrong, stop right away return; } + me.initZ(); // check whether existing paste needs to be shown try { @@ -5098,7 +4975,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { ServerInteraction: ServerInteraction, PasteEncrypter: PasteEncrypter, PasteDecrypter: PasteDecrypter, - InitialCheck: InitialCheck, Controller: Controller }; })(jQuery, RawDeflate); diff --git a/js/test/Alert.js b/js/test/Alert.js index dfaf353..d59f38c 100644 --- a/js/test/Alert.js +++ b/js/test/Alert.js @@ -4,16 +4,55 @@ var common = require('../common'); describe('Alert', function () { describe('showStatus', function () { jsc.property( - 'shows a status message', + 'shows a status message (basic)', jsc.array(common.jscAlnumString()), jsc.array(common.jscAlnumString()), function (icon, message) { icon = icon.join(''); message = message.join(''); - var expected = ''; $('body').html( ''; + $('body').html( + '
' + ); + $.PrivateBin.Alert.init(); + $.PrivateBin.Alert.showWarning(message, icon); + const result = $('body').html(); + return expected === result; + } + ); + + jsc.property( + 'shows a warning message (bootstrap)', + jsc.array(common.jscAlnumString()), + jsc.array(common.jscAlnumString()), + function (message) { + message = message.join(''); + const expected = ''; + $('body').html( + '' + ); + $.PrivateBin.Alert.init(); + $.PrivateBin.Alert.showWarning(message); + const result = $('body').html(); + return expected === result; + } + ); + + jsc.property( + 'shows a warning message (bootstrap, custom icon)', + jsc.array(common.jscAlnumString()), + jsc.array(common.jscAlnumString()), + function (icon, message) { + icon = icon.join(''); + message = message.join(''); + const expected = ''; + $('body').html( + '' + ); + $.PrivateBin.Alert.init(); + $.PrivateBin.Alert.showWarning(message, icon); + const result = $('body').html(); return expected === result; } ); @@ -33,16 +141,56 @@ describe('Alert', function () { }); jsc.property( - 'shows an error message', + 'shows an error message (basic)', jsc.array(common.jscAlnumString()), jsc.array(common.jscAlnumString()), function (icon, message) { icon = icon.join(''); message = message.join(''); - var expected = ''; $('body').html( ''; $('body').html( '' + + '', { + 'userAgent': prefix + botBit + suffix + } + ); + Legacy.Check.init(); + const result1 = Legacy.Check.getInit() && !Legacy.Check.getStatus(), + result2 = (document.getElementById('errormessage').className !== 'hidden'); + clean(); + return result1 && result2; + } + ), + {tests: 10}); + }); + + jsc.property( + 'shows error, if no webcrypto is detected', + 'bool', + jsc.elements(['localhost', '127.0.0.1', '[::1]', '']), + jsc.nearray(common.jscA2zString()), + jsc.elements(['.onion', '.i2p', '']), + function (secureProtocol, localhost, domain, tld) { + const isDomain = localhost === '', + isSecureContext = secureProtocol || !isDomain || tld.length > 0, + clean = jsdom( + '' + + '' + + '', + { + 'url': (secureProtocol ? 'https' : 'http' ) + '://' + + (isDomain ? domain.join('') + tld : localhost) + '/' + } + ); + Legacy.Check.init(); + const result1 = Legacy.Check.getInit() && !Legacy.Check.getStatus(), + result2 = isSecureContext === (document.getElementById('insecurecontextnotice').className === 'hidden'), + result3 = (document.getElementById('oldnotice').className !== 'hidden'); + clean(); + return result1 && result2 && result3; + } + ); + + jsc.property( + 'shows error, if HTTP only site is detected', + 'bool', + jsc.nearray(common.jscA2zString()), + function (secureProtocol, domain) { + const clean = jsdom( + '' + + '', + { + 'url': (secureProtocol ? 'https' : 'http' ) + '://' + domain.join('') + '/' + } + ); + window.crypto = new WebCrypto(); + Legacy.Check.init(); + const result1 = Legacy.Check.getInit() && Legacy.Check.getStatus(), + result2 = secureProtocol === (document.getElementById('httpnotice').className === 'hidden'); + clean(); + return result1 && result2; + } + ); + }); +}); + diff --git a/js/test/CryptTool.js b/js/test/CryptTool.js index 80ea5ec..627a242 100644 --- a/js/test/CryptTool.js +++ b/js/test/CryptTool.js @@ -18,13 +18,15 @@ describe('CryptTool', function () { // pause to let async functions conclude await new Promise(resolve => setTimeout(resolve, 300)); let clean = jsdom(); + // ensure zlib is getting loaded + $.PrivateBin.Controller.initZ(); window.crypto = new WebCrypto(); message = message.trim(); let cipherMessage = await $.PrivateBin.CryptTool.cipher( key, password, message, [] ), plaintext = await $.PrivateBin.CryptTool.decipher( - key, password, cipherMessage + key, password, cipherMessage ); clean(); return message === plaintext; @@ -179,6 +181,8 @@ describe('CryptTool', function () { let message = fs.readFileSync('test/compression-sample.txt', 'utf8'), clean = jsdom(); window.crypto = new WebCrypto(); + // ensure zlib is getting loaded + $.PrivateBin.Controller.initZ(); let cipherMessage = await $.PrivateBin.CryptTool.cipher( 'foo', 'bar', message, [] ), @@ -222,6 +226,8 @@ isWhile : interp (while expr sBody) (MemElem mem) = conseq_or_bottom inv (interp (nth_iterate sBody n) (MemElem mem)) `; let clean = jsdom(); + // ensure zlib is getting loaded + $.PrivateBin.Controller.initZ(); window.crypto = new WebCrypto(); let cipherMessage = await $.PrivateBin.CryptTool.cipher( key, password, message, [] diff --git a/js/test/Helper.js b/js/test/Helper.js index eac22fa..3002d2a 100644 --- a/js/test/Helper.js +++ b/js/test/Helper.js @@ -183,9 +183,9 @@ describe('Helper', function () { 'string', 'string', function (prefix, uint, middle, string, postfix) { - prefix = prefix.replace(/%(s|d)/g, '%%'); - middle = middle.replace(/%(s|d)/g, '%%'); - postfix = postfix.replace(/%(s|d)/g, '%%'); + prefix = prefix.replace(/%(s|d)/g, ''); + middle = middle.replace(/%(s|d)/g, ''); + postfix = postfix.replace(/%(s|d)/g, ''); var params = [prefix + '%d' + middle + '%s' + postfix, uint, string], result = prefix + uint + middle + string + postfix; return result === $.PrivateBin.Helper.sprintf.apply(this, params); @@ -199,9 +199,9 @@ describe('Helper', function () { 'string', 'string', function (prefix, uint, middle, string, postfix) { - prefix = prefix.replace(/%(s|d)/g, '%%'); - middle = middle.replace(/%(s|d)/g, '%%'); - postfix = postfix.replace(/%(s|d)/g, '%%'); + prefix = prefix.replace(/%(s|d)/g, ''); + middle = middle.replace(/%(s|d)/g, ''); + postfix = postfix.replace(/%(s|d)/g, ''); var params = [prefix + '%s' + middle + '%d' + postfix, string, uint], result = prefix + string + middle + uint + postfix; return result === $.PrivateBin.Helper.sprintf.apply(this, params); diff --git a/js/test/InitialCheck.js b/js/test/InitialCheck.js deleted file mode 100644 index 5b0778c..0000000 --- a/js/test/InitialCheck.js +++ /dev/null @@ -1,88 +0,0 @@ -'use strict'; -var common = require('../common'); - -describe('InitialCheck', function () { - describe('init', function () { - this.timeout(30000); - before(function () { - cleanup(); - }); - - it('returns false and shows error, if a bot UA is detected', function () { - jsc.assert(jsc.forall( - 'string', - jsc.elements(['Bot', 'bot']), - 'string', - function (prefix, botBit, suffix) { - const clean = jsdom('', { - 'userAgent': prefix + botBit + suffix - }); - $('body').html( - '' + - '' - ); - $.PrivateBin.Alert.init(); - window.crypto = null; - const result1 = !$.PrivateBin.InitialCheck.init(), - result2 = !$('#errormessage').hasClass('hidden'); - clean(); - return result1 && result2; - } - ), - {tests: 10}); - }); - - jsc.property( - 'shows error, if no webcrypto is detected', - 'bool', - jsc.elements(['localhost', '127.0.0.1', '[::1]', '']), - jsc.nearray(common.jscA2zString()), - jsc.elements(['.onion', '.i2p', '']), - function (secureProtocol, localhost, domain, tld) { - const isDomain = localhost === '', - isSecureContext = secureProtocol || !isDomain || tld.length > 0, - clean = jsdom('', { - 'url': (secureProtocol ? 'https' : 'http' ) + '://' + - (isDomain ? domain.join('') + tld : localhost) + '/' - }); - $('body').html( - ''+ - '' - ); - $.PrivateBin.Alert.init(); - const result1 = !$.PrivateBin.InitialCheck.init(), - result2 = isSecureContext === $('#errormessage').hasClass('hidden'), - result3 = !$('#oldnotice').hasClass('hidden'); - clean(); - return result1 && result2 && result3; - } - ); - - jsc.property( - 'shows error, if HTTP only site is detected', - 'bool', - jsc.elements(['localhost', '127.0.0.1', '[::1]', '']), - jsc.nearray(common.jscA2zString()), - jsc.elements(['.onion', '.i2p', '']), - function (secureProtocol, localhost, domain, tld) { - const isDomain = localhost === '', - isSecureContext = secureProtocol || !isDomain || tld.length > 0, - clean = jsdom('', { - 'url': (secureProtocol ? 'https' : 'http' ) + '://' + - (isDomain ? domain.join('') + tld : localhost) + '/' - }); - $('body').html( - ''+ - '' - ); - $.PrivateBin.Alert.init(); - window.crypto = null; - const result1 = $.PrivateBin.InitialCheck.init(), - result2 = isSecureContext === $('#httpnotice').hasClass('hidden'); - clean(); - return result1 && result2; - } - ); - }); -}); - diff --git a/lib/Controller.php b/lib/Controller.php index 1a70873..55248c6 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -388,6 +388,7 @@ class Controller $page->assign('URLSHORTENER', $this->_conf->getKey('urlshortener')); $page->assign('QRCODE', $this->_conf->getKey('qrcode')); $page->assign('HTTPWARNING', $this->_conf->getKey('httpwarning')); + $page->assign('HTTPSLINK', 'https://' . $this->_request->getHost() . $this->_request->getRequestUri()); $page->assign('COMPRESSION', $this->_conf->getKey('compression')); $page->draw($this->_conf->getKey('template')); } diff --git a/lib/Request.php b/lib/Request.php index 3c885e4..80aac6a 100644 --- a/lib/Request.php +++ b/lib/Request.php @@ -193,6 +193,19 @@ class Request $this->_params[$param] : $default; } + /** + * Get host as requested by the client + * + * @access public + * @return string + */ + public function getHost() + { + return array_key_exists('HTTP_HOST', $_SERVER) ? + htmlspecialchars($_SERVER['HTTP_HOST']) : + 'localhost'; + } + /** * Get request URI * @@ -202,8 +215,8 @@ class Request public function getRequestUri() { return array_key_exists('REQUEST_URI', $_SERVER) ? - htmlspecialchars( - parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) + htmlspecialchars( + parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ) : '/'; } diff --git a/robots.txt b/robots.txt index a1537be..7aa8150 100644 --- a/robots.txt +++ b/robots.txt @@ -5,5 +5,4 @@ # directory. User-agent: * -Allow: /index.php Disallow: / diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 162f7c1..639664d 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -71,10 +71,8 @@ if ($MARKDOWN): endif; ?> - - + + @@ -446,10 +444,6 @@ endif; - + diff --git a/tpl/page.php b/tpl/page.php index 3e23dbf..d453439 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -49,10 +49,8 @@ if ($MARKDOWN): endif; ?> - - + + @@ -77,8 +75,7 @@ endif;


-
-
+