Parcourir la source

Merge branch 'master' into chrono-privacy

El RIDO il y a 2 ans
Parent
commit
b00528388f
64 fichiers modifiés avec 944 ajouts et 215 suppressions
  1. 7 2
      .github/workflows/tests.yml
  2. 4 1
      CHANGELOG.md
  3. 1 0
      LICENSE.md
  4. 9 4
      cfg/conf.sample.php
  5. 2 2
      composer.json
  6. 3 53
      css/bootstrap/privatebin.css
  7. 4 0
      css/bootstrap5/bootstrap-5.3.3.css
  8. 4 0
      css/bootstrap5/bootstrap.rtl-5.3.3.css
  9. 69 0
      css/bootstrap5/privatebin.css
  10. 65 0
      css/common.css
  11. 1 2
      css/noscript.css
  12. 3 48
      css/privatebin.css
  13. 1 0
      doc/Installation.md
  14. 2 1
      i18n/ar.json
  15. 2 1
      i18n/bg.json
  16. 2 1
      i18n/ca.json
  17. 2 1
      i18n/co.json
  18. 2 1
      i18n/cs.json
  19. 2 1
      i18n/de.json
  20. 2 1
      i18n/el.json
  21. 2 1
      i18n/en.json
  22. 2 1
      i18n/es.json
  23. 2 1
      i18n/et.json
  24. 2 1
      i18n/fi.json
  25. 2 1
      i18n/fr.json
  26. 2 1
      i18n/he.json
  27. 2 1
      i18n/hi.json
  28. 2 1
      i18n/hu.json
  29. 2 1
      i18n/id.json
  30. 2 1
      i18n/it.json
  31. 2 1
      i18n/ja.json
  32. 2 1
      i18n/jbo.json
  33. 2 1
      i18n/ku.json
  34. 2 1
      i18n/la.json
  35. 2 1
      i18n/lt.json
  36. 2 1
      i18n/nl.json
  37. 2 1
      i18n/no.json
  38. 2 1
      i18n/oc.json
  39. 2 1
      i18n/pl.json
  40. 2 1
      i18n/pt.json
  41. 2 1
      i18n/ro.json
  42. 2 1
      i18n/ru.json
  43. 2 1
      i18n/sk.json
  44. 2 1
      i18n/sl.json
  45. 2 1
      i18n/sv.json
  46. 2 1
      i18n/th.json
  47. 4 3
      i18n/tr.json
  48. 2 1
      i18n/uk.json
  49. 2 1
      i18n/zh.json
  50. 0 0
      img/bootstrap-icons.svg
  51. 5 0
      js/bootstrap-5.3.3.js
  52. 1 1
      js/common.js
  53. 81 0
      js/dark-mode-switch.js
  54. 36 24
      js/privatebin.js
  55. 0 1
      js/purify-3.0.8.js
  56. 1 0
      js/purify-3.1.2.js
  57. 1 1
      lib/Configuration.php
  58. 5 5
      lib/Controller.php
  59. 1 1
      lib/Persistence/ServerSalt.php
  60. 1 1
      lib/View.php
  61. 10 10
      lib/Vizhash16x16.php
  62. 28 12
      tpl/bootstrap.php
  63. 502 0
      tpl/bootstrap5.php
  64. 25 9
      tpl/page.php

+ 7 - 2
.github/workflows/tests.yml

@@ -16,11 +16,16 @@ jobs:
       run: composer install --prefer-dist --no-dev
       run: composer install --prefer-dist --no-dev
 
 
   PHPunit:
   PHPunit:
+    name: PHP ${{ matrix.php-versions }} unit tests on ${{ matrix.operating-system }}
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
+    continue-on-error: ${{ matrix.experimental }}
     strategy:
     strategy:
       matrix:
       matrix:
-        php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
-    name: PHP ${{ matrix.php-versions }} unit tests on ${{ matrix.operating-system }}
+        php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
+        experimental: [false]
+        include:
+          - php-versions: '8.4' # development release, things can break
+            experimental: true
     env:
     env:
       extensions: gd, sqlite3
       extensions: gd, sqlite3
       extensions-cache-key-name: phpextensions
       extensions-cache-key-name: phpextensions

+ 4 - 1
CHANGELOG.md

@@ -3,8 +3,11 @@
 ## 1.7.2 (not yet released)
 ## 1.7.2 (not yet released)
 * ADDED: Allow use of `shortenviayourls` in query parameters (#1267)
 * ADDED: Allow use of `shortenviayourls` in query parameters (#1267)
 * ADDED: Input sanitation to some not yet filtered query and server parameters
 * ADDED: Input sanitation to some not yet filtered query and server parameters
+* ADDED: Optional Bootstrap CSS 5.3.3 based template, use configuration `template = "bootstrap5"` to switch to it (#728)
 * CHANGED: "Send" button now labeled "Create" (#946)
 * CHANGED: "Send" button now labeled "Create" (#946)
-* CHANGED: drop some PHP < 5.6 fallbacks, minimum version is PHP 7.3 as of release 1.6.0
+* CHANGED: Drop some PHP < 5.6 fallbacks, minimum version is PHP 7.3 as of release 1.6.0
+* CHANGED: Set `lang` cookie with lax `SameSite` property
+* CHANGED: Upgrading libraries to: DOMpurify 3.1.2 (#1299)
 * CHANGED: `create` attribute is no longer returned in API for pastes & can be disabled for comments using `discussiondatedisplay` as well (#1290)
 * CHANGED: `create` attribute is no longer returned in API for pastes & can be disabled for comments using `discussiondatedisplay` as well (#1290)
 * FIXED: Add cache control headers also to API calls (#1263)
 * FIXED: Add cache control headers also to API calls (#1263)
 * FIXED: Shortened paste URL does not appear in email (#606)
 * FIXED: Shortened paste URL does not appear in email (#606)

+ 1 - 0
LICENSE.md

@@ -351,6 +351,7 @@ Copyright © 2016 Nils Adermann, Jordi Boggiano
 Copyright © 2016 Lars Jung (https://larsjung.de)
 Copyright © 2016 Lars Jung (https://larsjung.de)
 Copyright © 2018 base-x contributors
 Copyright © 2018 base-x contributors
 Copyright © 2014-2018 The Bitcoin Core developers
 Copyright © 2014-2018 The Bitcoin Core developers
+Copyright © 2019-2024 The Bootstrap Authors
 
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 of this software and associated documentation files (the "Software"), to deal

+ 9 - 4
cfg/conf.sample.php

@@ -42,9 +42,12 @@ defaultformatter = "plaintext"
 ; size limit per paste or comment in bytes, defaults to 10 Mebibytes
 ; size limit per paste or comment in bytes, defaults to 10 Mebibytes
 sizelimit = 10485760
 sizelimit = 10485760
 
 
-; template to include, default is "bootstrap" (tpl/bootstrap.php)
-; Also available is a dark version ("bootstrap-dark",) and
-; a theme that resembles the classic ZeroBin style ("page".)
+; template to include, default is "bootstrap" (tpl/bootstrap.php), also
+; available are "page" (tpl/page.php), the classic ZeroBin style and several
+; bootstrap variants: "bootstrap-dark", "bootstrap-compact", "bootstrap-page",
+; which can be combined with "-dark" and "-compact" for "bootstrap-dark-page"
+; and finally "bootstrap-compact-page" - previews at:
+; https://privatebin.info/screenshots.html
 template = "bootstrap"
 template = "bootstrap"
 
 
 ; (optional) info text to display
 ; (optional) info text to display
@@ -90,8 +93,10 @@ languageselection = false
 ; scripts or run your site behind certain DDoS-protection services.
 ; scripts or run your site behind certain DDoS-protection services.
 ; Check the documentation at https://content-security-policy.com/
 ; Check the documentation at https://content-security-policy.com/
 ; Notes:
 ; Notes:
-; - If you use a bootstrap theme, you can remove the allow-popups from the
+; - If you use any bootstrap theme, you can remove the allow-popups from the
 ;   sandbox restrictions.
 ;   sandbox restrictions.
+; - If you use the bootstrap5 theme, you must change default-src to 'self' to
+;   enable display of the svg icons
 ; - By default this disallows to load images from third-party servers, e.g. when
 ; - 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
 ;   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
 ;   policy here. See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-it-load-embedded-images

+ 2 - 2
composer.json

@@ -30,8 +30,8 @@
 		"yzalis/identicon": "2.0.0"
 		"yzalis/identicon": "2.0.0"
 	},
 	},
 	"suggest" : {
 	"suggest" : {
-		"google/cloud-storage" : "1.32.0",
-		"aws/aws-sdk-php" : "3.275.1"
+		"google/cloud-storage" : "1.41.0",
+		"aws/aws-sdk-php" : "3.302.0"
 	},
 	},
 	"require-dev" : {
 	"require-dev" : {
 		"phpunit/phpunit" : "^9"
 		"phpunit/phpunit" : "^9"

+ 3 - 53
css/bootstrap/privatebin.css

@@ -1,7 +1,7 @@
 /**
 /**
  * PrivateBin
  * PrivateBin
  *
  *
- * a zero-knowledge paste bin
+ * Cascading style sheets for bootstrap template.
  *
  *
  * @link      https://github.com/PrivateBin/PrivateBin
  * @link      https://github.com/PrivateBin/PrivateBin
  * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
  * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
@@ -9,6 +9,8 @@
  * @version   1.7.1
  * @version   1.7.1
  */
  */
 
 
+@import url("../common.css");
+
 body {
 body {
 	padding: 0 0 30px;
 	padding: 0 0 30px;
 }
 }
@@ -68,48 +70,6 @@ body.loading {
 	margin-right: 8px;
 	margin-right: 8px;
 }
 }
 
 
-#attachmentPreview img {
-	max-width: 100%;
-	height: auto;
-	margin-bottom: 20px;
-}
-
-#attachmentPreview .pdfPreview {
-	width: 100%;
-	height: 100vh;
-	margin-bottom: 20px;
-}
-
-#dropzone {
-	text-align: center;
-	position: fixed;
-	top: 0;
-	left: 0;
-	width: 100%;
-	height: 100%;
-	z-index: 1000;
-	opacity: 0.6;
-	background-color: #99ccff;
-	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E");
-	background-repeat: no-repeat;
-	background-position: center;
-	background-size: 25vh;
-	outline: 2px dashed #228bff;
-	outline-offset: -50px;
-}
-
-.dragAndDropFile{
-	color: #777;
-	font-size: 1em;
-	display: inline;
-	white-space: normal;
-}
-
-#deletelink {
-	float: right;
-	margin-left: 5px;
-}
-
 #qrcodemodalClose {
 #qrcodemodalClose {
 	float: right;
 	float: right;
 }
 }
@@ -145,22 +105,12 @@ body.loading {
 	margin-bottom: 10px;
 	margin-bottom: 10px;
 }
 }
 
 
-#filewrap {
-	transition: background-color 0.75s ease-out;
-}
-
 .comment {
 .comment {
 	border-left: 1px solid #ccc;
 	border-left: 1px solid #ccc;
 	padding: 5px 0 5px 10px;
 	padding: 5px 0 5px 10px;
-	white-space: pre-wrap;
 	transition: background-color 0.75s ease-out;
 	transition: background-color 0.75s ease-out;
 }
 }
 
 
-.highlight {
-	background-color: #ffdd86;
-	transition: background-color 0.2s ease-in;
-}
-
 footer h4 {
 footer h4 {
 	margin-top: 0;
 	margin-top: 0;
 }
 }

Fichier diff supprimé car celui-ci est trop grand
+ 4 - 0
css/bootstrap5/bootstrap-5.3.3.css


Fichier diff supprimé car celui-ci est trop grand
+ 4 - 0
css/bootstrap5/bootstrap.rtl-5.3.3.css


+ 69 - 0
css/bootstrap5/privatebin.css

@@ -0,0 +1,69 @@
+/**
+ * PrivateBin
+ *
+ * Cascading style sheets for bootstrap 5 template.
+ *
+ * @link      https://github.com/PrivateBin/PrivateBin
+ * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
+ * @license   https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
+ * @version   1.7.1
+ */
+
+@import url("../common.css");
+
+.hidden {
+	display: none !important;
+}
+
+#qrcodemodalClose {
+	float: right;
+}
+
+#qrcode-display {
+	width: 200px;
+	height: 200px;
+	margin: auto;
+}
+
+#pastelink {
+	display: inline;
+}
+
+#pastelink > a {
+	word-wrap: break-word;
+}
+
+#preview {
+	margin-bottom: 10px;
+}
+
+#message, .replymessage {
+	font-family: monospace;
+	resize: vertical;
+}
+
+#nickname {
+	margin: 5px 0;
+}
+
+#comments, #comments button {
+	margin-bottom: 10px;
+}
+
+.comment {
+	border-left: 1px solid #ccc;
+	padding: 5px 0 5px 10px;
+	transition: background-color 0.75s ease-out;
+}
+
+li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 {
+	list-style-type: decimal !important;
+}
+
+.text-right button {
+	float: right;
+}
+
+html[dir="rtl"] #deletelink, html[dir="rtl"] #qrcodemodalClose {
+	float: left;
+}

+ 65 - 0
css/common.css

@@ -0,0 +1,65 @@
+/**
+ * PrivateBin
+ *
+ * Common cascading style sheets for all templates.
+ *
+ * @link      https://github.com/PrivateBin/PrivateBin
+ * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
+ * @license   https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
+ * @version   1.7.1
+ */
+
+#attachmentPreview img {
+	max-width: 100%;
+	height: auto;
+	margin-bottom: 20px;
+}
+
+#attachmentPreview .pdfPreview {
+	width: 100%;
+	height: 100vh;
+	margin-bottom: 20px;
+}
+
+#dropzone {
+	text-align: center;
+	position: fixed;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	z-index: 1000;
+	opacity: 0.6;
+	background-color: #9cf;
+	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E");
+	background-repeat: no-repeat;
+	background-position: center;
+	background-size: 25vh;
+	outline: 2px dashed #28f;
+	outline-offset: -50px;
+}
+
+.dragAndDropFile {
+	color: #777;
+	font-size: 1em;
+	display: inline;
+	white-space: normal;
+}
+
+#filewrap {
+	transition: background-color 0.75s ease-out;
+}
+
+.highlight {
+	background-color: #fd8;
+	transition: background-color 0.2s ease-in;
+}
+
+#deletelink {
+	float: right;
+	margin-left: 5px;
+}
+
+.commentdata {
+	white-space: pre-wrap;
+}

+ 1 - 2
css/noscript.css

@@ -1,7 +1,7 @@
 /**
 /**
  * PrivateBin
  * PrivateBin
  *
  *
- * CSS file only loaded when no JavaScript available.
+ * Cascading style sheet only loaded when JavaScript is not available.
  *
  *
  * @link      https://github.com/PrivateBin/PrivateBin
  * @link      https://github.com/PrivateBin/PrivateBin
  * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
  * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
@@ -9,7 +9,6 @@
  * @version   1.7.1
  * @version   1.7.1
  */
  */
 
 
-/* When there is no script at all other */
 .noscript-hide {
 .noscript-hide {
 	display: none;
 	display: none;
 }
 }

+ 3 - 48
css/privatebin.css

@@ -1,7 +1,7 @@
 /**
 /**
  * PrivateBin
  * PrivateBin
  *
  *
- * Main CSS file.
+ * Cascading style sheets for page template.
  *
  *
  * @link      https://github.com/PrivateBin/PrivateBin
  * @link      https://github.com/PrivateBin/PrivateBin
  * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
  * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
@@ -9,6 +9,8 @@
  * @version   1.7.1
  * @version   1.7.1
  */
  */
 
 
+@import url("common.css");
+
 /*  CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
 /*  CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
 Licensed under the BSD License. - http://yuilibrary.com/license/    */
 Licensed under the BSD License. - http://yuilibrary.com/license/    */
 html{color:#000;background:#fff}body,div,dl,dt,dd,ul,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}input,textarea,select{font-size:100%;}legend{color:#000}
 html{color:#000;background:#fff}body,div,dl,dt,dd,ul,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}input,textarea,select{font-size:100%;}legend{color:#000}
@@ -105,42 +107,6 @@ h3.title {
 	resize: vertical;
 	resize: vertical;
 }
 }
 
 
-#attachmentPreview img {
-	max-width: 100%;
-	height: auto;
-}
-
-#attachmentPreview .pdfPreview {
-	width: 100%;
-	height: 100vh;
-	margin-bottom: 20px;
-}
-
-#dropzone {
-	text-align: center;
-	position: fixed;
-	top: 0;
-	left: 0;
-	width: 100%;
-	height: 100%;
-	z-index: 1000;
-	opacity: 0.6;
-	background-color: #99ccff;
-	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E");
-	background-repeat: no-repeat;
-	background-position: center;
-	background-size: 25vh;
-	outline: 2px dashed #228bff;
-	outline-offset: -50px;
-}
-
-.dragAndDropFile{
-	color: #777;
-	font-size: 1em;
-	display: inline;
-	white-space: normal;
-}
-
 #status {
 #status {
 	clear: both;
 	clear: both;
 	padding: 5px 10px;
 	padding: 5px 10px;
@@ -160,8 +126,6 @@ h3.title {
 
 
 #pasteresult button { margin-left: 11px; }
 #pasteresult button { margin-left: 11px; }
 
 
-#deletelink { float: right; }
-
 #toolbar, #status { margin-bottom: 5px; }
 #toolbar, #status { margin-bottom: 5px; }
 
 
 #copyhint { color: #666; font-size: 0.85em }
 #copyhint { color: #666; font-size: 0.85em }
@@ -430,15 +394,6 @@ h4.title {
 
 
 .commentdate { color: #bfcede; }
 .commentdate { color: #bfcede; }
 
 
-#filewrap {
-	transition: background-color 0.75s ease-out;
-}
-
-.highlight {
-	background-color: #ffdd86;
-	transition: background-color 0.2s ease-in;
-}
-
 img.vizhash {
 img.vizhash {
 	width: 16px;
 	width: 16px;
 	height: 16px;
 	height: 16px;

+ 1 - 0
doc/Installation.md

@@ -22,6 +22,7 @@ for more information.
 ### Minimal Requirements
 ### Minimal Requirements
 
 
 - PHP version 7.3 or above
 - PHP version 7.3 or above
+- ctype extension
 - GD extension (when using identicon or vizhash icons, jdenticon works without it)
 - GD extension (when using identicon or vizhash icons, jdenticon works without it)
 - zlib extension
 - zlib extension
 - some disk space or a database supported by [PDO](https://php.net/manual/book.pdo.php)
 - some disk space or a database supported by [PDO](https://php.net/manual/book.pdo.php)

+ 2 - 1
i18n/ar.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "خطأ في الاتصال بـ YOURLS. ربما تكون هناك مشكلة في التضبيط، مثل \"apiurl\" أو \"التوقيع\" الخاطئ أو المفقود.",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "خطأ في الاتصال بـ YOURLS. ربما تكون هناك مشكلة في التضبيط، مثل \"apiurl\" أو \"التوقيع\" الخاطئ أو المفقود.",
     "Error parsing YOURLS response.": "خطأ في تحليل استجابة YOURLS.",
     "Error parsing YOURLS response.": "خطأ في تحليل استجابة YOURLS.",
     "This secret message can only be displayed once. Would you like to see it now?": "لا يمكن عرض اللصق احرقه بعد قراءته إلا مرة واحدة عند تحميله. هل تريد فتحه الآن؟",
     "This secret message can only be displayed once. Would you like to see it now?": "لا يمكن عرض اللصق احرقه بعد قراءته إلا مرة واحدة عند تحميله. هل تريد فتحه الآن؟",
-    "Yes, see it": "نعم، حمله"
+    "Yes, see it": "نعم، حمله",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/bg.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/ca.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/co.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Sbagliu à a chjama di YOURLS. Seria forse una cunfigurazione gattiva, tale una \"apiurl\" o \"signature\" falsa o assente.",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Sbagliu à a chjama di YOURLS. Seria forse una cunfigurazione gattiva, tale una \"apiurl\" o \"signature\" falsa o assente.",
     "Error parsing YOURLS response.": "Sbagliu durante l’analisa di a risposta di YOURLS.",
     "Error parsing YOURLS response.": "Sbagliu durante l’analisa di a risposta di YOURLS.",
     "This secret message can only be displayed once. Would you like to see it now?": "Stu messaghju secretu pò esse affissatu solu una volta. Vulete fighjallu subitu ?",
     "This secret message can only be displayed once. Would you like to see it now?": "Stu messaghju secretu pò esse affissatu solu una volta. Vulete fighjallu subitu ?",
-    "Yes, see it": "Iè, fighjallu"
+    "Yes, see it": "Iè, fighjallu",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/cs.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/de.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Fehler beim Aufruf von YOURLS. Wahrscheinlich ein Konfigurationsproblem, wie eine falsche oder fehlende \"apiurl\" oder \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Fehler beim Aufruf von YOURLS. Wahrscheinlich ein Konfigurationsproblem, wie eine falsche oder fehlende \"apiurl\" oder \"signature\".",
     "Error parsing YOURLS response.": "Fehler beim Verarbeiten der YOURLS-Antwort.",
     "Error parsing YOURLS response.": "Fehler beim Verarbeiten der YOURLS-Antwort.",
     "This secret message can only be displayed once. Would you like to see it now?": "Texte des \"Einmal\"-Typs können nach dem Öffnen nur einmal angezeigt werden. Möchtest Du ihn jetzt einsehen?",
     "This secret message can only be displayed once. Would you like to see it now?": "Texte des \"Einmal\"-Typs können nach dem Öffnen nur einmal angezeigt werden. Möchtest Du ihn jetzt einsehen?",
-    "Yes, see it": "Ja, jetzt einsehen"
+    "Yes, see it": "Ja, jetzt einsehen",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/el.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/en.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/es.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/et.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Viga YOURLS-i kutsumisel. Tõenäoliselt konfiguratsiooniprobleem, näiteks vale või puuduv \"apiurl\" või \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Viga YOURLS-i kutsumisel. Tõenäoliselt konfiguratsiooniprobleem, näiteks vale või puuduv \"apiurl\" või \"signature\".",
     "Error parsing YOURLS response.": "Viga YOURLS vastuse parsimisel.",
     "Error parsing YOURLS response.": "Viga YOURLS vastuse parsimisel.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/fi.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Virhe kutsuttaessa YOURLS. Luultavasti asetusongelma kuten väärä tai puuttuuva \"apiurl\" tai \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Virhe kutsuttaessa YOURLS. Luultavasti asetusongelma kuten väärä tai puuttuuva \"apiurl\" tai \"signature\".",
     "Error parsing YOURLS response.": "Virhe jäsennettäessä YOURLS-vastausta.",
     "Error parsing YOURLS response.": "Virhe jäsennettäessä YOURLS-vastausta.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/fr.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Erreur lors de l'appel de YOURLS. Peut-être un problème de configuration, comme \"apiurl\" ou \"signature\" manquant.",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Erreur lors de l'appel de YOURLS. Peut-être un problème de configuration, comme \"apiurl\" ou \"signature\" manquant.",
     "Error parsing YOURLS response.": "Erreur d'analyse de la réponse YOURLS.",
     "Error parsing YOURLS response.": "Erreur d'analyse de la réponse YOURLS.",
     "This secret message can only be displayed once. Would you like to see it now?": "Les pastes de type \"Effacer après la lecture\" ne peuvent être affichés qu'une seule fois. Voulez-vous le voir maintenant ?",
     "This secret message can only be displayed once. Would you like to see it now?": "Les pastes de type \"Effacer après la lecture\" ne peuvent être affichés qu'une seule fois. Voulez-vous le voir maintenant ?",
-    "Yes, see it": "Oui, voyez le"
+    "Yes, see it": "Oui, voyez le",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/he.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/hi.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/hu.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/id.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/it.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Errore nella chiamata a YOURLS. Probabilmente un problema di configurazione, come un \"apiurl\" o una \"signature\" sbagliati o mancanti.",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Errore nella chiamata a YOURLS. Probabilmente un problema di configurazione, come un \"apiurl\" o una \"signature\" sbagliati o mancanti.",
     "Error parsing YOURLS response.": "Errore nell'analizzare la risposta YOURLS.",
     "Error parsing YOURLS response.": "Errore nell'analizzare la risposta YOURLS.",
     "This secret message can only be displayed once. Would you like to see it now?": "Questo messaggio di tipo Distruggi-dopo-lettura può essere visualizzato solo una volta. Vuoi vederlo ora?",
     "This secret message can only be displayed once. Would you like to see it now?": "Questo messaggio di tipo Distruggi-dopo-lettura può essere visualizzato solo una volta. Vuoi vederlo ora?",
-    "Yes, see it": "Sì, visualizzalo"
+    "Yes, see it": "Sì, visualizzalo",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/ja.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "YOURLSの呼び出し中にエラーが発生しました。\"apiurl\"または\"signature\"等の設定に問題がある可能性があります。",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "YOURLSの呼び出し中にエラーが発生しました。\"apiurl\"または\"signature\"等の設定に問題がある可能性があります。",
     "Error parsing YOURLS response.": "YOURLSレスポンスの解析中にエラーが発生しました。",
     "Error parsing YOURLS response.": "YOURLSレスポンスの解析中にエラーが発生しました。",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/jbo.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/ku.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/la.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/lt.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Klaida iškviečiant YOURLS. Tikriausiai, konfigūracijos klaida, pavyzdžiui, neteisingi „apiurl“ ar „signature“, arba jų nėra.",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Klaida iškviečiant YOURLS. Tikriausiai, konfigūracijos klaida, pavyzdžiui, neteisingi „apiurl“ ar „signature“, arba jų nėra.",
     "Error parsing YOURLS response.": "Klaida nagrinėjant YOURLS atsaką.",
     "Error parsing YOURLS response.": "Klaida nagrinėjant YOURLS atsaką.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/nl.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Foutmelding ophalen YOURLS. Waarschijnlijk een configuratiefout, zoals een verkeerde of missende \"apiurl\" of \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Foutmelding ophalen YOURLS. Waarschijnlijk een configuratiefout, zoals een verkeerde of missende \"apiurl\" of \"signature\".",
     "Error parsing YOURLS response.": "Foutmelding bij parsen van YOURLS respons.",
     "Error parsing YOURLS response.": "Foutmelding bij parsen van YOURLS respons.",
     "This secret message can only be displayed once. Would you like to see it now?": "Brand na het lezen van de plagen kan slechts eenmaal worden weergegeven wanneer deze worden geladen. Wilt u het nu zien?",
     "This secret message can only be displayed once. Would you like to see it now?": "Brand na het lezen van de plagen kan slechts eenmaal worden weergegeven wanneer deze worden geladen. Wilt u het nu zien?",
-    "Yes, see it": "Ja, zie het"
+    "Yes, see it": "Ja, zie het",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/no.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Feil ved å ringe YOURLS. Sannsynligvis et konfigurasjonsproblem, som feil eller mangler, \"apiurl\" eller \"signatur\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Feil ved å ringe YOURLS. Sannsynligvis et konfigurasjonsproblem, som feil eller mangler, \"apiurl\" eller \"signatur\".",
     "Error parsing YOURLS response.": "Feil ved analyse av YOURLS svar.",
     "Error parsing YOURLS response.": "Feil ved analyse av YOURLS svar.",
     "This secret message can only be displayed once. Would you like to see it now?": "Brenne etter lesing av pasta kan kun vises når den lastes inn. Vil du se den nå?",
     "This secret message can only be displayed once. Would you like to see it now?": "Brenne etter lesing av pasta kan kun vises når den lastes inn. Vil du se den nå?",
-    "Yes, see it": "Ja, se det"
+    "Yes, see it": "Ja, se det",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/oc.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error en cridant YOURLS. Es probablament un problèma de configuracion, quicòm coma « apirul » o « signature » marrit o absent.",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error en cridant YOURLS. Es probablament un problèma de configuracion, quicòm coma « apirul » o « signature » marrit o absent.",
     "Error parsing YOURLS response.": "Error d'analisi de la responsa YOURLS.",
     "Error parsing YOURLS response.": "Error d'analisi de la responsa YOURLS.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/pl.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/pt.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/ro.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Eroare la apelarea YOURLS. Probabil o problemă de configurare, cum ar fi \"apiurl\" sau \"signature\" greșite sau lipsă.",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Eroare la apelarea YOURLS. Probabil o problemă de configurare, cum ar fi \"apiurl\" sau \"signature\" greșite sau lipsă.",
     "Error parsing YOURLS response.": "Eroare la analizarea răspunsului YOURLS.",
     "Error parsing YOURLS response.": "Eroare la analizarea răspunsului YOURLS.",
     "This secret message can only be displayed once. Would you like to see it now?": "Paste-urile care se șterg după citire pot fi afișate numai o dată după încărcare. Doriți să o vedeți acum?",
     "This secret message can only be displayed once. Would you like to see it now?": "Paste-urile care se șterg după citire pot fi afișate numai o dată după încărcare. Doriți să o vedeți acum?",
-    "Yes, see it": "Da, vezi"
+    "Yes, see it": "Da, vezi",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/ru.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Ошибка обращения к YOURLS. Возможно в конфигурации допущена ошибка, например неверный или отсутствующий параметр \"apiurl\" или \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Ошибка обращения к YOURLS. Возможно в конфигурации допущена ошибка, например неверный или отсутствующий параметр \"apiurl\" или \"signature\".",
     "Error parsing YOURLS response.": "Ошибка разбора ответа от YOURLS.",
     "Error parsing YOURLS response.": "Ошибка разбора ответа от YOURLS.",
     "This secret message can only be displayed once. Would you like to see it now?": "Записи, удаляемые после прочтения, могут быть отображены после загрузки только один раз. Вы хотите открыть её сейчас?",
     "This secret message can only be displayed once. Would you like to see it now?": "Записи, удаляемые после прочтения, могут быть отображены после загрузки только один раз. Вы хотите открыть её сейчас?",
-    "Yes, see it": "Да, загрузить"
+    "Yes, see it": "Да, загрузить",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/sk.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/sl.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/sv.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/th.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "เกิดข้อผิดพลาดในการเรียก YOURLS อาจเป็นปัญหามาจากการกำหนดค่า เช่น \"apiurl\" หรือ \"signature\" ไม่ถูกต้องหรือขาดหายไป",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "เกิดข้อผิดพลาดในการเรียก YOURLS อาจเป็นปัญหามาจากการกำหนดค่า เช่น \"apiurl\" หรือ \"signature\" ไม่ถูกต้องหรือขาดหายไป",
     "Error parsing YOURLS response.": "เกิดข้อผิดพลาดในการแยกวิเคราะห์การตอบสนองของ YOURLS",
     "Error parsing YOURLS response.": "เกิดข้อผิดพลาดในการแยกวิเคราะห์การตอบสนองของ YOURLS",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Yes, see it",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 4 - 3
i18n/tr.json

@@ -3,7 +3,7 @@
     "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s sunucunun burada paylaştığınız veriyi görmediği, minimal, açık kaynak bir pastebindir. Veriler tarayıcıda 256 bit AES kullanılarak şifrelenir/çözülür.",
     "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s sunucunun burada paylaştığınız veriyi görmediği, minimal, açık kaynak bir pastebindir. Veriler tarayıcıda 256 bit AES kullanılarak şifrelenir/çözülür.",
     "More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Daha fazla bilgi için <a href=\"https://privatebin.info/\">proje sayfası</a>'na göz atabilirsiniz.",
     "More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Daha fazla bilgi için <a href=\"https://privatebin.info/\">proje sayfası</a>'na göz atabilirsiniz.",
     "Because ignorance is bliss": "Çünkü, cehalet mutluluktur",
     "Because ignorance is bliss": "Çünkü, cehalet mutluluktur",
-    "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.",
+    "Paste does not exist, has expired or has been deleted.": "Bu mevcut değil, süresi dolmuş veya silinmiş.",
     "%s requires php %s or above to work. Sorry.": "%s PHP %s veya daha üstünü gerektirir.",
     "%s requires php %s or above to work. Sorry.": "%s PHP %s veya daha üstünü gerektirir.",
     "%s requires configuration section [%s] to be present in configuration file.": "%s konfigürasyon bölümünün [%s] bulunmasını gerektir.",
     "%s requires configuration section [%s] to be present in configuration file.": "%s konfigürasyon bölümünün [%s] bulunmasını gerektir.",
     "Please wait %d seconds between each post.": [
     "Please wait %d seconds between each post.": [
@@ -188,7 +188,7 @@
     "Decrypting paste…": "Yazı şifresi çözülüyor…",
     "Decrypting paste…": "Yazı şifresi çözülüyor…",
     "Preparing new paste…": "Yeni yazı hazırlanıyor…",
     "Preparing new paste…": "Yeni yazı hazırlanıyor…",
     "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 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>.",
-    "+++ no paste text +++": "+++ no paste text +++",
+    "+++ no paste text +++": "+++ yazı içeriği yok +++",
     "Could not get paste data: %s": "Yazı verisi alınamıyor: %s",
     "Could not get paste data: %s": "Yazı verisi alınamıyor: %s",
     "QR code": "QR kodu",
     "QR code": "QR kodu",
     "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.",
     "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.",
@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "Error parsing YOURLS response.": "Error parsing YOURLS response.",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
     "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it"
+    "Yes, see it": "Evet, görüyorum",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/uk.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Помилка виклику YOURLS. Ймовірно проблема з конфігурацією, наприклад \"apiurl\" чи \"signature\".",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Помилка виклику YOURLS. Ймовірно проблема з конфігурацією, наприклад \"apiurl\" чи \"signature\".",
     "Error parsing YOURLS response.": "Помилка розбору відповіді YOURLS.",
     "Error parsing YOURLS response.": "Помилка розбору відповіді YOURLS.",
     "This secret message can only be displayed once. Would you like to see it now?": "Спалити після вставки читання можна вивести лише один раз під час завантаження. Відкрити його зараз?",
     "This secret message can only be displayed once. Would you like to see it now?": "Спалити після вставки читання можна вивести лише один раз під час завантаження. Відкрити його зараз?",
-    "Yes, see it": "Так, завантажити"
+    "Yes, see it": "Так, завантажити",
+    "Dark Mode": "Dark Mode"
 }
 }

+ 2 - 1
i18n/zh.json

@@ -216,5 +216,6 @@
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "调用 YOURLS 时出错。可能是配置问题,例如“apiurl”或“signature”错误或缺失。",
     "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "调用 YOURLS 时出错。可能是配置问题,例如“apiurl”或“signature”错误或缺失。",
     "Error parsing YOURLS response.": "解析 YOURLS 响应时出错。",
     "Error parsing YOURLS response.": "解析 YOURLS 响应时出错。",
     "This secret message can only be displayed once. Would you like to see it now?": "读取粘贴后只能在加载时显示一次。您想现在打开吗?",
     "This secret message can only be displayed once. Would you like to see it now?": "读取粘贴后只能在加载时显示一次。您想现在打开吗?",
-    "Yes, see it": "是的,加载它"
+    "Yes, see it": "是的,加载它",
+    "Dark Mode": "Dark Mode"
 }
 }

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
img/bootstrap-icons.svg


Fichier diff supprimé car celui-ci est trop grand
+ 5 - 0
js/bootstrap-5.3.3.js


+ 1 - 1
js/common.js

@@ -17,7 +17,7 @@ require('./prettify');
 global.prettyPrint = window.PR.prettyPrint;
 global.prettyPrint = window.PR.prettyPrint;
 global.prettyPrintOne = window.PR.prettyPrintOne;
 global.prettyPrintOne = window.PR.prettyPrintOne;
 global.showdown = require('./showdown-2.1.0');
 global.showdown = require('./showdown-2.1.0');
-global.DOMPurify = require('./purify-3.0.8');
+global.DOMPurify = require('./purify-3.1.2');
 global.baseX = require('./base-x-4.0.0').baseX;
 global.baseX = require('./base-x-4.0.0').baseX;
 global.Legacy = require('./legacy').Legacy;
 global.Legacy = require('./legacy').Legacy;
 require('./bootstrap-3.4.1');
 require('./bootstrap-3.4.1');

+ 81 - 0
js/dark-mode-switch.js

@@ -0,0 +1,81 @@
+/*!
+ * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
+ * Copyright 2011-2024 The Bootstrap Authors
+ * Licensed under the Creative Commons Attribution 3.0 Unported License.
+ * Modified to work with a simpler checkbox toggle & support prettify CSS themes
+ */
+
+(() => {
+  'use strict'
+
+  const getStoredTheme = () => localStorage.getItem('theme')
+  const setStoredTheme = theme => localStorage.setItem('theme', theme)
+  const getPreferredTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
+
+  const getStoredPreferredTheme = () => {
+    const storedTheme = getStoredTheme()
+    if (storedTheme) {
+      return storedTheme
+    }
+    return getPreferredTheme()
+  }
+
+  const delStoredPrettifyTheme = () => localStorage.removeItem('themePrettify')
+  const getStoredPrettifyTheme = () => localStorage.getItem('themePrettify')
+  const setStoredPrettifyTheme = theme => localStorage.setItem('themePrettify', theme)
+
+  const getPrettifyThemeLink = () => {
+    for (const sheet of document.getElementsByTagName('link')) {
+      if (sheet.rel === 'stylesheet' && sheet.href.includes('css/prettify/') && !sheet.href.includes('css/prettify/prettify.css')) {
+        return sheet
+      }
+    }
+    return null
+  }
+
+  const setTheme = theme => {
+    const preferredTheme = theme === 'auto' ? getPreferredTheme() : theme
+    document.documentElement.setAttribute('data-bs-theme', preferredTheme)
+    const sheetPrettify = getPrettifyThemeLink()
+    if (sheetPrettify) {
+      sheetPrettify.remove()
+    }
+    const link = document.createElement('link')
+    link.rel = 'stylesheet'
+    if (preferredTheme === 'dark') {
+      link.href = 'css/prettify/sons-of-obsidian.css'
+      document.head.appendChild(link)
+    } else {
+      const themePrettify = getStoredPrettifyTheme()
+      if (themePrettify) {
+        link.href = themePrettify
+        document.head.appendChild(link)
+      }
+    }
+  }
+
+  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
+    const storedTheme = getStoredTheme()
+    if (storedTheme !== 'light' && storedTheme !== 'dark') {
+      setTheme(getStoredPreferredTheme())
+    }
+  })
+
+  window.addEventListener('DOMContentLoaded', () => {
+    const sheetPrettify = getPrettifyThemeLink()
+    if (sheetPrettify) {
+      setStoredPrettifyTheme(sheetPrettify.href)
+    } else {
+      delStoredPrettifyTheme()
+    }
+    setTheme(getStoredPreferredTheme())
+    const toggle = document.querySelector('#bd-theme')
+    toggle.checked = getStoredTheme() === 'dark'
+    toggle.addEventListener('change', (event) => {
+      const theme = event.currentTarget.checked ? 'dark' : 'light'
+      setStoredTheme(theme)
+      setTheme(theme)
+      event.currentTarget.focus()
+    })
+  })
+})()

+ 36 - 24
js/privatebin.js

@@ -2305,6 +2305,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
                     backdrop: 'static',
                     backdrop: 'static',
                     keyboard: false
                     keyboard: false
                 });
                 });
+                $passwordModal.modal('show');
                 // focus password input
                 // focus password input
                 $passwordDecrypt.focus();
                 $passwordDecrypt.focus();
                 // then re-focus it, when modal causes it to loose focus again
                 // then re-focus it, when modal causes it to loose focus again
@@ -2390,7 +2391,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
 
 
         let $editorTabs,
         let $editorTabs,
             $messageEdit,
             $messageEdit,
+            $messageEditParent,
             $messagePreview,
             $messagePreview,
+            $messagePreviewParent,
             $message,
             $message,
             isPreview = false;
             isPreview = false;
 
 
@@ -2431,10 +2434,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         {
         {
             // toggle buttons
             // toggle buttons
             $messageEdit.addClass('active');
             $messageEdit.addClass('active');
+            $messageEditParent.addClass('active');
             $messagePreview.removeClass('active');
             $messagePreview.removeClass('active');
+            $messagePreviewParent.removeClass('active');
 
 
-            $('#messageedit').attr('aria-selected','true');
-            $('#messagepreview').attr('aria-selected','false');
+            $messageEdit.attr('aria-selected','true');
+            $messagePreview.attr('aria-selected','false');
 
 
             PasteViewer.hide();
             PasteViewer.hide();
 
 
@@ -2463,10 +2468,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         {
         {
             // toggle buttons
             // toggle buttons
             $messageEdit.removeClass('active');
             $messageEdit.removeClass('active');
+            $messageEditParent.removeClass('active');
             $messagePreview.addClass('active');
             $messagePreview.addClass('active');
+            $messagePreviewParent.addClass('active');
 
 
-            $('#messageedit').attr('aria-selected','false');
-            $('#messagepreview').attr('aria-selected','true');
+            $messageEdit.attr('aria-selected','false');
+            $messagePreview.attr('aria-selected','true');
 
 
             // hide input as now preview is shown
             // hide input as now preview is shown
             $message.addClass('hidden');
             $message.addClass('hidden');
@@ -2594,10 +2601,11 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             // bind events
             // bind events
             $message.keydown(supportTabs);
             $message.keydown(supportTabs);
 
 
-            // bind click events to tab switchers (a), but save parent of them
-            // (li)
-            $messageEdit = $('#messageedit').click(viewEditor).parent();
-            $messagePreview = $('#messagepreview').click(viewPreview).parent();
+            // bind click events to tab switchers (a), and save parents (li)
+            $messageEdit = $('#messageedit').click(viewEditor);
+            $messageEditParent = $messageEdit.parent();
+            $messagePreview = $('#messagepreview').click(viewPreview);
+            $messagePreviewParent = $messagePreview.parent();
         };
         };
 
 
         return me;
         return me;
@@ -2693,15 +2701,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             // otherwise hide the placeholder
             // otherwise hide the placeholder
             $placeholder.addClass('hidden');
             $placeholder.addClass('hidden');
 
 
-            switch (format) {
-                case 'markdown':
-                    $plainText.removeClass('hidden');
-                    $prettyMessage.addClass('hidden');
-                    break;
-                default:
-                    $plainText.addClass('hidden');
-                    $prettyMessage.removeClass('hidden');
-                    break;
+            if (format === 'markdown') {
+                $plainText.removeClass('hidden');
+                $prettyMessage.addClass('hidden');
+            } else {
+                $plainText.addClass('hidden');
+                $prettyMessage.removeClass('hidden');
             }
             }
         }
         }
 
 
@@ -2726,6 +2731,11 @@ jQuery.PrivateBin = (function($, RawDeflate) {
 
 
             format = newFormat;
             format = newFormat;
             isChanged = true;
             isChanged = true;
+
+            // update preview
+            if (Editor.isPreview()) {
+                PasteViewer.run();
+            }
         };
         };
 
 
         /**
         /**
@@ -3714,11 +3724,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             $('#pasteFormatterDisplay').text($target.text());
             $('#pasteFormatterDisplay').text($target.text());
             PasteViewer.setFormat(newFormat);
             PasteViewer.setFormat(newFormat);
 
 
-            // update preview
-            if (Editor.isPreview()) {
-                PasteViewer.run();
-            }
-
             event.preventDefault();
             event.preventDefault();
         }
         }
 
 
@@ -3851,7 +3856,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
          */
          */
         function setLanguage(event)
         function setLanguage(event)
         {
         {
-            document.cookie = 'lang=' + $(event.target).data('lang') + ';secure';
+            document.cookie = 'lang=' + $(event.target).data('lang') + '; SameSite=Lax; Secure';
             UiHelper.reloadHome();
             UiHelper.reloadHome();
             event.preventDefault();
             event.preventDefault();
         }
         }
@@ -3923,6 +3928,10 @@ jQuery.PrivateBin = (function($, RawDeflate) {
                 text: window.location.href
                 text: window.location.href
             });
             });
             $('#qrcode-display').html(qrCanvas);
             $('#qrcode-display').html(qrCanvas);
+            // only necessary for bootstrap 5, other templates won't have this
+            if (bootstrap.Tooltip.VERSION) {
+                $('#qrcodemodal').modal('show');
+            }
         }
         }
 
 
         /**
         /**
@@ -4362,7 +4371,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
          */
          */
         me.getExpiration = function()
         me.getExpiration = function()
         {
         {
-            return pasteExpiration;
+            return Model.getExpirationDefault() || pasteExpiration;
         };
         };
 
 
         /**
         /**
@@ -4545,6 +4554,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             // bootstrap template drop downs
             // bootstrap template drop downs
             $('ul.dropdown-menu li a', $('#expiration').parent()).click(updateExpiration);
             $('ul.dropdown-menu li a', $('#expiration').parent()).click(updateExpiration);
             $('ul.dropdown-menu li a', $('#formatter').parent()).click(updateFormat);
             $('ul.dropdown-menu li a', $('#formatter').parent()).click(updateFormat);
+            $('#pasteFormatter').on('change', function() {
+                PasteViewer.setFormat(Model.getFormatDefault());
+            });
 
 
             // initiate default state of checkboxes
             // initiate default state of checkboxes
             changeBurnAfterReading();
             changeBurnAfterReading();

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 1
js/purify-3.0.8.js


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
js/purify-3.1.2.js


+ 1 - 1
lib/Configuration.php

@@ -241,7 +241,7 @@ class Configuration
 
 
         // ensure the basepath ends in a slash, if one is set
         // ensure the basepath ends in a slash, if one is set
         if (
         if (
-            strlen($this->_configuration['main']['basepath']) &&
+            !empty($this->_configuration['main']['basepath']) &&
             substr_compare($this->_configuration['main']['basepath'], '/', -1) !== 0
             substr_compare($this->_configuration['main']['basepath'], '/', -1) !== 0
         ) {
         ) {
             $this->_configuration['main']['basepath'] .= '/';
             $this->_configuration['main']['basepath'] .= '/';

+ 5 - 5
lib/Controller.php

@@ -178,7 +178,7 @@ class Controller
         // force default language, if language selection is disabled and a default is set
         // force default language, if language selection is disabled and a default is set
         if (!$this->_conf->getKey('languageselection') && strlen($lang) == 2) {
         if (!$this->_conf->getKey('languageselection') && strlen($lang) == 2) {
             $_COOKIE['lang'] = $lang;
             $_COOKIE['lang'] = $lang;
-            setcookie('lang', $lang, 0, '', '', true);
+            setcookie('lang', $lang, array('SameSite' => 'Lax', 'Secure' => true));
         }
         }
     }
     }
 
 
@@ -320,10 +320,10 @@ class Controller
             $this->_error = $e->getMessage();
             $this->_error = $e->getMessage();
         }
         }
         if ($this->_request->isJsonApiCall()) {
         if ($this->_request->isJsonApiCall()) {
-            if (strlen($this->_error)) {
-                $this->_return_message(1, $this->_error);
-            } else {
+            if (empty($this->_error)) {
                 $this->_return_message(0, $dataid);
                 $this->_return_message(0, $dataid);
+            } else {
+                $this->_return_message(1, $this->_error);
             }
             }
         }
         }
     }
     }
@@ -389,7 +389,7 @@ class Controller
         $languageselection = '';
         $languageselection = '';
         if ($this->_conf->getKey('languageselection')) {
         if ($this->_conf->getKey('languageselection')) {
             $languageselection = I18n::getLanguage();
             $languageselection = I18n::getLanguage();
-            setcookie('lang', $languageselection, 0, '', '', true);
+            setcookie('lang', $languageselection, array('SameSite' => 'Lax', 'Secure' => true));
         }
         }
 
 
         // strip policies that are unsupported in meta tag
         // strip policies that are unsupported in meta tag

+ 1 - 1
lib/Persistence/ServerSalt.php

@@ -56,7 +56,7 @@ class ServerSalt extends AbstractPersistence
      */
      */
     public static function get()
     public static function get()
     {
     {
-        if (strlen(self::$_salt)) {
+        if (!empty(self::$_salt)) {
             return self::$_salt;
             return self::$_salt;
         }
         }
 
 

+ 1 - 1
lib/View.php

@@ -50,7 +50,7 @@ class View
      */
      */
     public function draw($template)
     public function draw($template)
     {
     {
-        $file = substr($template, 0, 9) === 'bootstrap' ? 'bootstrap' : $template;
+        $file = substr($template, 0, 10) === 'bootstrap-' ? 'bootstrap' : $template;
         $path = PATH . 'tpl' . DIRECTORY_SEPARATOR . $file . '.php';
         $path = PATH . 'tpl' . DIRECTORY_SEPARATOR . $file . '.php';
         if (!file_exists($path)) {
         if (!file_exists($path)) {
             throw new Exception('Template ' . $template . ' not found!', 80);
             throw new Exception('Template ' . $template . ' not found!', 80);

+ 10 - 10
lib/Vizhash16x16.php

@@ -109,9 +109,9 @@ class Vizhash16x16
         for ($i = 0; $i < 7; ++$i) {
         for ($i = 0; $i < 7; ++$i) {
             $action = $this->getInt();
             $action = $this->getInt();
             $color  = imagecolorallocate($image, $r, $g, $b);
             $color  = imagecolorallocate($image, $r, $g, $b);
-            $r      = $r0      = ($r0 + $this->getInt() / 25) % 256;
-            $g      = $g0      = ($g0 + $this->getInt() / 25) % 256;
-            $b      = $b0      = ($b0 + $this->getInt() / 25) % 256;
+            $r      = $r0      = ((int) $r0 + $this->getInt() / 25) % 256;
+            $g      = $g0      = ((int) $g0 + $this->getInt() / 25) % 256;
+            $b      = $b0      = ((int) $b0 + $this->getInt() / 25) % 256;
             $this->drawshape($image, $action, $color);
             $this->drawshape($image, $action, $color);
         }
         }
 
 
@@ -136,7 +136,7 @@ class Vizhash16x16
     {
     {
         $v = $this->VALUES[$this->VALUES_INDEX];
         $v = $this->VALUES[$this->VALUES_INDEX];
         ++$this->VALUES_INDEX;
         ++$this->VALUES_INDEX;
-        $this->VALUES_INDEX %= count($this->VALUES); // Warp around the array
+        $this->VALUES_INDEX %= count($this->VALUES); // Wrap around the array
         return $v;
         return $v;
     }
     }
 
 
@@ -148,7 +148,7 @@ class Vizhash16x16
      */
      */
     private function getX()
     private function getX()
     {
     {
-        return $this->width * $this->getInt() / 256;
+        return (int) $this->width * $this->getInt() / 256;
     }
     }
 
 
     /**
     /**
@@ -159,7 +159,7 @@ class Vizhash16x16
      */
      */
     private function getY()
     private function getY()
     {
     {
-        return $this->height * $this->getInt() / 256;
+        return (int) $this->height * $this->getInt() / 256;
     }
     }
 
 
     /**
     /**
@@ -190,9 +190,9 @@ class Vizhash16x16
             ($color2[2] - $color1[2]) / $size,
             ($color2[2] - $color1[2]) / $size,
         );
         );
         for ($i = 0; $i < $size; ++$i) {
         for ($i = 0; $i < $size; ++$i) {
-            $r = $color1[0] + ($diffs[0] * $i);
-            $g = $color1[1] + ($diffs[1] * $i);
-            $b = $color1[2] + ($diffs[2] * $i);
+            $r = $color1[0] + ((int) $diffs[0] * $i);
+            $g = $color1[1] + ((int) $diffs[1] * $i);
+            $b = $color1[2] + ((int) $diffs[2] * $i);
             if ($direction == 'h') {
             if ($direction == 'h') {
                 imageline($img, $i, 0, $i, $sizeinv, imagecolorallocate($img, $r, $g, $b));
                 imageline($img, $i, 0, $i, $sizeinv, imagecolorallocate($img, $r, $g, $b));
             } else {
             } else {
@@ -222,7 +222,7 @@ class Vizhash16x16
                 break;
                 break;
             case 3:
             case 3:
                 $points = array($this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY());
                 $points = array($this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY());
-                imagefilledpolygon($image, $points, 4, $color);
+                version_compare(PHP_VERSION, '8.1', '<') ? imagefilledpolygon($image, $points, 4, $color) : imagefilledpolygon($image, $points, $color);
                 break;
                 break;
             default:
             default:
                 $start = $this->getInt() * 360 / 256;
                 $start = $this->getInt() * 360 / 256;

+ 28 - 12
tpl/bootstrap.php

@@ -34,7 +34,7 @@ if ($SYNTAXHIGHLIGHTING) :
 ?>
 ?>
 		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
 		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
 <?php
 <?php
-    if (strlen($SYNTAXHIGHLIGHTINGTHEME)) :
+    if (!empty($SYNTAXHIGHLIGHTINGTHEME)) :
 ?>
 ?>
 		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
 		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
 <?php
 <?php
@@ -71,9 +71,9 @@ if ($MARKDOWN) :
 <?php
 <?php
 endif;
 endif;
 ?>
 ?>
-		<script type="text/javascript" data-cfasync="false" src="js/purify-3.0.8.js" integrity="sha512-wWBDKh5wYGtJ1Df+PPZIn59jHVBnJ4/Yb2W/pVnzaXab8cmlZnHVx+FEBGu5JX39s3P2Qlt+aNQou0XnjW86hg==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.2.js" integrity="sha512-voYCOVXik5/jcT+McTiptsB00iB0NWQrhBmSwSEfj0IH3UDphU8w12JV8w1y+m8FRaozbzW4efHSEWKZpOA+JQ==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-q2+Xxj6aqq8VCdEZs60z/nQTeHYb400bmfyWVh7gIICdNEz2LIVt95hH/DMVDr3pv+vkIcdDL8va5J9rtaY6WA==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-UdOSZnkEQtdvgsyYhMSTCw2/TRv7x/jL8AtCKLnT722eudYsGPAd8wvPOU6zvdoNNJ8R43CfSJCJuCaDP2ahzA==" crossorigin="anonymous"></script>
 		<!-- icon -->
 		<!-- icon -->
 		<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
 		<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />
@@ -437,7 +437,7 @@ endif;
 				</ul>
 				</ul>
 				<ul class="nav navbar-nav pull-right">
 				<ul class="nav navbar-nav pull-right">
 <?php
 <?php
-if (strlen($LANGUAGESELECTION)) :
+if (!empty($LANGUAGESELECTION)) :
 ?>
 ?>
 					<li id="language" class="dropdown">
 					<li id="language" class="dropdown">
 						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
 						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
@@ -468,7 +468,7 @@ endif;
 		<main>
 		<main>
 			<section class="container">
 			<section class="container">
 <?php
 <?php
-if (strlen($NOTICE)) :
+if (!empty($NOTICE)) :
 ?>
 ?>
 				<div role="alert" class="alert alert-info">
 				<div role="alert" class="alert alert-info">
 					<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
 					<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
@@ -485,7 +485,7 @@ if ($FILEUPLOAD) :
 ?>
 ?>
 				<div id="attachment" role="alert" class="hidden alert alert-info">
 				<div id="attachment" role="alert" class="hidden alert alert-info">
 					<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
 					<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
-					<a class="alert-link"><?php echo I18n::_('Download attachment'), PHP_EOL; ?></a>
+					<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
 				</div>
 				</div>
 <?php
 <?php
 endif;
 endif;
@@ -517,12 +517,12 @@ if ($HTTPWARNING) :
 ?>
 ?>
 				<div id="httpnotice" role="alert" class="hidden alert alert-danger">
 				<div id="httpnotice" role="alert" class="hidden alert alert-danger">
 					<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
 					<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 />
+					<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'); ?><br />
 					<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection'); ?></span>
 					<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection'); ?></span>
 				</div>
 				</div>
 				<div id="insecurecontextnotice" role="alert" class="hidden alert alert-danger">
 				<div id="insecurecontextnotice" role="alert" class="hidden alert alert-danger">
 					<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
 					<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
-					<?php echo I18n::_('Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.', $HTTPSLINK); ?>
+					<?php echo I18n::_('Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.', $HTTPSLINK), PHP_EOL; ?>
 				</div>
 				</div>
 <?php
 <?php
 endif;
 endif;
@@ -534,7 +534,7 @@ endif;
 						<div id="pastelink"></div>
 						<div id="pastelink"></div>
 					</div>
 					</div>
 <?php
 <?php
-if (strlen($URLSHORTENER)) :
+if (!empty($URLSHORTENER)) :
 ?>
 ?>
 					<p>
 					<p>
 						<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> btn-block">
 						<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> btn-block">
@@ -613,9 +613,25 @@ if ($DISCUSSION) :
 ?>
 ?>
 		<div id="serverdata" class="hidden" aria-hidden="true">
 		<div id="serverdata" class="hidden" aria-hidden="true">
 			<div id="templates">
 			<div id="templates">
-				<article id="commenttemplate" class="comment"><div class="commentmeta"><span class="nickname">name</span><span class="commentdate">0000-00-00</span></div><div class="commentdata">c</div><button class="btn btn-default btn-sm"><?php echo I18n::_('Reply'); ?></button></article>
-				<p id="commenttailtemplate" class="comment"><button class="btn btn-default btn-sm"><?php echo I18n::_('Add comment'); ?></button></p>
-				<div id="replytemplate" class="reply hidden"><input type="text" id="nickname" class="form-control" title="<?php echo I18n::_('Optional nickname…'); ?>" placeholder="<?php echo I18n::_('Optional nickname…'); ?>" /><textarea id="replymessage" class="replymessage form-control" cols="80" rows="7"></textarea><br /><div id="replystatus" role="alert" class="statusmessage hidden alert"><span class="glyphicon" aria-hidden="true"></span> </div><button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button></div>
+				<article id="commenttemplate" class="comment">
+					<div class="commentmeta">
+						<span class="nickname">name</span>
+						<span class="commentdate">0000-00-00</span>
+					</div>
+					<div class="commentdata">c</div>
+					<button class="btn btn-default btn-sm"><?php echo I18n::_('Reply'); ?></button>
+				</article>
+				<p id="commenttailtemplate" class="comment">
+					<button class="btn btn-default btn-sm"><?php echo I18n::_('Add comment'); ?></button>
+				</p>
+				<div id="replytemplate" class="reply hidden">
+					<input type="text" id="nickname" class="form-control" title="<?php echo I18n::_('Optional nickname…'); ?>" placeholder="<?php echo I18n::_('Optional nickname…'); ?>" />
+					<textarea id="replymessage" class="replymessage form-control" cols="80" rows="7"></textarea><br />
+					<div id="replystatus" role="alert" class="statusmessage hidden alert">
+						<span class="glyphicon" aria-hidden="true"></span>
+					</div>
+					<button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button>
+				</div>
 			</div>
 			</div>
 		</div>
 		</div>
 <?php
 <?php

+ 502 - 0
tpl/bootstrap5.php

@@ -0,0 +1,502 @@
+<?php
+use PrivateBin\I18n;
+?><!DOCTYPE html>
+<html lang="<?php echo I18n::getLanguage(); ?>"<?php echo I18n::isRtl() ? ' dir="rtl"' : ''; ?>>
+	<head>
+		<meta charset="utf-8" />
+		<meta http-equiv="Content-Security-Policy" content="<?php echo I18n::encode($CSPHEADER); ?>">
+		<meta http-equiv="X-UA-Compatible" content="IE=edge">
+		<meta name="viewport" content="width=device-width, initial-scale=1">
+		<meta name="robots" content="noindex" />
+		<meta name="google" content="notranslate">
+		<title><?php echo I18n::_($NAME); ?></title>
+		<link type="text/css" rel="stylesheet" href="css/bootstrap5/bootstrap<?php echo I18n::isRtl() ? '.rtl' : ''; ?>-5.3.3.css" />
+		<link type="text/css" rel="stylesheet" href="css/bootstrap5/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+if ($SYNTAXHIGHLIGHTING) :
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+    if (!empty($SYNTAXHIGHLIGHTINGTHEME)) :
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+    endif;
+endif;
+?>
+		<noscript><link type="text/css" rel="stylesheet" href="css/noscript.css" /></noscript>
+		<script type="text/javascript" data-cfasync="false" src="js/jquery-3.7.0.js" integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw==" crossorigin="anonymous"></script>
+<?php
+if ($QRCODE) :
+?>
+		<script async type="text/javascript" data-cfasync="false" src="js/kjua-0.9.0.js" integrity="sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==" crossorigin="anonymous"></script>
+<?php
+endif;
+if ($ZEROBINCOMPATIBILITY) :
+?>
+		<script type="text/javascript" data-cfasync="false" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
+<?php
+endif;
+?>
+		<script type="text/javascript" data-cfasync="false" src="js/zlib-1.3.1.js" integrity="sha512-Z90oppVx/mn0DG2k9airjFVQuliELlXLeT3SRiO6MLiUSbhGlAq+UFwmYbG4i9mwW87dkG8fgJPapGwnUq7Osg==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/base-x-4.0.0.js" integrity="sha512-nNPg5IGCwwrveZ8cA/yMGr5HiRS5Ps2H+s0J/mKTPjCPWUgFGGw7M5nqdnPD3VsRwCVysUh3Y8OWjeSKGkEQJQ==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/bootstrap-5.3.3.js" integrity="sha512-in2rcOpLTdJ7/pw5qjF4LWHFRtgoBDxXCy49H4YGOcVdGiPaQucGIbOqxt1JvmpvOpq3J/C7VTa0FlioakB2gQ==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/dark-mode-switch.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-xdW325H1OW06oUf/Lc4ccJXOUW41tU08iyXVOiVL3SbTufQtKVWi1/cQPrWZ3FagPTNL2CwDMqZsHNmXruHnHg==" crossorigin="anonymous"></script>
+<?php
+if ($SYNTAXHIGHLIGHTING) :
+?>
+		<script type="text/javascript" data-cfasync="false" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==" crossorigin="anonymous"></script>
+<?php
+endif;
+if ($MARKDOWN) :
+?>
+		<script type="text/javascript" data-cfasync="false" src="js/showdown-2.1.0.js" integrity="sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==" crossorigin="anonymous"></script>
+<?php
+endif;
+?>
+		<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.2.js" integrity="sha512-voYCOVXik5/jcT+McTiptsB00iB0NWQrhBmSwSEfj0IH3UDphU8w12JV8w1y+m8FRaozbzW4efHSEWKZpOA+JQ==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-UdOSZnkEQtdvgsyYhMSTCw2/TRv7x/jL8AtCKLnT722eudYsGPAd8wvPOU6zvdoNNJ8R43CfSJCJuCaDP2ahzA==" crossorigin="anonymous"></script>
+		<!-- icon -->
+		<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
+		<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />
+		<link rel="icon" type="image/png" href="img/favicon-16x16.png" sizes="16x16" />
+		<link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" />
+		<link rel="mask-icon" href="img/safari-pinned-tab.svg" color="#ffcc00" />
+		<link rel="shortcut icon" href="img/favicon.ico">
+		<meta name="msapplication-config" content="browserconfig.xml">
+		<meta name="theme-color" content="#ffe57e" />
+		<!-- Twitter/social media cards -->
+		<meta name="twitter:card" content="summary" />
+		<meta name="twitter:title" content="<?php echo I18n::_('Encrypted note on %s', I18n::_($NAME)) ?>" />
+		<meta name="twitter:description" content="<?php echo I18n::_('Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.') ?>" />
+		<meta name="twitter:image" content="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" />
+		<meta property="og:title" content="<?php echo I18n::_($NAME); ?>" />
+		<meta property="og:site_name" content="<?php echo I18n::_($NAME); ?>" />
+		<meta property="og:description" content="<?php echo I18n::_('Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.') ?>" />
+		<meta property="og:image" content="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" />
+		<meta property="og:image:type" content="image/png" />
+		<meta property="og:image:width" content="180" />
+		<meta property="og:image:height" content="180" />
+	</head>
+	<body role="document" data-compression="<?php echo rawurlencode($COMPRESSION); ?>">
+		<div id="passwordmodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
+			<div class="modal-dialog" role="document">
+				<div class="modal-content">
+					<div class="modal-body">
+						<form id="passwordform" role="form">
+							<div class="mb-3">
+								<label for="passworddecrypt"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#eye" /></svg> <?php echo I18n::_('Please enter the password for this paste:') ?></label>
+								<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>" required="required">
+							</div>
+							<button type="submit" class="btn btn-success btn-block"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#power" /></svg> <?php echo I18n::_('Decrypt') ?></button>
+						</form>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div id="loadconfirmmodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
+			<div class="modal-dialog" role="document">
+				<div class="modal-content">
+					<div class="modal-header">
+						<h5 class="modal-title"><?php echo I18n::_('This secret message can only be displayed once. Would you like to see it now?') ?></h5>
+						<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?php echo I18n::_('Close') ?>"></button>
+					</div>
+					<div class="modal-body text-center">
+						<button id="loadconfirm-open-now" type="button" class="btn btn-success" data-dismiss="modal"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#cloud-download" /></svg> <?php echo I18n::_('Yes, see it') ?></button>
+					</div>
+				</div>
+			</div>
+		</div>
+<?php
+if ($QRCODE) :
+?>
+		<div id="qrcodemodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
+			<div class="modal-dialog" role="document">
+				<div class="modal-content">
+					<div class="modal-header">
+						<h5 class="modal-title"><?php echo I18n::_('QR code') ?></h5>
+						<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?php echo I18n::_('Close') ?>"></button>
+					</div>
+					<div class="modal-body">
+						<div class="mx-auto" id="qrcode-display"></div>
+					</div>
+				</div>
+			</div>
+		</div>
+<?php
+endif;
+if ($EMAIL) :
+?>
+		<div id="emailconfirmmodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
+			<div class="modal-dialog" role="document">
+				<div class="modal-content">
+					<div class="modal-header">
+						<h5 class="modal-title"><?php echo I18n::_('Recipient may become aware of your timezone, convert time to UTC?') ?></h5>
+						<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?php echo I18n::_('Close') ?>"></button>
+					</div>
+					<div class="modal-body row">
+						<div class="col-xs-12 col-md-6">
+							<button id="emailconfirm-timezone-current" type="button" class="btn btn-danger"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#clock" /></svg> <?php echo I18n::_('Use Current Timezone') ?></button>
+						</div>
+						<div class="col-xs-12 col-md-6 text-right">
+							<button id="emailconfirm-timezone-utc" type="button" class="btn btn-success"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#globe" /></svg> <?php echo I18n::_('Convert To UTC') ?></button>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+<?php
+endif;
+?>
+		<nav class="navbar navbar-expand-lg bg-body-tertiary">
+			<div class="container-fluid">
+				<a class="reloadlink navbar-brand" href="">
+					<img alt="<?php echo I18n::_($NAME); ?>" src="img/icon.svg" height="38" />
+				</a>
+				<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="<?php echo I18n::_('Toggle navigation'); ?>">
+					<span class="navbar-toggler-icon"></span>
+				</button>
+				<div id="navbar" class="collapse navbar-collapse">
+					<ul class="navbar-nav me-auto">
+						<li id="loadingindicator" class="navbar-text hidden me-auto">
+							<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#clock" /></svg>
+							<?php echo I18n::_('Loading…'), PHP_EOL; ?>
+						</li>
+						<li class="nav-item me-2">
+							<button id="retrybutton" type="button" class="reloadlink hidden btn btn-primary">
+								<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#repeat" /></svg> <?php echo I18n::_('Retry'), PHP_EOL; ?>
+							</button>
+						</li>
+						<li class="nav-item">
+							<button id="newbutton" type="button" class="hidden btn btn-secondary me-2">
+								<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#file-earmark" /></svg> <?php echo I18n::_('New'), PHP_EOL; ?>
+							</button>
+							<button id="clonebutton" type="button" class="hidden btn btn-secondary me-2">
+								<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#copy" /></svg> <?php echo I18n::_('Clone'), PHP_EOL; ?>
+							</button>
+							<button id="rawtextbutton" type="button" class="hidden btn btn-secondary me-2">
+								<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#filetype-txt" /></svg> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
+							</button>
+							<button id="downloadtextbutton" type="button" class="hidden btn btn-secondary me-2">
+								<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#download" /></svg> <?php echo I18n::_('Save paste'), PHP_EOL; ?>
+							</button>
+<?php
+if ($EMAIL) :
+?>
+
+							<button id="emaillink" type="button" class="hidden btn btn-secondary me-2">
+								<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#envelope" /></svg> <?php echo I18n::_('Email'), PHP_EOL; ?>
+							</button>
+<?php
+endif;
+if ($QRCODE) :
+?>
+							<button id="qrcodelink" type="button" data-toggle="modal" data-target="#qrcodemodal" class="hidden btn btn-secondary me-2">
+								<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#qr-code" /></svg> <?php echo I18n::_('QR code'), PHP_EOL; ?>
+							</button>
+<?php
+endif;
+?>
+						</li>
+						<li id="expiration" class="nav-item me-2 d-flex hidden">
+							<label for="pasteExpiration" class="form-label my-auto me-1"><?php echo I18n::_('Expires'); ?>:</label>
+							<select id="pasteExpiration" name="pasteExpiration" class="form-select">
+<?php
+foreach ($EXPIRE as $key => $value) :
+?>
+								<option value="<?php echo $key; ?>"<?php
+    if ($key == $EXPIREDEFAULT) :
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
+							</select>
+						</li>
+						<li class="nav-item me-2">
+							<div id="burnafterreadingoption" class="navbar-text form-check hidden">
+								<input class="form-check-input" type="checkbox" id="burnafterreading" name="burnafterreading"<?php
+if ($BURNAFTERREADINGSELECTED) :
+?> checked="checked"<?php
+endif;
+?> />
+								<label class="form-check-label" for="burnafterreading">
+									<?php echo I18n::_('Burn after reading'), PHP_EOL; ?>
+								</label>
+							</div>
+						</li>
+<?php
+if ($DISCUSSION) :
+?>
+						<li class="nav-item me-2">
+							<div id="opendiscussionoption" class="navbar-text form-check hidden">
+								<input class="form-check-input" type="checkbox" id="opendiscussion" name="opendiscussion"<?php
+	if ($OPENDISCUSSION) :
+?> checked="checked"<?php
+	endif;
+?> />
+								<label class="form-check-label" for="opendiscussion">
+									<?php echo I18n::_('Open discussion'), PHP_EOL; ?>
+								</label>
+							</div>
+						</li>
+<?php
+endif;
+if ($PASSWORD) :
+?>
+						<li class="nav-item me-2">
+							<div id="password" class="navbar-form hidden">
+								<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="23" />
+							</div>
+						</li>
+<?php
+endif;
+if ($FILEUPLOAD) :
+?>
+						<li id="attach" class="nav-item hidden dropdown me-2">
+							<a href="#" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?></a>
+							<ul class="dropdown-menu">
+								<li id="filewrap">
+									<div>
+										<input type="file" id="file" name="file" class="form-control" />
+									</div>
+									<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('alternatively drag & drop a file or paste an image from the clipboard'); ?></div>
+								</li>
+								<li id="customattachment" class="hidden"></li>
+								<li>
+									<a id="fileremovebutton" href="#" class="dropdown-item">
+										<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
+									</a>
+								</li>
+							</ul>
+						</li>
+<?php
+endif;
+?>
+						<li id="formatter" class="nav-item me-2 d-flex hidden">
+							<label for="pasteFormatter" class="form-label my-auto me-1"><?php echo I18n::_('Format'); ?>:</label>
+							<select id="pasteFormatter" name="pasteFormatter" class="form-select">
+<?php
+    foreach ($FORMATTER as $key => $value) :
+?>
+								<option value="<?php echo $key; ?>"<?php
+        if ($key == $FORMATTERDEFAULT) :
+?> selected="selected"<?php
+        endif;
+?>><?php echo $value; ?></option>
+<?php
+    endforeach;
+?>
+							</select>
+						</li>
+					</ul>
+					<ul class="navbar-nav">
+						<li class="nav-item">
+							<div class="form-check form-switch navbar-text">
+								<input id="bd-theme" type="checkbox" class="form-check-input">
+								<label for="bd-theme" class="form-check-label"><?php echo I18n::_('Dark Mode'); ?></label>
+							</div>
+						</li>
+<?php
+if (!empty($LANGUAGESELECTION)) :
+?>
+						<li id="language" class="nav-item dropdown ms-2">
+							<a href="#" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-expanded="false">
+								<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#flag" /></svg> <?php echo $LANGUAGES[$LANGUAGESELECTION][0], PHP_EOL; ?>
+							</a>
+							<ul class="dropdown-menu dropdown-menu-end" role="menu">
+<?php
+    foreach ($LANGUAGES as $key => $value) :
+?>
+								<li>
+									<a href="#" class="dropdown-item" data-lang="<?php echo $key; ?>">
+										<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
+									</a>
+								</li>
+<?php
+    endforeach;
+?>
+							</ul>
+						</li>
+<?php
+endif;
+?>
+					</ul>
+				</div>
+			</div>
+		</nav>
+		<main>
+			<section class="container mt-2">
+<?php
+if (!empty($NOTICE)) :
+?>
+				<div role="alert" class="alert alert-info">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#info-circle" /></svg>
+					<?php echo I18n::encode($NOTICE), PHP_EOL; ?>
+				</div>
+<?php
+endif;
+?>
+				<div id="remainingtime" role="alert" class="hidden alert alert-info">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#fire" /></svg>
+				</div>
+<?php
+if ($FILEUPLOAD) :
+?>
+				<div id="attachment" role="alert" class="hidden alert alert-info">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#download" /></svg>
+					<a class="alert-link"><?php echo I18n::_('Download attachment'); ?></a>
+				</div>
+<?php
+endif;
+?>
+				<div id="status" role="alert" class="alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#info-circle" /></svg>
+					<?php echo I18n::encode($STATUS), PHP_EOL; ?>
+				</div>
+				<div id="errormessage" role="alert" class="<?php echo empty($ERROR) ? 'hidden' : '' ?> alert alert-danger">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-triangle" /></svg>
+					<?php echo I18n::encode($ERROR), PHP_EOL; ?>
+				</div>
+				<noscript>
+					<div id="noscript" role="alert" class="alert alert-warning">
+						<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-circle" /></svg>
+						<?php echo I18n::_('JavaScript is required for %s to work. Sorry for the inconvenience.', I18n::_($NAME)), PHP_EOL; ?>
+					</div>
+				</noscript>
+				<div id="oldnotice" role="alert" class="hidden alert alert-danger">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-triangle" /></svg>
+					<?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?>
+					<a href="https://www.mozilla.org/firefox/">Firefox</a>,
+					<a href="https://www.opera.com/">Opera</a>,
+					<a href="https://www.google.com/chrome">Chrome</a>…<br />
+					<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-the-error-privatebin-requires-a-modern-browser-to-work'); ?></span>
+				</div>
+<?php
+if ($HTTPWARNING) :
+?>
+				<div id="httpnotice" role="alert" class="hidden alert alert-danger">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-triangle" /></svg>
+					<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'); ?><br />
+					<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection'); ?></span>
+				</div>
+				<div id="insecurecontextnotice" role="alert" class="hidden alert alert-danger">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-triangle" /></svg>
+					<?php echo I18n::_('Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.', $HTTPSLINK), PHP_EOL; ?>
+				</div>
+<?php
+endif;
+?>
+				<div id="pastesuccess" class="hidden">
+					<div role="alert" class="alert alert-success">
+						<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#check" /></svg>
+						<div id="deletelink"></div>
+						<div id="pastelink"></div>
+					</div>
+<?php
+if (!empty($URLSHORTENER)) :
+?>
+					<p>
+						<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>" type="button" class="btn btn-primary btn-block">
+						<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#send" /></svg> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
+					</button>
+					</p>
+					<div role="alert" class="alert alert-danger">
+						<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-circle" /></svg>
+						<?php echo I18n::_('URL shortener may expose your decrypt key in URL.'), PHP_EOL; ?>
+					</div>
+<?php
+endif;
+?>
+				</div>
+				<ul id="editorTabs" class="nav nav-tabs hidden">
+					<li role="presentation" class="nav-item me-1"><a class="nav-link active" role="tab" id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
+					<li role="presentation" class="nav-item me-1"><a class="nav-link" role="tab" id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
+					<li role="presentation" class="nav-item ms-auto">
+						<button id="sendbutton" type="button" class="hidden btn btn-primary">
+							<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#cloud-upload" /></svg> <?php echo I18n::_('Create'), PHP_EOL; ?>
+						</button>
+					</li>
+				</ul>
+			</section>
+			<section class="container">
+				<article class="row">
+					<div id="placeholder" class="col-md-12 hidden"><?php echo I18n::_('+++ no paste text +++'); ?></div>
+					<div id="attachmentPreview" class="col-md-12 text-center hidden"></div>
+					<div id="prettymessage" class="col-md-12 hidden">
+						<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
+					</div>
+					<div id="plaintext" class="col-md-12 hidden"></div>
+					<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
+				</article>
+			</section>
+			<section class="container">
+				<div id="discussion" class="hidden">
+					<h4><?php echo I18n::_('Discussion'); ?></h4>
+					<div id="commentcontainer"></div>
+				</div>
+			</section>
+			<section class="container">
+				<div id="noscript" role="alert" class="alert alert-info noscript-hide">
+					<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-circle" /></svg>
+					<?php echo I18n::_('Loading…'); ?><br />
+					<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-the-loading-message-not-go-away'); ?></span>
+				</div>
+			</section>
+			<footer class="container">
+				<div class="row">
+					<h4 class="col-md-5 col-xs-8"><?php echo I18n::_($NAME); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
+					<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
+					<p id="aboutbox" class="col-md-6 col-xs-12">
+						<?php echo sprintf(
+                            I18n::_('%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.',
+                                I18n::_($NAME),
+                                '%s', '%s'
+                            ),
+                            '<i>', '</i>'), ' ', $INFO, PHP_EOL;
+                        ?>
+					</p>
+				</div>
+			</footer>
+		</main>
+<?php
+if ($DISCUSSION) :
+?>
+		<div id="serverdata" class="hidden" aria-hidden="true">
+			<div id="templates">
+				<article id="commenttemplate" class="comment">
+					<div class="commentmeta">
+						<span class="nickname">name</span>
+						<span class="commentdate">0000-00-00</span>
+					</div>
+					<div class="commentdata">c</div>
+					<button class="btn btn-secondary btn-sm"><?php echo I18n::_('Reply'); ?></button>
+				</article>
+				<p id="commenttailtemplate" class="comment">
+					<button class="btn btn-secondary btn-sm"><?php echo I18n::_('Add comment'); ?></button>
+				</p>
+				<div id="replytemplate" class="reply hidden">
+					<input type="text" id="nickname" class="form-control" title="<?php echo I18n::_('Optional nickname…'); ?>" placeholder="<?php echo I18n::_('Optional nickname…'); ?>" />
+					<textarea id="replymessage" class="replymessage form-control" cols="80" rows="7"></textarea><br />
+					<div id="replystatus" role="alert" class="statusmessage hidden alert">
+						<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#info-circle" /></svg>
+					</div>
+					<button id="replybutton" class="btn btn-secondary btn-sm"><?php echo I18n::_('Post comment'); ?></button>
+				</div>
+			</div>
+		</div>
+<?php
+endif;
+?>
+<?php
+if ($FILEUPLOAD) :
+?>
+		<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
+<?php
+endif;
+?>
+	</body>
+</html>

+ 25 - 9
tpl/page.php

@@ -14,7 +14,7 @@ if ($SYNTAXHIGHLIGHTING):
 ?>
 ?>
 		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
 		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
 <?php
 <?php
-    if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
+    if (!empty($SYNTAXHIGHLIGHTINGTHEME)):
 ?>
 ?>
 		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
 		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
 <?php
 <?php
@@ -49,9 +49,9 @@ if ($MARKDOWN):
 <?php
 <?php
 endif;
 endif;
 ?>
 ?>
-		<script type="text/javascript" data-cfasync="false" src="js/purify-3.0.8.js" integrity="sha512-wWBDKh5wYGtJ1Df+PPZIn59jHVBnJ4/Yb2W/pVnzaXab8cmlZnHVx+FEBGu5JX39s3P2Qlt+aNQou0XnjW86hg==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.2.js" integrity="sha512-voYCOVXik5/jcT+McTiptsB00iB0NWQrhBmSwSEfj0IH3UDphU8w12JV8w1y+m8FRaozbzW4efHSEWKZpOA+JQ==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-q2+Xxj6aqq8VCdEZs60z/nQTeHYb400bmfyWVh7gIICdNEz2LIVt95hH/DMVDr3pv+vkIcdDL8va5J9rtaY6WA==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-UdOSZnkEQtdvgsyYhMSTCw2/TRv7x/jL8AtCKLnT722eudYsGPAd8wvPOU6zvdoNNJ8R43CfSJCJuCaDP2ahzA==" crossorigin="anonymous"></script>
 		<!-- icon -->
 		<!-- icon -->
 		<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
 		<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
@@ -86,7 +86,7 @@ endif;
                 ?>
                 ?>
 				<br />
 				<br />
 <?php
 <?php
-if (strlen($NOTICE)):
+if (!empty($NOTICE)):
 ?>
 ?>
 				<span class="blink">▶</span> <?php echo I18n::encode($NOTICE);
 				<span class="blink">▶</span> <?php echo I18n::encode($NOTICE);
 endif;
 endif;
@@ -203,7 +203,7 @@ endforeach;
 						</select>
 						</select>
 					</div>
 					</div>
 <?php
 <?php
-if (strlen($LANGUAGESELECTION)):
+if (!empty($LANGUAGESELECTION)):
 ?>
 ?>
 					<div id="language" class="button">
 					<div id="language" class="button">
 						<select name="lang">
 						<select name="lang">
@@ -234,7 +234,7 @@ endif;
 					<div id="deletelink"></div>
 					<div id="deletelink"></div>
 					<div id="pastelink"></div>
 					<div id="pastelink"></div>
 <?php
 <?php
-if (strlen($URLSHORTENER)):
+if (!empty($URLSHORTENER)):
 ?>
 ?>
 					<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>"><img src="img/icon_shorten.png" width="13" height="15" /><?php echo I18n::_('Shorten URL'); ?></button>
 					<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>"><img src="img/icon_shorten.png" width="13" height="15" /><?php echo I18n::_('Shorten URL'); ?></button>
 <?php
 <?php
@@ -277,9 +277,25 @@ if ($DISCUSSION):
 ?>
 ?>
 		<div id="serverdata" class="hidden" aria-hidden="true">
 		<div id="serverdata" class="hidden" aria-hidden="true">
 			<div id="templates">
 			<div id="templates">
-				<article id="commenttemplate" class="comment"><div class="commentmeta"><span class="nickname">name</span><span class="commentdate">0000-00-00</span></div><div class="commentdata">c</div><button class="btn btn-default btn-sm"><?php echo I18n::_('Reply'); ?></button></article>
-				<div id="commenttailtemplate" class="comment"><button class="btn btn-default btn-sm"><?php echo I18n::_('Add comment'); ?></button></div>
-				<div id="replytemplate" class="reply hidden"><input type="text" id="nickname" class="form-control" title="<?php echo I18n::_('Optional nickname…'); ?>" placeholder="<?php echo I18n::_('Optional nickname…'); ?>" /><textarea id="replymessage" class="replymessage form-control" cols="80" rows="7"></textarea><br /><div id="replystatus" role="alert" class="statusmessage hidden alert"><span class="glyphicon" aria-hidden="true"></span> </div><button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button></div>
+				<article id="commenttemplate" class="comment">
+					<div class="commentmeta">
+						<span class="nickname">name</span>
+						<span class="commentdate">0000-00-00</span>
+					</div>
+					<div class="commentdata">c</div>
+					<button class="btn btn-default btn-sm"><?php echo I18n::_('Reply'); ?></button>
+				</article>
+				<div id="commenttailtemplate" class="comment">
+					<button class="btn btn-default btn-sm"><?php echo I18n::_('Add comment'); ?></button>
+				</div>
+				<div id="replytemplate" class="reply hidden">
+					<input type="text" id="nickname" class="form-control" title="<?php echo I18n::_('Optional nickname…'); ?>" placeholder="<?php echo I18n::_('Optional nickname…'); ?>" />
+					<textarea id="replymessage" class="replymessage form-control" cols="80" rows="7"></textarea><br />
+					<div id="replystatus" role="alert" class="statusmessage hidden alert">
+						<span class="glyphicon" aria-hidden="true"></span>
+					</div>
+					<button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button>
+				</div>
 			</div>
 			</div>
 		</div>
 		</div>
 <?php
 <?php

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff