Kaynağa Gözat

Merge branch 'httpinsecure'

El RIDO 7 yıl önce
ebeveyn
işleme
f5fee9b44a

+ 6 - 0
cfg/conf.sample.php

@@ -77,6 +77,12 @@ languageselection = false
 ; sha256 in HMAC for the deletion token
 zerobincompatibility = false
 
+; Enable or disable the warning message when the site is served over an insecure connection (insecure HTTP instead of HTTPS), defaults to true.
+; Secure transport methods like Tor and I2P domains are automatically whitelisted.
+; It is **strongly discouraged** to disable this.
+; See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection for more information.
+httpwarning = true
+
 [expire]
 ; expire value that is selected per default
 ; make sure the value exists in [expire_options]

+ 3 - 4
css/bootstrap/privatebin.css

@@ -81,12 +81,11 @@ body.loading {
 }
 
 .dragAndDropFile{
-        color:#777;
-        font-size:1em;
-        display:inline;
+	color:#777;
+	font-size:1em;
+	display:inline;
 }
 
-
 #deletelink {
 	float: right;
 	margin-left: 5px;

+ 2 - 2
css/privatebin.css

@@ -290,9 +290,9 @@ input {
 
 #ienotice a { color: #000; }
 
-#oldienotice { display: none; }
+#oldnotice, #httpnotice { display: none; }
 
-.errorMessage {
+#errormessage, .errorMessage {
 	background-color: #f77 !important;
 	color:#ff0;
 }

+ 10 - 3
i18n/de.json

@@ -149,10 +149,17 @@
     "Loading…": "Lädt…",
     "Decrypting paste…": "Entschlüssle Text…",
     "Preparing new paste…": "Bereite neuen Text vor…",
-    "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>.":
-        "Wenn diese Nachricht nicht mehr verschwindet, schau bitte in <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">die FAQ</a> (englisch), um zu sehen, wie der Fehler behoben werden kann.",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "Wenn diese Nachricht nicht mehr verschwindet, schau bitte in <a href=\"%s\">die FAQ</a> (englisch), um zu sehen, wie der Fehler behoben werden kann.",
     "+++ no paste text +++": "+++ kein Paste-Text +++",
     "Could not get paste data: %s":
         "Text konnte nicht geladen werden: %s",
-    "QR code": "QR code"
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 11 - 4
i18n/es.json

@@ -149,10 +149,17 @@
     "Loading…": "Cargando…",
     "Decrypting paste…": "Descifrando \"paste\"…",
     "Preparing new paste…": "Preparando \"paste\" nuevo…",
-    "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>.":
-        "En caso de que este mensaje nunca desaparezca por favor revise <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">este FAQ para obtener información para solucionar problemas</a>.",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "En caso de que este mensaje nunca desaparezca por favor revise <a href=\"%s\">este FAQ para obtener información para solucionar problemas</a>.",
     "+++ no paste text +++": "+++ \"paste\" sin texto +++",
     "Could not get paste data: %s":
         "No se pudieron obtener los datos: %s",
-    "QR code": "Código QR"
-}
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
+}

+ 11 - 4
i18n/fr.json

@@ -158,10 +158,17 @@
     "Loading…": "Chargement…",
     "Decrypting paste…": "Déchiffrement du paste…",
     "Preparing new paste…": "Préparation du paste…",
-    "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>.":
-        "Si ce message ne disparaîssait pas, jetez un oeil à <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">cette FAQ pour des idées de résolution</a> (en Anglais).",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "Si ce message ne disparaîssait pas, jetez un oeil à <a href=\"%s\">cette FAQ pour des idées de résolution</a> (en Anglais).",
     "+++ no paste text +++": "+++ pas de paste-text +++",
     "Could not get paste data: %s":
         "Could not get paste data: %s",
-    "QR code": "QR code"
-}
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
+}

+ 11 - 4
i18n/hu.json

@@ -149,10 +149,17 @@
     "Loading…": "Folyamatban...",
     "Decrypting paste…": "Bejegyzés dekódolása...",
     "Preparing new paste…": "Új bejegyzés előkészítése...",
-    "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>.":
-        "Abban az esetben, ha ez az üzenet mindig látható lenne, látogass el a <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">Gyakran Ismételt Kérdések szekcióba a megoldásához</a>.",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "Abban az esetben, ha ez az üzenet mindig látható lenne, látogass el a <a href=\"%s\">Gyakran Ismételt Kérdések szekcióba a megoldásához</a>.",
     "+++ no paste text +++": "+++ nincs beillesztett szöveg +++",
     "Could not get paste data: %s":
         "Could not get paste data: %s",
-    "QR code": "QR code"
-}
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
+}

+ 11 - 4
i18n/it.json

@@ -149,10 +149,17 @@
     "Loading…": "Carico…",
     "Decrypting paste…": "Decifro il messaggio…",
     "Preparing new paste…": "Preparo il nuovo messaggio…",
-    "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>.":
-        "Nel caso questo messaggio non scompaia, controlla questa <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">FAQ</a> per trovare informazioni su come risolvere il problema (in Inglese).",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "Nel caso questo messaggio non scompaia, controlla questa <a href=\"%s\">FAQ</a> per trovare informazioni su come risolvere il problema (in Inglese).",
     "+++ no paste text +++": "+++ nessun testo nel messaggio +++",
     "Could not get paste data: %s":
         "Could not get paste data: %s",
-    "QR code": "QR code"
-}
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
+}

+ 11 - 4
i18n/nl.json

@@ -149,10 +149,17 @@
     "Loading…": "Laden…",
     "Decrypting paste…": "Geplakte tekst decoderen…",
     "Preparing new paste…": "Nieuwe geplakte tekst voorbereiden…",
-    "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>.":
-        "In het geval dat dit bericht nooit verdwijnt, kijkt u dan eens naar <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\"> veelgestelde vragen voor informatie over het oplossen van problemen </a>.",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "In het geval dat dit bericht nooit verdwijnt, kijkt u dan eens naar <a href=\"%s\"> veelgestelde vragen voor informatie over het oplossen van problemen </a>.",
     "+++ no paste text +++": "+++ geen geplakte tekst +++",
     "Could not get paste data: %s":
         "Could not get paste data: %s",
-    "QR code": "QR code"
-}
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
+}

+ 10 - 3
i18n/no.json

@@ -149,10 +149,17 @@
     "Loading…": "Laster…",
     "Decrypting paste…": "Dekrypterer innlegg…",
     "Preparing new paste…": "Klargjør nytt innlegg…",
-    "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>.":
-        "Hvis denne meldingen ikke forsvinner kan du ta en titt på siden med <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">ofte stilte spørsmål</a> for informasjon om feilsøking.",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "Hvis denne meldingen ikke forsvinner kan du ta en titt på siden med <a href=\"%s\">ofte stilte spørsmål</a> for informasjon om feilsøking.",
     "+++ no paste text +++": "+++ ingen innleggstekst +++",
     "Could not get paste data: %s":
         "Kunne ikke hente utklippsdata: %s",
-    "QR code": "QR code"
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 10 - 3
i18n/oc.json

@@ -158,10 +158,17 @@
     "Loading…": "Cargament…",
     "Decrypting paste…": "Deschirament del tèxte…",
     "Preparing new paste…": "Preparacion…",
-    "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>.":
-        "Se per cas aqueste messatge quita pas de s’afichar mercés de gaitar <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">aquesta FAQ per las solucions</a> (en anglés).",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "Se per cas aqueste messatge quita pas de s’afichar mercés de gaitar <a href=\"%s\">aquesta FAQ per las solucions</a> (en anglés).",
     "+++ no paste text +++": "+++ cap de tèxte pegat +++",
     "Could not get paste data: %s":
         "Recuperacion impossibla de las donadas copiadas : %s",
-    "QR code": "Còdi QR"
+    "QR code": "Còdi 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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 10 - 3
i18n/pl.json

@@ -149,10 +149,17 @@
     "Loading…": "Wczytywanie…",
     "Decrypting paste…": "Odszyfrowywanie wklejki…",
     "Preparing new paste…": "Przygotowywanie nowej wklejki…",
-    "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>.":
-        "W przypadku gdy ten komunikat nigdy nie znika, proszę spójrz na <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">to FAQ aby rozwiązać problem</a> (po angielsku).",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "W przypadku gdy ten komunikat nigdy nie znika, proszę spójrz na <a href=\"%s\">to FAQ aby rozwiązać problem</a> (po angielsku).",
     "+++ no paste text +++": "+++ brak wklejonego tekstu +++",
     "Could not get paste data: %s":
         "Nie można było pobrać danych wklejki: %s",
-    "QR code": "Kod QR"
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 11 - 4
i18n/pt.json

@@ -149,10 +149,17 @@
     "Loading…": "Carregando…",
     "Decrypting paste…": "Decifrando cópia…",
     "Preparing new paste…": "Preparando nova cópia…",
-    "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>.":
-        "Caso essa mensagem nunca desapareça, por favor veja <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">este FAQ para saber como resolver os problemas</a>.",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "Caso essa mensagem nunca desapareça, por favor veja <a href=\"%s\">este FAQ para saber como resolver os problemas</a>.",
     "+++ no paste text +++": "+++ sem texto de cópia +++",
     "Could not get paste data: %s":
         "Could not get paste data: %s",
-    "QR code": "QR code"
-}
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
+}

+ 10 - 3
i18n/ru.json

@@ -159,10 +159,17 @@
     "Loading…": "Загрузка…",
     "Decrypting paste…": "Расшифровка записи…",
     "Preparing new paste…": "Подготовка новой записи…",
-    "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>.":
-        "Если данное сообщение не исчезает длительное время, посмотрите <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">этот FAQ с информацией о возможном решении проблемы (на английском)</a>.",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "Если данное сообщение не исчезает длительное время, посмотрите <a href=\"%s\">этот FAQ с информацией о возможном решении проблемы (на английском)</a>.",
     "+++ no paste text +++": "+++ в записи нет текста +++",
     "Could not get paste data: %s":
         "Не удалось получить данные записи: %s",
-    "QR code": "QR code"
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 10 - 3
i18n/sl.json

@@ -158,10 +158,17 @@
     "Loading…": "Loading…",
     "Decrypting paste…": "Decrypting paste…",
     "Preparing new paste…": "Preparing new paste…",
-    "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>.":
-        "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> (in English).",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a> (in English).",
     "+++ no paste text +++": "+++ no paste text +++",
     "Could not get paste data: %s":
         "Could not get paste data: %s",
-    "QR code": "QR code"
+    "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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 10 - 3
i18n/zh.json

@@ -149,10 +149,17 @@
     "Loading…": "载入中…",
     "Decrypting paste…": "正在解密",
     "Preparing new paste…": "正在准备新的粘贴内容",
-    "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>.":
-        "如果这个消息一直存在,请参考 <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">这里的 FAQ (英文版)</a>进行故障排除。",
+    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
+        "如果这个消息一直存在,请参考 <a href=\"%s\">这里的 FAQ (英文版)</a>进行故障排除。",
     "+++ no paste text +++": "+++ 没有粘贴内容 +++",
     "Could not get paste data: %s":
         "无法获取粘贴数据:%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 <a href=\"%s\">see this FAQ entry</a>.":
+        "For more information <a href=\"%s\">see this FAQ entry</a>.",
+    "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
+        "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
 }

+ 1 - 0
js/common.js

@@ -5,6 +5,7 @@ global.assert = require('assert');
 global.jsc = require('jsverify');
 global.jsdom = require('jsdom-global');
 global.cleanup = global.jsdom();
+global.URL = require('jsdom-url').URL;
 global.fs = require('fs');
 global.WebCrypto = require('node-webcrypto-ossl');
 

+ 1 - 0
js/package.json

@@ -10,6 +10,7 @@
   "devDependencies": {
     "jsdom": "^9.12.0",
     "jsdom-global": "^2.1.1",
+    "jsdom-url": "^2.2.1",
     "jsverify": "^0.8.3",
     "mime-types": "^2.1.20",
     "node-webcrypto-ossl": "^1.0.37"

+ 179 - 93
js/privatebin.js

@@ -176,18 +176,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
     const Helper = (function () {
         const me = {};
 
-        /**
-         * blacklist of UserAgents (parts) known to belong to a bot
-         *
-         * @private
-         * @enum   {Object}
-         * @readonly
-         */
-        const BadBotUA = [
-            'Bot',
-            'bot'
-        ];
-
         /**
          * cache for script location
          *
@@ -365,25 +353,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             return baseUri;
         };
 
-
-        /**
-         * checks whether this is a bot we dislike
-         *
-         * @name   Helper.isBadBot
-         * @function
-         * @return {bool}
-         */
-        me.isBadBot = function() {
-            // check whether a bot user agent part can be found in the current
-            // user agent
-            for (let i = 0; i < BadBotUA.length; ++i) {
-                if (navigator.userAgent.indexOf(BadBotUA) >= 0) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
         /**
          * wrap an object into a Paste, used for mocking in the unit tests
          *
@@ -861,28 +830,13 @@ jQuery.PrivateBin = (function($, RawDeflate) {
          */
         function getRandomBytes(length)
         {
-            if (
-                typeof window !== 'undefined' &&
-                typeof Uint8Array !== 'undefined' &&
-                String.fromCodePoint &&
-                (
-                    typeof window.crypto !== 'undefined' ||
-                    typeof window.msCrypto !== 'undefined'
-                )
-            ) {
-                // modern browser environment
-                let bytes       = '';
-                const byteArray = new Uint8Array(length),
-                      crypto    = window.crypto || window.msCrypto;
-                crypto.getRandomValues(byteArray);
-                for (let i = 0; i < length; ++i) {
-                    bytes += String.fromCharCode(byteArray[i]);
-                }
-                return bytes;
-            } else {
-                // legacy browser or unsupported environment
-                throw 'No supported crypto API detected, you may read pastes and comments, but can\'t create pastes or add new comments.';
+            let bytes       = '';
+            const byteArray = new Uint8Array(length);
+            window.crypto.getRandomValues(byteArray);
+            for (let i = 0; i < length; ++i) {
+                bytes += String.fromCharCode(byteArray[i]);
             }
+            return bytes;
         }
 
         /**
@@ -1227,30 +1181,20 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             }
 
             // do use URL interface, if possible
-            if (window.URL && window.URL.prototype && ('searchParams' in window.URL.prototype)) {
-                try {
-                    const url = new URL(window.location);
+            const url = new URL(window.location);
 
-                    for (const param of url.searchParams) {
-                        const key = param[0];
-                        const value = param[1];
+            for (const param of url.searchParams) {
+                const key = param[0];
+                const value = param[1];
 
-                        if (value === '' && idRegEx.test(key)) {
-                            // safe, as the whole regex is matched
-                            id = key;
-                            return id;
-                        }
-                    }
-                } catch (e) {
-                    // fallback below
-                    console.error('URL interface not properly supported, error:', e);
+                if (value === '' && idRegEx.test(key)) {
+                    // safe, as the whole regex is matched
+                    id = key;
+                    return key;
                 }
             }
 
-            // Attention: This also returns the delete token inside of the ID, if it is specified
-            id = (window.location.search.match(idRegExFind) || [''])[0];
-
-            if (id === '') {
+            if (id === null) {
                 throw 'no paste id given';
             }
 
@@ -1685,7 +1629,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
          */
         me.hideMessages = function()
         {
-            // also possible: $('.statusmessage').addClass('hidden');
             $statusMessage.addClass('hidden');
             $errorMessage.addClass('hidden');
         };
@@ -4555,6 +4498,163 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         return me;
     })();
 
+
+    /**
+     * initial (security) check
+     *
+     * @name   InitialCheck
+     * @param  {object} window
+     * @param  {object} document
+     * @class
+     */
+    var InitialCheck = (function () {
+        var 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 false;
+            }
+
+            if (typeof WebAssembly !== 'object' && typeof WebAssembly.instantiate !== 'function') {
+                return false;
+            }
+            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 false;
+                }
+            } catch (e) {
+                return false;
+            }
+
+             // 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 true;
+        }
+
+        /**
+         * 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 <a href="%s">switching to HTTPS</a>.', 'https' + window.location.href.slice(4)]);
+                }
+                $('#oldnotice').removeClass('hidden');
+                return false;
+            }
+
+            if (isInsecureConnection()) {
+                $('#httpnotice').removeClass('hidden');
+            }
+
+            return true;
+        }
+
+        return me;
+    })();
+
     /**
      * (controller) main PrivateBin logic
      *
@@ -4602,18 +4702,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             Alert.hideLoading();
         };
 
-        /**
-         * shows how we much we love bots that execute JS ;)
-         *
-         * @name   Controller.showBadBotMessage
-         * @function
-         */
-        me.showBadBotMessage = function()
-        {
-            TopNav.hideAllButtons();
-            Alert.showError('I love you too, bot…');
-        }
-
         /**
          * shows the loaded paste
          *
@@ -4741,6 +4829,10 @@ jQuery.PrivateBin = (function($, RawDeflate) {
 
             // initialize other modules/"classes"
             Alert.init();
+            if (!InitialCheck.init()) {
+                // something major is wrong, stop right away
+                return;
+            }
             Model.init();
             AttachmentViewer.init();
             DiscussionViewer.init();
@@ -4760,19 +4852,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
                 return me.newPaste();
             }
 
-            // if delete token is passed (i.e. paste has been deleted by this access)
-            // there is no more stuf we need to do
+            // if delete token is passed (i.e. paste has been deleted by this
+            // access), there is nothing more to do
             if (Model.hasDeleteToken()) {
                 return;
             }
 
-            // prevent bots from viewing a paste and potentially deleting data
-            // when burn-after-reading is set
-            // see https://github.com/elrido/ZeroBin/issues/11
-            if (Helper.isBadBot()) {
-                return me.showBadBotMessage();
-            }
-
             // display an existing paste
             return me.showPaste();
         }
@@ -4797,6 +4882,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         ServerInteraction: ServerInteraction,
         PasteEncrypter: PasteEncrypter,
         PasteDecrypter: PasteDecrypter,
+        InitialCheck: InitialCheck,
         Controller: Controller
     };
 })(jQuery, RawDeflate);

+ 1 - 0
js/test/Alert.js

@@ -218,6 +218,7 @@ describe('Alert', function () {
                     return jsc.random(0, 1) ? true : $element;
                 });
                 functions[trigger](message);
+                $.PrivateBin.Alert.setCustomHandler(null);
                 return handlerCalled;
             }
         );

+ 2 - 2
js/test/CryptTool.js

@@ -10,7 +10,7 @@ describe('CryptTool', function () {
 
         this.timeout(30000);
         it('can en- and decrypt any message', function () {
-            jsc.check(jsc.forall(
+            jsc.assert(jsc.forall(
                 'string',
                 'string',
                 'string',
@@ -193,7 +193,7 @@ describe('CryptTool', function () {
         });
 
         it('can en- and decrypt a particular message (#260)', function () {
-            jsc.check(jsc.forall(
+            jsc.assert(jsc.forall(
                 'string',
                 'string',
                 async function (key, password) {

+ 89 - 0
js/test/InitialCheck.js

@@ -0,0 +1,89 @@
+'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(
+                        '<html><body><div id="errormessage" class="hidden"></div>' +
+                        '</body></html>'
+                    );
+                    $.PrivateBin.Alert.init();
+                    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(
+                    '<html><body><div id="errormessage" class="hidden"></div>'+
+                    '<div id="oldnotice" class="hidden"></div></body></html>'
+                );
+                const crypto = window.crypto;
+                window.crypto = null;
+                $.PrivateBin.Alert.init();
+                const result1 = !$.PrivateBin.InitialCheck.init(),
+                      result2 = isSecureContext === $('#errormessage').hasClass('hidden'),
+                      result3 = !$('#oldnotice').hasClass('hidden');
+                window.crypto = crypto;
+                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(
+                    '<html><body><div id="httpnotice" class="hidden"></div>'+
+                    '</body></html>'
+                );
+                $.PrivateBin.Alert.init();
+                const result1 = $.PrivateBin.InitialCheck.init(),
+                      result2 = isSecureContext === $('#httpnotice').hasClass('hidden');
+                clean();
+                return result1 && result2;
+            }
+        );
+    });
+});
+

+ 4 - 2
js/test/Model.js

@@ -93,8 +93,9 @@ describe('Model', function () {
                     clean            = jsdom('', {
                         url: schema.join('') + '://' + address.join('') +
                              '/?' + queryString + '#' + fragment
-                    }),
-                    result = $.PrivateBin.Model.getPasteId();
+                    });
+                    global.URL = require('jsdom-url').URL;
+                    var result = $.PrivateBin.Model.getPasteId();
                 $.PrivateBin.Model.reset();
                 clean();
                 return pasteIdString === result;
@@ -111,6 +112,7 @@ describe('Model', function () {
                              '/#' + fragment
                     }),
                     result = false;
+                global.URL = require('jsdom-url').URL;
                 try {
                     $.PrivateBin.Model.getPasteId();
                 }

+ 1 - 1
js/test/ServerInteraction.js

@@ -9,7 +9,7 @@ describe('ServerInteraction', function () {
         });
         this.timeout(30000);
         it('can prepare an encrypted paste', function () {
-            jsc.check(jsc.forall(
+            jsc.assert(jsc.forall(
                 'string',
                 'string',
                 'string',

+ 1 - 0
lib/Configuration.php

@@ -55,6 +55,7 @@ class Configuration
             'icon'                     => 'identicon',
             'cspheader'                => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\' \'unsafe-eval\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; Referrer-Policy: \'no-referrer\'; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals',
             'zerobincompatibility'     => false,
+            'httpwarning'              => true,
         ),
         'expire' => array(
             'default' => '1week',

+ 1 - 0
lib/Controller.php

@@ -386,6 +386,7 @@ class Controller
         $page->assign('EXPIREDEFAULT', $this->_conf->getKey('default', 'expire'));
         $page->assign('URLSHORTENER', $this->_conf->getKey('urlshortener'));
         $page->assign('QRCODE', $this->_conf->getKey('qrcode'));
+        $page->assign('HTTPWARNING', $this->_conf->getKey('httpwarning'));
         $page->draw($this->_conf->getKey('template'));
     }
 

+ 21 - 10
tpl/bootstrap.php

@@ -72,9 +72,9 @@ if ($MARKDOWN):
 endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.10.js" integrity="sha512-CqskSFXERL38A1PJP9BlO04me7kmwgDIhN1+k24RoFiisEwXA0BMdm0lzJC7g5jCRZ4k5OYdOJGEqW9CwDl4CA==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-lGood7Jy+Un5JTf3z5vfcE8an2fkQTxXOP9iEJFTIWi0d77RWlqumSTD1eB9ruzKCZ1a8fJC9gNei6GnEeW2vg==" crossorigin="anonymous"></script>
-		<!--[if lt IE 10]>
-		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-V0v5OOCcrMFtPsP9xWbKjoaRBobWrMdKdiDPn1tK8Kq8uzbEOK8tY0JXCbEqVpPyJ3/hVrtfjdXhgGaxeMUj3g==" crossorigin="anonymous"></script>
+		<!--[if IE]>
+		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;}</style>
 		<![endif]-->
 		<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" />
@@ -440,31 +440,42 @@ if ($FILEUPLOAD):
 <?php
 endif;
 ?>
-				<div id="status" role="alert" class="statusmessage alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>">
+				<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; ?>
 				</div>
-				<div id="errormessage" role="alert" class="statusmessage<?php echo empty($ERROR) ? ' hidden' : '' ?> alert alert-danger">
+				<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; ?>
 				</div>
 				<noscript>
-					<div id="noscript" role="alert" class="nonworking alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
+					<div id="noscript" role="alert" class="alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
 						<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
 						<?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)), PHP_EOL; ?>
 					</div>
 				</noscript>
-				<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger">
+				<div id="oldnotice" role="alert" class="hidden alert alert-danger">
 					<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
 					<?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?>
 				</div>
-				<div id="ienotice" role="alert" class="hidden alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
+				<div id="ienotice" role="alert" class="hidden alert alert-danger">
 					<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
 					<?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), 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>…
 				</div>
+<?php
+if ($HTTPWARNING):
+?>
+				<div id="httpnotice" role="alert" class="hidden alert alert-danger">
+					<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
+					<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'), PHP_EOL; ?><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>
+<?php
+endif;
+?>
 				<div id="pastesuccess" role="alert" class="hidden alert alert-success">
 					<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
 					<div id="deletelink"></div>
@@ -502,10 +513,10 @@ endif;
 				</div>
 			</section>
 			<section class="container">
-				<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide">
+				<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="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-not-the-loading-message-go-away'); ?></span>
 				</div>
 			</section>
 			<footer class="container">

+ 15 - 5
tpl/page.php

@@ -50,9 +50,9 @@ if ($MARKDOWN):
 endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.10.js" integrity="sha512-CqskSFXERL38A1PJP9BlO04me7kmwgDIhN1+k24RoFiisEwXA0BMdm0lzJC7g5jCRZ4k5OYdOJGEqW9CwDl4CA==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-lGood7Jy+Un5JTf3z5vfcE8an2fkQTxXOP9iEJFTIWi0d77RWlqumSTD1eB9ruzKCZ1a8fJC9gNei6GnEeW2vg==" crossorigin="anonymous"></script>
-		<!--[if lt IE 10]>
-		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-V0v5OOCcrMFtPsP9xWbKjoaRBobWrMdKdiDPn1tK8Kq8uzbEOK8tY0JXCbEqVpPyJ3/hVrtfjdXhgGaxeMUj3g==" crossorigin="anonymous"></script>
+		<!--[if IE]>
+		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;}</style>
 		<![endif]-->
 		<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" />
@@ -78,12 +78,22 @@ endif;
 			<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="oldienotice" class="nonworking"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)); ?></div>
-			<div id="ienotice"><?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
+			<div id="oldnotice" class="nonworking"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)); ?></div>
+			<div id="ienotice" class="nonworking"><?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), 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>…
 			</div>
+<?php
+if ($HTTPWARNING):
+?>
+			<div id="httpnotice" class="errorMessage">
+				<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'); ?>
+				<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>
+<?php
+endif;
+?>
 		</header>
 		<section>
 			<article>

+ 1 - 1
tst/README.md

@@ -89,7 +89,7 @@ and jsdom-global locally:
 ```console
 $ npm install -g mocha nyc
 $ cd PrivateBin/js
-$ npm install jsverify jsdom@9 jsdom-global@2 mime-types node-webcrypto-ossl
+$ npm install jsverify jsdom@9 jsdom-global@2 mime-types node-webcrypto-ossl jsdom-url
 ```
 
 Example for Debian and Ubuntu, including steps to allow the current user to

+ 1 - 0
tst/ViewTest.php

@@ -55,6 +55,7 @@ class ViewTest extends PHPUnit_Framework_TestCase
         $page->assign('EXPIREDEFAULT', self::$expire_default);
         $page->assign('URLSHORTENER', '');
         $page->assign('QRCODE', true);
+        $page->assign('HTTPWARNING', true);
 
         $dir = dir(PATH . 'tpl');
         while (false !== ($file = $dir->read())) {