From a4a32f6b9e0213797ad43b9b458dbd5fbc86614b Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 20 Jun 2021 08:43:44 +0200 Subject: [PATCH 001/783] switch to streaming WASM loading, fixes #814 --- js/zlib-1.2.11.js | 57 ++++++++++++++++++++--------------------------- tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 3 files changed, 26 insertions(+), 35 deletions(-) diff --git a/js/zlib-1.2.11.js b/js/zlib-1.2.11.js index ed0abea8..835cb968 100644 --- a/js/zlib-1.2.11.js +++ b/js/zlib-1.2.11.js @@ -1,6 +1,6 @@ 'use strict'; -(function() { +(function () { let ret; async function initialize() { @@ -23,16 +23,7 @@ _abort: errno => { console.error(`Error: ${errno}`) }, _grow: () => { }, }; - - let buff; - if (typeof fetch === 'undefined') { - buff = fs.readFileSync('zlib-1.2.11.wasm'); - } else { - const resp = await fetch('js/zlib-1.2.11.wasm'); - buff = await resp.arrayBuffer(); - } - const module = await WebAssembly.compile(buff); - const ins = await WebAssembly.instantiate(module, { env }); + const ins = await WebAssembly.instantiateStreaming(fetch('js/zlib-1.2.11.wasm'), { env }); const srcPtr = ins.exports._malloc(CHUNK_SIZE); const dstPtr = ins.exports._malloc(CHUNK_SIZE); @@ -116,28 +107,28 @@ } ret = { - inflate(rawDeflateBuffer) { - const rawInf = new RawInf(); - for (let offset = 0; offset < rawDeflateBuffer.length; offset += CHUNK_SIZE) { - const end = Math.min(offset + CHUNK_SIZE, rawDeflateBuffer.length); - const chunk = rawDeflateBuffer.subarray(offset, end); - rawInf.inflate(chunk); - } - const ret = rawInf.getBuffer(); - rawInf.destroy(); - return ret; - }, - deflate(rawInflateBuffer) { - const rawDef = new RawDef(); - for (let offset = 0; offset < rawInflateBuffer.length; offset += CHUNK_SIZE) { - const end = Math.min(offset + CHUNK_SIZE, rawInflateBuffer.length); - const chunk = rawInflateBuffer.subarray(offset, end); - rawDef.deflate(chunk, rawInflateBuffer.length <= offset + CHUNK_SIZE); - } - const ret = rawDef.getBuffer(); - rawDef.destroy(); - return ret; - }, + inflate(rawDeflateBuffer) { + const rawInf = new RawInf(); + for (let offset = 0; offset < rawDeflateBuffer.length; offset += CHUNK_SIZE) { + const end = Math.min(offset + CHUNK_SIZE, rawDeflateBuffer.length); + const chunk = rawDeflateBuffer.subarray(offset, end); + rawInf.inflate(chunk); + } + const ret = rawInf.getBuffer(); + rawInf.destroy(); + return ret; + }, + deflate(rawInflateBuffer) { + const rawDef = new RawDef(); + for (let offset = 0; offset < rawInflateBuffer.length; offset += CHUNK_SIZE) { + const end = Math.min(offset + CHUNK_SIZE, rawInflateBuffer.length); + const chunk = rawInflateBuffer.subarray(offset, end); + rawDef.deflate(chunk, rawInflateBuffer.length <= offset + CHUNK_SIZE); + } + const ret = rawDef.getBuffer(); + rawDef.destroy(); + return ret; + }, } return ret; diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 1e4eae00..86c15de2 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -54,7 +54,7 @@ if ($ZEROBINCOMPATIBILITY) : - + diff --git a/tpl/page.php b/tpl/page.php index 28f37b90..f3b26d4e 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -33,7 +33,7 @@ if ($ZEROBINCOMPATIBILITY): - + Date: Sun, 20 Jun 2021 08:44:25 +0200 Subject: [PATCH 002/783] remove unsafe-eval from CSP --- cfg/conf.sample.php | 2 +- lib/Configuration.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index d362f3f2..bfae7563 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -87,7 +87,7 @@ languageselection = false ; async functions and display an error if not and for Chrome to enable ; webassembly support (used for zlib compression). You can remove it if Chrome ; doesn't need to be supported and old browsers don't need to be warned. -; cspheader = "default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval' resource:; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads" +; cspheader = "default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' resource:; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads" ; stay compatible with PrivateBin Alpha 0.19, less secure ; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of diff --git a/lib/Configuration.php b/lib/Configuration.php index 7c4eb106..35e5b40f 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -54,7 +54,7 @@ class Configuration 'urlshortener' => '', 'qrcode' => true, 'icon' => 'identicon', - 'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\' resource:; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads', + 'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' resource:; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads', 'zerobincompatibility' => false, 'httpwarning' => true, 'compression' => 'zlib', From f797311650b4deebc32b79eb31efdbebe7ae4dae Mon Sep 17 00:00:00 2001 From: "J. Fernando LAGRANGE" Date: Tue, 28 Jun 2022 09:40:53 +0200 Subject: [PATCH 003/783] Change "Send" button label to "Save" Includes french translation. --- i18n/en.json | 2 +- i18n/fr.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index 2ba6068f..9ebee8bd 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -25,7 +25,7 @@ "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", "%s requires a modern browser to work.": "%s requires a modern browser to work.", "New": "New", - "Send": "Send", + "Send": "Save", "Clone": "Clone", "Raw text": "Raw text", "Expires": "Expires", diff --git a/i18n/fr.json b/i18n/fr.json index 2f3d491e..3ba422dd 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -25,7 +25,7 @@ "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript est requis pour faire fonctionner %s. Désolé pour cet inconvénient.", "%s requires a modern browser to work.": "%s nécessite un navigateur moderne pour fonctionner.", "New": "Nouveau", - "Send": "Envoyer", + "Send": "Sauvegarder", "Clone": "Cloner", "Raw text": "Texte brut", "Expires": "Expire", From 6133f6c35cbf728a2099608eee575b02a80b1513 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:37:40 +0000 Subject: [PATCH 004/783] Bump phpunit/phpunit from 9.6.14 to 9.6.15 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.14 to 9.6.15. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.15/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.14...9.6.15) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 87ba850e..bf8fa3fd 100644 --- a/composer.lock +++ b/composer.lock @@ -802,16 +802,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.14", + "version": "9.6.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "43653e6ad7adc22e7b667dd561bf8fcb74c10cf0" + "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43653e6ad7adc22e7b667dd561bf8fcb74c10cf0", - "reference": "43653e6ad7adc22e7b667dd561bf8fcb74c10cf0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", + "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", "shasum": "" }, "require": { @@ -885,7 +885,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.14" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" }, "funding": [ { @@ -901,7 +901,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T06:10:48+00:00" + "time": "2023-12-01T16:55:19+00:00" }, { "name": "sebastian/cli-parser", From 33e9025d093d686dba25e92a89240c8f0cc976c1 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:14:57 +0100 Subject: [PATCH 005/783] New translations en.json (Finnish) --- i18n/fi.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/fi.json b/i18n/fi.json index 4f426c53..2b0b81c5 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -212,7 +212,7 @@ "URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.", "Save paste": "Tallenna paste", "Your IP is not authorized to create pastes.": "IP:llesi ei ole annettu oikeutta luoda pasteja.", - "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", - "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\".", + "Trying to shorten a URL that isn't pointing at our instance.": "Yritetään lyhentää URL-osoite, joka ei osoita meidän instanssiiin.", + "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.": "Error parsing YOURLS response." } From 5b2f788e482b7068019429956ee6903844cbfc88 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:43:03 +0100 Subject: [PATCH 006/783] New translations en.json (Finnish) --- i18n/fi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fi.json b/i18n/fi.json index 2b0b81c5..440caf77 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -214,5 +214,5 @@ "Your IP is not authorized to create pastes.": "IP:llesi ei ole annettu oikeutta luoda pasteja.", "Trying to shorten a URL that isn't pointing at our instance.": "Yritetään lyhentää URL-osoite, joka ei osoita meidän instanssiiin.", "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.": "Error parsing YOURLS response." + "Error parsing YOURLS response.": "Virhe jäsennettäessä YOURLS-vastausta." } From bb89eb7fba6a68a369f2a3a13ae8f272d39cce7d Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:46:19 +0100 Subject: [PATCH 007/783] New translations en.json (Finnish) --- i18n/fi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fi.json b/i18n/fi.json index 440caf77..063df4a3 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -208,7 +208,7 @@ "Convert To UTC": "Muuta UTC:ksi", "Close": "Sulje", "Encrypted note on %s": "Salattu viesti %sissä", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Käy tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomeen viestiä. ", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Vieraile tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomaan viestiä.", "URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.", "Save paste": "Tallenna paste", "Your IP is not authorized to create pastes.": "IP:llesi ei ole annettu oikeutta luoda pasteja.", From f8c2f58604a93f97e823990be9772ce9e0714944 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 4 Dec 2023 21:24:12 +0100 Subject: [PATCH 008/783] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ab195ffc..dbb625ed 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ without losing any data. paste (first) might still be disclosed via access logs. - In case of a server breach your data is secure as it is only stored encrypted - on the server. However, the server could be absused or the server admin could + on the server. However, the server could be abused or the server admin could be legally forced into sending malicious code to their users, which logs the decryption key and sends it to a server when a user accesses a paste. Therefore, do not access any PrivateBin instance if you think it has been From 7a5036d9570f803bbebc32eac0939fe388b50f76 Mon Sep 17 00:00:00 2001 From: Joe Skeen Date: Fri, 8 Dec 2023 15:34:00 +0000 Subject: [PATCH 009/783] move postCreateCommands to a separate file --- .devcontainer/devcontainer.json | 6 +----- .devcontainer/postCreateCommand.sh | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100755 .devcontainer/postCreateCommand.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a0c531ee..961135ed 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -40,11 +40,7 @@ "forwardPorts": [ 8080 ], - "postCreateCommand": [ - "composer install --no-dev --optimize-autoloader", - "sudo chmod a+x \"$(pwd)\" && sudo rm -rf /var/www/html && sudo ln -s \"$(pwd)\" /var/www/html", - "npm install --global nyc" - ], + "postCreateCommand": ".devcontainer/postCreateCommand.sh", // alternatiuve: apache2ctl start (but requires root) "postAttachCommand": "php -S 0.0.0.0:8080" } diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh new file mode 100755 index 00000000..41b61ef9 --- /dev/null +++ b/.devcontainer/postCreateCommand.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +composer install --no-dev --optimize-autoloader +sudo chmod a+x "$(pwd)" && sudo rm -rf /var/www/html && sudo ln -s "$(pwd)" /var/www/html +npm install --global nyc From 49a87c6038532f3a47ea2145aa0f98179041f71b Mon Sep 17 00:00:00 2001 From: Joe Skeen Date: Fri, 8 Dec 2023 16:30:45 +0000 Subject: [PATCH 010/783] add workspace settings with config files treated as INI --- .vscode/settings.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..ac8225cd --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "**/cfg/conf*.php": "ini" + } +} From 10c6841f8a26277ff69b29fd6a6d3f6cdd2f93ed Mon Sep 17 00:00:00 2001 From: Joe Skeen Date: Fri, 8 Dec 2023 15:31:45 -0700 Subject: [PATCH 011/783] Update .devcontainer/postCreateCommand.sh Co-authored-by: rugk --- .devcontainer/postCreateCommand.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh index 41b61ef9..dd613dbe 100755 --- a/.devcontainer/postCreateCommand.sh +++ b/.devcontainer/postCreateCommand.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh composer install --no-dev --optimize-autoloader sudo chmod a+x "$(pwd)" && sudo rm -rf /var/www/html && sudo ln -s "$(pwd)" /var/www/html From 826444bef74cda2bc6ee63dff0408eae0744b74d Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 9 Dec 2023 10:50:49 +0100 Subject: [PATCH 012/783] fix shasum in release pipeline, hope this fixes #1169 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 47b163fa..7847c9c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,7 +34,7 @@ jobs: - name: Generate hashes shell: bash id: hash - run: echo "hashes=$(sha256sum ${GITHUB_REF_NAME} | base64 -w0)" >> "$GITHUB_OUTPUT" + run: echo "hashes=$(sha256sum ${GITHUB_REF_NAME}.* | base64 -w0)" >> "$GITHUB_OUTPUT" provenance: needs: From a7f720d82545bacf062339eeb930581f678a6ad6 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 9 Dec 2023 11:39:53 +0100 Subject: [PATCH 013/783] ensure English is always added to available languages, fixes #1208 bug got introduced in 3668f1e3f4808d7232606349035c6a43c5a84c23 and started affecting release after 896a49c8cf96ae9351796bd84050d2a0b249ddb3 --- CHANGELOG.md | 3 +++ lib/Data/Filesystem.php | 3 ++- lib/I18n.php | 15 +++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 754af8b5..4f6cc164 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # PrivateBin version history +## 1.6.2 (not yet released) +* FIXED: English not selectable when languageselection enabled (#1208) + ## 1.6.1 (2023-12-04) * ADDED: Right-To-Left (RTL) support for Arabic & Hebrew (#1174) * CHANGED: Upgrading libraries to: DOMpurify 3.0.6 diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index 38cd70ac..2ac594a4 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -13,6 +13,7 @@ namespace PrivateBin\Data; use Exception; +use GlobIterator; use PrivateBin\Json; /** @@ -394,7 +395,7 @@ class Filesystem extends AbstractData public function getAllPastes() { $pastes = array(); - foreach (new \GlobIterator($this->_path . self::PASTE_FILE_PATTERN) as $file) { + foreach (new GlobIterator($this->_path . self::PASTE_FILE_PATTERN) as $file) { if ($file->isFile()) { $pastes[] = $file->getBasename('.php'); } diff --git a/lib/I18n.php b/lib/I18n.php index 31eedb47..2d7d73b0 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -12,6 +12,9 @@ namespace PrivateBin; +use AppendIterator; +use GlobIterator; + /** * I18n * @@ -193,10 +196,14 @@ class I18n public static function getAvailableLanguages() { if (count(self::$_availableLanguages) == 0) { - $i18n = dir(self::_getPath()); - while (false !== ($file = $i18n->read())) { - if (preg_match('/^([a-z]{2,3}).json$/', $file, $match) === 1) { - self::$_availableLanguages[] = $match[1]; + self::$_availableLanguages[] = 'en'; // en.json is not part of the release archive + $languageIterator = new AppendIterator(); + $languageIterator->append(new GlobIterator(self::_getPath('??.json'))); + $languageIterator->append(new GlobIterator(self::_getPath('???.json'))); // for jbo + foreach ($languageIterator as $file) { + $language = $file->getBasename('.json'); + if ($language != 'en') { + self::$_availableLanguages[] = $language; } } } From 684924e9e57af8797edcc0bb48ebe3732d1a61c8 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 9 Dec 2023 12:00:57 +0100 Subject: [PATCH 014/783] apply StyleCI patch --- lib/I18n.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/I18n.php b/lib/I18n.php index 2d7d73b0..02ea3f3a 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -197,7 +197,7 @@ class I18n { if (count(self::$_availableLanguages) == 0) { self::$_availableLanguages[] = 'en'; // en.json is not part of the release archive - $languageIterator = new AppendIterator(); + $languageIterator = new AppendIterator(); $languageIterator->append(new GlobIterator(self::_getPath('??.json'))); $languageIterator->append(new GlobIterator(self::_getPath('???.json'))); // for jbo foreach ($languageIterator as $file) { From 03e3e4fa06066bf989c81e3088ce1b31c48df281 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:52:46 +0000 Subject: [PATCH 015/783] Bump github/codeql-action from 2 to 3 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/snyk-scan.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d0c0c63e..ac6143c7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -37,7 +37,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -46,4 +46,4 @@ jobs: # queries: ./path/to/local/query, your-org/your-repo/queries@main - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/snyk-scan.yml b/.github/workflows/snyk-scan.yml index 7cba1864..29bc2b45 100644 --- a/.github/workflows/snyk-scan.yml +++ b/.github/workflows/snyk-scan.yml @@ -24,6 +24,6 @@ jobs: with: args: --sarif-file-output=snyk.sarif - name: Upload result to GitHub Code Scanning - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: snyk.sarif From d0420fb418669633f2dd4db1dee5681fb4201c16 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Fri, 15 Dec 2023 07:20:20 +0100 Subject: [PATCH 016/783] 1.6.2 release --- CHANGELOG.md | 5 +++-- Makefile | 4 ++-- README.md | 2 +- SECURITY.md | 4 ++-- bin/administration | 2 +- css/bootstrap/privatebin.css | 2 +- css/noscript.css | 2 +- css/privatebin.css | 2 +- doc/Installation.md | 2 +- index.php | 2 +- js/common.js | 2 +- js/package.json | 2 +- js/privatebin.js | 2 +- js/{zlib-1.2.13.js => zlib-1.2.13-1.js} | 0 lib/Configuration.php | 2 +- lib/Controller.php | 4 ++-- lib/Data/AbstractData.php | 2 +- lib/Data/Database.php | 2 +- lib/Data/Filesystem.php | 2 +- lib/Data/S3Storage.php | 2 +- lib/Filter.php | 2 +- lib/FormatV2.php | 2 +- lib/I18n.php | 2 +- lib/Json.php | 2 +- lib/Model.php | 2 +- lib/Model/AbstractModel.php | 2 +- lib/Model/Comment.php | 2 +- lib/Model/Paste.php | 2 +- lib/Persistence/AbstractPersistence.php | 2 +- lib/Persistence/PurgeLimiter.php | 2 +- lib/Persistence/ServerSalt.php | 2 +- lib/Persistence/TrafficLimiter.php | 2 +- lib/Request.php | 2 +- lib/View.php | 2 +- lib/Vizhash16x16.php | 2 +- lib/YourlsProxy.php | 2 +- tpl/bootstrap.php | 4 ++-- tpl/page.php | 4 ++-- 38 files changed, 44 insertions(+), 43 deletions(-) rename js/{zlib-1.2.13.js => zlib-1.2.13-1.js} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f6cc164..341f554e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # PrivateBin version history -## 1.6.2 (not yet released) -* FIXED: English not selectable when languageselection enabled (#1208) +## 1.6.2 (2023-12-15) +* FIXED: English not selectable when `languageselection` enabled (#1208) +* FIXED: SRI mismatch due to cached file having changed (#1207) ## 1.6.1 (2023-12-04) * ADDED: Right-To-Left (RTL) support for Arabic & Hebrew (#1174) diff --git a/Makefile b/Makefile index be8982bf..5b61d9e4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: all coverage coverage-js coverage-php doc doc-js doc-php increment sign test test-js test-php help -CURRENT_VERSION = 1.6.1 -VERSION ?= 1.6.2 +CURRENT_VERSION = 1.6.2 +VERSION ?= 1.6.3 VERSION_FILES = index.php bin/ cfg/ *.md doc/Installation.md css/ i18n/ img/ js/package.json js/privatebin.js lib/ Makefile tpl/ tst/ REGEX_CURRENT_VERSION := $(shell echo $(CURRENT_VERSION) | sed "s/\./\\\./g") REGEX_VERSION := $(shell echo $(VERSION) | sed "s/\./\\\./g") diff --git a/README.md b/README.md index dbb625ed..d4e61dad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/) -*Current version: 1.6.1* +*Current version: 1.6.2* **PrivateBin** is a minimalist, open source online [pastebin](https://en.wikipedia.org/wiki/Pastebin) diff --git a/SECURITY.md b/SECURITY.md index 01275439..ce11f255 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,8 +4,8 @@ | Version | Supported | | ------- | ------------------ | -| 1.6.1 | :heavy_check_mark: | -| < 1.6.1 | :x: | +| 1.6.2 | :heavy_check_mark: | +| < 1.6.2 | :x: | ## Reporting a Vulnerability diff --git a/bin/administration b/bin/administration index 0f96c75c..5b4a72fc 100755 --- a/bin/administration +++ b/bin/administration @@ -9,7 +9,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/css/bootstrap/privatebin.css b/css/bootstrap/privatebin.css index d1eb5756..94084c48 100644 --- a/css/bootstrap/privatebin.css +++ b/css/bootstrap/privatebin.css @@ -6,7 +6,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ body { diff --git a/css/noscript.css b/css/noscript.css index d3c7a6d3..b347ba3c 100644 --- a/css/noscript.css +++ b/css/noscript.css @@ -6,7 +6,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ /* When there is no script at all other */ diff --git a/css/privatebin.css b/css/privatebin.css index def613c9..b4e99381 100644 --- a/css/privatebin.css +++ b/css/privatebin.css @@ -6,7 +6,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ /* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved. diff --git a/doc/Installation.md b/doc/Installation.md index f6bab4aa..98e57e7d 100644 --- a/doc/Installation.md +++ b/doc/Installation.md @@ -201,7 +201,7 @@ CREATE INDEX parent ON prefix_comment(pasteid); CREATE TABLE prefix_config ( id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id) ); -INSERT INTO prefix_config VALUES('VERSION', '1.6.1'); +INSERT INTO prefix_config VALUES('VERSION', '1.6.2'); ``` In **PostgreSQL**, the `data`, `attachment`, `nickname` and `vizhash` columns diff --git a/index.php b/index.php index 7c970c6d..0de23e4b 100644 --- a/index.php +++ b/index.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ // change this, if your php files and data is outside of your webservers document root diff --git a/js/common.js b/js/common.js index e3153863..a1f4421a 100644 --- a/js/common.js +++ b/js/common.js @@ -12,7 +12,7 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto; // application libraries to test global.$ = global.jQuery = require('./jquery-3.7.0'); global.RawDeflate = require('./rawinflate-0.3').RawDeflate; -global.zlib = require('./zlib-1.2.13').zlib; +global.zlib = require('./zlib-1.2.13-1').zlib; require('./prettify'); global.prettyPrint = window.PR.prettyPrint; global.prettyPrintOne = window.PR.prettyPrintOne; diff --git a/js/package.json b/js/package.json index 224b4d42..6194fbbb 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "privatebin", - "version": "1.6.1", + "version": "1.6.2", "description": "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bit AES in Galois Counter mode (GCM).", "main": "privatebin.js", "directories": { diff --git a/js/privatebin.js b/js/privatebin.js index d5d1b9ca..c5ee7fb0 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -6,7 +6,7 @@ * @see {@link https://github.com/PrivateBin/PrivateBin} * @copyright 2012 Sébastien SAUVAGE ({@link http://sebsauvage.net}) * @license {@link https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License} - * @version 1.6.1 + * @version 1.6.2 * @name PrivateBin * @namespace */ diff --git a/js/zlib-1.2.13.js b/js/zlib-1.2.13-1.js similarity index 100% rename from js/zlib-1.2.13.js rename to js/zlib-1.2.13-1.js diff --git a/lib/Configuration.php b/lib/Configuration.php index 9fd69be9..9224af9b 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/lib/Controller.php b/lib/Controller.php index 5dd66364..fdb2846e 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; @@ -28,7 +28,7 @@ class Controller * * @const string */ - const VERSION = '1.6.1'; + const VERSION = '1.6.2'; /** * minimal required PHP version diff --git a/lib/Data/AbstractData.php b/lib/Data/AbstractData.php index 68d452cd..cadf586a 100644 --- a/lib/Data/AbstractData.php +++ b/lib/Data/AbstractData.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Data; diff --git a/lib/Data/Database.php b/lib/Data/Database.php index 4fd25e77..6d597714 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Data; diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index 2ac594a4..3ba694ef 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Data; diff --git a/lib/Data/S3Storage.php b/lib/Data/S3Storage.php index a5279c40..fbb0497f 100644 --- a/lib/Data/S3Storage.php +++ b/lib/Data/S3Storage.php @@ -4,7 +4,7 @@ * * an S3 compatible data backend for PrivateBin with CEPH/RadosGW in mind * see https://docs.ceph.com/en/latest/radosgw/s3/php/ - * based on lib/Data/GoogleCloudStorage.php from PrivateBin version 1.6.1 + * based on lib/Data/GoogleCloudStorage.php from PrivateBin version 1.6.2 * * @link https://github.com/PrivateBin/PrivateBin * @copyright 2022 Felix J. Ogris (https://ogris.de/) diff --git a/lib/Filter.php b/lib/Filter.php index 919e63a5..6af37f11 100644 --- a/lib/Filter.php +++ b/lib/Filter.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/lib/FormatV2.php b/lib/FormatV2.php index 7cf24f1f..b9687db0 100644 --- a/lib/FormatV2.php +++ b/lib/FormatV2.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/lib/I18n.php b/lib/I18n.php index 02ea3f3a..3fed6754 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/lib/Json.php b/lib/Json.php index 203ad443..5fa818cb 100644 --- a/lib/Json.php +++ b/lib/Json.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/lib/Model.php b/lib/Model.php index e588f8d1..534cd882 100644 --- a/lib/Model.php +++ b/lib/Model.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/lib/Model/AbstractModel.php b/lib/Model/AbstractModel.php index 2a184ae6..e5a04057 100644 --- a/lib/Model/AbstractModel.php +++ b/lib/Model/AbstractModel.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Model; diff --git a/lib/Model/Comment.php b/lib/Model/Comment.php index 59095e58..e0fd0f5f 100644 --- a/lib/Model/Comment.php +++ b/lib/Model/Comment.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Model; diff --git a/lib/Model/Paste.php b/lib/Model/Paste.php index c36ca2c3..eed786f6 100644 --- a/lib/Model/Paste.php +++ b/lib/Model/Paste.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Model; diff --git a/lib/Persistence/AbstractPersistence.php b/lib/Persistence/AbstractPersistence.php index 14ecfb01..fad42063 100644 --- a/lib/Persistence/AbstractPersistence.php +++ b/lib/Persistence/AbstractPersistence.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Persistence; diff --git a/lib/Persistence/PurgeLimiter.php b/lib/Persistence/PurgeLimiter.php index 8cb0bd7c..b9d1853e 100644 --- a/lib/Persistence/PurgeLimiter.php +++ b/lib/Persistence/PurgeLimiter.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Persistence; diff --git a/lib/Persistence/ServerSalt.php b/lib/Persistence/ServerSalt.php index 44870a43..666e50d1 100644 --- a/lib/Persistence/ServerSalt.php +++ b/lib/Persistence/ServerSalt.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Persistence; diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index 95eabecd..f29a27b6 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -8,7 +8,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin\Persistence; diff --git a/lib/Request.php b/lib/Request.php index bb0af143..b5feb497 100644 --- a/lib/Request.php +++ b/lib/Request.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/lib/View.php b/lib/View.php index ad26754d..d125933b 100644 --- a/lib/View.php +++ b/lib/View.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/lib/Vizhash16x16.php b/lib/Vizhash16x16.php index 4f3aafbc..0e6ce3fc 100644 --- a/lib/Vizhash16x16.php +++ b/lib/Vizhash16x16.php @@ -8,7 +8,7 @@ * @link https://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 0.0.5 beta PrivateBin 1.6.1 + * @version 0.0.5 beta PrivateBin 1.6.2 */ namespace PrivateBin; diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php index 26876534..9d226c02 100644 --- a/lib/YourlsProxy.php +++ b/lib/YourlsProxy.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.6.1 + * @version 1.6.2 */ namespace PrivateBin; diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 41813697..be24e666 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -55,7 +55,7 @@ if ($ZEROBINCOMPATIBILITY) : - + @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index 96696a94..c00462c9 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY): - + - + From 43d162f452223f4fecf4c6ea251a1e2e4feda172 Mon Sep 17 00:00:00 2001 From: rugk Date: Fri, 15 Dec 2023 14:17:51 +0100 Subject: [PATCH 017/783] =?UTF-8?q?Created=20doc=20for=20=E2=80=9Chow=20to?= =?UTF-8?q?=20verify=20and=20how=20to=20do=20release=E2=80=9D=20(release?= =?UTF-8?q?=20doc)=20(WIP)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This documents/should document: * what the signatures are and what they proof * how to verify them * how to build releases (I know more of a maintainer doc, but yeah, I found it a good place here, if you want a separate one feel free) This should also make it easier for other maintainers to create releases or so. @elrido feel free to adjust/push to the branch if you want to have some details fixed. I have left some TODOs of stuff where I am unsure. --- doc/Release.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 doc/Release.md diff --git a/doc/Release.md b/doc/Release.md new file mode 100644 index 00000000..97ec02ff --- /dev/null +++ b/doc/Release.md @@ -0,0 +1,70 @@ +# Release + +## Properties + +### Supply-chain security + +Since [v1.6.2](https://github.com/PrivateBin/PrivateBin/releases/tag/1.6.2) our release assets are [verified with the SLSA framework](https://slsa.dev/). +SLSA stands for „Supply-chain Levels for Software Artifacts”. + +This achieves the following: +1. It ensures no maintainer has gone rogue and has modified/tampered with the source code before “building” the release. +2. It ensures the release is build exactly according to the source as defined by the branch that was used for the release. + This includes the workflow file defining how the release is done itself. +3. Our release should achieve [SLSA build level 3](https://slsa.dev/spec/v1.0/levels#build-l3) as it [runs on GitHub](https://slsa.dev/spec/v1.0/threats). Some more properties [are thus achieved](https://slsa.dev/spec/v1.0/threats). + +That said, here are some caveasts: +* None of our dependencies has any SLSA verification yet (as of Dec 2023) and thus we (cannot) verify any of our own supply chain. + That said, this is mitigated by the fact that the project has not that many dependencies at all. + +For more information [see the corresponding issue](https://github.com/PrivateBin/PrivateBin/issues/1169) and [the GitHub workflow file](/.github/workflows/release.yml). + +#### How to verify + +Git signature for verifying the reproducibility and that a maintainer in posession with that PGP private key created the release with that content: +``` +$ gpg2 --verify PrivateBin-1.2.1.tar.gz.asc # TODO: update for v1.6.2 +gpg: assuming signed data in 'PrivateBin-1.2.1.tar.gz' +gpg: Signature made Sat Aug 11 22:38:29 2018 CEST +gpg: using RSA key 0xE11B7950E9E183DB +gpg: Good signature from "PrivateBin release (solely used for signing releases)" [] +gpg: aka "PrivateBin code-sign (solely used for code signing) " [] +Primary key fingerprint: 28CA 7C96 4938 EA5C 1481 D42A E11B 7950 E9E1 83DB +``` + +For a more step-by-step guide in detail [see this FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-can-i-securely-clonedownload-your-project). + +## Reproducible builds + +Since a long time, we signed release `.tar.gz` and `.zip` files with personal PGP keys confirming the authenticity of the fact that the release has been build by a PrivateBin maintainer. + +This uses traditional [PGP](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) signatures. + +### How to verify + +Git signature for verifying the reproducibility and that a maintainer in posession with that PGP private key created the release with that content: +``` +$ gpg2 --verify PrivateBin-1.2.1.tar.gz.asc # TODO: update for v1.6.2 +gpg: assuming signed data in 'PrivateBin-1.2.1.tar.gz' +gpg: Signature made Sat Aug 11 22:38:29 2018 CEST +gpg: using RSA key 0xE11B7950E9E183DB +gpg: Good signature from "PrivateBin release (solely used for signing releases)" [] +gpg: aka "PrivateBin code-sign (solely used for code signing) " [] +Primary key fingerprint: 28CA 7C96 4938 EA5C 1481 D42A E11B 7950 E9E1 83DB +``` + +For a more step-by-step guide in detail [see this FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-can-i-securely-clonedownload-your-project). + +## How to release + +1. Create a release branch (schema: `x.y.z`) and push that as a new branch to GitHub. +2. This will automatically trigger the worflow [/.github/workflows/release.yml](/.github/workflows/release.yml) on GitHub that will generate SLSA provenance _and_ draft a release with most artifacts attached at the end. +3. Now you will need to generate a release `.zip` and `.tar.gz` locally too. Just use `git archive` command for that (TODO: please add specifics). + **Important:** Please don't just download them from GitHub, this bringes no security benefit as that would basically mean trusting GitHub and letting GitHub “build” the release. +4. Sign that release with GPG with your private key: + ``` + git sign # TODO + ``` +5. Upload the `.tar.gz.sig` and `.zip.sig` on GitHub/attach them to the release. + **Note** It may also be a good idea to follow the above guide on how to verify the reproducible builds by verifying the hashes of the two release archives. + Alternatively, you can also compare the hashes of the release file from GitHub and your local one to verify the are the same. From 255fd4b12b1a1e34b3ab1f5adb3a3e980c287dcd Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 16 Dec 2023 07:02:21 +0100 Subject: [PATCH 018/783] updated release document - removed duplicate content - clarified what is signed and since which release - updated verification sample output (also in wiki) using the output of https://github.com/PrivateBin/docker-nginx-fpm-alpine/actions/runs/7228527399/job/19698112056#step:7:156 - Corrected release process - we trigger the release on the push of the tag, not a branch (fixed point in time instead of a moving target) --- doc/Release.md | 62 +++++++++++++++----------------------------------- 1 file changed, 18 insertions(+), 44 deletions(-) diff --git a/doc/Release.md b/doc/Release.md index 97ec02ff..209c4471 100644 --- a/doc/Release.md +++ b/doc/Release.md @@ -1,11 +1,10 @@ # Release -## Properties +## Overview of Supply-Chain Security -### Supply-chain security +As of the PrivateBin 1.0 release we [cryptographically sign](https://git-scm.com/book/uz/v2/Git-Tools-Signing-Your-Work) our git commits and tags, so that you can verify we actually developed the software. Later, we also [started signing the release archives on GitHub](https://github.com/PrivateBin/PrivateBin/issues/219) and retroactively signed all releases from 1.0 forward. -Since [v1.6.2](https://github.com/PrivateBin/PrivateBin/releases/tag/1.6.2) our release assets are [verified with the SLSA framework](https://slsa.dev/). -SLSA stands for „Supply-chain Levels for Software Artifacts”. +Since [release 1.6.2](https://github.com/PrivateBin/PrivateBin/releases/tag/1.6.2) our release assets additionally also are [verified with the SLSA (Supply-chain Levels for Software Artifacts) framework](https://slsa.dev/), providing an in-toto manifest of the release archive. This achieves the following: 1. It ensures no maintainer has gone rogue and has modified/tampered with the source code before “building” the release. @@ -13,58 +12,33 @@ This achieves the following: This includes the workflow file defining how the release is done itself. 3. Our release should achieve [SLSA build level 3](https://slsa.dev/spec/v1.0/levels#build-l3) as it [runs on GitHub](https://slsa.dev/spec/v1.0/threats). Some more properties [are thus achieved](https://slsa.dev/spec/v1.0/threats). -That said, here are some caveasts: -* None of our dependencies has any SLSA verification yet (as of Dec 2023) and thus we (cannot) verify any of our own supply chain. - That said, this is mitigated by the fact that the project has not that many dependencies at all. - For more information [see the corresponding issue](https://github.com/PrivateBin/PrivateBin/issues/1169) and [the GitHub workflow file](/.github/workflows/release.yml). -#### How to verify - -Git signature for verifying the reproducibility and that a maintainer in posession with that PGP private key created the release with that content: -``` -$ gpg2 --verify PrivateBin-1.2.1.tar.gz.asc # TODO: update for v1.6.2 -gpg: assuming signed data in 'PrivateBin-1.2.1.tar.gz' -gpg: Signature made Sat Aug 11 22:38:29 2018 CEST -gpg: using RSA key 0xE11B7950E9E183DB -gpg: Good signature from "PrivateBin release (solely used for signing releases)" [] -gpg: aka "PrivateBin code-sign (solely used for code signing) " [] -Primary key fingerprint: 28CA 7C96 4938 EA5C 1481 D42A E11B 7950 E9E1 83DB -``` - -For a more step-by-step guide in detail [see this FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-can-i-securely-clonedownload-your-project). - ## Reproducible builds -Since a long time, we signed release `.tar.gz` and `.zip` files with personal PGP keys confirming the authenticity of the fact that the release has been build by a PrivateBin maintainer. +All releases `.tar.gz` and `.zip` archives since 1.0 come with corresponding `.asc` signatures that can be used to confirm the authenticity of the fact that the release has been issued by a PrivateBin maintainer. This uses traditional [PGP](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) signatures. -### How to verify +## Verification + +You can use the gpg signatures for verifying the reproducibility and that a maintainer in posession with that PGP private key created the release with that content: -Git signature for verifying the reproducibility and that a maintainer in posession with that PGP private key created the release with that content: ``` -$ gpg2 --verify PrivateBin-1.2.1.tar.gz.asc # TODO: update for v1.6.2 -gpg: assuming signed data in 'PrivateBin-1.2.1.tar.gz' -gpg: Signature made Sat Aug 11 22:38:29 2018 CEST -gpg: using RSA key 0xE11B7950E9E183DB -gpg: Good signature from "PrivateBin release (solely used for signing releases)" [] -gpg: aka "PrivateBin code-sign (solely used for code signing) " [] +$ gpg2 --verify 1.6.2.tar.gz.asc +gpg: assuming signed data in '1.6.2.tar.gz' +gpg: Signature made Fri Dec 15 06:21:08 2023 UTC +gpg: using RSA key 28CA7C964938EA5C1481D42AE11B7950E9E183DB +gpg: Good signature from "PrivateBin release (solely used for signing releases)" [unknown] +gpg: WARNING: This key is not certified with a trusted signature! +gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 28CA 7C96 4938 EA5C 1481 D42A E11B 7950 E9E1 83DB ``` For a more step-by-step guide in detail [see this FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-can-i-securely-clonedownload-your-project). -## How to release +SLSA verification can be performed using the [SLSA verifier](https://github.com/slsa-framework/slsa-verifier#verification-of-slsa-provenance). -1. Create a release branch (schema: `x.y.z`) and push that as a new branch to GitHub. -2. This will automatically trigger the worflow [/.github/workflows/release.yml](/.github/workflows/release.yml) on GitHub that will generate SLSA provenance _and_ draft a release with most artifacts attached at the end. -3. Now you will need to generate a release `.zip` and `.tar.gz` locally too. Just use `git archive` command for that (TODO: please add specifics). - **Important:** Please don't just download them from GitHub, this bringes no security benefit as that would basically mean trusting GitHub and letting GitHub “build” the release. -4. Sign that release with GPG with your private key: - ``` - git sign # TODO - ``` -5. Upload the `.tar.gz.sig` and `.zip.sig` on GitHub/attach them to the release. - **Note** It may also be a good idea to follow the above guide on how to verify the reproducible builds by verifying the hashes of the two release archives. - Alternatively, you can also compare the hashes of the release file from GitHub and your local one to verify the are the same. +## Release process + +The release process is outlined in the [release checklist](https://github.com/PrivateBin/PrivateBin/wiki/Release-Checklist). The key manual steps are performed using a [Makefile](https://github.com/PrivateBin/PrivateBin/blob/master/Makefile#L31-L43) and using a [shell script](https://github.com/rugk/gittools/blob/master/signrelease.sh). From d88945663e85dd5b6fbb103662c73d9be040380b Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 16 Dec 2023 07:38:09 +0100 Subject: [PATCH 019/783] detect and report on damaged pastes May occur during statistics or purge, when existing pastes get parsed, addresses #1214 --- bin/administration | 19 +++++++++++++++++-- lib/Controller.php | 15 ++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/bin/administration b/bin/administration index 5b4a72fc..efd19f0e 100755 --- a/bin/administration +++ b/bin/administration @@ -14,6 +14,7 @@ namespace PrivateBin; +use Exception; use PrivateBin\Configuration; use PrivateBin\Data\AbstractData; use PrivateBin\Model\Paste; @@ -195,6 +196,7 @@ EOT, PHP_EOL; { $counters = array( 'burn' => 0, + 'damaged' => 0, 'discussion' => 0, 'expired' => 0, 'md' => 0, @@ -217,7 +219,12 @@ EOT, PHP_EOL; echo "Total:\t\t\t{$counters['total']}", PHP_EOL; foreach ($ids as $pasteid) { - $paste = $this->_store->read($pasteid); + try { + $paste = $this->_store->read($pasteid); + } catch (Exception $e) { + echo "Error reading paste {$pasteid}: ", $e->getMessage(), PHP_EOL; + ++$counters['damaged']; + } ++$counters['progress']; if ( @@ -271,6 +278,9 @@ Plain Text:\t\t{$counters['plain']} Source Code:\t\t{$counters['syntax']} Markdown:\t\t{$counters['md']} EOT, PHP_EOL; + if ($counters['damaged'] > 0) { + echo "Damaged:\t\t{$counters['damaged']}", PHP_EOL; + } if ($counters['unknown'] > 0) { echo "Unknown format:\t\t{$counters['unknown']}", PHP_EOL; } @@ -305,7 +315,12 @@ EOT, PHP_EOL; } if ($this->_option('p', 'purge') !== null) { - $this->_store->purge(PHP_INT_MAX); + try { + $this->_store->purge(PHP_INT_MAX); + } catch (Exception $e) { + echo 'Error purging pastes: ', $e->getMessage(), PHP_EOL, + 'Run the statistics to find damaged paste IDs and either delete them or restore them from backup.', PHP_EOL; + } exit('purging of expired pastes concluded' . PHP_EOL); } diff --git a/lib/Controller.php b/lib/Controller.php index fdb2846e..849eb354 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -111,10 +111,12 @@ class Controller public function __construct() { if (version_compare(PHP_VERSION, self::MIN_PHP_VERSION) < 0) { - throw new Exception(I18n::_('%s requires php %s or above to work. Sorry.', I18n::_('PrivateBin'), self::MIN_PHP_VERSION), 1); + error_log(I18n::_('%s requires php %s or above to work. Sorry.', I18n::_('PrivateBin'), self::MIN_PHP_VERSION)); + return; } if (strlen(PATH) < 0 && substr(PATH, -1) !== DIRECTORY_SEPARATOR) { - throw new Exception(I18n::_('%s requires the PATH to end in a "%s". Please update the PATH in your index.php.', I18n::_('PrivateBin'), DIRECTORY_SEPARATOR), 5); + error_log(I18n::_('%s requires the PATH to end in a "%s". Please update the PATH in your index.php.', I18n::_('PrivateBin'), DIRECTORY_SEPARATOR)); + return; } // load config from ini file, initialize required classes @@ -250,7 +252,14 @@ class Controller } // The user posts a standard paste. else { - $this->_model->purge(); + try { + $this->_model->purge(); + } catch (Exception $e) { + error_log('Error purging pastes: ' . $e->getMessage() . PHP_EOL . + 'Use the administration scripts statistics to find ' . + 'damaged paste IDs and either delete them or restore them ' . + 'from backup.'); + } $paste = $this->_model->getPaste(); try { $paste->setData($data); From a17529c7e1f06f5da9c4a5c18725c2fc349eefb9 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 18 Dec 2023 21:02:27 +0100 Subject: [PATCH 020/783] document change --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 341f554e..bdee9864 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # PrivateBin version history +## 1.6.3 (not yet released) +* ADDED: Detect and report on damaged pastes (#1218) + ## 1.6.2 (2023-12-15) * FIXED: English not selectable when `languageselection` enabled (#1208) * FIXED: SRI mismatch due to cached file having changed (#1207) From d49be80ffb442f3be76a53c4bf80c2de3ce691f9 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 18 Dec 2023 21:45:26 +0100 Subject: [PATCH 021/783] prevent regression around presence or absence of en.json it gets excluded in the release archive, it's absence should not make any difference --- lib/I18n.php | 4 ++-- tst/I18nTest.php | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/I18n.php b/lib/I18n.php index 3fed6754..22142c00 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -315,10 +315,10 @@ class I18n */ protected static function _getPath($file = '') { - if (strlen(self::$_path) == 0) { + if (empty(self::$_path)) { self::$_path = PUBLIC_PATH . DIRECTORY_SEPARATOR . 'i18n'; } - return self::$_path . (strlen($file) ? DIRECTORY_SEPARATOR . $file : ''); + return self::$_path . (empty($file) ? '' : DIRECTORY_SEPARATOR . $file); } /** diff --git a/tst/I18nTest.php b/tst/I18nTest.php index e53c36d0..e606a8b3 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -3,6 +3,24 @@ use PHPUnit\Framework\TestCase; use PrivateBin\I18n; +class I18nMock extends I18n +{ + public static function resetAvailableLanguages() + { + self::$_availableLanguages = array(); + } + + public static function resetPath($path = '') + { + self::$_path = $path; + } + + public static function getPath($file = '') + { + return self::_getPath($file); + } +} + class I18nTest extends TestCase { private $_translations = array(); @@ -167,6 +185,38 @@ class I18nTest extends TestCase $this->assertEquals($result . $result, I18n::_($input . '%s', $input), 'encodes message ID as well, when no link'); } + public function testFallbackAlwaysPresent() + { + $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_i18n'; + if (!is_dir($path)) { + mkdir($path); + } + + $languageIterator = new AppendIterator(); + $languageIterator->append(new GlobIterator(I18nMock::getPath('??.json'))); + $languageIterator->append(new GlobIterator(I18nMock::getPath('???.json'))); // for jbo + $languageCount = 0; + foreach ($languageIterator as $file) { + ++$languageCount; + $this->assertTrue(copy($file, $path . DIRECTORY_SEPARATOR . $file->getBasename())); + } + + I18nMock::resetPath($path); + $languagesDevelopment = I18nMock::getAvailableLanguages(); + $this->assertEquals($languageCount, count($languagesDevelopment), 'all copied languages detected'); + $this->assertTrue(in_array('en', $languagesDevelopment), 'English fallback present'); + + unlink($path . DIRECTORY_SEPARATOR . 'en.json'); + I18nMock::resetAvailableLanguages(); + $languagesDeployed = I18nMock::getAvailableLanguages(); + $this->assertEquals($languageCount, count($languagesDeployed), 'all copied languages detected, plus fallback'); + $this->assertTrue(in_array('en', $languagesDeployed), 'English fallback still present'); + + I18nMock::resetAvailableLanguages(); + I18nMock::resetPath(); + Helper::rmDir($path); + } + public function testMessageIdsExistInAllLanguages() { $messageIds = array(); From dc8cb66adcb72218a08e60d639754058988bc9e7 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 19 Dec 2023 06:22:30 +0100 Subject: [PATCH 022/783] updating zlib to 1.3 --- CHANGELOG.md | 1 + js/common.js | 2 +- js/{zlib-1.2.13-1.js => zlib-1.3.js} | 4 ++-- js/{zlib-1.2.13.wasm => zlib-1.3.wasm} | Bin 58828 -> 58825 bytes tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 6 files changed, 6 insertions(+), 5 deletions(-) rename js/{zlib-1.2.13-1.js => zlib-1.3.js} (97%) rename js/{zlib-1.2.13.wasm => zlib-1.3.wasm} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdee9864..36830d6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.6.3 (not yet released) * ADDED: Detect and report on damaged pastes (#1218) +* CHANGED: Upgrading libraries to: zlib 1.3 ## 1.6.2 (2023-12-15) * FIXED: English not selectable when `languageselection` enabled (#1208) diff --git a/js/common.js b/js/common.js index a1f4421a..7e406acb 100644 --- a/js/common.js +++ b/js/common.js @@ -12,7 +12,7 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto; // application libraries to test global.$ = global.jQuery = require('./jquery-3.7.0'); global.RawDeflate = require('./rawinflate-0.3').RawDeflate; -global.zlib = require('./zlib-1.2.13-1').zlib; +global.zlib = require('./zlib-1.3').zlib; require('./prettify'); global.prettyPrint = window.PR.prettyPrint; global.prettyPrintOne = window.PR.prettyPrintOne; diff --git a/js/zlib-1.2.13-1.js b/js/zlib-1.3.js similarity index 97% rename from js/zlib-1.2.13-1.js rename to js/zlib-1.3.js index a9760e96..268d0841 100644 --- a/js/zlib-1.2.13-1.js +++ b/js/zlib-1.3.js @@ -26,9 +26,9 @@ let buff; if (typeof fs === 'object') { - buff = fs.readFileSync('zlib-1.2.13.wasm'); + buff = fs.readFileSync('zlib-1.3.wasm'); } else { - const resp = await fetch('js/zlib-1.2.13.wasm'); + const resp = await fetch('js/zlib-1.3.wasm'); buff = await resp.arrayBuffer(); } const module = await WebAssembly.compile(buff); diff --git a/js/zlib-1.2.13.wasm b/js/zlib-1.3.wasm similarity index 99% rename from js/zlib-1.2.13.wasm rename to js/zlib-1.3.wasm index 145060df799555df0311644a0e00801b00a803ed..c954fbd400e2f4cecc5d8c4188a451b1a93c6ca2 100644 GIT binary patch delta 39 xcmV+?0NDS`%LB>F1F-hF6wcRxfB-iDK?Dl|uvGv-5DNn_F0&1~yek970Lw{Y4vPQ) delta 42 ycmX?kn)%FW<_+I=ieJ3m(7<5M;K;(wv>}wiQGlDxP|rxua5LAgJ=)BN7#sm_nGTcy diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index be24e666..a307c4e7 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -55,7 +55,7 @@ if ($ZEROBINCOMPATIBILITY) : - + diff --git a/tpl/page.php b/tpl/page.php index c00462c9..fa70097a 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY): - + Date: Wed, 27 Dec 2023 18:58:39 +0100 Subject: [PATCH 023/783] improve SDK install docs fixes #1222 --- doc/Installation.md | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/doc/Installation.md b/doc/Installation.md index 98e57e7d..a60ae65f 100644 --- a/doc/Installation.md +++ b/doc/Installation.md @@ -213,11 +213,25 @@ to be `CLOB` and not `BLOB` or `MEDIUMBLOB`, the `id` column in the `config` table needs to be `VARCHAR2(16)` and the `meta` column in the `paste` table and the `value` column in the `config` table need to be `VARCHAR2(4000)`. +### Cloud Storage Backends + +Due to the large size of the respective cloud SDKs required for these, we didn't +include these in the `vendor` directory shipped in our release archives. To use +these in your manual installation, you will need [composer installed](https://getcomposer.org/) +and require the used library (see instructions below). + +This is not required if using the dedicated container images that have these SDKs +preinstalled. + #### Using Google Cloud Storage If you want to deploy PrivateBin in a serverless manner in the Google Cloud, you -can choose the `GoogleCloudStorage` as backend. To use this backend, you create -a GCS bucket and specify the name as the model option `bucket`. Alternatively, -you can set the name through the environment variable `PRIVATEBIN_GCS_BUCKET`. +can choose the `GoogleCloudStorage` as backend. + +To use this backend, you first have to install the SDK from the installation +directory of PrivateBin: `composer require google/cloud-storage` + +You have to create a GCS bucket and specify the name as the model option `bucket`. +Alternatively, you can set the name through the environment variable `PRIVATEBIN_GCS_BUCKET`. The default prefix for pastes stored in the bucket is `pastes`. To change the prefix, specify the option `prefix`. @@ -226,15 +240,15 @@ Google Cloud Storage buckets may be significantly slower than a `FileSystem` or `Database` backend. The big advantage is that the deployment on Google Cloud Platform using Google Cloud Run is easy and cheap. -To use the Google Cloud Storage backend you have to install the suggested -library using the command `composer require google/cloud-storage`. - #### Using S3 Storage Similar to Google Cloud Storage, you can choose S3 as storage backend. It uses -the AWS SDK for PHP, but can also talk to a Rados gateway as part of a CEPH -cluster. To use this backend, you first have to install the SDK in the -document root of PrivateBin: `composer require aws/aws-sdk-php`. You have to -create the S3 bucket on the CEPH cluster before using the S3 backend. +the AWS SDK for PHP, but can also talk to a Rados gateway as part of a Ceph +cluster. + +To use this backend, you first have to install the SDK from the installation +directory of PrivateBin: `composer require aws/aws-sdk-php` + +You have to create an S3 bucket on the Ceph cluster before using the S3 backend. In the `[model]` section of cfg/conf.php, set `class` to `S3Storage`. @@ -256,7 +270,7 @@ data beneath this prefix. For AWS, you have to provide at least `region`, `bucket`, `accesskey`, and `secretkey`. -For CEPH, follow this example: +For Ceph, follow this example: ``` region = "" From c264904f7778e731430e23f5d37b693c8677a2e9 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Mon, 1 Jan 2024 12:29:13 +0100 Subject: [PATCH 024/783] New translations en.json (Chinese Simplified) --- i18n/zh.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/zh.json b/i18n/zh.json index 450bd39c..61b32cbd 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -2,7 +2,7 @@ "PrivateBin": "PrivateBin", "%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 是一个极简、开源、对粘贴内容毫不知情的在线粘贴板,数据%s在浏览器内%s进行 AES-256 加密和解密。", "More information on the project page.": "更多信息请查看项目主页。", - "Because ignorance is bliss": "因为无知是福", + "Because ignorance is bliss": "以不知为幸", "Paste does not exist, has expired or has been deleted.": "粘贴内容不存在、已过期或已被删除。", "%s requires php %s or above to work. Sorry.": "抱歉,%s 需要 PHP %s 及以上版本才能运行。", "%s requires configuration section [%s] to be present in configuration file.": "%s 需要设置配置文件中的 [%s] 部分。", From 7cb1f8ca67c1422e0609f6912007f57557a2c7b4 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 4 Jan 2024 06:48:34 +0100 Subject: [PATCH 025/783] relax URL regex to support finding IDN domains, filter using built in function, removing non-URLs --- js/privatebin.js | 4 ++-- tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index c5ee7fb0..db85eef7 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2041,8 +2041,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { responseString = JSON.stringify(responseString); } if (typeof responseString === 'string' && responseString.length > 0) { - const shortUrlMatcher = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; - const shortUrl = (responseString.match(shortUrlMatcher) || []).sort(function(a, b) { + const shortUrlMatcher = /https?:\/\/[^\s]+/g; + const shortUrl = (responseString.match(shortUrlMatcher) || []).filter(URL.canParse).sort(function(a, b) { return a.length - b.length; })[0]; if (typeof shortUrl === 'string' && shortUrl.length > 0) { diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index a307c4e7..386705fa 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index fa70097a..026b4ae1 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From 8427c1136c7d9c82322004901e75bd18f5963361 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 4 Jan 2024 06:52:27 +0100 Subject: [PATCH 026/783] document change --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36830d6a..3d39cd30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.6.3 (not yet released) * ADDED: Detect and report on damaged pastes (#1218) * CHANGED: Upgrading libraries to: zlib 1.3 +* FIXED: Support more types of valid URLs for shorteners, incl. IDN ones (#1224) ## 1.6.2 (2023-12-15) * FIXED: English not selectable when `languageselection` enabled (#1208) From b3b97b69c6c78eb66d8d88e03fef46da0c31f9ab Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:47:08 +0100 Subject: [PATCH 027/783] New translations en.json (Romanian) --- i18n/ro.json | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 i18n/ro.json diff --git a/i18n/ro.json b/i18n/ro.json new file mode 100644 index 00000000..68ff1aae --- /dev/null +++ b/i18n/ro.json @@ -0,0 +1,218 @@ +{ + "PrivateBin": "PrivateBin", + "%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 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.", + "More information on the project page.": "More information on the project page.", + "Because ignorance is bliss": "Because ignorance is bliss", + "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.", + "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.", + "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", + "Please wait %d seconds between each post.": [ + "Please wait %d second between each post. (singular)", + "Please wait %d seconds between each post. (1st plural)", + "Please wait %d seconds between each post. (2nd plural)", + "Please wait %d seconds between each post. (3rd plural)", + "Please wait %d seconds between each post. (4th plural)", + "Please wait %d seconds between each post. (5th plural)" + ], + "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", + "Invalid data.": "Invalid data.", + "You are unlucky. Try again.": "You are unlucky. Try again.", + "Error saving comment. Sorry.": "Error saving comment. Sorry.", + "Error saving paste. Sorry.": "Error saving paste. Sorry.", + "Invalid paste ID.": "Invalid paste ID.", + "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", + "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", + "Paste was properly deleted.": "Paste was properly deleted.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", + "%s requires a modern browser to work.": "%s requires a modern browser to work.", + "New": "New", + "Send": "Send", + "Clone": "Clone", + "Raw text": "Raw text", + "Expires": "Expires", + "Burn after reading": "Burn after reading", + "Open discussion": "Open discussion", + "Password (recommended)": "Password (recommended)", + "Discussion": "Discussion", + "Toggle navigation": "Toggle navigation", + "%d seconds": [ + "%d second (singular)", + "%d seconds (1st plural)", + "%d seconds (2nd plural)", + "%d seconds (3rd plural)", + "%d seconds (4th plural)", + "%d seconds (5th plural)" + ], + "%d minutes": [ + "%d minute (singular)", + "%d minutes (1st plural)", + "%d minutes (2nd plural)", + "%d minutes (3rd plural)", + "%d minutes (4th plural)", + "%d minutes (5th plural)" + ], + "%d hours": [ + "%d hour (singular)", + "%d hours (1st plural)", + "%d hours (2nd plural)", + "%d hours (3rd plural)", + "%d hours (4th plural)", + "%d hours (5th plural)" + ], + "%d days": [ + "%d day (singular)", + "%d days (1st plural)", + "%d days (2nd plural)", + "%d days (3rd plural)", + "%d days (4th plural)", + "%d days (5th plural)" + ], + "%d weeks": [ + "%d week (singular)", + "%d weeks (1st plural)", + "%d weeks (2nd plural)", + "%d weeks (3rd plural)", + "%d weeks (4th plural)", + "%d weeks (5th plural)" + ], + "%d months": [ + "%d month (singular)", + "%d months (1st plural)", + "%d months (2nd plural)", + "%d months (3rd plural)", + "%d months (4th plural)", + "%d months (5th plural)" + ], + "%d years": [ + "%d year (singular)", + "%d years (1st plural)", + "%d years (2nd plural)", + "%d years (3rd plural)", + "%d years (4th plural)", + "%d years (5th plural)" + ], + "Never": "Never", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "This document will expire in %d seconds.": [ + "This document will expire in %d second. (singular)", + "This document will expire in %d seconds. (1st plural)", + "This document will expire in %d seconds. (2nd plural)", + "This document will expire in %d seconds. (3rd plural)", + "This document will expire in %d seconds. (4th plural)", + "This document will expire in %d seconds. (5th plural)" + ], + "This document will expire in %d minutes.": [ + "This document will expire in %d minute. (singular)", + "This document will expire in %d minutes. (1st plural)", + "This document will expire in %d minutes. (2nd plural)", + "This document will expire in %d minutes. (3rd plural)", + "This document will expire in %d minutes. (4th plural)", + "This document will expire in %d minutes. (5th plural)" + ], + "This document will expire in %d hours.": [ + "This document will expire in %d hour. (singular)", + "This document will expire in %d hours. (1st plural)", + "This document will expire in %d hours. (2nd plural)", + "This document will expire in %d hours. (3rd plural)", + "This document will expire in %d hours. (4th plural)", + "This document will expire in %d hours. (5th plural)" + ], + "This document will expire in %d days.": [ + "This document will expire in %d day. (singular)", + "This document will expire in %d days. (1st plural)", + "This document will expire in %d days. (2nd plural)", + "This document will expire in %d days. (3rd plural)", + "This document will expire in %d days. (4th plural)", + "This document will expire in %d days. (5th plural)" + ], + "This document will expire in %d months.": [ + "This document will expire in %d month. (singular)", + "This document will expire in %d months. (1st plural)", + "This document will expire in %d months. (2nd plural)", + "This document will expire in %d months. (3rd plural)", + "This document will expire in %d months. (4th plural)", + "This document will expire in %d months. (5th plural)" + ], + "Please enter the password for this paste:": "Please enter the password for this paste:", + "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", + "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", + "Reply": "Reply", + "Anonymous": "Anonymous", + "Avatar generated from IP address": "Avatar generated from IP address", + "Add comment": "Add comment", + "Optional nickname…": "Optional nickname…", + "Post comment": "Post comment", + "Sending comment…": "Sending comment…", + "Comment posted.": "Comment posted.", + "Could not refresh display: %s": "Could not refresh display: %s", + "unknown status": "unknown status", + "server error or not responding": "server error or not responding", + "Could not post comment: %s": "Could not post comment: %s", + "Sending paste…": "Sending paste…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", + "Delete data": "Delete data", + "Could not create paste: %s": "Could not create paste: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "B": "B", + "KiB": "KiB", + "MiB": "MiB", + "GiB": "GiB", + "TiB": "TiB", + "PiB": "PiB", + "EiB": "EiB", + "ZiB": "ZiB", + "YiB": "YiB", + "Format": "Format", + "Plain Text": "Plain Text", + "Source Code": "Source Code", + "Markdown": "Markdown", + "Download attachment": "Download attachment", + "Cloned: '%s'": "Cloned: '%s'", + "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", + "Attach a file": "Attach a file", + "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", + "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", + "Remove attachment": "Remove attachment", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", + "Invalid attachment.": "Invalid attachment.", + "Options": "Options", + "Shorten URL": "Shorten URL", + "Editor": "Editor", + "Preview": "Preview", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", + "Decrypt": "Decrypt", + "Enter password": "Enter password", + "Loading…": "Loading…", + "Decrypting paste…": "Decrypting paste…", + "Preparing new paste…": "Preparing new paste…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", + "+++ no paste text +++": "+++ no paste text +++", + "Could not get paste data: %s": "Could not get paste data: %s", + "QR code": "QR code", + "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", + "For more information see this FAQ entry.": "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", + "waiting on user to provide a password": "waiting on user to provide a password", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Retry": "Retry", + "Showing raw text…": "Showing raw text…", + "Notice:": "Notice:", + "This link will expire after %s.": "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": "Use Current Timezone", + "Convert To UTC": "Convert To UTC", + "Close": "Close", + "Encrypted note on %s": "Encrypted note on %s", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", + "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "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." +} From a80bd4e4ea1dd97889998b1dca08b511245c06a5 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 4 Jan 2024 23:08:17 +0100 Subject: [PATCH 028/783] fix url filter, IDN URL unit test --- js/common.js | 2 +- js/package-lock.json | 4 +-- js/privatebin.js | 60 ++++++++++++++++++++++++++---------------- js/test/PasteStatus.js | 45 +++++++++++++++++++++++++++++++ tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 6 files changed, 87 insertions(+), 28 deletions(-) diff --git a/js/common.js b/js/common.js index 7e406acb..295fd090 100644 --- a/js/common.js +++ b/js/common.js @@ -37,7 +37,7 @@ var a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m', }) ), schemas = ['ftp','http','https'], - supportedLanguages = ['de', 'es', 'fr', 'it', 'no', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh'], + supportedLanguages = ['ar', 'bg', 'ca', 'co', 'cs', 'de', 'el', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sk', 'sl', 'th', 'tr', 'uk', 'zh'], mimeTypes = ['image/png', 'application/octet-stream'], formats = ['plaintext', 'markdown', 'syntaxhighlighting'], mimeFile = fs.createReadStream('/etc/mime.types'), diff --git a/js/package-lock.json b/js/package-lock.json index b7b29ab7..ed57b711 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -1,12 +1,12 @@ { "name": "privatebin", - "version": "1.5.2", + "version": "1.6.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "privatebin", - "version": "1.5.2", + "version": "1.6.2", "license": "zlib-acknowledgement", "devDependencies": { "@peculiar/webcrypto": "^1.1.1", diff --git a/js/privatebin.js b/js/privatebin.js index db85eef7..e63ab5fb 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2035,29 +2035,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { xhrFields: { withCredentials: false }, - success: function(response) { - let responseString = response; - if (typeof responseString === 'object') { - responseString = JSON.stringify(responseString); - } - if (typeof responseString === 'string' && responseString.length > 0) { - const shortUrlMatcher = /https?:\/\/[^\s]+/g; - const shortUrl = (responseString.match(shortUrlMatcher) || []).filter(URL.canParse).sort(function(a, b) { - return a.length - b.length; - })[0]; - if (typeof shortUrl === 'string' && shortUrl.length > 0) { - // we disable the button to avoid calling shortener again - $shortenButton.addClass('buttondisabled'); - // update link - $pasteUrl.text(shortUrl); - $pasteUrl.prop('href', shortUrl); - // we pre-select the link so that the user only has to [Ctrl]+[c] the link - Helper.selectText($pasteUrl[0]); - return; - } - } - Alert.showError('Cannot parse response from URL shortener.'); - } + success: PasteStatus.extractUrl }) .fail(function(data, textStatus, errorThrown) { console.error(textStatus, errorThrown); @@ -2123,6 +2101,42 @@ jQuery.PrivateBin = (function($, RawDeflate) { Helper.selectText($pasteUrl[0]); }; + /** + * extracts URLs from given string + * + * if at least one is found, it disables the shortener button and + * replaces the paste URL + * + * @name PasteStatus.extractUrl + * @function + * @param {string} response + */ + me.extractUrl = function(response) + { + if (typeof response === 'object') { + response = JSON.stringify(response); + } + if (typeof response === 'string' && response.length > 0) { + const shortUrlMatcher = /https?:\/\/[^\s]+/g; + const shortUrl = (response.match(shortUrlMatcher) || []).filter(function(a) { + return URL.canParse(a); + }).sort(function(a, b) { + return a.length - b.length; + })[0]; + if (typeof shortUrl === 'string' && shortUrl.length > 0) { + // we disable the button to avoid calling shortener again + $shortenButton.addClass('buttondisabled'); + // update link + $pasteUrl.text(shortUrl); + $pasteUrl.prop('href', shortUrl); + // we pre-select the link so that the user only has to [Ctrl]+[c] the link + Helper.selectText($pasteUrl[0]); + return; + } + } + Alert.showError('Cannot parse response from URL shortener.'); + }; + /** * shows the remaining time * diff --git a/js/test/PasteStatus.js b/js/test/PasteStatus.js index cf1f7e0c..9a5c60d0 100644 --- a/js/test/PasteStatus.js +++ b/js/test/PasteStatus.js @@ -34,6 +34,51 @@ describe('PasteStatus', function () { ); }); + describe('extractUrl', function () { + this.timeout(30000); + + jsc.property( + 'extracts and updates URLs found in given response', + jsc.elements(['http','https']), + 'nestring', + jsc.nearray(common.jscA2zString()), + jsc.array(common.jscQueryString()), + jsc.array(common.jscAlnumString()), + 'string', + function (schema, domain, tld, query, shortid, fragment) { + domain = domain.replace(/\P{Letter}|[\u00AA-\u00BA]/gu,'').toLowerCase(); + if (domain.length === 0) { + domain = 'a'; + } + const expected = '.' + tld.join('') + '/' + (query.length > 0 ? + ('?' + encodeURI(query.join('').replace(/^&+|&+$/gm,'')) + + shortid.join('')) : '') + (fragment.length > 0 ? + ('#' + encodeURI(fragment)) : ''), + clean = jsdom(); + + // not available in node before v19.9.0, v18.17.0 + if (typeof URL.canParse !== 'function') { + URL.canParse = function(a) { + return true; + } + } + + $('body').html('
'); + $.PrivateBin.PasteStatus.init(); + $.PrivateBin.PasteStatus.createPasteNotification('', ''); + $.PrivateBin.PasteStatus.extractUrl(schema + '://' + domain + expected); + + const result = $('#pasteurl')[0].href; + clean(); + + return result.endsWith(expected) && ( + result.startsWith(schema + '://xn--') || + result.startsWith(schema + '://' + domain) + ); + } + ); + }); + describe('showRemainingTime', function () { this.timeout(30000); diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 386705fa..3c72c00b 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index 026b4ae1..c66c2ee5 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From cc0b6e387ab6e4924d8539800a8a98ebff4ca318 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 4 Jan 2024 23:23:47 +0100 Subject: [PATCH 029/783] avoid use of bleeding edge function only supported in Firefox & Chrome >= 120 & node >= 19.9.0 & 18.17.0 --- js/privatebin.js | 6 +++++- js/test/PasteStatus.js | 7 ------- tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index e63ab5fb..930a1315 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2119,7 +2119,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { if (typeof response === 'string' && response.length > 0) { const shortUrlMatcher = /https?:\/\/[^\s]+/g; const shortUrl = (response.match(shortUrlMatcher) || []).filter(function(a) { - return URL.canParse(a); + try { + return !!new URL(a); + } catch (error) { + return false; + } }).sort(function(a, b) { return a.length - b.length; })[0]; diff --git a/js/test/PasteStatus.js b/js/test/PasteStatus.js index 9a5c60d0..baa6ab33 100644 --- a/js/test/PasteStatus.js +++ b/js/test/PasteStatus.js @@ -56,13 +56,6 @@ describe('PasteStatus', function () { ('#' + encodeURI(fragment)) : ''), clean = jsdom(); - // not available in node before v19.9.0, v18.17.0 - if (typeof URL.canParse !== 'function') { - URL.canParse = function(a) { - return true; - } - } - $('body').html('
'); $.PrivateBin.PasteStatus.init(); $.PrivateBin.PasteStatus.createPasteNotification('', ''); diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 3c72c00b..927891ac 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index c66c2ee5..ba08d2ef 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From c3331070cb1c83328e49b68f443a6abf27d3ce62 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Fri, 5 Jan 2024 06:28:19 +0100 Subject: [PATCH 030/783] codestyle, let's use readable variable names Co-authored-by: rugk --- js/privatebin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index 930a1315..b10f2d0d 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2118,9 +2118,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { } if (typeof response === 'string' && response.length > 0) { const shortUrlMatcher = /https?:\/\/[^\s]+/g; - const shortUrl = (response.match(shortUrlMatcher) || []).filter(function(a) { + const shortUrl = (response.match(shortUrlMatcher) || []).filter(function(urlRegExMatch) { try { - return !!new URL(a); + return !!new URL(urlRegExMatch); } catch (error) { return false; } From ba17e94c5e5763aa42c1fbe49a2bd81e7bd419b2 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Fri, 5 Jan 2024 06:40:12 +0100 Subject: [PATCH 031/783] use the newer function, if possible --- js/privatebin.js | 4 ++++ tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index b10f2d0d..4e370e91 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2119,6 +2119,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { if (typeof response === 'string' && response.length > 0) { const shortUrlMatcher = /https?:\/\/[^\s]+/g; const shortUrl = (response.match(shortUrlMatcher) || []).filter(function(urlRegExMatch) { + if (typeof URL.canParse === 'function') { + return URL.canParse(urlRegExMatch); + } + // polyfill for older browsers (< 120) & node (< 19.9 & < 18.17) try { return !!new URL(urlRegExMatch); } catch (error) { diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 927891ac..d1a54fcb 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index ba08d2ef..b0b9cc1a 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From cc5c81afbc2dea064d456c9a8dac4388e23d1811 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 6 Jan 2024 22:12:59 +0100 Subject: [PATCH 032/783] New translations en.json (Romanian) --- i18n/ro.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/i18n/ro.json b/i18n/ro.json index 68ff1aae..1be106cb 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -1,21 +1,21 @@ { "PrivateBin": "PrivateBin", - "%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 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.", - "More information on the project page.": "More information on the project page.", - "Because ignorance is bliss": "Because ignorance is bliss", - "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.", - "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.", - "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", + "%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 este un pastebin online, minimalist și cu sursă deschisă unde serverul are zero acces la datele introduse. Datele sunt criptate/decriptate %sîn browser%s folosind AES cu 256 de biți.", + "More information on the project page.": "Mai multe informații pe pagina proiectului.", + "Because ignorance is bliss": "Ignoranța este o binecuvântare", + "Paste does not exist, has expired or has been deleted.": "Paste-ul nu există, a expirat sau a fost șters.", + "%s requires php %s or above to work. Sorry.": "%s necesită php %s sau mai nou pentru a funcționa. Scuze.", + "%s requires configuration section [%s] to be present in configuration file.": "%s necesită ca secțiunea de configurare [%s] să fie prezentă în fișierul de configurare.", "Please wait %d seconds between each post.": [ - "Please wait %d second between each post. (singular)", - "Please wait %d seconds between each post. (1st plural)", - "Please wait %d seconds between each post. (2nd plural)", + "Vă rugăm să așteptați %d secundă între fiecare postare", + "Vă rugăm să așteptați %d secunde între fiecare postare", + "Vă rugăm să așteptați %d de secunde între fiecare postare", "Please wait %d seconds between each post. (3rd plural)", "Please wait %d seconds between each post. (4th plural)", "Please wait %d seconds between each post. (5th plural)" ], - "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", - "Invalid data.": "Invalid data.", + "Paste is limited to %s of encrypted data.": "Paste-ul este limitat la %s de date criptate.", + "Invalid data.": "Date invalide.", "You are unlucky. Try again.": "You are unlucky. Try again.", "Error saving comment. Sorry.": "Error saving comment. Sorry.", "Error saving paste. Sorry.": "Error saving paste. Sorry.", From 7ab20c23e9ce20ab184410eb2352bbd1ef2851f8 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 6 Jan 2024 23:17:48 +0100 Subject: [PATCH 033/783] New translations en.json (Romanian) --- i18n/ro.json | 248 +++++++++++++++++++++++++-------------------------- 1 file changed, 124 insertions(+), 124 deletions(-) diff --git a/i18n/ro.json b/i18n/ro.json index 1be106cb..169e57b3 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -16,87 +16,87 @@ ], "Paste is limited to %s of encrypted data.": "Paste-ul este limitat la %s de date criptate.", "Invalid data.": "Date invalide.", - "You are unlucky. Try again.": "You are unlucky. Try again.", - "Error saving comment. Sorry.": "Error saving comment. Sorry.", - "Error saving paste. Sorry.": "Error saving paste. Sorry.", - "Invalid paste ID.": "Invalid paste ID.", - "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", - "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", - "Paste was properly deleted.": "Paste was properly deleted.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", - "%s requires a modern browser to work.": "%s requires a modern browser to work.", - "New": "New", - "Send": "Send", - "Clone": "Clone", - "Raw text": "Raw text", - "Expires": "Expires", - "Burn after reading": "Burn after reading", - "Open discussion": "Open discussion", - "Password (recommended)": "Password (recommended)", - "Discussion": "Discussion", - "Toggle navigation": "Toggle navigation", + "You are unlucky. Try again.": "Ați avut ghinion. Încercați din nou.", + "Error saving comment. Sorry.": "Eroare la salvarea comentariului. Ne pare rău.", + "Error saving paste. Sorry.": "Eroare la salvarea paste-ului. Ne pare rău.", + "Invalid paste ID.": "ID paste invalid.", + "Paste is not of burn-after-reading type.": "Paste-ul nu se șterge după citire.", + "Wrong deletion token. Paste was not deleted.": "Token de ștergere incorect. Paste-ul nu a fost șters.", + "Paste was properly deleted.": "Paste-ul a fost șters cu succes.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript este necesar pentru ca %s să funcționeze. Ne cerem scuze pentru neplăceri.", + "%s requires a modern browser to work.": "%s necesită un browser modern pentru a funcționa.", + "New": "Nou", + "Send": "Trimiteți", + "Clone": "Clonați", + "Raw text": "Text brut", + "Expires": "Expiră", + "Burn after reading": "Ștergere după citire", + "Open discussion": "Deschideți discuția", + "Password (recommended)": "Parolă (recomandată)", + "Discussion": "Discuție", + "Toggle navigation": "Comutați navigarea", "%d seconds": [ - "%d second (singular)", - "%d seconds (1st plural)", - "%d seconds (2nd plural)", + "%d secundă", + "%d secunde", + "%d de secunde", "%d seconds (3rd plural)", "%d seconds (4th plural)", "%d seconds (5th plural)" ], "%d minutes": [ - "%d minute (singular)", - "%d minutes (1st plural)", - "%d minutes (2nd plural)", + "%d minut", + "%d minute", + "%d de minute", "%d minutes (3rd plural)", "%d minutes (4th plural)", "%d minutes (5th plural)" ], "%d hours": [ - "%d hour (singular)", - "%d hours (1st plural)", - "%d hours (2nd plural)", + "%d oră", + "%d ore", + "%d de ore", "%d hours (3rd plural)", "%d hours (4th plural)", "%d hours (5th plural)" ], "%d days": [ - "%d day (singular)", - "%d days (1st plural)", - "%d days (2nd plural)", + "%d zi", + "%d zile", + "%d de zile", "%d days (3rd plural)", "%d days (4th plural)", "%d days (5th plural)" ], "%d weeks": [ "%d week (singular)", - "%d weeks (1st plural)", - "%d weeks (2nd plural)", - "%d weeks (3rd plural)", + "%d săptămână", + "%d săptămâni", + "%d de săptămâni", "%d weeks (4th plural)", "%d weeks (5th plural)" ], "%d months": [ - "%d month (singular)", - "%d months (1st plural)", - "%d months (2nd plural)", + "%d lună", + "%d luni", + "%d de luni", "%d months (3rd plural)", "%d months (4th plural)", "%d months (5th plural)" ], "%d years": [ - "%d year (singular)", - "%d years (1st plural)", - "%d years (2nd plural)", + "%d an", + "%d ani", + "%d de ani", "%d years (3rd plural)", "%d years (4th plural)", "%d years (5th plural)" ], - "Never": "Never", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "Never": "Niciodată", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Notă: Acesta este un serviciu de test: Datele ar putea fi șterse oricând. Vor muri niște pisicuțe dacă abuzați acest serviciu.", "This document will expire in %d seconds.": [ - "This document will expire in %d second. (singular)", - "This document will expire in %d seconds. (1st plural)", - "This document will expire in %d seconds. (2nd plural)", + "Acest document va expira în %d secundă.", + "Acest document va expira în %d secunde.", + "Acest document va expira în %d de secunde.", "This document will expire in %d seconds. (3rd plural)", "This document will expire in %d seconds. (4th plural)", "This document will expire in %d seconds. (5th plural)" @@ -110,51 +110,51 @@ "This document will expire in %d minutes. (5th plural)" ], "This document will expire in %d hours.": [ - "This document will expire in %d hour. (singular)", - "This document will expire in %d hours. (1st plural)", - "This document will expire in %d hours. (2nd plural)", + "Acest document va expira în %d oră.", + "Acest document va expira în %d ore.", + "Acest document va expira în %d de ore.", "This document will expire in %d hours. (3rd plural)", "This document will expire in %d hours. (4th plural)", "This document will expire in %d hours. (5th plural)" ], "This document will expire in %d days.": [ - "This document will expire in %d day. (singular)", - "This document will expire in %d days. (1st plural)", - "This document will expire in %d days. (2nd plural)", + "Acest document va expira în %d zi.", + "Acest document va expira în %d zile.", + "Acest document va expira în %d de zile.", "This document will expire in %d days. (3rd plural)", "This document will expire in %d days. (4th plural)", "This document will expire in %d days. (5th plural)" ], "This document will expire in %d months.": [ - "This document will expire in %d month. (singular)", - "This document will expire in %d months. (1st plural)", - "This document will expire in %d months. (2nd plural)", + "Acest document va expira în %d lună.", + "Acest document va expira în %d luni.", + "Acest document va expira în %d de luni.", "This document will expire in %d months. (3rd plural)", "This document will expire in %d months. (4th plural)", "This document will expire in %d months. (5th plural)" ], - "Please enter the password for this paste:": "Please enter the password for this paste:", - "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", - "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", - "Reply": "Reply", - "Anonymous": "Anonymous", - "Avatar generated from IP address": "Avatar generated from IP address", - "Add comment": "Add comment", - "Optional nickname…": "Optional nickname…", - "Post comment": "Post comment", - "Sending comment…": "Sending comment…", - "Comment posted.": "Comment posted.", - "Could not refresh display: %s": "Could not refresh display: %s", - "unknown status": "unknown status", - "server error or not responding": "server error or not responding", - "Could not post comment: %s": "Could not post comment: %s", - "Sending paste…": "Sending paste…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", - "Delete data": "Delete data", - "Could not create paste: %s": "Could not create paste: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "Please enter the password for this paste:": "Va rugăm să introduceți parola pentru acest paste:", + "Could not decrypt data (Wrong key?)": "Nu s-au putut decripta datele (Cheie gresită?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Nu s-a putut șterge paste-ul, nu a fost stocat în modul de ștergere după citire.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "NUMAI PENTRU OCHII DVS. Nu închideți această fereastră, acest mesaj nu poate fi afișat din nou.", + "Could not decrypt comment; Wrong key?": "Nu s-a putut decripta comentariul; Cheie greșită?", + "Reply": "Răspundeți", + "Anonymous": "Anonim", + "Avatar generated from IP address": "Avatar generat din adresa IP", + "Add comment": "Adăugați un comentariu", + "Optional nickname…": "Poreclă opțională…", + "Post comment": "Postați comentariul", + "Sending comment…": "Se trimite comentariul…", + "Comment posted.": "Comentariul a fost postat.", + "Could not refresh display: %s": "Nu s-a putut actualiza afișarea: %s", + "unknown status": "stare necunoscută", + "server error or not responding": "eroare de server sau nu răspunde", + "Could not post comment: %s": "Nu s-a putut posta comentariul: %s", + "Sending paste…": "Se trimite paste-ul…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Paste-ul dvs. este %s (Apăsați [Ctrl]+[c] pentru a copia)", + "Delete data": "Ștergeți datele", + "Could not create paste: %s": "Nu s-a putut crea paste-ul: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nu s-a putut decripta paste-ul: Cheia de decriptare lipsește din URL (Ați folosit un redirector sau un scurtător de URL care a tăiat o parte din URL?)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -164,55 +164,55 @@ "EiB": "EiB", "ZiB": "ZiB", "YiB": "YiB", - "Format": "Format", - "Plain Text": "Plain Text", - "Source Code": "Source Code", + "Format": "Formatare", + "Plain Text": "Text neformatat", + "Source Code": "Cod sursă", "Markdown": "Markdown", - "Download attachment": "Download attachment", - "Cloned: '%s'": "Cloned: '%s'", - "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", - "Attach a file": "Attach a file", - "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", - "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", - "Remove attachment": "Remove attachment", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", - "Invalid attachment.": "Invalid attachment.", - "Options": "Options", - "Shorten URL": "Shorten URL", + "Download attachment": "Descărcați fișierul atașat", + "Cloned: '%s'": "S-a clonat: '%s'", + "The cloned file '%s' was attached to this paste.": "Fișierul clonat '%s' a fost atașat la acest paste.", + "Attach a file": "Atașați un fișier", + "alternatively drag & drop a file or paste an image from the clipboard": "alternativ, trageți și plasați un fișier sau lipiți o imagine din clipboard", + "File too large, to display a preview. Please download the attachment.": "Fișierul este prea mare pentru a afișa o previzualizare. Vă rugăm să descărcaţi fișierul.", + "Remove attachment": "Eliminați fișierul atașat", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Browserul dvs. nu acceptă încărcarea fișierelor criptate. Vă rugăm să folosiți un browser mai nou.", + "Invalid attachment.": "Fișier invalid.", + "Options": "Opţiuni", + "Shorten URL": "Scurtați URL-ul", "Editor": "Editor", - "Preview": "Preview", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", - "Decrypt": "Decrypt", - "Enter password": "Enter password", - "Loading…": "Loading…", - "Decrypting paste…": "Decrypting paste…", - "Preparing new paste…": "Preparing new paste…", - "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", - "+++ no paste text +++": "+++ no paste text +++", - "Could not get paste data: %s": "Could not get paste data: %s", - "QR code": "QR code", - "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", - "For more information see this FAQ entry.": "For more information see this FAQ entry.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", - "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", - "Retry": "Retry", - "Showing raw text…": "Showing raw text…", - "Notice:": "Notice:", - "This link will expire after %s.": "This link will expire after %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", + "Preview": "Previzualizare", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s necesită ca PATH să se termine cu \"%s\". Vă rugăm să actualizați PATH în index.php.", + "Decrypt": "Decriptare", + "Enter password": "Introduceţi parola", + "Loading…": "Se încarcă…", + "Decrypting paste…": "Se decriptează paste-ul…", + "Preparing new paste…": "Se pregătește un paste nou…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "În cazul în care acest mesaj nu dispare niciodată, vă rugăm să aruncaţi o privire la acest FAQ pentru informații de depanare.", + "+++ no paste text +++": "+++ fără text +++", + "Could not get paste data: %s": "Nu s-a putut obține datele paste-ului: %s", + "QR code": "Cod QR", + "This website is using an insecure HTTP connection! Please use it only for testing.": "Acest website folosește o conexiune HTTP nesigură! Vă rugăm să îl folosiți doar pentru teste.", + "For more information see this FAQ entry.": "Pentru mai multe informații a se vedea secțiunea FAQ.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Este posibil ca browserul dvs. să necesite o conexiune HTTPS pentru a suporta API-ul WebCrypto. Încercați să comutați la HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Browserul dvs. nu acceptă WebAssembly folosit pentru compresia zlib. Puteți crea documente necompresate, dar nu le puteți citi pe cele compresate.", + "waiting on user to provide a password": "se așteaptă ca utilizatorul să furnizeze o parolă", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Nu s-au putut decripta datele. Ați introdus parola greșită? Reîncercați folosind butonul de sus.", + "Retry": "Reîncercați", + "Showing raw text…": "Se afișează textul brut…", + "Notice:": "Observaţie:", + "This link will expire after %s.": "Acest link va expira după %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Acest link poate fi accesat o singură dată, nu folosiți butonul înapoi sau reîmprospătare din browserul dvs.", "Link:": "Link:", - "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", - "Use Current Timezone": "Use Current Timezone", - "Convert To UTC": "Convert To UTC", - "Close": "Close", - "Encrypted note on %s": "Encrypted note on %s", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", - "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", - "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", - "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." + "Recipient may become aware of your timezone, convert time to UTC?": "Destinatarul vă poate afla fusul dvs. orar, convertiți timpul în UTC?", + "Use Current Timezone": "Se folosește fusul orar actual", + "Convert To UTC": "Convertire la UTC", + "Close": "Închideți", + "Encrypted note on %s": "Notă criptată pe %s", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Accesați acest link pentru a vedea nota. Nota poate fi accesată de către oricine care are acest URL.", + "URL shortener may expose your decrypt key in URL.": "Scurtătorul de URL ar putea să vă expună cheia de decriptare din URL.", + "Save paste": "Salvați paste-ul", + "Your IP is not authorized to create pastes.": "Adresa dvs. IP nu este autorizată să creeze paste-uri.", + "Trying to shorten a URL that isn't pointing at our instance.": "Încercarea de a scurta un URL care nu direcționează spre instanța noastră.", + "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." } From 37ee3b1c7c0cdf7c17bf8b48b5ecb47d84185bda Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 7 Jan 2024 14:10:43 +0100 Subject: [PATCH 034/783] refactor URL generators --- js/common.js | 21 +++++++++++++ js/test/PasteStatus.js | 68 ++++++++++++------------------------------ 2 files changed, 40 insertions(+), 49 deletions(-) diff --git a/js/common.js b/js/common.js index 295fd090..c14a76ca 100644 --- a/js/common.js +++ b/js/common.js @@ -131,3 +131,24 @@ exports.jscMimeTypes = function() { exports.jscFormats = function() { return jsc.elements(formats); }; + +// provides random URLs +exports.jscUrl = function(withFragment = true, withQuery = true) { + let url = { + schema: exports.jscSchemas(), + address: jsc.nearray(exports.jscA2zString()), + }; + if (withFragment) { + url.fragment = jsc.string; + } + if(withQuery) { + url.query = jsc.array(exports.jscQueryString()); + } + return jsc.record(url); +}; + +exports.urlToString = function (url) { + return url.schema + '://' + url.address.join('') + '/' + (url.query ? '?' + + encodeURI(url.query.join('').replace(/^&+|&+$/gm,'')) : '') + + (url.fragment ? '#' + encodeURI(url.fragment) : ''); +}; \ No newline at end of file diff --git a/js/test/PasteStatus.js b/js/test/PasteStatus.js index baa6ab33..8b19c75b 100644 --- a/js/test/PasteStatus.js +++ b/js/test/PasteStatus.js @@ -7,21 +7,11 @@ describe('PasteStatus', function () { jsc.property( 'creates a notification after a successfull paste upload', - common.jscSchemas(), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - 'string', - common.jscSchemas(), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - function ( - schema1, address1, query1, fragment1, - schema2, address2, query2 - ) { - var expected1 = schema1 + '://' + address1.join('') + '/?' + - encodeURI(query1.join('').replace(/^&+|&+$/gm,'') + '#' + fragment1), - expected2 = schema2 + '://' + address2.join('') + '/?' + - encodeURI(query2.join('').replace(/^&+|&+$/gm,'')), + common.jscUrl(), + common.jscUrl(false), + function (url1, url2) { + const expected1 = common.urlToString(url1), + expected2 = common.urlToString(url2), clean = jsdom(); $('body').html('
'); $.PrivateBin.PasteStatus.init(); @@ -41,25 +31,23 @@ describe('PasteStatus', function () { 'extracts and updates URLs found in given response', jsc.elements(['http','https']), 'nestring', - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - jsc.array(common.jscAlnumString()), - 'string', - function (schema, domain, tld, query, shortid, fragment) { + common.jscUrl(), + function (schema, domain, url) { domain = domain.replace(/\P{Letter}|[\u00AA-\u00BA]/gu,'').toLowerCase(); if (domain.length === 0) { domain = 'a'; } - const expected = '.' + tld.join('') + '/' + (query.length > 0 ? - ('?' + encodeURI(query.join('').replace(/^&+|&+$/gm,'')) + - shortid.join('')) : '') + (fragment.length > 0 ? - ('#' + encodeURI(fragment)) : ''), + url.schema = schema; + url.address.unshift('.'); + url.address = domain.split('').concat(url.address); + const urlString = common.urlToString(url), + expected = urlString.substring((schema + '://' + domain).length), clean = jsdom(); $('body').html('
'); $.PrivateBin.PasteStatus.init(); $.PrivateBin.PasteStatus.createPasteNotification('', ''); - $.PrivateBin.PasteStatus.extractUrl(schema + '://' + domain + expected); + $.PrivateBin.PasteStatus.extractUrl(urlString); const result = $('#pasteurl')[0].href; clean(); @@ -79,18 +67,9 @@ describe('PasteStatus', function () { 'shows burn after reading message or remaining time v1', 'bool', 'nat', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscQueryString()), - 'string', - function ( - burnafterreading, remainingTime, - schema, address, query, fragment - ) { - var clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + - '/?' + query.join('') + '#' + fragment - }), + common.jscUrl(), + function (burnafterreading, remainingTime, url) { + let clean = jsdom('', {url: common.urlToString(url)}), result; $('body').html(''); $.PrivateBin.PasteStatus.init(); @@ -117,18 +96,9 @@ describe('PasteStatus', function () { 'shows burn after reading message or remaining time v2', 'bool', 'nat', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscQueryString()), - 'string', - function ( - burnafterreading, remainingTime, - schema, address, query, fragment - ) { - var clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + - '/?' + query.join('') + '#' + fragment - }), + common.jscUrl(), + function (burnafterreading, remainingTime, url) { + let clean = jsdom('', {url: common.urlToString(url)}), result; $('body').html(''); $.PrivateBin.PasteStatus.init(); From d493ba73376b3036f539dcfb4ec42ae17c9c81ed Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 7 Jan 2024 15:47:29 +0100 Subject: [PATCH 035/783] refactor URL generators --- js/test/Helper.js | 28 ++++++------ js/test/Model.js | 112 ++++++++++++++++------------------------------ 2 files changed, 52 insertions(+), 88 deletions(-) diff --git a/js/test/Helper.js b/js/test/Helper.js index 2cd5202f..434cd3e5 100644 --- a/js/test/Helper.js +++ b/js/test/Helper.js @@ -96,36 +96,34 @@ describe('Helper', function () { jsc.property( 'replaces URLs with anchors', 'string', - jsc.elements(['http', 'https', 'ftp']), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), + common.jscUrl(), jsc.array(common.jscHashString()), 'string', - function (prefix, schema, address, query, fragment, postfix) { - query = query.join(''); - fragment = fragment.join(''); + function (prefix, url, fragment, postfix) { prefix = prefix.replace(/\r|\f/g, '\n').replace(/\u0000/g, '').replace(/\u000b/g, ''); postfix = ' ' + postfix.replace(/\r/g, '\n').replace(/\u0000/g, ''); - let url = schema + '://' + address.join('') + '/?' + query + '#' + fragment, + url.fragment = fragment.join(''); + let urlString = common.urlToString(url), clean = jsdom(); $('body').html('
'); let e = $('#foo'); // special cases: When the query string and fragment imply the beginning of an HTML entity, eg. � or &#x if ( - query.slice(-1) === '&' && - (parseInt(fragment.substring(0, 1), 10) >= 0 || fragment.charAt(0) === 'x' ) - ) - { - url = schema + '://' + address.join('') + '/?' + query.substring(0, query.length - 1); + url.query[-1] === '&' && + (parseInt(url.fragment.charAt(0), 10) >= 0 || url.fragment.charAt(0) === 'x') + ) { + url.query.pop(); + urlString = common.urlToString(url); postfix = ''; } - e.text(prefix + url + postfix); + e.text(prefix + urlString + postfix); $.PrivateBin.Helper.urls2links(e); let result = e.html(); clean(); - url = $('
').text(url).html(); - return $('
').text(prefix).html() + '' + url + '' + $('
').text(postfix).html() === result; + urlString = $('
').text(urlString).html(); + const expected = $('
').text(prefix).html() + '' + urlString + '' + $('
').text(postfix).html(); + return $('
').text(prefix).html() + '' + urlString + '' + $('
').text(postfix).html() === result; } ); jsc.property( diff --git a/js/test/Model.js b/js/test/Model.js index 9ebc5472..491154b4 100644 --- a/js/test/Model.js +++ b/js/test/Model.js @@ -80,23 +80,22 @@ describe('Model', function () { jsc.property( 'returns the query string without separator, if any', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), + common.jscUrl(), jsc.tuple(new Array(16).fill(common.jscHexString)), jsc.array(common.jscQueryString()), jsc.array(common.jscQueryString()), - 'string', - function (schema, address, pasteId, queryStart, queryEnd, fragment) { - var pasteIdString = pasteId.join(''), - queryStartString = queryStart.join('') + (queryStart.length > 0 ? '&' : ''), - queryEndString = (queryEnd.length > 0 ? '&' : '') + queryEnd.join(''), - queryString = queryStartString + pasteIdString + queryEndString, - clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + - '/?' + queryString + '#' + fragment - }); - global.URL = require('jsdom-url').URL; - var result = $.PrivateBin.Model.getPasteId(); + function (url, pasteId, queryStart, queryEnd) { + if (queryStart.length > 0) { + queryStart.push('&'); + } + if (queryEnd.length > 0) { + queryEnd.unshift('&'); + } + url.query = queryStart.concat(pasteId, queryEnd); + const pasteIdString = pasteId.join(''), + clean = jsdom('', {url: common.urlToString(url)}); + global.URL = require('jsdom-url').URL; + const result = $.PrivateBin.Model.getPasteId(); $.PrivateBin.Model.reset(); clean(); return pasteIdString === result; @@ -104,14 +103,9 @@ describe('Model', function () { ); jsc.property( 'throws exception on empty query string', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), - 'string', - function (schema, address, fragment) { - var clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + - '/#' + fragment - }), + common.jscUrl(true, false), + function (url) { + let clean = jsdom('', {url: common.urlToString(url)}), result = false; global.URL = require('jsdom-url').URL; try { @@ -135,35 +129,24 @@ describe('Model', function () { jsc.property( 'returns the fragment of a v1 URL', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - 'nestring', - function (schema, address, query, fragment) { - const fragmentString = common.btoa(fragment.padStart(32, '\u0000')); - let clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + - '/?' + query.join('') + '#' + fragmentString - }), + common.jscUrl(), + function (url) { + url.fragment = common.btoa(url.fragment.padStart(32, '\u0000')); + const clean = jsdom('', {url: common.urlToString(url)}), result = $.PrivateBin.Model.getPasteKey(); $.PrivateBin.Model.reset(); clean(); - return fragmentString === result; + return url.fragment === result; } ); jsc.property( 'returns the v1 fragment stripped of trailing query parts', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - 'nestring', + common.jscUrl(), jsc.array(common.jscHashString()), - function (schema, address, query, fragment, trail) { - const fragmentString = common.btoa(fragment.padStart(32, '\u0000')); - let clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + '/?' + - query.join('') + '#' + fragmentString + '&' + trail.join('') - }), + function (url, trail) { + const fragmentString = common.btoa(url.fragment.padStart(32, '\u0000')); + url.fragment = fragmentString + '&' + trail.join(''); + const clean = jsdom('', {url: common.urlToString(url)}), result = $.PrivateBin.Model.getPasteKey(); $.PrivateBin.Model.reset(); clean(); @@ -172,18 +155,12 @@ describe('Model', function () { ); jsc.property( 'returns the fragment of a v2 URL', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - 'nestring', - function (schema, address, query, fragment) { + common.jscUrl(), + function (url) { // base58 strips leading NULL bytes, so the string is padded with these if not found - fragment = fragment.padStart(32, '\u0000'); - let fragmentString = $.PrivateBin.CryptTool.base58encode(fragment), - clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + - '/?' + query.join('') + '#' + fragmentString - }), + const fragment = url.fragment.padStart(32, '\u0000'); + url.fragment = $.PrivateBin.CryptTool.base58encode(fragment); + const clean = jsdom('', {url: common.urlToString(url)}), result = $.PrivateBin.Model.getPasteKey(); $.PrivateBin.Model.reset(); clean(); @@ -192,19 +169,13 @@ describe('Model', function () { ); jsc.property( 'returns the v2 fragment stripped of trailing query parts', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - 'nestring', + common.jscUrl(), jsc.array(common.jscHashString()), - function (schema, address, query, fragment, trail) { + function (url, trail) { // base58 strips leading NULL bytes, so the string is padded with these if not found - fragment = fragment.padStart(32, '\u0000'); - let fragmentString = $.PrivateBin.CryptTool.base58encode(fragment), - clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + '/?' + - query.join('') + '#' + fragmentString + '&' + trail.join('') - }), + const fragment = url.fragment.padStart(32, '\u0000'); + url.fragment = $.PrivateBin.CryptTool.base58encode(fragment) + '&' + trail.join(''); + const clean = jsdom('', {url: common.urlToString(url)}), result = $.PrivateBin.Model.getPasteKey(); $.PrivateBin.Model.reset(); clean(); @@ -213,14 +184,9 @@ describe('Model', function () { ); jsc.property( 'throws exception on empty fragment of the URL', - jsc.nearray(common.jscA2zString()), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - function (schema, address, query) { - var clean = jsdom('', { - url: schema.join('') + '://' + address.join('') + - '/?' + query.join('') - }), + common.jscUrl(false, false), + function (url) { + let clean = jsdom('', {url: common.urlToString(url)}), result = false; try { $.PrivateBin.Model.getPasteKey(); From fd82b937a9e81a78ad32124615294281e3506d6a Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 7 Jan 2024 16:06:24 +0100 Subject: [PATCH 036/783] refactor URL generators --- js/test/Model.js | 4 ++-- js/test/UiHelper.js | 32 +++++++++++++------------------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/js/test/Model.js b/js/test/Model.js index 491154b4..db2198ba 100644 --- a/js/test/Model.js +++ b/js/test/Model.js @@ -80,7 +80,7 @@ describe('Model', function () { jsc.property( 'returns the query string without separator, if any', - common.jscUrl(), + common.jscUrl(true, false), jsc.tuple(new Array(16).fill(common.jscHexString)), jsc.array(common.jscQueryString()), jsc.array(common.jscQueryString()), @@ -184,7 +184,7 @@ describe('Model', function () { ); jsc.property( 'throws exception on empty fragment of the URL', - common.jscUrl(false, false), + common.jscUrl(false), function (url) { let clean = jsdom('', {url: common.urlToString(url)}), result = false; diff --git a/js/test/UiHelper.js b/js/test/UiHelper.js index 817345c6..63968fdb 100644 --- a/js/test/UiHelper.js +++ b/js/test/UiHelper.js @@ -13,10 +13,9 @@ describe('UiHelper', function () { jsc.property( 'redirects to home, when the state is null', - common.jscSchemas(), - jsc.nearray(common.jscA2zString()), - function (schema, address) { - var expected = schema + '://' + address.join('') + '/', + common.jscUrl(false, false), + function (url) { + const expected = common.urlToString(url), clean = jsdom('', {url: expected}); // make window.location.href writable @@ -34,13 +33,11 @@ describe('UiHelper', function () { jsc.property( 'does not redirect to home, when a new paste is created', - common.jscSchemas(), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), + common.jscUrl(false), jsc.nearray(common.jscBase64String()), - function (schema, address, query, fragment) { - var expected = schema + '://' + address.join('') + '/?' + - query.join('') + '#' + fragment.join(''), + function (url, fragment) { + url.fragment = fragment.join(''); + const expected = common.urlToString(url), clean = jsdom('', {url: expected}); // make window.location.href writable @@ -67,15 +64,12 @@ describe('UiHelper', function () { jsc.property( 'redirects to home', - common.jscSchemas(), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscQueryString()), - jsc.nearray(common.jscBase64String()), - function (schema, address, query, fragment) { - var expected = schema + '://' + address.join('') + '/', - clean = jsdom('', { - url: expected + '?' + query.join('') + '#' + fragment.join('') - }); + common.jscUrl(), + function (url) { + const clean = jsdom('', {url: common.urlToString(url)}); + delete(url.query); + delete(url.fragment); + const expected = common.urlToString(url); // make window.location.href writable Object.defineProperty(window.location, 'href', { From 405479642ffeec59fed70aaa37a90c94f38fc20a Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 7 Jan 2024 17:45:01 +0100 Subject: [PATCH 037/783] add YOURLS API samples for extractUrl validation --- js/common.js | 4 +- js/privatebin.js | 4 +- js/test/Helper.js | 18 +++---- js/test/PasteStatus.js | 117 ++++++++++++++++++++++++++++++++++++++++- tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 6 files changed, 130 insertions(+), 17 deletions(-) diff --git a/js/common.js b/js/common.js index c14a76ca..d3953d36 100644 --- a/js/common.js +++ b/js/common.js @@ -113,8 +113,8 @@ exports.jscBase64String = function() { }; // provides a random URL schema supported by the whatwg-url library -exports.jscSchemas = function() { - return jsc.elements(schemas); +exports.jscSchemas = function(withFtp = true) { + return jsc.elements(withFtp ? schemas : schemas.slice(1)); }; // provides a random supported language string diff --git a/js/privatebin.js b/js/privatebin.js index 4e370e91..9196ca5f 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2117,7 +2117,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { response = JSON.stringify(response); } if (typeof response === 'string' && response.length > 0) { - const shortUrlMatcher = /https?:\/\/[^\s]+/g; + const shortUrlMatcher = /https?:\/\/[^\s"<]+/g; // JSON API will have URL in quotes, XML in tags const shortUrl = (response.match(shortUrlMatcher) || []).filter(function(urlRegExMatch) { if (typeof URL.canParse === 'function') { return URL.canParse(urlRegExMatch); @@ -2129,7 +2129,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { return false; } }).sort(function(a, b) { - return a.length - b.length; + return a.length - b.length; // shortest first })[0]; if (typeof shortUrl === 'string' && shortUrl.length > 0) { // we disable the button to avoid calling shortener again diff --git a/js/test/Helper.js b/js/test/Helper.js index 434cd3e5..95ae5709 100644 --- a/js/test/Helper.js +++ b/js/test/Helper.js @@ -259,16 +259,16 @@ describe('Helper', function () { this.timeout(30000); jsc.property( 'returns the URL without query & fragment', - jsc.elements(['http', 'https']), - jsc.nearray(common.jscA2zString()), - jsc.array(common.jscA2zString()), - jsc.array(common.jscQueryString()), - 'string', - function (schema, address, path, query, fragment) { + common.jscSchemas(false), + common.jscUrl(), + function (schema, url) { + url.schema = schema; + const fullUrl = common.urlToString(url); + delete(url.query); + delete(url.fragment); $.PrivateBin.Helper.reset(); - var path = path.join('') + (path.length > 0 ? '/' : ''), - expected = schema + '://' + address.join('') + '/' + path, - clean = jsdom('', {url: expected + '?' + query.join('') + '#' + fragment}), + const expected = common.urlToString(url), + clean = jsdom('', {url: fullUrl}), result = $.PrivateBin.Helper.baseUri(); clean(); return expected === result; diff --git a/js/test/PasteStatus.js b/js/test/PasteStatus.js index 8b19c75b..2e8e6dc7 100644 --- a/js/test/PasteStatus.js +++ b/js/test/PasteStatus.js @@ -1,6 +1,23 @@ 'use strict'; var common = require('../common'); +function urlStrings(schema, longUrl, shortUrl) { + longUrl.schema = schema; + shortUrl.schema = schema; + let longUrlString = common.urlToString(longUrl), + shortUrlString = common.urlToString(shortUrl); + // ensure the two random URLs actually are sorted as expected + if (longUrlString.length <= shortUrlString.length) { + if (longUrlString.length === shortUrlString.length) { + longUrl.address.unshift('a'); + longUrlString = common.urlToString(longUrl); + } else { + [longUrlString, shortUrlString] = [shortUrlString, longUrlString]; + } + } + return [longUrlString, shortUrlString]; +} + describe('PasteStatus', function () { describe('createPasteNotification', function () { this.timeout(30000); @@ -28,8 +45,8 @@ describe('PasteStatus', function () { this.timeout(30000); jsc.property( - 'extracts and updates URLs found in given response', - jsc.elements(['http','https']), + 'extracts and updates IDN URLs found in given response', + common.jscSchemas(false), 'nestring', common.jscUrl(), function (schema, domain, url) { @@ -58,6 +75,102 @@ describe('PasteStatus', function () { ); } ); + + // YOURLS API samples from: https://yourls.org/readme.html#API;apireturn + jsc.property( + 'extracts and updates URLs found in YOURLS API JSON response', + common.jscSchemas(false), + common.jscUrl(), + common.jscUrl(false), + function (schema, longUrl, shortUrl) { + const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl), + yourlsResponse = { + url: { + keyword: longUrl.address.join(''), + url: longUrlString, + title: "example title", + date: "2014-10-24 16:01:39", + ip: "127.0.0.1" + }, + status: "success", + message: longUrlString + " added to database", + title: "example title", + shorturl: shortUrlString, + statusCode: 200 + }, + clean = jsdom(); + + $('body').html('
'); + $.PrivateBin.PasteStatus.init(); + $.PrivateBin.PasteStatus.createPasteNotification('', ''); + $.PrivateBin.PasteStatus.extractUrl(JSON.stringify(yourlsResponse, undefined, 4)); + + const result = $('#pasteurl')[0].href; + clean(); + + return result === shortUrlString; + } + ); + jsc.property( + 'extracts and updates URLs found in YOURLS API XML response', + common.jscSchemas(false), + common.jscUrl(), + common.jscUrl(false), + function (schema, longUrl, shortUrl) { + const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl), + yourlsResponse = '\n' + + ' ' + longUrl.address.join('') + '\n' + + ' ' + shortUrlString + '\n' + + ' ' + longUrlString + '\n' + + ' success\n' + + ' 200\n' + + '', + clean = jsdom(); + + $('body').html('
'); + $.PrivateBin.PasteStatus.init(); + $.PrivateBin.PasteStatus.createPasteNotification('', ''); + $.PrivateBin.PasteStatus.extractUrl(yourlsResponse); + + const result = $('#pasteurl')[0].href; + clean(); + + return result === shortUrlString; + } + ); + jsc.property( + 'extracts and updates URLs found in YOURLS proxy HTML response', + common.jscSchemas(false), + common.jscUrl(), + common.jscUrl(false), + function (schema, longUrl, shortUrl) { + const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl), + yourlsResponse = '\n' + + '\n' + + '\t\n' + + '\t\t\n' + + '\t\t\n' + + '\t\t\n' + + '\t\t\n' + + '\t\tPrivateBin\n' + + '\t\n' + + '\t\n' + + '\t\t

Your paste is ' + shortUrlString + ' (Hit [Ctrl]+[c] to copy)

\n' + + '\t\n' + + '', + clean = jsdom(); + + $('body').html('
'); + $.PrivateBin.PasteStatus.init(); + $.PrivateBin.PasteStatus.createPasteNotification('', ''); + $.PrivateBin.PasteStatus.extractUrl(yourlsResponse); + + const result = $('#pasteurl')[0].href; + clean(); + + return result === shortUrlString; + } + ); }); describe('showRemainingTime', function () { diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index d1a54fcb..0cf27f5f 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index b0b9cc1a..7e62f37e 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From 4e62e1f6efd27289f3bd5f56aed27cdd32762f51 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 8 Jan 2024 08:09:29 +0100 Subject: [PATCH 038/783] address jsverify rngState 87ab3f64de258190c7, fixes #1139 --- js/test/PasteStatus.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/test/PasteStatus.js b/js/test/PasteStatus.js index 2e8e6dc7..a233bb48 100644 --- a/js/test/PasteStatus.js +++ b/js/test/PasteStatus.js @@ -27,13 +27,13 @@ describe('PasteStatus', function () { common.jscUrl(), common.jscUrl(false), function (url1, url2) { - const expected1 = common.urlToString(url1), - expected2 = common.urlToString(url2), + const expected1 = common.urlToString(url1).replace(/&(gt|lt)$/, '&$1a'), + expected2 = common.urlToString(url2).replace(/&(gt|lt)$/, '&$1a'), clean = jsdom(); $('body').html('
'); $.PrivateBin.PasteStatus.init(); $.PrivateBin.PasteStatus.createPasteNotification(expected1, expected2); - var result1 = $('#pasteurl')[0].href, + const result1 = $('#pasteurl')[0].href, result2 = $('#deletelink a')[0].href; clean(); return result1 === expected1 && result2 === expected2; @@ -50,7 +50,7 @@ describe('PasteStatus', function () { 'nestring', common.jscUrl(), function (schema, domain, url) { - domain = domain.replace(/\P{Letter}|[\u00AA-\u00BA]/gu,'').toLowerCase(); + domain = domain.replace(/\P{Letter}|[\u00AA-\u00BA]/gu, '').toLowerCase(); if (domain.length === 0) { domain = 'a'; } From 7fddefeb05d837e41e4ebf313eec2563fb912883 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jan 2024 10:36:59 +0100 Subject: [PATCH 039/783] password Signed-off-by: Tobias Gurtzick --- js/privatebin.js | 50 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index a3756f21..41ef9da0 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -228,7 +228,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { '<': '<', '>': '>', '"': '"', - "'": ''', + '\'': ''', '/': '/', '`': '`', '=': '=' @@ -2197,7 +2197,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @function * @param {Event} event */ - function submitPasswordModal(event) + async function submitPasswordModal(event) { event.preventDefault(); @@ -2207,6 +2207,19 @@ jQuery.PrivateBin = (function($, RawDeflate) { // hide modal $passwordModal.modal('hide'); + // check if protected pathname + const url = new URL(window.location); + + // if protected request password + if(url.pathname === '/protected') { + const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); + const cipherdata = [enc.ct, enc.adata]; + + const plaindata = await CryptTool.decipher(enc.k, password, cipherdata); + window.location.replace(Helper.baseUri() + plaindata); + return; + } + PasteDecrypter.run(); } @@ -4778,16 +4791,32 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @param {int} status * @param {object} data */ - function showCreatedPaste(status, data) { + async function showCreatedPaste(status, data) { Alert.hideLoading(); Alert.hideMessages(); // show notification const baseUri = Helper.baseUri() + '?', - url = baseUri + data.id + '#' + CryptTool.base58encode(data.encryptionKey), - deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; + deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; PasteStatus.createPasteNotification(url, deleteUrl); + const pw = TopNav.getPassword() + const sm = CryptTool.getSymmetricKey(); + + let openUri = + '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); + let cipherResult = await CryptTool.cipher(sm, pw, openUri, []); + + let dt = {} + dt['v'] = 2; + dt['ct'] = cipherResult[0]; + dt['adata'] = cipherResult[1]; + dt['k'] = sm; + + const encUrl = CryptTool.base58encode(JSON.stringify(dt)) + + const url = baseUri + 'protected/#' + encUrl; + + // show new URL in browser bar history.pushState({type: 'newpaste'}, document.title, url); @@ -5518,6 +5547,17 @@ jQuery.PrivateBin = (function($, RawDeflate) { try { Model.getPasteId(); } catch (e) { + + // check if protected pathname + const url = new URL(window.location); + + // if protected request password + if(url.pathname === '/protected') { + const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); + return Prompt.requestPassword(); + + } + // otherwise create a new paste return me.newPaste(); } From 2cc2cf0de769cee96311f639a3b338a7da50b0f9 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jan 2024 12:28:41 +0100 Subject: [PATCH 040/783] working browser password Signed-off-by: Tobias Gurtzick --- js/privatebin.js | 80 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index bd5466f2..ed94a356 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -1512,7 +1512,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.getPasteKey = function() { if (symmetricKey === null) { - let newKey = window.location.hash.substring(1); + let pos = 1; + const pt = '#protected/'; + if(window.location.hash.startsWith(pt)) { + pos = pt.length; + } + let newKey = window.location.hash.substring(pos); if (newKey === '') { throw 'no encryption key given'; } @@ -2229,13 +2234,28 @@ jQuery.PrivateBin = (function($, RawDeflate) { const url = new URL(window.location); // if protected request password - if(url.pathname === '/protected') { - const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); - const cipherdata = [enc.ct, enc.adata]; + if(url.hash.startsWith('#protected/')) { + const pt = '#protected/'; + let pos = pt.length; + let newKey = window.location.hash.substring(pos); + if (newKey === '') { + throw 'no encryption key given'; + } - const plaindata = await CryptTool.decipher(enc.k, password, cipherdata); + // Some web 2.0 services and redirectors add data AFTER the anchor + // (such as &utm_source=...). We will strip any additional data. + let ampersandPos = newKey.indexOf('&'); + if (ampersandPos > -1) + { + newKey = newKey.substring(0, ampersandPos); + } + const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); + const dt = JSON.parse(enc); + const cipherdata = [dt.ct, dt.adata] + + const plaindata = await CryptTool.decipher(dt.k, password, cipherdata); window.location.replace(Helper.baseUri() + plaindata); - return; + return; } PasteDecrypter.run(); @@ -4814,25 +4834,36 @@ jQuery.PrivateBin = (function($, RawDeflate) { Alert.hideMessages(); // show notification - const baseUri = Helper.baseUri() + '?', - deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; - PasteStatus.createPasteNotification(url, deleteUrl); + const baseUri = Helper.baseUri(), + deleteUrl = baseUri + '?pasteid=' + data.id + '&deletetoken=' + data.deletetoken; + let url; const pw = TopNav.getPassword() - const sm = CryptTool.getSymmetricKey(); - - let openUri = + '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); - let cipherResult = await CryptTool.cipher(sm, pw, openUri, []); - let dt = {} - dt['v'] = 2; - dt['ct'] = cipherResult[0]; - dt['adata'] = cipherResult[1]; - dt['k'] = sm; + if(pw && pw.length) { + + const sm = CryptTool.getSymmetricKey(); + + let openUri = '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); + let cipherResult = await CryptTool.cipher(sm, pw, openUri, []); + + let dt = {} + dt['v'] = 2; + dt['ct'] = cipherResult[0]; + dt['adata'] = cipherResult[1]; + dt['k'] = sm; + + const encUrl = CryptTool.base58encode(JSON.stringify(dt)) + + url = baseUri + '#protected/' + encUrl; + } else { + url = baseUri + '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); + } + + PasteStatus.createPasteNotification(url, deleteUrl); + - const encUrl = CryptTool.base58encode(JSON.stringify(dt)) - const url = baseUri + 'protected/#' + encUrl; // show new URL in browser bar @@ -4979,7 +5010,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { // prepare server interaction ServerInteraction.prepare(); - ServerInteraction.setCryptParameters(TopNav.getPassword()); + // This is not needed when encrypting browser side + // ServerInteraction.setCryptParameters(TopNav.getPassword()); + ServerInteraction.setCryptParameters(''); // set success/fail functions ServerInteraction.setSuccess(showCreatedPaste); @@ -5565,13 +5598,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { try { Model.getPasteId(); } catch (e) { - + // check if protected pathname const url = new URL(window.location); // if protected request password - if(url.pathname === '/protected') { - const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); + if(url.hash.startsWith('#protected/')) { return Prompt.requestPassword(); } From 2a508cb7bfa541193901e8f89dd720635e334c63 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Mon, 8 Jan 2024 12:38:48 +0100 Subject: [PATCH 041/783] burn after reading only Signed-off-by: Tobias Gurtzick --- js/privatebin.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index 4fd5f1c7..23a4fe20 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -4862,7 +4862,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { const pw = TopNav.getPassword() - if(pw && pw.length) { + // only execute when it is a single time view + if(pw && pw.length && TopNav.getBurnAfterReading()) { const sm = CryptTool.getSymmetricKey(); @@ -5032,9 +5033,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { // prepare server interaction ServerInteraction.prepare(); - // This is not needed when encrypting browser side - // ServerInteraction.setCryptParameters(TopNav.getPassword()); - ServerInteraction.setCryptParameters(''); + if(!TopNav.getBurnAfterReading()) { + ServerInteraction.setCryptParameters(TopNav.getPassword()); + } else { + // not needed in this scenario + ServerInteraction.setCryptParameters(''); + } // set success/fail functions ServerInteraction.setSuccess(showCreatedPaste); From ba25ab8fa97a34f0236d9adbe0a464884fa2a06a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:21:35 +0000 Subject: [PATCH 042/783] Bump actions/cache from 3 to 4 Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index dd5f59b6..730de26e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -41,7 +41,7 @@ jobs: key: ${{ runner.os }}-${{ env.extensions-cache-key }} - name: Cache extensions - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.extcache.outputs.dir }} key: ${{ steps.extcache.outputs.key }} @@ -76,7 +76,7 @@ jobs: shell: bash - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}-${{ hashFiles('**/composer.json') }} From 3ff3db72a16f36f0ca886b467e90905785c43967 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 11:44:19 +0000 Subject: [PATCH 043/783] Bump phpunit/phpunit from 9.6.15 to 9.6.16 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.15 to 9.6.16. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.16/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.15...9.6.16) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 66 +++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/composer.lock b/composer.lock index bf8fa3fd..5f8d2963 100644 --- a/composer.lock +++ b/composer.lock @@ -316,16 +316,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.17.1", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { @@ -366,9 +366,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" }, - "time": "2023-08-13T19:53:39+00:00" + "time": "2023-12-10T21:03:43+00:00" }, { "name": "phar-io/manifest", @@ -483,23 +483,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.29", + "version": "9.2.30", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -549,7 +549,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" }, "funding": [ { @@ -557,7 +557,7 @@ "type": "github" } ], - "time": "2023-09-19T04:57:46+00:00" + "time": "2023-12-22T06:47:57+00:00" }, { "name": "phpunit/php-file-iterator", @@ -802,16 +802,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.15", + "version": "9.6.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" + "reference": "3767b2c56ce02d01e3491046f33466a1ae60a37f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3767b2c56ce02d01e3491046f33466a1ae60a37f", + "reference": "3767b2c56ce02d01e3491046f33466a1ae60a37f", "shasum": "" }, "require": { @@ -885,7 +885,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.16" }, "funding": [ { @@ -901,7 +901,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T16:55:19+00:00" + "time": "2024-01-19T07:03:14+00:00" }, { "name": "sebastian/cli-parser", @@ -1146,20 +1146,20 @@ }, { "name": "sebastian/complexity", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3" }, "require-dev": { @@ -1191,7 +1191,7 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" }, "funding": [ { @@ -1199,7 +1199,7 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2023-12-22T06:19:30+00:00" }, { "name": "sebastian/diff", @@ -1473,20 +1473,20 @@ }, { "name": "sebastian/lines-of-code", - "version": "1.0.3", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3" }, "require-dev": { @@ -1518,7 +1518,7 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" }, "funding": [ { @@ -1526,7 +1526,7 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-12-22T06:20:34+00:00" }, { "name": "sebastian/object-enumerator", From 0d2376cd8829d40f52c2fe9ecee47e273be21fc5 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 27 Jan 2024 11:33:54 +0100 Subject: [PATCH 044/783] bump libraries to DOMpurify 3.0.8 & zlib 1.3.1, increase compression level to 9 --- CHANGELOG.md | 3 ++- js/common.js | 6 +++--- js/purify-3.0.6.js | 2 -- js/purify-3.0.8.js | 2 ++ js/{zlib-1.3.js => zlib-1.3.1.js} | 2 +- js/{zlib-1.3.wasm => zlib-1.3.1.wasm} | Bin 58825 -> 58827 bytes tpl/bootstrap.php | 4 ++-- tpl/page.php | 4 ++-- 8 files changed, 12 insertions(+), 11 deletions(-) delete mode 100644 js/purify-3.0.6.js create mode 100644 js/purify-3.0.8.js rename js/{zlib-1.3.js => zlib-1.3.1.js} (99%) rename js/{zlib-1.3.wasm => zlib-1.3.1.wasm} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d39cd30..d1a6bdc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ## 1.6.3 (not yet released) * ADDED: Detect and report on damaged pastes (#1218) -* CHANGED: Upgrading libraries to: zlib 1.3 +* CHANGED: Increase zlib compression level from 7 to 9 +* CHANGED: Upgrading libraries to: DOMpurify 3.0.8 & zlib 1.3.1 * FIXED: Support more types of valid URLs for shorteners, incl. IDN ones (#1224) ## 1.6.2 (2023-12-15) diff --git a/js/common.js b/js/common.js index d3953d36..4519030f 100644 --- a/js/common.js +++ b/js/common.js @@ -12,12 +12,12 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto; // application libraries to test global.$ = global.jQuery = require('./jquery-3.7.0'); global.RawDeflate = require('./rawinflate-0.3').RawDeflate; -global.zlib = require('./zlib-1.3').zlib; +global.zlib = require('./zlib-1.3.1').zlib; require('./prettify'); global.prettyPrint = window.PR.prettyPrint; global.prettyPrintOne = window.PR.prettyPrintOne; global.showdown = require('./showdown-2.1.0'); -global.DOMPurify = require('./purify-3.0.6'); +global.DOMPurify = require('./purify-3.0.8'); global.baseX = require('./base-x-4.0.0').baseX; global.Legacy = require('./legacy').Legacy; require('./bootstrap-3.4.1'); @@ -151,4 +151,4 @@ exports.urlToString = function (url) { return url.schema + '://' + url.address.join('') + '/' + (url.query ? '?' + encodeURI(url.query.join('').replace(/^&+|&+$/gm,'')) : '') + (url.fragment ? '#' + encodeURI(url.fragment) : ''); -}; \ No newline at end of file +}; diff --git a/js/purify-3.0.6.js b/js/purify-3.0.6.js deleted file mode 100644 index 65b3163d..00000000 --- a/js/purify-3.0.6.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! @license DOMPurify 3.0.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.6/LICENSE */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=N(Array.prototype.forEach),m=N(Array.prototype.pop),f=N(Array.prototype.push),p=N(String.prototype.toLowerCase),d=N(String.prototype.toString),h=N(String.prototype.match),g=N(String.prototype.replace),T=N(String.prototype.indexOf),y=N(String.prototype.trim),E=N(RegExp.prototype.test),A=(_=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:p;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function S(t){const n=l(null);for(const[o,i]of e(t))void 0!==r(t,o)&&(n[o]=i);return n}function R(e,t){for(;null!==e;){const n=r(e,t);if(n){if(n.get)return N(n.get);if("function"==typeof n.value)return N(n.value)}e=o(e)}return function(e){return console.warn("fallback value for",e),null}}const w=i(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),D=i(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),L=i(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),v=i(["animate","color-profile","cursor","discard","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),x=i(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover","mprescripts"]),k=i(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),C=i(["#text"]),O=i(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","face","for","headers","height","hidden","high","href","hreflang","id","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","playsinline","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","xmlns","slot"]),I=i(["accent-height","accumulate","additive","alignment-baseline","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","targetx","targety","transform","transform-origin","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),M=i(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),U=i(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),P=a(/\{\{[\w\W]*|[\w\W]*\}\}/gm),F=a(/<%[\w\W]*|[\w\W]*%>/gm),H=a(/\${[\w\W]*}/gm),z=a(/^data-[\-\w.\u00B7-\uFFFF]/),B=a(/^aria-[\-\w]+$/),W=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),G=a(/^(?:\w+script|data):/i),Y=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),j=a(/^html$/i);var q=Object.freeze({__proto__:null,MUSTACHE_EXPR:P,ERB_EXPR:F,TMPLIT_EXPR:H,DATA_ATTR:z,ARIA_ATTR:B,IS_ALLOWED_URI:W,IS_SCRIPT_OR_DATA:G,ATTR_WHITESPACE:Y,DOCTYPE_NAME:j});const X=function(){return"undefined"==typeof window?null:window},K=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}};var V=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:X();const o=e=>t(e);if(o.version="3.0.6",o.removed=[],!n||!n.document||9!==n.document.nodeType)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:_,Node:N,Element:P,NodeFilter:F,NamedNodeMap:H=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:z,DOMParser:B,trustedTypes:G}=n,Y=P.prototype,V=R(Y,"cloneNode"),$=R(Y,"nextSibling"),Z=R(Y,"childNodes"),J=R(Y,"parentNode");if("function"==typeof _){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let Q,ee="";const{implementation:te,createNodeIterator:ne,createDocumentFragment:oe,getElementsByTagName:re}=r,{importNode:ie}=a;let ae={};o.isSupported="function"==typeof e&&"function"==typeof J&&te&&void 0!==te.createHTMLDocument;const{MUSTACHE_EXPR:le,ERB_EXPR:ce,TMPLIT_EXPR:se,DATA_ATTR:ue,ARIA_ATTR:me,IS_SCRIPT_OR_DATA:fe,ATTR_WHITESPACE:pe}=q;let{IS_ALLOWED_URI:de}=q,he=null;const ge=b({},[...w,...D,...L,...x,...C]);let Te=null;const ye=b({},[...O,...I,...M,...U]);let Ee=Object.seal(l(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ae=null,_e=null,Ne=!0,be=!0,Se=!1,Re=!0,we=!1,De=!1,Le=!1,ve=!1,xe=!1,ke=!1,Ce=!1,Oe=!0,Ie=!1;const Me="user-content-";let Ue=!0,Pe=!1,Fe={},He=null;const ze=b({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Be=null;const We=b({},["audio","video","img","source","image","track"]);let Ge=null;const Ye=b({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),je="http://www.w3.org/1998/Math/MathML",qe="http://www.w3.org/2000/svg",Xe="http://www.w3.org/1999/xhtml";let Ke=Xe,Ve=!1,$e=null;const Ze=b({},[je,qe,Xe],d);let Je=null;const Qe=["application/xhtml+xml","text/html"],et="text/html";let tt=null,nt=null;const ot=r.createElement("form"),rt=function(e){return e instanceof RegExp||e instanceof Function},it=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!nt||nt!==e){if(e&&"object"==typeof e||(e={}),e=S(e),Je=Je=-1===Qe.indexOf(e.PARSER_MEDIA_TYPE)?et:e.PARSER_MEDIA_TYPE,tt="application/xhtml+xml"===Je?d:p,he="ALLOWED_TAGS"in e?b({},e.ALLOWED_TAGS,tt):ge,Te="ALLOWED_ATTR"in e?b({},e.ALLOWED_ATTR,tt):ye,$e="ALLOWED_NAMESPACES"in e?b({},e.ALLOWED_NAMESPACES,d):Ze,Ge="ADD_URI_SAFE_ATTR"in e?b(S(Ye),e.ADD_URI_SAFE_ATTR,tt):Ye,Be="ADD_DATA_URI_TAGS"in e?b(S(We),e.ADD_DATA_URI_TAGS,tt):We,He="FORBID_CONTENTS"in e?b({},e.FORBID_CONTENTS,tt):ze,Ae="FORBID_TAGS"in e?b({},e.FORBID_TAGS,tt):{},_e="FORBID_ATTR"in e?b({},e.FORBID_ATTR,tt):{},Fe="USE_PROFILES"in e&&e.USE_PROFILES,Ne=!1!==e.ALLOW_ARIA_ATTR,be=!1!==e.ALLOW_DATA_ATTR,Se=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Re=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,we=e.SAFE_FOR_TEMPLATES||!1,De=e.WHOLE_DOCUMENT||!1,xe=e.RETURN_DOM||!1,ke=e.RETURN_DOM_FRAGMENT||!1,Ce=e.RETURN_TRUSTED_TYPE||!1,ve=e.FORCE_BODY||!1,Oe=!1!==e.SANITIZE_DOM,Ie=e.SANITIZE_NAMED_PROPS||!1,Ue=!1!==e.KEEP_CONTENT,Pe=e.IN_PLACE||!1,de=e.ALLOWED_URI_REGEXP||W,Ke=e.NAMESPACE||Xe,Ee=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&rt(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Ee.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&rt(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Ee.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Ee.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),we&&(be=!1),ke&&(xe=!0),Fe&&(he=b({},[...C]),Te=[],!0===Fe.html&&(b(he,w),b(Te,O)),!0===Fe.svg&&(b(he,D),b(Te,I),b(Te,U)),!0===Fe.svgFilters&&(b(he,L),b(Te,I),b(Te,U)),!0===Fe.mathMl&&(b(he,x),b(Te,M),b(Te,U))),e.ADD_TAGS&&(he===ge&&(he=S(he)),b(he,e.ADD_TAGS,tt)),e.ADD_ATTR&&(Te===ye&&(Te=S(Te)),b(Te,e.ADD_ATTR,tt)),e.ADD_URI_SAFE_ATTR&&b(Ge,e.ADD_URI_SAFE_ATTR,tt),e.FORBID_CONTENTS&&(He===ze&&(He=S(He)),b(He,e.FORBID_CONTENTS,tt)),Ue&&(he["#text"]=!0),De&&b(he,["html","head","body"]),he.table&&(b(he,["tbody"]),delete Ae.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');Q=e.TRUSTED_TYPES_POLICY,ee=Q.createHTML("")}else void 0===Q&&(Q=K(G,c)),null!==Q&&"string"==typeof ee&&(ee=Q.createHTML(""));i&&i(e),nt=e}},at=b({},["mi","mo","mn","ms","mtext"]),lt=b({},["foreignobject","desc","title","annotation-xml"]),ct=b({},["title","style","font","a","script"]),st=b({},D);b(st,L),b(st,v);const ut=b({},x);b(ut,k);const mt=function(e){let t=J(e);t&&t.tagName||(t={namespaceURI:Ke,tagName:"template"});const n=p(e.tagName),o=p(t.tagName);return!!$e[e.namespaceURI]&&(e.namespaceURI===qe?t.namespaceURI===Xe?"svg"===n:t.namespaceURI===je?"svg"===n&&("annotation-xml"===o||at[o]):Boolean(st[n]):e.namespaceURI===je?t.namespaceURI===Xe?"math"===n:t.namespaceURI===qe?"math"===n&<[o]:Boolean(ut[n]):e.namespaceURI===Xe?!(t.namespaceURI===qe&&!lt[o])&&(!(t.namespaceURI===je&&!at[o])&&(!ut[n]&&(ct[n]||!st[n]))):!("application/xhtml+xml"!==Je||!$e[e.namespaceURI]))},ft=function(e){f(o.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){e.remove()}},pt=function(e,t){try{f(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){f(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Te[e])if(xe||ke)try{ft(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},dt=function(e){let t=null,n=null;if(ve)e=""+e;else{const t=h(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===Je&&Ke===Xe&&(e=''+e+"");const o=Q?Q.createHTML(e):e;if(Ke===Xe)try{t=(new B).parseFromString(o,Je)}catch(e){}if(!t||!t.documentElement){t=te.createDocument(Ke,"template",null);try{t.documentElement.innerHTML=Ve?ee:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),Ke===Xe?re.call(t,De?"html":"body")[0]:De?t.documentElement:i},ht=function(e){return ne.call(e.ownerDocument||e,e,F.SHOW_ELEMENT|F.SHOW_COMMENT|F.SHOW_TEXT,null)},gt=function(e){return e instanceof z&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof H)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Tt=function(e){return"function"==typeof N&&e instanceof N},yt=function(e,t,n){ae[e]&&u(ae[e],(e=>{e.call(o,t,n,nt)}))},Et=function(e){let t=null;if(yt("beforeSanitizeElements",e,null),gt(e))return ft(e),!0;const n=tt(e.nodeName);if(yt("uponSanitizeElement",e,{tagName:n,allowedTags:he}),e.hasChildNodes()&&!Tt(e.firstElementChild)&&E(/<[/\w]/g,e.innerHTML)&&E(/<[/\w]/g,e.textContent))return ft(e),!0;if(!he[n]||Ae[n]){if(!Ae[n]&&_t(n)){if(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,n))return!1;if(Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(n))return!1}if(Ue&&!He[n]){const t=J(e)||e.parentNode,n=Z(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o)t.insertBefore(V(n[o],!0),$(e))}}return ft(e),!0}return e instanceof P&&!mt(e)?(ft(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!E(/<\/no(script|embed|frames)/i,e.innerHTML)?(we&&3===e.nodeType&&(t=e.textContent,u([le,ce,se],(e=>{t=g(t,e," ")})),e.textContent!==t&&(f(o.removed,{element:e.cloneNode()}),e.textContent=t)),yt("afterSanitizeElements",e,null),!1):(ft(e),!0)},At=function(e,t,n){if(Oe&&("id"===t||"name"===t)&&(n in r||n in ot))return!1;if(be&&!_e[t]&&E(ue,t));else if(Ne&&E(me,t));else if(!Te[t]||_e[t]){if(!(_t(e)&&(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,e)||Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(e))&&(Ee.attributeNameCheck instanceof RegExp&&E(Ee.attributeNameCheck,t)||Ee.attributeNameCheck instanceof Function&&Ee.attributeNameCheck(t))||"is"===t&&Ee.allowCustomizedBuiltInElements&&(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,n)||Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(n))))return!1}else if(Ge[t]);else if(E(de,g(n,pe,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==T(n,"data:")||!Be[e]){if(Se&&!E(fe,g(n,pe,"")));else if(n)return!1}else;return!0},_t=function(e){return e.indexOf("-")>0},Nt=function(e){yt("beforeSanitizeAttributes",e,null);const{attributes:t}=e;if(!t)return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Te};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=tt(a);let f="value"===a?c:y(c);if(n.attrName=s,n.attrValue=f,n.keepAttr=!0,n.forceKeepAttr=void 0,yt("uponSanitizeAttribute",e,n),f=n.attrValue,n.forceKeepAttr)continue;if(pt(a,e),!n.keepAttr)continue;if(!Re&&E(/\/>/i,f)){pt(a,e);continue}we&&u([le,ce,se],(e=>{f=g(f,e," ")}));const p=tt(e.nodeName);if(At(p,s,f)){if(!Ie||"id"!==s&&"name"!==s||(pt(a,e),f=Me+f),Q&&"object"==typeof G&&"function"==typeof G.getAttributeType)if(l);else switch(G.getAttributeType(p,s)){case"TrustedHTML":f=Q.createHTML(f);break;case"TrustedScriptURL":f=Q.createScriptURL(f)}try{l?e.setAttributeNS(l,a,f):e.setAttribute(a,f),m(o.removed)}catch(e){}}}yt("afterSanitizeAttributes",e,null)},bt=function e(t){let n=null;const o=ht(t);for(yt("beforeSanitizeShadowDOM",t,null);n=o.nextNode();)yt("uponSanitizeShadowNode",n,null),Et(n)||(n.content instanceof s&&e(n.content),Nt(n));yt("afterSanitizeShadowDOM",t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(Ve=!e,Ve&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Tt(e)){if("function"!=typeof e.toString)throw A("toString is not a function");if("string"!=typeof(e=e.toString()))throw A("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Le||it(t),o.removed=[],"string"==typeof e&&(Pe=!1),Pe){if(e.nodeName){const t=tt(e.nodeName);if(!he[t]||Ae[t])throw A("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof N)n=dt("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),1===r.nodeType&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!xe&&!we&&!De&&-1===e.indexOf("<"))return Q&&Ce?Q.createHTML(e):e;if(n=dt(e),!n)return xe?null:Ce?ee:""}n&&ve&&ft(n.firstChild);const c=ht(Pe?e:n);for(;i=c.nextNode();)Et(i)||(i.content instanceof s&&bt(i.content),Nt(i));if(Pe)return e;if(xe){if(ke)for(l=oe.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Te.shadowroot||Te.shadowrootmode)&&(l=ie.call(a,l,!0)),l}let m=De?n.outerHTML:n.innerHTML;return De&&he["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&E(j,n.ownerDocument.doctype.name)&&(m="\n"+m),we&&u([le,ce,se],(e=>{m=g(m,e," ")})),Q&&Ce?Q.createHTML(m):m},o.setConfig=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};it(e),Le=!0},o.clearConfig=function(){nt=null,Le=!1},o.isValidAttribute=function(e,t,n){nt||it({});const o=tt(e),r=tt(t);return At(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&(ae[e]=ae[e]||[],f(ae[e],t))},o.removeHook=function(e){if(ae[e])return m(ae[e])},o.removeHooks=function(e){ae[e]&&(ae[e]=[])},o.removeAllHooks=function(){ae={}},o}();return V})); diff --git a/js/purify-3.0.8.js b/js/purify-3.0.8.js new file mode 100644 index 00000000..9f090115 --- /dev/null +++ b/js/purify-3.0.8.js @@ -0,0 +1,2 @@ +/*! @license DOMPurify 3.0.8 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.8/LICENSE */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=b(Array.prototype.forEach),m=b(Array.prototype.pop),f=b(Array.prototype.push),p=b(String.prototype.toLowerCase),d=b(String.prototype.toString),h=b(String.prototype.match),g=b(String.prototype.replace),T=b(String.prototype.indexOf),y=b(String.prototype.trim),E=b(RegExp.prototype.test),A=(_=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:p;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function S(e){for(let t=0;t/gm),z=a(/\${[\w\W]*}/gm),B=a(/^data-[\-\w.\u00B7-\uFFFF]/),W=a(/^aria-[\-\w]+$/),G=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Y=a(/^(?:\w+script|data):/i),j=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),q=a(/^html$/i);var X=Object.freeze({__proto__:null,MUSTACHE_EXPR:F,ERB_EXPR:H,TMPLIT_EXPR:z,DATA_ATTR:B,ARIA_ATTR:W,IS_ALLOWED_URI:G,IS_SCRIPT_OR_DATA:Y,ATTR_WHITESPACE:j,DOCTYPE_NAME:q});const K=function(){return"undefined"==typeof window?null:window},V=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}};var $=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:K();const o=e=>t(e);if(o.version="3.0.8",o.removed=[],!n||!n.document||9!==n.document.nodeType)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:_,Node:b,Element:S,NodeFilter:F,NamedNodeMap:H=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:z,DOMParser:B,trustedTypes:W}=n,Y=S.prototype,j=w(Y,"cloneNode"),$=w(Y,"nextSibling"),Z=w(Y,"childNodes"),J=w(Y,"parentNode");if("function"==typeof _){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let Q,ee="";const{implementation:te,createNodeIterator:ne,createDocumentFragment:oe,getElementsByTagName:re}=r,{importNode:ie}=a;let ae={};o.isSupported="function"==typeof e&&"function"==typeof J&&te&&void 0!==te.createHTMLDocument;const{MUSTACHE_EXPR:le,ERB_EXPR:ce,TMPLIT_EXPR:se,DATA_ATTR:ue,ARIA_ATTR:me,IS_SCRIPT_OR_DATA:fe,ATTR_WHITESPACE:pe}=X;let{IS_ALLOWED_URI:de}=X,he=null;const ge=N({},[...D,...L,...v,...k,...O]);let Te=null;const ye=N({},[...I,...M,...U,...P]);let Ee=Object.seal(l(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ae=null,_e=null,be=!0,Ne=!0,Se=!1,Re=!0,we=!1,De=!1,Le=!1,ve=!1,xe=!1,ke=!1,Ce=!1,Oe=!0,Ie=!1;const Me="user-content-";let Ue=!0,Pe=!1,Fe={},He=null;const ze=N({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Be=null;const We=N({},["audio","video","img","source","image","track"]);let Ge=null;const Ye=N({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),je="http://www.w3.org/1998/Math/MathML",qe="http://www.w3.org/2000/svg",Xe="http://www.w3.org/1999/xhtml";let Ke=Xe,Ve=!1,$e=null;const Ze=N({},[je,qe,Xe],d);let Je=null;const Qe=["application/xhtml+xml","text/html"],et="text/html";let tt=null,nt=null;const ot=r.createElement("form"),rt=function(e){return e instanceof RegExp||e instanceof Function},it=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!nt||nt!==e){if(e&&"object"==typeof e||(e={}),e=R(e),Je=-1===Qe.indexOf(e.PARSER_MEDIA_TYPE)?et:e.PARSER_MEDIA_TYPE,tt="application/xhtml+xml"===Je?d:p,he="ALLOWED_TAGS"in e?N({},e.ALLOWED_TAGS,tt):ge,Te="ALLOWED_ATTR"in e?N({},e.ALLOWED_ATTR,tt):ye,$e="ALLOWED_NAMESPACES"in e?N({},e.ALLOWED_NAMESPACES,d):Ze,Ge="ADD_URI_SAFE_ATTR"in e?N(R(Ye),e.ADD_URI_SAFE_ATTR,tt):Ye,Be="ADD_DATA_URI_TAGS"in e?N(R(We),e.ADD_DATA_URI_TAGS,tt):We,He="FORBID_CONTENTS"in e?N({},e.FORBID_CONTENTS,tt):ze,Ae="FORBID_TAGS"in e?N({},e.FORBID_TAGS,tt):{},_e="FORBID_ATTR"in e?N({},e.FORBID_ATTR,tt):{},Fe="USE_PROFILES"in e&&e.USE_PROFILES,be=!1!==e.ALLOW_ARIA_ATTR,Ne=!1!==e.ALLOW_DATA_ATTR,Se=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Re=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,we=e.SAFE_FOR_TEMPLATES||!1,De=e.WHOLE_DOCUMENT||!1,xe=e.RETURN_DOM||!1,ke=e.RETURN_DOM_FRAGMENT||!1,Ce=e.RETURN_TRUSTED_TYPE||!1,ve=e.FORCE_BODY||!1,Oe=!1!==e.SANITIZE_DOM,Ie=e.SANITIZE_NAMED_PROPS||!1,Ue=!1!==e.KEEP_CONTENT,Pe=e.IN_PLACE||!1,de=e.ALLOWED_URI_REGEXP||G,Ke=e.NAMESPACE||Xe,Ee=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&rt(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Ee.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&rt(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Ee.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Ee.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),we&&(Ne=!1),ke&&(xe=!0),Fe&&(he=N({},O),Te=[],!0===Fe.html&&(N(he,D),N(Te,I)),!0===Fe.svg&&(N(he,L),N(Te,M),N(Te,P)),!0===Fe.svgFilters&&(N(he,v),N(Te,M),N(Te,P)),!0===Fe.mathMl&&(N(he,k),N(Te,U),N(Te,P))),e.ADD_TAGS&&(he===ge&&(he=R(he)),N(he,e.ADD_TAGS,tt)),e.ADD_ATTR&&(Te===ye&&(Te=R(Te)),N(Te,e.ADD_ATTR,tt)),e.ADD_URI_SAFE_ATTR&&N(Ge,e.ADD_URI_SAFE_ATTR,tt),e.FORBID_CONTENTS&&(He===ze&&(He=R(He)),N(He,e.FORBID_CONTENTS,tt)),Ue&&(he["#text"]=!0),De&&N(he,["html","head","body"]),he.table&&(N(he,["tbody"]),delete Ae.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');Q=e.TRUSTED_TYPES_POLICY,ee=Q.createHTML("")}else void 0===Q&&(Q=V(W,c)),null!==Q&&"string"==typeof ee&&(ee=Q.createHTML(""));i&&i(e),nt=e}},at=N({},["mi","mo","mn","ms","mtext"]),lt=N({},["foreignobject","desc","title","annotation-xml"]),ct=N({},["title","style","font","a","script"]),st=N({},[...L,...v,...x]),ut=N({},[...k,...C]),mt=function(e){let t=J(e);t&&t.tagName||(t={namespaceURI:Ke,tagName:"template"});const n=p(e.tagName),o=p(t.tagName);return!!$e[e.namespaceURI]&&(e.namespaceURI===qe?t.namespaceURI===Xe?"svg"===n:t.namespaceURI===je?"svg"===n&&("annotation-xml"===o||at[o]):Boolean(st[n]):e.namespaceURI===je?t.namespaceURI===Xe?"math"===n:t.namespaceURI===qe?"math"===n&<[o]:Boolean(ut[n]):e.namespaceURI===Xe?!(t.namespaceURI===qe&&!lt[o])&&(!(t.namespaceURI===je&&!at[o])&&(!ut[n]&&(ct[n]||!st[n]))):!("application/xhtml+xml"!==Je||!$e[e.namespaceURI]))},ft=function(e){f(o.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){e.remove()}},pt=function(e,t){try{f(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){f(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Te[e])if(xe||ke)try{ft(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},dt=function(e){let t=null,n=null;if(ve)e=""+e;else{const t=h(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===Je&&Ke===Xe&&(e=''+e+"");const o=Q?Q.createHTML(e):e;if(Ke===Xe)try{t=(new B).parseFromString(o,Je)}catch(e){}if(!t||!t.documentElement){t=te.createDocument(Ke,"template",null);try{t.documentElement.innerHTML=Ve?ee:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),Ke===Xe?re.call(t,De?"html":"body")[0]:De?t.documentElement:i},ht=function(e){return ne.call(e.ownerDocument||e,e,F.SHOW_ELEMENT|F.SHOW_COMMENT|F.SHOW_TEXT,null)},gt=function(e){return e instanceof z&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof H)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Tt=function(e){return"function"==typeof b&&e instanceof b},yt=function(e,t,n){ae[e]&&u(ae[e],(e=>{e.call(o,t,n,nt)}))},Et=function(e){let t=null;if(yt("beforeSanitizeElements",e,null),gt(e))return ft(e),!0;const n=tt(e.nodeName);if(yt("uponSanitizeElement",e,{tagName:n,allowedTags:he}),e.hasChildNodes()&&!Tt(e.firstElementChild)&&E(/<[/\w]/g,e.innerHTML)&&E(/<[/\w]/g,e.textContent))return ft(e),!0;if(!he[n]||Ae[n]){if(!Ae[n]&&_t(n)){if(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,n))return!1;if(Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(n))return!1}if(Ue&&!He[n]){const t=J(e)||e.parentNode,n=Z(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o)t.insertBefore(j(n[o],!0),$(e))}}return ft(e),!0}return e instanceof S&&!mt(e)?(ft(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!E(/<\/no(script|embed|frames)/i,e.innerHTML)?(we&&3===e.nodeType&&(t=e.textContent,u([le,ce,se],(e=>{t=g(t,e," ")})),e.textContent!==t&&(f(o.removed,{element:e.cloneNode()}),e.textContent=t)),yt("afterSanitizeElements",e,null),!1):(ft(e),!0)},At=function(e,t,n){if(Oe&&("id"===t||"name"===t)&&(n in r||n in ot))return!1;if(Ne&&!_e[t]&&E(ue,t));else if(be&&E(me,t));else if(!Te[t]||_e[t]){if(!(_t(e)&&(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,e)||Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(e))&&(Ee.attributeNameCheck instanceof RegExp&&E(Ee.attributeNameCheck,t)||Ee.attributeNameCheck instanceof Function&&Ee.attributeNameCheck(t))||"is"===t&&Ee.allowCustomizedBuiltInElements&&(Ee.tagNameCheck instanceof RegExp&&E(Ee.tagNameCheck,n)||Ee.tagNameCheck instanceof Function&&Ee.tagNameCheck(n))))return!1}else if(Ge[t]);else if(E(de,g(n,pe,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==T(n,"data:")||!Be[e]){if(Se&&!E(fe,g(n,pe,"")));else if(n)return!1}else;return!0},_t=function(e){return e.indexOf("-")>0},bt=function(e){yt("beforeSanitizeAttributes",e,null);const{attributes:t}=e;if(!t)return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Te};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=tt(a);let f="value"===a?c:y(c);if(n.attrName=s,n.attrValue=f,n.keepAttr=!0,n.forceKeepAttr=void 0,yt("uponSanitizeAttribute",e,n),f=n.attrValue,n.forceKeepAttr)continue;if(pt(a,e),!n.keepAttr)continue;if(!Re&&E(/\/>/i,f)){pt(a,e);continue}we&&u([le,ce,se],(e=>{f=g(f,e," ")}));const p=tt(e.nodeName);if(At(p,s,f)){if(!Ie||"id"!==s&&"name"!==s||(pt(a,e),f=Me+f),Q&&"object"==typeof W&&"function"==typeof W.getAttributeType)if(l);else switch(W.getAttributeType(p,s)){case"TrustedHTML":f=Q.createHTML(f);break;case"TrustedScriptURL":f=Q.createScriptURL(f)}try{l?e.setAttributeNS(l,a,f):e.setAttribute(a,f),m(o.removed)}catch(e){}}}yt("afterSanitizeAttributes",e,null)},Nt=function e(t){let n=null;const o=ht(t);for(yt("beforeSanitizeShadowDOM",t,null);n=o.nextNode();)yt("uponSanitizeShadowNode",n,null),Et(n)||(n.content instanceof s&&e(n.content),bt(n));yt("afterSanitizeShadowDOM",t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(Ve=!e,Ve&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Tt(e)){if("function"!=typeof e.toString)throw A("toString is not a function");if("string"!=typeof(e=e.toString()))throw A("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Le||it(t),o.removed=[],"string"==typeof e&&(Pe=!1),Pe){if(e.nodeName){const t=tt(e.nodeName);if(!he[t]||Ae[t])throw A("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof b)n=dt("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),1===r.nodeType&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!xe&&!we&&!De&&-1===e.indexOf("<"))return Q&&Ce?Q.createHTML(e):e;if(n=dt(e),!n)return xe?null:Ce?ee:""}n&&ve&&ft(n.firstChild);const c=ht(Pe?e:n);for(;i=c.nextNode();)Et(i)||(i.content instanceof s&&Nt(i.content),bt(i));if(Pe)return e;if(xe){if(ke)for(l=oe.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Te.shadowroot||Te.shadowrootmode)&&(l=ie.call(a,l,!0)),l}let m=De?n.outerHTML:n.innerHTML;return De&&he["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&E(q,n.ownerDocument.doctype.name)&&(m="\n"+m),we&&u([le,ce,se],(e=>{m=g(m,e," ")})),Q&&Ce?Q.createHTML(m):m},o.setConfig=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};it(e),Le=!0},o.clearConfig=function(){nt=null,Le=!1},o.isValidAttribute=function(e,t,n){nt||it({});const o=tt(e),r=tt(t);return At(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&(ae[e]=ae[e]||[],f(ae[e],t))},o.removeHook=function(e){if(ae[e])return m(ae[e])},o.removeHooks=function(e){ae[e]&&(ae[e]=[])},o.removeAllHooks=function(){ae={}},o}();return $})); diff --git a/js/zlib-1.3.js b/js/zlib-1.3.1.js similarity index 99% rename from js/zlib-1.3.js rename to js/zlib-1.3.1.js index 268d0841..fbfb7154 100644 --- a/js/zlib-1.3.js +++ b/js/zlib-1.3.1.js @@ -6,7 +6,7 @@ async function initialize() { if (ret) return ret; - const COMPRESSION_LEVEL = 7; + const COMPRESSION_LEVEL = 9; const NO_ZLIB_HEADER = -1; const CHUNK_SIZE = 32 * 1024; const map = {}; diff --git a/js/zlib-1.3.wasm b/js/zlib-1.3.1.wasm similarity index 99% rename from js/zlib-1.3.wasm rename to js/zlib-1.3.1.wasm index c954fbd400e2f4cecc5d8c4188a451b1a93c6ca2..2fbc9169aa9773114c878399fddd11eb94890301 100644 GIT binary patch delta 42 ycmX?kn)&o;<_+I=ieI?i(7<5M;K;(wv>}wiQGlD(P|sM;a5ML=-P+8j8GHe6cn+rk delta 40 ycmV+@0N4M^%LB>F1F-hF70%ayfB-iDK?Dl|uvGv-5DNn_E;F+Yy1Od_#sJGz=MKF9 diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 0cf27f5f..cea3da44 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -55,7 +55,7 @@ if ($ZEROBINCOMPATIBILITY) : - + @@ -71,7 +71,7 @@ if ($MARKDOWN) : - + diff --git a/tpl/page.php b/tpl/page.php index 7e62f37e..011415be 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY): - + - + From d0e03e5167f5714da720a088915df75509356f42 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 27 Jan 2024 18:26:19 +0100 Subject: [PATCH 045/783] change logic into asking for loading confirmation also: - fixes #1039 - email buttons overlapping in some languages - fixes #1191 - language change URL mangling - adds focus to password input in modal - prevents needless reload on visiting default URL --- i18n/ar.json | 4 +- i18n/bg.json | 4 +- i18n/ca.json | 4 +- i18n/co.json | 4 +- i18n/cs.json | 4 +- i18n/de.json | 4 +- i18n/el.json | 4 +- i18n/en.json | 4 +- i18n/es.json | 4 +- i18n/et.json | 4 +- i18n/fi.json | 4 +- i18n/fr.json | 4 +- i18n/he.json | 4 +- i18n/hi.json | 4 +- i18n/hu.json | 4 +- i18n/id.json | 4 +- i18n/it.json | 4 +- i18n/ja.json | 4 +- i18n/jbo.json | 4 +- i18n/ku.json | 4 +- i18n/la.json | 4 +- i18n/lt.json | 4 +- i18n/nl.json | 4 +- i18n/no.json | 4 +- i18n/oc.json | 4 +- i18n/pl.json | 4 +- i18n/pt.json | 4 +- i18n/ru.json | 4 +- i18n/sk.json | 4 +- i18n/sl.json | 4 +- i18n/sv.json | 4 +- i18n/th.json | 4 +- i18n/tr.json | 4 +- i18n/uk.json | 4 +- i18n/zh.json | 4 +- js/privatebin.js | 152 +++++++++++++++++++--------------------------- tpl/bootstrap.php | 52 +++++++++------- tpl/page.php | 2 +- 38 files changed, 196 insertions(+), 150 deletions(-) diff --git a/i18n/ar.json b/i18n/ar.json index 06d50166..3752a362 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "عنوان IP الخاص بك غير مصرح له بإنشاء لصُق.", "Trying to shorten a URL that isn't pointing at our instance.": "محاولة تقصير عنوان URL لا يشير إلى خادمنا.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/bg.json b/i18n/bg.json index 9327467a..e7cb35a3 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/ca.json b/i18n/ca.json index b9c5efbd..7ed9846b 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/co.json b/i18n/co.json index 0be1ff54..b848f0ef 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "U vostru indirizzu IP ùn hè micca auturizatu à creà l’appiccichi.", "Trying to shorten a URL that isn't pointing at our instance.": "Pruvate d’ammuzzà un indirizzu web chì ùn punta micca versu a vostra instanza.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/cs.json b/i18n/cs.json index c049c733..49afae50 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Vaše IP adresa nemá oprávnění k vytvoření vložení.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/de.json b/i18n/de.json index fce60cc3..8e81f73c 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Deine IP ist nicht berechtigt, Texte zu erstellen.", "Trying to shorten a URL that isn't pointing at our instance.": "Versuch eine URL zu verkürzen, die nicht auf unsere Instanz zeigt.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/el.json b/i18n/el.json index 388edec6..94e13fb9 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/en.json b/i18n/en.json index 68ff1aae..6ef3280b 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/es.json b/i18n/es.json index 97fab2fb..e5e4c9b5 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Tu IP no está autorizada para crear contenido.", "Trying to shorten a URL that isn't pointing at our instance.": "Intentando acortar una URL que no apunta a nuestra instancia.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/et.json b/i18n/et.json index 3cc47d55..e123e7f9 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/fi.json b/i18n/fi.json index 063df4a3..da935c52 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "IP:llesi ei ole annettu oikeutta luoda pasteja.", "Trying to shorten a URL that isn't pointing at our instance.": "Yritetään lyhentää URL-osoite, joka ei osoita meidän instanssiiin.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/fr.json b/i18n/fr.json index ad9012db..d90f8578 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Votre adresse IP n'est pas autorisée à créer des pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/he.json b/i18n/he.json index 93509e63..658e586b 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/hi.json b/i18n/hi.json index 68ff1aae..6ef3280b 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/hu.json b/i18n/hu.json index 9384be7e..d9161090 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/id.json b/i18n/id.json index 85439d03..a0e844e8 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/it.json b/i18n/it.json index f12ed03b..c23b1655 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Il tuo IP non è autorizzato a creare dei messaggi.", "Trying to shorten a URL that isn't pointing at our instance.": "Tantativo in corso di accorciare un URL che non punta alla nostra istanza.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/ja.json b/i18n/ja.json index f06f37be..07323772 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "あなたのIPアドレスにはペーストを作成する権限がありません。", "Trying to shorten a URL that isn't pointing at our instance.": "このインスタンスを指していないURLを短縮しようとしています。", "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レスポンスの解析中にエラーが発生しました。", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/jbo.json b/i18n/jbo.json index a8105510..f729f613 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/ku.json b/i18n/ku.json index 68ff1aae..6ef3280b 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/la.json b/i18n/la.json index 8ee0d6db..895f0b02 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/lt.json b/i18n/lt.json index 25364269..81dfe123 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Jūsų IP adresas neturi įgaliojimų kurti įdėjimų.", "Trying to shorten a URL that isn't pointing at our instance.": "Bandoma sutrumpinti URL adresą, kuris nenurodo į mūsų egzempliorių.", "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ą.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/nl.json b/i18n/nl.json index d7a26664..fc058a20 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Je IP-adres is niet gemachtigd om pastes te maken.", "Trying to shorten a URL that isn't pointing at our instance.": "Proberen om een URL te verkorten dat niet naar ons systeem wijst.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/no.json b/i18n/no.json index fbbd5dc5..00417f24 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/oc.json b/i18n/oc.json index 4c5c40f2..7553fb0e 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Vòstra adreça IP a pas l’autorizacion de crear de tèxtes.", "Trying to shorten a URL that isn't pointing at our instance.": "Ensag d’abracar una URL que mena pas a nòstra instància.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/pl.json b/i18n/pl.json index 6bd76b99..ec1930dd 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/pt.json b/i18n/pt.json index 4adb56c4..3b7866db 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Seu IP não está autorizado a criar cópias.", "Trying to shorten a URL that isn't pointing at our instance.": "Tentando encurtar uma URL que não aponta para a nossa instância.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/ru.json b/i18n/ru.json index 54f8239f..00084dc8 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Вашему IP адресу не разрешено создавать записи.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/sk.json b/i18n/sk.json index bab0ab36..c73fe638 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať príspevky.", "Trying to shorten a URL that isn't pointing at our instance.": "Pokúšate sa skrátiť adresu URL, ktorá neukazuje na túto inštanciu.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/sl.json b/i18n/sl.json index 1a93bed5..f3baab91 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/sv.json b/i18n/sv.json index 68ff1aae..6ef3280b 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/th.json b/i18n/th.json index 48237005..4325ab1d 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "IP ของคุณไม่ได้รับอนุญาตให้สร้างการฝากโค้ด", "Trying to shorten a URL that isn't pointing at our instance.": "กำลังพยายามใช้เครื่องมือสร้างลิงก์ย่อ ที่ไม่ได้ชี้ไปที่อินสแตนซ์ของเรา", "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", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/tr.json b/i18n/tr.json index 4dc8c4a4..5164aee6 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "IP adresinizin yazı oluşturmaya yetkisi yoktur.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/uk.json b/i18n/uk.json index ad80289f..0d514b5a 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "Вашому IP не дозволено створювати вставки.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "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.", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/i18n/zh.json b/i18n/zh.json index 61b32cbd..421622f5 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -214,5 +214,7 @@ "Your IP is not authorized to create pastes.": "您的 IP 无权创建粘贴。", "Trying to shorten a URL that isn't pointing at our instance.": "尝试缩短一个不指向我们实例的URL。", "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 响应时出错。", + "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?", + "Yes, load it": "Yes, load it" } diff --git a/js/privatebin.js b/js/privatebin.js index 23a4fe20..83865562 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -77,6 +77,13 @@ jQuery.PrivateBin = (function($, RawDeflate) { } }; + /** + * URL fragment prefix requiring load confirmation + * + * @private + */ + const loadConfirmPrefix = '#?'; + /** * CryptoData class * @@ -1512,15 +1519,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.getPasteKey = function() { if (symmetricKey === null) { - let pos = 1; - const pt = '#protected/'; - if(window.location.hash.startsWith(pt)) { - pos = pt.length; - } - let newKey = window.location.hash.substring(pos); - if (newKey === '') { - throw 'no encryption key given'; + let startPos = 1; + if(window.location.hash.startsWith(loadConfirmPrefix)) { + startPos = loadConfirmPrefix.length; } + let newKey = window.location.hash.substring(startPos); // Some web 2.0 services and redirectors add data AFTER the anchor // (such as &utm_source=...). We will strip any additional data. @@ -1529,6 +1532,9 @@ jQuery.PrivateBin = (function($, RawDeflate) { { newKey = newKey.substring(0, ampersandPos); } + if (newKey === '') { + throw 'no encryption key given'; + } // version 2 uses base58, version 1 uses base64 without decoding try { @@ -2242,7 +2248,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @function * @param {Event} event */ - async function submitPasswordModal(event) + function submitPasswordModal(event) { event.preventDefault(); @@ -2252,37 +2258,37 @@ jQuery.PrivateBin = (function($, RawDeflate) { // hide modal $passwordModal.modal('hide'); - // check if protected pathname - const url = new URL(window.location); - - // if protected request password - if(url.hash.startsWith('#protected/')) { - const pt = '#protected/'; - let pos = pt.length; - let newKey = window.location.hash.substring(pos); - if (newKey === '') { - throw 'no encryption key given'; - } - - // Some web 2.0 services and redirectors add data AFTER the anchor - // (such as &utm_source=...). We will strip any additional data. - let ampersandPos = newKey.indexOf('&'); - if (ampersandPos > -1) - { - newKey = newKey.substring(0, ampersandPos); - } - const enc = CryptTool.base58decode(newKey).padStart(32, '\u0000'); - const dt = JSON.parse(enc); - const cipherdata = [dt.ct, dt.adata] - - const plaindata = await CryptTool.decipher(dt.k, password, cipherdata); - window.location.replace(Helper.baseUri() + plaindata); - return; - } - PasteDecrypter.run(); } + /** + * Request users confirmation to load possibly burn after reading paste + * + * @name Prompt.requestLoadConfirmation + * @function + */ + me.requestLoadConfirmation = function() + { + const $loadconfirmmodal = $('#loadconfirmmodal'); + if ($loadconfirmmodal.length > 0) { + const $loadconfirmOpenNow = $loadconfirmmodal.find('#loadconfirm-open-now'); + $loadconfirmOpenNow.off('click.loadPaste'); + $loadconfirmOpenNow.on('click.loadPaste', PasteDecrypter.run); + const $loadconfirmClose = $loadconfirmmodal.find('.close'); + $loadconfirmClose.off('click.close'); + $loadconfirmClose.on('click.close', Controller.newPaste); + $loadconfirmmodal.modal('show'); + } else { + if (window.confirm( + I18n._('Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?') + )) { + PasteDecrypter.run(); + } else { + Controller.newPaste(); + } + } + } + /** * ask the user for the password and set it * @@ -2297,6 +2303,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { backdrop: 'static', keyboard: false }); + $passwordDecrypt.focus(); return; } @@ -3844,6 +3851,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { { document.cookie = 'lang=' + $(event.target).data('lang') + ';secure'; UiHelper.reloadHome(); + event.preventDefault(); } /** @@ -3999,10 +4007,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { const $emailconfirmmodal = $('#emailconfirmmodal'); if ($emailconfirmmodal.length > 0) { if (expirationDate !== null) { - I18n._( - $emailconfirmmodal.find('#emailconfirm-display'), - 'Recipient may become aware of your timezone, convert time to UTC?' - ); const $emailconfirmTimezoneCurrent = $emailconfirmmodal.find('#emailconfirm-timezone-current'); const $emailconfirmTimezoneUtc = $emailconfirmmodal.find('#emailconfirm-timezone-utc'); $emailconfirmTimezoneCurrent.off('click.sendEmailCurrentTimezone'); @@ -4851,44 +4855,16 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @param {int} status * @param {object} data */ - async function showCreatedPaste(status, data) { + function showCreatedPaste(status, data) { Alert.hideLoading(); Alert.hideMessages(); // show notification - const baseUri = Helper.baseUri(), - deleteUrl = baseUri + '?pasteid=' + data.id + '&deletetoken=' + data.deletetoken; - let url; - - const pw = TopNav.getPassword() - - // only execute when it is a single time view - if(pw && pw.length && TopNav.getBurnAfterReading()) { - - const sm = CryptTool.getSymmetricKey(); - - let openUri = '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); - let cipherResult = await CryptTool.cipher(sm, pw, openUri, []); - - let dt = {} - dt['v'] = 2; - dt['ct'] = cipherResult[0]; - dt['adata'] = cipherResult[1]; - dt['k'] = sm; - - const encUrl = CryptTool.base58encode(JSON.stringify(dt)) - - url = baseUri + '#protected/' + encUrl; - } else { - url = baseUri + '?' + data.id + '#' + CryptTool.base58encode(data.encryptionKey); - } - + const baseUri = Helper.baseUri() + '?', + url = baseUri + data.id + (TopNav.getBurnAfterReading() ? loadConfirmPrefix : '#') + CryptTool.base58encode(data.encryptionKey), + deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; PasteStatus.createPasteNotification(url, deleteUrl); - - - - // show new URL in browser bar history.pushState({type: 'newpaste'}, document.title, url); @@ -5033,12 +5009,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // prepare server interaction ServerInteraction.prepare(); - if(!TopNav.getBurnAfterReading()) { - ServerInteraction.setCryptParameters(TopNav.getPassword()); - } else { - // not needed in this scenario - ServerInteraction.setCryptParameters(''); - } + ServerInteraction.setCryptParameters(TopNav.getPassword()); // set success/fail functions ServerInteraction.setSuccess(showCreatedPaste); @@ -5309,7 +5280,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { Alert.hideMessages(); Alert.showLoading('Decrypting paste…', 'cloud-download'); - if (typeof paste === 'undefined') { + if (typeof paste === 'undefined' || paste.type === 'click') { // get cipher data and wait until it is available Model.getPasteData(me.run); return; @@ -5416,7 +5387,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { AttachmentViewer.removeAttachmentData(); Alert.hideLoading(); - history.pushState({type: 'create'}, document.title, Helper.baseUri()); + // only push new state if we are coming from a different one + if (Helper.baseUri() != window.location) { + history.pushState({type: 'create'}, document.title, Helper.baseUri()); + } // clear discussion DiscussionViewer.prepareNewDiscussion(); @@ -5442,6 +5416,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { } } + // check if we should request loading confirmation + if(window.location.hash.startsWith(loadConfirmPrefix)) { + Prompt.requestLoadConfirmation(); + return; + } + // show proper elements on screen PasteDecrypter.run(); }; @@ -5624,16 +5604,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { try { Model.getPasteId(); } catch (e) { - - // check if protected pathname - const url = new URL(window.location); - - // if protected request password - if(url.hash.startsWith('#protected/')) { - return Prompt.requestPassword(); - - } - // otherwise create a new paste return me.newPaste(); } diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index d1a54fcb..70b1b0cf 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + @@ -123,22 +123,32 @@ if (count($class)) {
+ - -
+

-

From 471f6ba355feae4d4a151d423566a9ed9cbe6d55 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:27:21 +0200 Subject: [PATCH 419/783] New translations en.json (Ukrainian) --- i18n/uk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/uk.json b/i18n/uk.json index cfb8c44e..8ddfb55c 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -219,5 +219,5 @@ "Yes, see it": "Так, побачити", "Dark Mode": "Темний режим", "Error compressing paste, due to missing WebAssembly support.": "Помилка при стисканні допису, через відсутність підтримки WebAssembly сервера.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте інший браузер для перегляду цього допису." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте в іншому браузері для перегляду цього допису." } From 50ac504fed8b419b8f4f609cb1fb3b95a602ba3f Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:54:37 +0200 Subject: [PATCH 420/783] New translations en.json (Greek) --- i18n/el.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/el.json b/i18n/el.json index f1278fd5..0f4be548 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -212,7 +212,7 @@ "URL shortener may expose your decrypt key in URL.": "Συντομευτές συνδέσμων πιθανώς να δημοσιοποιήσουν το κλειδί αποκρυπτογράφισης στον σύνδεσμο.", "Save paste": "Αποθήκευση επικόλλησης", "Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις.", - "Trying to shorten a URL that isn't pointing at our instance.": "Προσπαθώντας να συντομεύσει μια διεύθυνση URL που δεν δείχνει στην περίπτωσή μας.", + "Trying to shorten a URL that isn't pointing at our instance.": "Έγινε προσπάθεια συντόμευσης ενός URL που δε δείχνει προς τη δική μας υπηρεσία.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Σφάλμα κατά την κλήση YOURLS. Πιθανώς ένα ζήτημα διαμόρφωσης, όπως λάθος ή λείπει \"apiurl\" ή \"υπογραφή\".", "Error parsing YOURLS response.": "Σφάλμα ανάλυσης της απόκρισης YOURLS.", "This secret message can only be displayed once. Would you like to see it now?": "Αυτό το μυστικό μήνυμα μπορεί να εμφανιστεί μόνο μία φορά. Θα θέλατε να το δείτε τώρα;", From d9fa9786c9007a137fcea8da8395fd93bd559ee9 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 1 Oct 2024 21:54:54 +0200 Subject: [PATCH 421/783] New translations en.json (Ukrainian) --- i18n/uk.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/i18n/uk.json b/i18n/uk.json index 8ddfb55c..8b1d03a7 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -16,15 +16,15 @@ ], "Paste is limited to %s of encrypted data.": "Розмір допису обмежений %s зашифрованих даних.", "Invalid data.": "Неправильні дані.", - "You are unlucky. Try again.": "Вам не пощастило. Спробуйте ще раз.", + "You are unlucky. Try again.": "Якась халепа! Спробуйте ще раз.", "Error saving comment. Sorry.": "Помилка при збереженні коментаря. Вибачте.", "Error saving paste. Sorry.": "Помилка при збереженні допису. Вибачте.", "Invalid paste ID.": "Неправильний ID допису.", "Paste is not of burn-after-reading type.": "Тип допису не \"Знищити після прочитання\".", - "Wrong deletion token. Paste was not deleted.": "Неправильний ключ вилучення допису. Допис не вилучено.", + "Wrong deletion token. Paste was not deleted.": "Неправильний жетон вилучення допису. Допис не вилучено.", "Paste was properly deleted.": "Допис був вилучений повністю.", "JavaScript is required for %s to work. Sorry for the inconvenience.": "Для роботи %s потрібен увімкнутий JavaScript. Вибачте.", - "%s requires a modern browser to work.": "Для роботи %s потрібен більш сучасний переглядач.", + "%s requires a modern browser to work.": "Для роботи %s потрібен більш сучасний браузер.", "New": "Новий допис", "Create": "Створити", "Clone": "Дублювати", @@ -36,8 +36,8 @@ "Discussion": "Обговорення", "Toggle navigation": "Перемкнути навігацію", "%d seconds": [ - "%d секунду", - "%d секунди", + "%d секунд", + "%d секунд", "%d секунд", "%d секунд", "%d секунд", From d8a986dbdabaa2a2b3862de32735b42859fd972d Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 1 Oct 2024 21:54:55 +0200 Subject: [PATCH 422/783] New translations en.json (Greek) --- i18n/el.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/el.json b/i18n/el.json index 0f4be548..746b4dc5 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -1,6 +1,6 @@ { "PrivateBin": "PrivateBin", - "%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 είναι ένα λιτό, ανοικτού λογισμικού διαδικτυακής υπηρεσίας επικόλλησης όπου ο διακομιστής έχει πλήρη άγνια του περιεχομένου που επικολλήθηκαν. Τα Δεδομένα κρυπτογραφούνται και αποκρυπτογραφούνται %sστον φιλομετρητή (browser)%s χρησιμοποιόντας 256 bits AES.", + "%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 αποτελεί ένα εργαλείο επικόλλησης δεδομένων στο διαδίκτυο, που βασίζεται σε λογισμικό ανοιχτού κώδικα. Ο διακομιστής έχει πλήρη άγνοια αυτών των δεδομένων, τα οποία από/κρυπτογραφούνται %sστο πρόγραμμα περιήγησης%s, χρησιμοποιώντας τη μέθοδο 256-bits AES.", "More information on the project page.": "Περισσότερες πληροφορίες στον ιστότοπο του εργαλείου.", "Because ignorance is bliss": "Επειδή η άγνοια είναι ευτυχία", "Paste does not exist, has expired or has been deleted.": "Η επικόλληση δεν υπάρχει, έληξε ή διαγράφηκε", From a58b7b80f8dca32090aa3a3be1d446ac0b36d866 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Wed, 2 Oct 2024 06:03:27 +0200 Subject: [PATCH 423/783] New translations en.json (Ukrainian) --- i18n/uk.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/uk.json b/i18n/uk.json index 8b1d03a7..1b46edc5 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -1,6 +1,6 @@ { "PrivateBin": "PrivateBin", - "%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 це мінімалістичний Open Source проєкт для створення нотаток, де сервер не знає нічого про дані, що зберігаються. Дані шифруються/розшифровуються %sу переглядачі%s з використанням 256-бітного шифрувания AES.", + "%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 це мінімалістичний Open Source проєкт для створення нотаток, де сервер не знає нічого про дані, що зберігаються. Дані шифруються/розшифровуються %sу браузері%s з використанням 256-бітного шифрування AES.", "More information on the project page.": "Подробиці можна дізнатися на сайті проєкту.", "Because ignorance is bliss": "Бо незнання - благо", "Paste does not exist, has expired or has been deleted.": "Допис не існує, протермінований чи був видалений.", @@ -134,7 +134,7 @@ "Документ буде вилучений через %d місяців." ], "Please enter the password for this paste:": "Будь ласка, введіть пароль від допису:", - "Could not decrypt data (Wrong key?)": "Неможливо розшифрувати дані (Неправильний ключ?)", + "Could not decrypt data (Wrong key?)": "Неможливо розшифрувати дані (можливо, невірний ключ?)", "Could not delete the paste, it was not stored in burn after reading mode.": "Неможливо вилучити допис, він не був збережений в режимі знищити після прочитання.", "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ЛИШЕ ДЛЯ ВАШИХ ОЧЕЙ. Не закривайте це вікно, це повідомлення не може бути показано знову.", "Could not decrypt comment; Wrong key?": "Неможливо розшифрувати коментар; Неправильний ключ?", @@ -166,7 +166,7 @@ "YiB": "Йбайт", "Format": "Формат", "Plain Text": "Звичайний текст", - "Source Code": "Джерельний код", + "Source Code": "Вихідний код", "Markdown": "Мова розмітки", "Download attachment": "Звантажити прикріплений файл", "Cloned: '%s'": "Дубльовано: '%s'", From 4cc2a20d660527d1798119432b0cffd7e1fe51d2 Mon Sep 17 00:00:00 2001 From: Mormegil Date: Thu, 3 Oct 2024 16:26:47 +0200 Subject: [PATCH 424/783] Fix/improve/complete Czech translation --- i18n/cs.json | 240 +++++++++++++++++++++++++-------------------------- 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/i18n/cs.json b/i18n/cs.json index 5e4b88b2..052d9cbc 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -1,34 +1,34 @@ { "PrivateBin": "PrivateBin", - "%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 je minimalistický open source 'pastebin' server, který neanalyzuje vložená data. Data jsou šifrována %sv prohlížeči%s pomocí 256 bitů AES.", - "More information on the project page.": "Více informací na stránce projetu.", + "%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 je minimalistický open source 'pastebin' server, který nemá přístup ke vloženým datům. Data jsou šifrována %sv prohlížeči%s pomocí 256bitového AES.", + "More information on the project page.": "Více informací na stránce projektu.", "Because ignorance is bliss": "Protože nevědomost je sladká", "Paste does not exist, has expired or has been deleted.": "Vložený text neexistuje, expiroval nebo byl odstraněn.", "%s requires php %s or above to work. Sorry.": "%s vyžaduje php %s nebo vyšší. Lituji.", - "%s requires configuration section [%s] to be present in configuration file.": "%s vyžaduje, aby byla v konfiguračním souboru přítomna sekce [%s].", + "%s requires configuration section [%s] to be present in configuration file.": "%s vyžaduje, aby byla v konfiguračním souboru přítomna sekce [%s].", "Please wait %d seconds between each post.": [ - "Počet sekund do dalšího příspěvku: %d.", - "Počet sekund do dalšího příspěvku: %d.", - "Počet sekund do dalšího příspěvku: %d.", - "Počet sekund do dalšího příspěvku: %d.", - "Počet sekund do dalšího příspěvku: %d.", - "Počet sekund do dalšího příspěvku: %d." + "Vyčkejte prosím %d sekundu mezi následujícími příspěvky.", + "Vyčkejte prosím %d sekundy mezi následujícími příspěvky.", + "Vyčkejte prosím %d sekund mezi následujícími příspěvky.", + "Vyčkejte prosím %d sekund mezi následujícími příspěvky.", + "Vyčkejte prosím %d sekund mezi následujícími příspěvky.", + "Vyčkejte prosím %d sekund mezi následujícími příspěvky." ], "Paste is limited to %s of encrypted data.": "Příspěvek je limitován na %s šífrovaných dat", "Invalid data.": "Chybná data.", "You are unlucky. Try again.": "Lituji, zkuste to znovu.", - "Error saving comment. Sorry.": "Chyba při ukládání komentáře.", - "Error saving paste. Sorry.": "Chyba při ukládání příspěvku.", - "Invalid paste ID.": "Chybně vložené ID.", - "Paste is not of burn-after-reading type.": "Příspěvek není nastaven na smazaní po přečtení.", + "Error saving comment. Sorry.": "Chyba při ukládání komentáře. Promiňte.", + "Error saving paste. Sorry.": "Chyba při ukládání příspěvku. Promiňte.", + "Invalid paste ID.": "Chybné ID příspěvku.", + "Paste is not of burn-after-reading type.": "Příspěvek není nastaven na smazání po přečtení.", "Wrong deletion token. Paste was not deleted.": "Chybný token pro odstranění. Příspěvek nebyl smazán.", "Paste was properly deleted.": "Příspěvek byl řádně smazán.", "JavaScript is required for %s to work. Sorry for the inconvenience.": "Pro fungování %s je vyžadován JavaScript. Omlouváme se za nepříjemnosti.", - "%s requires a modern browser to work.": "%%s requires a modern browser to work.", + "%s requires a modern browser to work.": "Pro fungování %s je vyžadován moderní prohlížeč.", "New": "Nový", "Create": "Vytvořit", "Clone": "Klonovat", - "Raw text": "Pouze Text", + "Raw text": "Čistý text", "Expires": "Expirace", "Burn after reading": "Po přečtení smazat", "Open discussion": "Povolit komentáře", @@ -36,113 +36,113 @@ "Discussion": "Komentáře", "Toggle navigation": "Přepnout navigaci", "%d seconds": [ - "%d sekuda", - "%d sekundy", - "%d sekund", - "%d sekund", - "%d sekund", - "%d sekund" + "%d sekunda", + "%d sekundy", + "%d sekund", + "%d sekund", + "%d sekund", + "%d sekund" ], "%d minutes": [ - "%d minuta", - "%d minuty", - "%d minut", - "%d minut", - "%d minut", - "%d minut" + "%d minuta", + "%d minuty", + "%d minut", + "%d minut", + "%d minut", + "%d minut" ], "%d hours": [ - "%d hodina", - "%d hodiny", - "%d hodin", - "%d hodin", - "%d hodin", - "%d hodin" + "%d hodina", + "%d hodiny", + "%d hodin", + "%d hodin", + "%d hodin", + "%d hodin" ], "%d days": [ - "%d den", - "%d dny", - "%d dní", - "%d dní", - "%d dní", - "%d dní" + "%d den", + "%d dny", + "%d dní", + "%d dní", + "%d dní", + "%d dní" ], "%d weeks": [ - "%d týden", - "%d týdeny", - "%d týdnů", - "%d týdnů", - "%d týdnů", - "%d týdnů" + "%d týden", + "%d týdny", + "%d týdnů", + "%d týdnů", + "%d týdnů", + "%d týdnů" ], "%d months": [ - "%d měsíc", - "%d měsíce", - "%d měsíců", - "%d měsíců", - "%d měsíců", - "%d měsíců" + "%d měsíc", + "%d měsíce", + "%d měsíců", + "%d měsíců", + "%d měsíců", + "%d měsíců" ], "%d years": [ - "%d rok", - "%d roky", - "%d roků", - "%d roků", - "%d roků", - "%d roků" + "%d rok", + "%d roky", + "%d let", + "%d let", + "%d let", + "%d let" ], "Never": "Nikdy", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Poznámka: Tato služba slouží k vyzkoušení: Data mohou být kdykoliv smazána. Při zneužití této služby zemřou koťátka.", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Poznámka: Toto je testovací služba: Data mohou být kdykoliv smazána. Při zneužití této služby zemřou koťátka.", "This document will expire in %d seconds.": [ - "Tento dokument expiruje za %d sekundu.", - "Tento dokument expiruje za %d sekundy.", - "Tento dokument expiruje za %d sekund.", - "Tento dokument expiruje za %d sekund.", - "Tento dokument expiruje za %d sekund.", - "Tento dokument expiruje za %d sekund." + "Tento dokument expiruje za %d sekundu.", + "Tento dokument expiruje za %d sekundy.", + "Tento dokument expiruje za %d sekund.", + "Tento dokument expiruje za %d sekund.", + "Tento dokument expiruje za %d sekund.", + "Tento dokument expiruje za %d sekund." ], "This document will expire in %d minutes.": [ - "Tento dokument expiruje za %d minutu.", - "Tento dokument expiruje za %d minuty.", - "Tento dokument expiruje za %d minut.", - "Tento dokument expiruje za %d minut.", - "Tento dokument expiruje za %d minut.", - "Tento dokument expiruje za %d minut." + "Tento dokument expiruje za %d minutu.", + "Tento dokument expiruje za %d minuty.", + "Tento dokument expiruje za %d minut.", + "Tento dokument expiruje za %d minut.", + "Tento dokument expiruje za %d minut.", + "Tento dokument expiruje za %d minut." ], "This document will expire in %d hours.": [ - "Tento dokument expiruje za %d hodinu.", - "Tento dokument expiruje za %d hodiny.", - "Tento dokument expiruje za %d hodin.", - "Tento dokument expiruje za %d hodin.", - "Tento dokument expiruje za %d hodin.", - "Tento dokument expiruje za %d hodin." + "Tento dokument expiruje za %d hodinu.", + "Tento dokument expiruje za %d hodiny.", + "Tento dokument expiruje za %d hodin.", + "Tento dokument expiruje za %d hodin.", + "Tento dokument expiruje za %d hodin.", + "Tento dokument expiruje za %d hodin." ], "This document will expire in %d days.": [ - "Tento dokument expiruje za %d den.", - "Tento dokument expiruje za %d dny.", - "Tento dokument expiruje za %d dny.", - "Tento dokument expiruje za %d dny.", - "Tento dokument expiruje za %d dny.", - "Tento dokument expiruje za %d dny." + "Tento dokument expiruje za %d den.", + "Tento dokument expiruje za %d dny.", + "Tento dokument expiruje za %d dní.", + "Tento dokument expiruje za %d dní.", + "Tento dokument expiruje za %d dní.", + "Tento dokument expiruje za %d dní." ], "This document will expire in %d months.": [ - "Tento dokument expiruje za %d měsíc.", - "Tento dokument expiruje za %d měsíce.", - "Tento dokument expiruje za %d měsíců.", - "Tento dokument expiruje za %d měsíců.", - "Tento dokument expiruje za %d měsíců.", - "Tento dokument expiruje za %d měsíců." + "Tento dokument expiruje za %d měsíc.", + "Tento dokument expiruje za %d měsíce.", + "Tento dokument expiruje za %d měsíců.", + "Tento dokument expiruje za %d měsíců.", + "Tento dokument expiruje za %d měsíců.", + "Tento dokument expiruje za %d měsíců." ], - "Please enter the password for this paste:": "Zadejte prosím heslo:", + "Please enter the password for this paste:": "Zadejte prosím heslo k tomuto příspěvku:", "Could not decrypt data (Wrong key?)": "Nepodařilo se dešifrovat data (Špatný klíč?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Nepodařilo se odstranit příspěvek, nebyl uložen v režimu smazání po přečtení.", + "Could not delete the paste, it was not stored in burn after reading mode.": "Nepodařilo se odstranit příspěvek, nebyl uložen v režimu smazání po přečtení.", "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "POUZE PRO VAŠE OČI. Nezavírejte toto okno, tuto zprávu nelze znovu zobrazit.", "Could not decrypt comment; Wrong key?": "Nepodařilo se dešifrovat komentář; Špatný klíč?", "Reply": "Odpovědět", "Anonymous": "Anonym", - "Avatar generated from IP address": "Avatar vygenerován z IP adresy", + "Avatar generated from IP address": "Avatar vygenerován podle IP adresy", "Add comment": "Přidat komentář", - "Optional nickname…": "Volitelný nickname…", + "Optional nickname…": "Nepovinná přezdívka…", "Post comment": "Odeslat komentář", "Sending comment…": "Odesílání komentáře…", "Comment posted.": "Komentář odeslán.", @@ -151,10 +151,10 @@ "server error or not responding": "Chyba na serveru nebo server neodpovídá", "Could not post comment: %s": "Nelze odeslat komentář: %s", "Sending paste…": "Odesílání příspěvku…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Váš link je %s (Stiskněte [Ctrl]+[c] pro zkopírování)", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Váš příspěvek je %s (Stiskněte [Ctrl]+[c] pro zkopírování)", "Delete data": "Odstranit data", - "Could not create paste: %s": "Nelze vytvořit příspěvek: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nepodařilo se dešifrovat příspěvek: V adrese chybí dešifrovací klíč (Možnou příčinou může být URL shortener?)", + "Could not create paste: %s": "Nepodařilo se vytvořit příspěvek: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nepodařilo se dešifrovat příspěvek: V adrese chybí dešifrovací klíč (Nepoužili jste přesměrovač nebo zkracovač URL, který maže části URL?)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -165,59 +165,59 @@ "ZiB": "ZiB", "YiB": "YiB", "Format": "Formát", - "Plain Text": "Prostý Text", + "Plain Text": "Prostý text", "Source Code": "Zdrojový kód", "Markdown": "Markdown", "Download attachment": "Stáhnout přílohu", - "Cloned: '%s'": "Klonováno: '%s'", - "The cloned file '%s' was attached to this paste.": "Naklonovaný soubor '%s' byl připojen k tomuto příspěvku.", + "Cloned: '%s'": "Naklonováno: '%s'", + "The cloned file '%s' was attached to this paste.": "Naklonovaný soubor „%s“ byl připojen k tomuto příspěvku.", "Attach a file": "Připojit soubor", - "alternatively drag & drop a file or paste an image from the clipboard": "alternativně přetáhněte soubor nebo vložte obrázek ze schránky", + "alternatively drag & drop a file or paste an image from the clipboard": "případně přetáhněte soubor nebo vložte obrázek ze schránky", "File too large, to display a preview. Please download the attachment.": "Soubor je příliš velký pro zobrazení náhledu. Stáhněte si přílohu.", "Remove attachment": "Odstranit přílohu", "Your browser does not support uploading encrypted files. Please use a newer browser.": "Váš prohlížeč nepodporuje nahrávání šifrovaných souborů. Použijte modernější verzi prohlížeče.", "Invalid attachment.": "Chybná příloha.", - "Options": "Volby", + "Options": "Možnosti", "Shorten URL": "Zkrátit URL", "Editor": "Editor", "Preview": "Náhled", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH skončil s \"%s\". Aktualizujte PATH ve vašem souboru index.php.", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH končilo na „%s“. Aktualizujte PATH ve vašem souboru index.php.", "Decrypt": "Dešifrovat", "Enter password": "Zadejte heslo", "Loading…": "Načítání…", "Decrypting paste…": "Dešifruji příspěvek…", "Preparing new paste…": "Připravuji nový příspěvek…", - "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "V případě, že tato zpráva nezmizí, se podívejte na tyto často kladené otázky pro řešení.", - "+++ no paste text +++": "+++ žádný vložený text +++", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "Pokud tato zpráva nezmizí, podívejte se na tyto často kladené otázky pro řešení problémů.", + "+++ no paste text +++": "+++ žádný text příspěvku +++", "Could not get paste data: %s": "Nepodařilo se získat data příspěvku: %s", "QR code": "QR kód", - "This website is using an insecure HTTP connection! Please use it only for testing.": "Tato stránka používá nezabezpečený připojení HTTP! Použijte ji prosím jen pro testování.", - "For more information see this FAQ entry.": "Více informací naleznete v této položce FAQ.", + "This website is using an insecure HTTP connection! Please use it only for testing.": "Tato stránka používá nezabezpečené HTTP připojení! Použijte ji prosím jen pro testování.", + "For more information see this FAQ entry.": "Více informací naleznete v této položce FAQ.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Váš prohlížeč může vyžadovat připojení HTTPS pro podporu WebCrypto API. Zkuste přepnout na HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Váš prohlížeč nepodporuje WebAssembly, který se používá pro zlib kompresi. Můžete vytvořit nekomprimované dokumenty, ale nebudete moct číst ty komprimované.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Váš prohlížeč nepodporuje WebAssembly, které se používá pro zlib kompresi. Můžete vytvořit nekomprimované dokumenty, ale nebudete moct číst ty komprimované.", "waiting on user to provide a password": "čekám na zadání hesla", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Nepodařilo se dešifrovat data. Zadali jste špatné heslo? Zkuste to znovu pomocí tlačítka nahoře.", "Retry": "Opakovat", - "Showing raw text…": "Zobrazuji surový text…", + "Showing raw text…": "Zobrazuji čistý text…", "Notice:": "Upozornění:", "This link will expire after %s.": "Tento odkaz vyprší za %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "Tento odkaz je přístupný pouze jednou, nepoužívejte tlačítko zpět ani neobnovujte tuto stránku ve vašem prohlížeči.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Tento odkaz je přístupný pouze jednou, nepoužívejte tlačítko zpět ani neobnovujte tuto stránku v prohlížeči.", "Link:": "Odkaz:", - "Recipient may become aware of your timezone, convert time to UTC?": "Příjemce se může dozvědět o vašem časovém pásmu, převést čas na UTC?", + "Recipient may become aware of your timezone, convert time to UTC?": "Příjemce může zjistit vaše časové pásmo, převést čas na UTC?", "Use Current Timezone": "Použít aktuální časové pásmo", "Convert To UTC": "Převést na UTC", "Close": "Zavřít", "Encrypted note on %s": "Šifrovaná poznámka ve službě %s", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.", - "URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Pro zobrazení poznámky navštivte tento odkaz. Přeposláním URL umožníte přístup také jiným lidem.", + "URL shortener may expose your decrypt key in URL.": "Zkracovač URL může prozradit váš dešifrovací klíč v URL.", "Save paste": "Uložit příspěvek", - "Your IP is not authorized to create pastes.": "Vaše IP adresa nemá oprávnění k vytvoření vložení.", - "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", - "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.", - "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", - "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Your IP is not authorized to create pastes.": "Vaše IP adresa nemá oprávnění k vytváření příspěvků.", + "Trying to shorten a URL that isn't pointing at our instance.": "Pokus o zkrácení URL, které neodkazuje na naši instanci.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Chyba volání YOURLS. Pravděpodobně chyba konfigurace, např. nesprávné či chybějící „apiurl“ nebo „signature“.", + "Error parsing YOURLS response.": "Chyba čtení odpovědi YOURLS.", + "This secret message can only be displayed once. Would you like to see it now?": "Tuto tajnou zprávu lze zobrazit pouze jednou. Chcete si ji prohlédnout teď?", + "Yes, see it": "Ano, zobrazit", + "Dark Mode": "Tmavý režim", + "Error compressing paste, due to missing WebAssembly support.": "Chyba při komprimování příspěvku kvůli chybějící podpoře WebAssembly.", + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Chyba při dekomprimování příspěvku, váš prohlížeč nepodporuje WebAssembly. Pro zobrazení tohoto příspěvku prosím použijte jiný prohlížeč." } From d69d29f3a940b443760f1e227df6628e3f4cfb3f Mon Sep 17 00:00:00 2001 From: parthiv-m Date: Mon, 7 Oct 2024 17:42:37 -0400 Subject: [PATCH 425/783] Fix: Once a paste is deleted, navigate to the home page after 5 seconds; change type of the corresponding alert to alert-success --- js/privatebin.js | 5 ++++- tpl/bootstrap.php | 2 +- tpl/bootstrap5.php | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index 9c843628..a5ab23bd 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -5626,8 +5626,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.initZ(); // if delete token is passed (i.e. paste has been deleted by this - // access), there is nothing more to do + // access), redirect to baseurl after 5 seconds if (Model.hasDeleteToken()) { + setTimeout(() => { + UiHelper.reloadHome(); + }, 5000); return; } diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 901bced7..74712355 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -490,7 +490,7 @@ if ($FILEUPLOAD) : - +
+ + +
From 3d59d3da500c6a7276e80fbe2b2c21753846e90b Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 24 Nov 2024 16:17:45 +0100 Subject: [PATCH 487/783] change focus order for accessibility tabbing out of the textarea jumps to the "Create" button, then the tab-toggle --- tpl/bootstrap.php | 6 +++--- tpl/bootstrap5.php | 6 +++--- tpl/page.php | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 9c8d0aa3..a34bcec0 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -567,7 +567,7 @@ if ($isPage) : -
-

+

diff --git a/tpl/bootstrap5.php b/tpl/bootstrap5.php index fb28fc55..4db055ca 100644 --- a/tpl/bootstrap5.php +++ b/tpl/bootstrap5.php @@ -425,7 +425,7 @@ endif; @@ -439,9 +439,9 @@ endif;

 					
-

+

- + diff --git a/tpl/page.php b/tpl/page.php index 5504ddfe..9b8fe408 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -125,7 +125,7 @@ endif;

- + @@ -263,9 +263,9 @@ endif;

 				
- +
- +
From 6587466a9b29a5f2af49d849243e3783cf4ab9ca Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 26 Nov 2024 07:01:34 +0100 Subject: [PATCH 488/783] remove async & ES6 feature detection It requires eval and webcrypto got introduced in older Chrome & Firefox versions, so seems superfluous to keep. --- CHANGELOG.md | 1 + js/legacy.js | 12 ------------ lib/Configuration.php | 2 +- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 456c6c29..262edc9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # PrivateBin version history ## 1.7.6 (not yet released) +* CHANGED: Switched to WASM streaming and replace unsafe-eval with wasm-unsafe-eval CSP declaration (#1464), requires webserver to have `application/wasm` MIME type configured. ## 1.7.5 (2024-11-16) * ADDED: Allow non persistent SQL connections, if configured (#1394) diff --git a/js/legacy.js b/js/legacy.js index be85f981..922e9a0e 100644 --- a/js/legacy.js +++ b/js/legacy.js @@ -174,18 +174,6 @@ )) { return true; } - - // async & ES6 support - try { - async () => {}; - } catch (e) { - if (e instanceof SyntaxError) { - return true; - } else { - throw e; // throws CSP error - } - } - return false; } diff --git a/lib/Configuration.php b/lib/Configuration.php index 78aa9fe5..9dd7f4f3 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -106,7 +106,7 @@ class Configuration 'js/dark-mode-switch.js' => 'sha512-CCbdHdeWDbDO7aqFFmhgnvFESzaILHbUYmbhNjTpcjyO/XYdouQ9Pw8W9rpV8oJT1TsK5FbwSHU1oazmnb7BWA==', 'js/jquery-3.7.1.js' => 'sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==', 'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==', - 'js/legacy.js' => 'sha512-p76t5AT6YHgvhG5RqWGOQ6o87aObfYWYwOPHYhhN4KfExVEZJ0/I0D+1daKprxgbL37/gtXxbd1qZx4PIhSU3g==', + 'js/legacy.js' => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', 'js/privatebin.js' => 'sha512-JUj/Sbl/bMHlIoIUT1U9e89JU33fDBxCxLSGxwwaeydBFXOBHyfdF7hwSIjgbPxb4d9CO7CSe4meouTIRMy8Vg==', 'js/purify-3.1.7.js' => 'sha512-LegvqULiMtOfboJZw9MpETN/b+xnLRXZI90gG7oIFHW+yAeHmKvRtEUbiMFx2WvUqQoL9XB3gwU+hWXUT0X+8A==', From 652cf0cf26f34e29f2fb373ead49630085cfc52c Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 28 Nov 2024 07:48:27 +0100 Subject: [PATCH 489/783] bump PHP libraries --- CHANGELOG.md | 1 + composer.json | 4 ++-- composer.lock | 12 ++++++------ vendor/composer/installed.php | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 262edc9e..d96eabb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.7.6 (not yet released) * CHANGED: Switched to WASM streaming and replace unsafe-eval with wasm-unsafe-eval CSP declaration (#1464), requires webserver to have `application/wasm` MIME type configured. +* CHANGED: Upgrading libraries to: cloud-storage 1.44.0, aws-sdk-php 3.331.0 ## 1.7.5 (2024-11-16) * ADDED: Allow non persistent SQL connections, if configured (#1394) diff --git a/composer.json b/composer.json index d16a562b..10024a08 100644 --- a/composer.json +++ b/composer.json @@ -30,8 +30,8 @@ "yzalis/identicon": "2.0.0" }, "suggest" : { - "google/cloud-storage" : "1.43.0", - "aws/aws-sdk-php" : "3.325.0" + "google/cloud-storage" : "1.44.0", + "aws/aws-sdk-php" : "3.331.0" }, "require-dev" : { "phpunit/phpunit" : "^9" diff --git a/composer.lock b/composer.lock index 3b298cb5..a72fb37c 100644 --- a/composer.lock +++ b/composer.lock @@ -257,16 +257,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -305,7 +305,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -313,7 +313,7 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "nikic/php-parser", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 6631bab7..7c68f160 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'privatebin/privatebin', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '365782ebeb864a851a9ece915028f6cac97f8fab', + 'reference' => '1c7d63954642b3852177793c0c17963303484051', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -31,7 +31,7 @@ 'privatebin/privatebin' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '365782ebeb864a851a9ece915028f6cac97f8fab', + 'reference' => '1c7d63954642b3852177793c0c17963303484051', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), From 75ec510f2dfea3d4b2bc92a445f8e9f5971c4e17 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:44:35 +0100 Subject: [PATCH 490/783] New translations en.json (Corsican) --- i18n/co.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/co.json b/i18n/co.json index b79964a3..d590be28 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -168,15 +168,15 @@ "Plain Text": "Testu in chjaru", "Source Code": "Codice di fonte", "Markdown": "Markdown", - "Download attachment": "Scaricà a pezza aghjunta", + "Download attachment": "Scaricà a pezza ghjunta", "Cloned: '%s'": "Duppiatu : « %s »", "The cloned file '%s' was attached to this paste.": "U schedariu duppiatu « %s » hè statu aghjuntu à st’appiccicu.", "Attach a file": "Aghjunghje un schedariu", "alternatively drag & drop a file or paste an image from the clipboard": "in alternanza, sguillà è depone un schedariu o incullà una fiura da u preme’papei", - "File too large, to display a preview. Please download the attachment.": "Schedariu troppu maiò per affissà una fighjulata. Scaricate a pezza aghjunta.", - "Remove attachment": "Caccià a pezza aghjunta", + "File too large, to display a preview. Please download the attachment.": "Schedariu troppu maiò per affissà una fighjulata. Scaricate a pezza ghjunta.", + "Remove attachment": "Caccià a pezza ghjunta", "Your browser does not support uploading encrypted files. Please use a newer browser.": "U vostru navigatore ùn accetta micca l’inviu di i schedarii cifrati. Impiegate un navigatore più recente.", - "Invalid attachment.": "A pezza aghjunta hè inaccettevule.", + "Invalid attachment.": "A pezza ghjunta hè inaccettevule.", "Options": "Ozzioni", "Shorten URL": "Ammuzzà l’indirizzu", "Editor": "Editore", From 7ee6bcafc4887981a5d804cee9cd9da35ed9b2fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 11:11:25 +0000 Subject: [PATCH 491/783] Bump dawidd6/action-download-artifact from 6 to 7 Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 6 to 7. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/bf251b5aa9c2f7eeb574a96ee720e24f801b7c11...80620a5d27ce0ae443b965134db88467fc607b43) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test-results.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-results.yml b/.github/workflows/test-results.yml index 4e20737d..5254960f 100644 --- a/.github/workflows/test-results.yml +++ b/.github/workflows/test-results.yml @@ -24,7 +24,7 @@ jobs: steps: - name: Download and Extract Artifacts - uses: dawidd6/action-download-artifact@bf251b5aa9c2f7eeb574a96ee720e24f801b7c11 + uses: dawidd6/action-download-artifact@80620a5d27ce0ae443b965134db88467fc607b43 with: run_id: ${{ github.event.workflow_run.id }} path: artifacts From e92f2ac9ca6fb9557f7cb59f252095e726065820 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 3 Dec 2024 09:49:56 +0100 Subject: [PATCH 492/783] New translations en.json (Thai) --- i18n/th.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/th.json b/i18n/th.json index ddebf39f..089de3fe 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -217,7 +217,7 @@ "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": "โหมดสีเข้ม", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over" From f9094874eb1639a6c6cbb84e118441a6b0d0d42a Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:59:49 +0100 Subject: [PATCH 493/783] New translations en.json (Thai) --- i18n/th.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/i18n/th.json b/i18n/th.json index 089de3fe..b088d68f 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -215,10 +215,10 @@ "Trying to shorten a URL that isn't pointing at our instance.": "กำลังพยายามใช้เครื่องมือสร้างลิงก์ย่อ ที่ไม่ได้ชี้ไปที่อินสแตนซ์ของเรา", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "เกิดข้อผิดพลาดในการเรียก YOURLS อาจเป็นปัญหามาจากการกำหนดค่า เช่น \"apiurl\" หรือ \"signature\" ไม่ถูกต้องหรือขาดหายไป", "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", + "This secret message can only be displayed once. Would you like to see it now?": "ข้อความลับนี้จะแสดงได้เพียงครั้งเดียวเท่านั้น คุณต้องการดูข้อความนี้ตอนนี้เลยใช่หรือไม่", + "Yes, see it": "ใช่ ดูเลย", "Dark Mode": "โหมดสีเข้ม", - "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", - "Start over": "Start over" + "Error compressing paste, due to missing WebAssembly support.": "ไม่สามารถบีบอัดข้อมูลที่คุณต้องการฝากโค้ดได้ เนื่องจากอุปกรณ์ของคุณขาดการรองรับ WebAssembly", + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "ไม่สามารถอ่านข้อมูลที่คุณได้ฝากโค้ดไว้ เบราว์เซอร์ของคุณไม่รองรับ WebAssembly กรุณาลองเปลี่ยนใช้เบราว์เซอร์ตัวอื่นเพื่อดูการฝากโค้ดนี้อีกครั้ง", + "Start over": "เริ่มใหม่" } From f7a9631a2fddf2c78bb08a04422010127850bf7f Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:29:46 +0100 Subject: [PATCH 494/783] New translations en.json (Ukrainian) --- i18n/uk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/uk.json b/i18n/uk.json index 9b1f2970..2d7796cb 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -220,5 +220,5 @@ "Dark Mode": "Темний режим", "Error compressing paste, due to missing WebAssembly support.": "Помилка при стисканні допису, через відсутність підтримки WebAssembly сервера.", "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте в іншому браузері для перегляду цього допису.", - "Start over": "Start over" + "Start over": "Почати знову" } From 15488d3405cfe28d08ca9662456181d48d550fec Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 14 Dec 2024 09:14:44 +0100 Subject: [PATCH 495/783] bump checkout action --- codacy-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codacy-analysis.yml b/codacy-analysis.yml index 9850708b..31d065cd 100644 --- a/codacy-analysis.yml +++ b/codacy-analysis.yml @@ -24,7 +24,7 @@ jobs: steps: # Checkout the repository to the GitHub Actions runner - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis - name: Run Codacy Analysis CLI From be18dcb838d50fd68794b25bc7c883de7fb626eb Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 22 Dec 2024 11:17:34 +0100 Subject: [PATCH 496/783] upgrading DOMpurify library to 3.2.3 --- CHANGELOG.md | 2 +- js/common.js | 2 +- js/purify-3.1.7.js | 2 -- js/purify-3.2.3.js | 2 ++ lib/Configuration.php | 2 +- tpl/bootstrap.php | 2 +- tpl/bootstrap5.php | 2 +- tpl/page.php | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) delete mode 100644 js/purify-3.1.7.js create mode 100644 js/purify-3.2.3.js diff --git a/CHANGELOG.md b/CHANGELOG.md index d96eabb1..a0506712 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 1.7.6 (not yet released) * CHANGED: Switched to WASM streaming and replace unsafe-eval with wasm-unsafe-eval CSP declaration (#1464), requires webserver to have `application/wasm` MIME type configured. -* CHANGED: Upgrading libraries to: cloud-storage 1.44.0, aws-sdk-php 3.331.0 +* CHANGED: Upgrading libraries to: DOMpurify 3.2.3, cloud-storage 1.44.0, aws-sdk-php 3.331.0 ## 1.7.5 (2024-11-16) * ADDED: Allow non persistent SQL connections, if configured (#1394) diff --git a/js/common.js b/js/common.js index a81dbc82..5ad72afd 100644 --- a/js/common.js +++ b/js/common.js @@ -17,7 +17,7 @@ require('./prettify'); global.prettyPrint = window.PR.prettyPrint; global.prettyPrintOne = window.PR.prettyPrintOne; global.showdown = require('./showdown-2.1.0'); -global.DOMPurify = require('./purify-3.1.7'); +global.DOMPurify = require('./purify-3.2.3'); global.baseX = require('./base-x-4.0.0').baseX; global.Legacy = require('./legacy').Legacy; require('./bootstrap-3.4.1'); diff --git a/js/purify-3.1.7.js b/js/purify-3.1.7.js deleted file mode 100644 index ec61bc61..00000000 --- a/js/purify-3.1.7.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! @license DOMPurify 3.1.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.7/LICENSE */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=b(Array.prototype.forEach),m=b(Array.prototype.pop),p=b(Array.prototype.push),f=b(String.prototype.toLowerCase),d=b(String.prototype.toString),h=b(String.prototype.match),g=b(String.prototype.replace),T=b(String.prototype.indexOf),y=b(String.prototype.trim),E=b(Object.prototype.hasOwnProperty),_=b(RegExp.prototype.test),A=(N=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:f;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function R(e){for(let t=0;t/gm),B=a(/\${[\w\W]*}/gm),W=a(/^data-[\-\w.\u00B7-\uFFFF]/),G=a(/^aria-[\-\w]+$/),Y=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),j=a(/^(?:\w+script|data):/i),X=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),q=a(/^html$/i),$=a(/^[a-z][.\w]*(-[.\w]+)+$/i);var K=Object.freeze({__proto__:null,MUSTACHE_EXPR:H,ERB_EXPR:z,TMPLIT_EXPR:B,DATA_ATTR:W,ARIA_ATTR:G,IS_ALLOWED_URI:Y,IS_SCRIPT_OR_DATA:j,ATTR_WHITESPACE:X,DOCTYPE_NAME:q,CUSTOM_ELEMENT:$});const V=1,Z=3,J=7,Q=8,ee=9,te=function(){return"undefined"==typeof window?null:window};var ne=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:te();const o=e=>t(e);if(o.version="3.1.7",o.removed=[],!n||!n.document||n.document.nodeType!==ee)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:N,Node:b,Element:R,NodeFilter:H,NamedNodeMap:z=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:B,DOMParser:W,trustedTypes:G}=n,j=R.prototype,X=C(j,"cloneNode"),$=C(j,"remove"),ne=C(j,"nextSibling"),oe=C(j,"childNodes"),re=C(j,"parentNode");if("function"==typeof N){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let ie,ae="";const{implementation:le,createNodeIterator:ce,createDocumentFragment:se,getElementsByTagName:ue}=r,{importNode:me}=a;let pe={};o.isSupported="function"==typeof e&&"function"==typeof re&&le&&void 0!==le.createHTMLDocument;const{MUSTACHE_EXPR:fe,ERB_EXPR:de,TMPLIT_EXPR:he,DATA_ATTR:ge,ARIA_ATTR:Te,IS_SCRIPT_OR_DATA:ye,ATTR_WHITESPACE:Ee,CUSTOM_ELEMENT:_e}=K;let{IS_ALLOWED_URI:Ae}=K,Ne=null;const be=S({},[...L,...v,...D,...x,...M]);let Se=null;const Re=S({},[...I,...U,...P,...F]);let we=Object.seal(l(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ce=null,Le=null,ve=!0,De=!0,Oe=!1,xe=!0,ke=!1,Me=!0,Ie=!1,Ue=!1,Pe=!1,Fe=!1,He=!1,ze=!1,Be=!0,We=!1,Ge=!0,Ye=!1,je={},Xe=null;const qe=S({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let $e=null;const Ke=S({},["audio","video","img","source","image","track"]);let Ve=null;const Ze=S({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Je="http://www.w3.org/1998/Math/MathML",Qe="http://www.w3.org/2000/svg",et="http://www.w3.org/1999/xhtml";let tt=et,nt=!1,ot=null;const rt=S({},[Je,Qe,et],d);let it=null;const at=["application/xhtml+xml","text/html"];let lt=null,ct=null;const st=r.createElement("form"),ut=function(e){return e instanceof RegExp||e instanceof Function},mt=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!ct||ct!==e){if(e&&"object"==typeof e||(e={}),e=w(e),it=-1===at.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,lt="application/xhtml+xml"===it?d:f,Ne=E(e,"ALLOWED_TAGS")?S({},e.ALLOWED_TAGS,lt):be,Se=E(e,"ALLOWED_ATTR")?S({},e.ALLOWED_ATTR,lt):Re,ot=E(e,"ALLOWED_NAMESPACES")?S({},e.ALLOWED_NAMESPACES,d):rt,Ve=E(e,"ADD_URI_SAFE_ATTR")?S(w(Ze),e.ADD_URI_SAFE_ATTR,lt):Ze,$e=E(e,"ADD_DATA_URI_TAGS")?S(w(Ke),e.ADD_DATA_URI_TAGS,lt):Ke,Xe=E(e,"FORBID_CONTENTS")?S({},e.FORBID_CONTENTS,lt):qe,Ce=E(e,"FORBID_TAGS")?S({},e.FORBID_TAGS,lt):{},Le=E(e,"FORBID_ATTR")?S({},e.FORBID_ATTR,lt):{},je=!!E(e,"USE_PROFILES")&&e.USE_PROFILES,ve=!1!==e.ALLOW_ARIA_ATTR,De=!1!==e.ALLOW_DATA_ATTR,Oe=e.ALLOW_UNKNOWN_PROTOCOLS||!1,xe=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,ke=e.SAFE_FOR_TEMPLATES||!1,Me=!1!==e.SAFE_FOR_XML,Ie=e.WHOLE_DOCUMENT||!1,Fe=e.RETURN_DOM||!1,He=e.RETURN_DOM_FRAGMENT||!1,ze=e.RETURN_TRUSTED_TYPE||!1,Pe=e.FORCE_BODY||!1,Be=!1!==e.SANITIZE_DOM,We=e.SANITIZE_NAMED_PROPS||!1,Ge=!1!==e.KEEP_CONTENT,Ye=e.IN_PLACE||!1,Ae=e.ALLOWED_URI_REGEXP||Y,tt=e.NAMESPACE||et,we=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&ut(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(we.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&ut(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(we.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(we.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),ke&&(De=!1),He&&(Fe=!0),je&&(Ne=S({},M),Se=[],!0===je.html&&(S(Ne,L),S(Se,I)),!0===je.svg&&(S(Ne,v),S(Se,U),S(Se,F)),!0===je.svgFilters&&(S(Ne,D),S(Se,U),S(Se,F)),!0===je.mathMl&&(S(Ne,x),S(Se,P),S(Se,F))),e.ADD_TAGS&&(Ne===be&&(Ne=w(Ne)),S(Ne,e.ADD_TAGS,lt)),e.ADD_ATTR&&(Se===Re&&(Se=w(Se)),S(Se,e.ADD_ATTR,lt)),e.ADD_URI_SAFE_ATTR&&S(Ve,e.ADD_URI_SAFE_ATTR,lt),e.FORBID_CONTENTS&&(Xe===qe&&(Xe=w(Xe)),S(Xe,e.FORBID_CONTENTS,lt)),Ge&&(Ne["#text"]=!0),Ie&&S(Ne,["html","head","body"]),Ne.table&&(S(Ne,["tbody"]),delete Ce.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');ie=e.TRUSTED_TYPES_POLICY,ae=ie.createHTML("")}else void 0===ie&&(ie=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}}(G,c)),null!==ie&&"string"==typeof ae&&(ae=ie.createHTML(""));i&&i(e),ct=e}},pt=S({},["mi","mo","mn","ms","mtext"]),ft=S({},["annotation-xml"]),dt=S({},["title","style","font","a","script"]),ht=S({},[...v,...D,...O]),gt=S({},[...x,...k]),Tt=function(e){p(o.removed,{element:e});try{re(e).removeChild(e)}catch(t){$(e)}},yt=function(e,t){try{p(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){p(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Se[e])if(Fe||He)try{Tt(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},Et=function(e){let t=null,n=null;if(Pe)e=""+e;else{const t=h(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===it&&tt===et&&(e=''+e+"");const o=ie?ie.createHTML(e):e;if(tt===et)try{t=(new W).parseFromString(o,it)}catch(e){}if(!t||!t.documentElement){t=le.createDocument(tt,"template",null);try{t.documentElement.innerHTML=nt?ae:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),tt===et?ue.call(t,Ie?"html":"body")[0]:Ie?t.documentElement:i},_t=function(e){return ce.call(e.ownerDocument||e,e,H.SHOW_ELEMENT|H.SHOW_COMMENT|H.SHOW_TEXT|H.SHOW_PROCESSING_INSTRUCTION|H.SHOW_CDATA_SECTION,null)},At=function(e){return e instanceof B&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof z)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Nt=function(e){return"function"==typeof b&&e instanceof b},bt=function(e,t,n){pe[e]&&u(pe[e],(e=>{e.call(o,t,n,ct)}))},St=function(e){let t=null;if(bt("beforeSanitizeElements",e,null),At(e))return Tt(e),!0;const n=lt(e.nodeName);if(bt("uponSanitizeElement",e,{tagName:n,allowedTags:Ne}),e.hasChildNodes()&&!Nt(e.firstElementChild)&&_(/<[/\w]/g,e.innerHTML)&&_(/<[/\w]/g,e.textContent))return Tt(e),!0;if(e.nodeType===J)return Tt(e),!0;if(Me&&e.nodeType===Q&&_(/<[/\w]/g,e.data))return Tt(e),!0;if(!Ne[n]||Ce[n]){if(!Ce[n]&&wt(n)){if(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,n))return!1;if(we.tagNameCheck instanceof Function&&we.tagNameCheck(n))return!1}if(Ge&&!Xe[n]){const t=re(e)||e.parentNode,n=oe(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o){const r=X(n[o],!0);r.__removalCount=(e.__removalCount||0)+1,t.insertBefore(r,ne(e))}}}return Tt(e),!0}return e instanceof R&&!function(e){let t=re(e);t&&t.tagName||(t={namespaceURI:tt,tagName:"template"});const n=f(e.tagName),o=f(t.tagName);return!!ot[e.namespaceURI]&&(e.namespaceURI===Qe?t.namespaceURI===et?"svg"===n:t.namespaceURI===Je?"svg"===n&&("annotation-xml"===o||pt[o]):Boolean(ht[n]):e.namespaceURI===Je?t.namespaceURI===et?"math"===n:t.namespaceURI===Qe?"math"===n&&ft[o]:Boolean(gt[n]):e.namespaceURI===et?!(t.namespaceURI===Qe&&!ft[o])&&!(t.namespaceURI===Je&&!pt[o])&&!gt[n]&&(dt[n]||!ht[n]):!("application/xhtml+xml"!==it||!ot[e.namespaceURI]))}(e)?(Tt(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!_(/<\/no(script|embed|frames)/i,e.innerHTML)?(ke&&e.nodeType===Z&&(t=e.textContent,u([fe,de,he],(e=>{t=g(t,e," ")})),e.textContent!==t&&(p(o.removed,{element:e.cloneNode()}),e.textContent=t)),bt("afterSanitizeElements",e,null),!1):(Tt(e),!0)},Rt=function(e,t,n){if(Be&&("id"===t||"name"===t)&&(n in r||n in st))return!1;if(De&&!Le[t]&&_(ge,t));else if(ve&&_(Te,t));else if(!Se[t]||Le[t]){if(!(wt(e)&&(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,e)||we.tagNameCheck instanceof Function&&we.tagNameCheck(e))&&(we.attributeNameCheck instanceof RegExp&&_(we.attributeNameCheck,t)||we.attributeNameCheck instanceof Function&&we.attributeNameCheck(t))||"is"===t&&we.allowCustomizedBuiltInElements&&(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,n)||we.tagNameCheck instanceof Function&&we.tagNameCheck(n))))return!1}else if(Ve[t]);else if(_(Ae,g(n,Ee,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==T(n,"data:")||!$e[e]){if(Oe&&!_(ye,g(n,Ee,"")));else if(n)return!1}else;return!0},wt=function(e){return"annotation-xml"!==e&&h(e,_e)},Ct=function(e){bt("beforeSanitizeAttributes",e,null);const{attributes:t}=e;if(!t)return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Se};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=lt(a);let p="value"===a?c:y(c);if(n.attrName=s,n.attrValue=p,n.keepAttr=!0,n.forceKeepAttr=void 0,bt("uponSanitizeAttribute",e,n),p=n.attrValue,n.forceKeepAttr)continue;if(yt(a,e),!n.keepAttr)continue;if(!xe&&_(/\/>/i,p)){yt(a,e);continue}ke&&u([fe,de,he],(e=>{p=g(p,e," ")}));const f=lt(e.nodeName);if(Rt(f,s,p))if(!We||"id"!==s&&"name"!==s||(yt(a,e),p="user-content-"+p),Me&&_(/((--!?|])>)|<\/(style|title)/i,p))yt(a,e);else{if(ie&&"object"==typeof G&&"function"==typeof G.getAttributeType)if(l);else switch(G.getAttributeType(f,s)){case"TrustedHTML":p=ie.createHTML(p);break;case"TrustedScriptURL":p=ie.createScriptURL(p)}try{l?e.setAttributeNS(l,a,p):e.setAttribute(a,p),At(e)?Tt(e):m(o.removed)}catch(e){}}}bt("afterSanitizeAttributes",e,null)},Lt=function e(t){let n=null;const o=_t(t);for(bt("beforeSanitizeShadowDOM",t,null);n=o.nextNode();)bt("uponSanitizeShadowNode",n,null),St(n)||(n.content instanceof s&&e(n.content),Ct(n));bt("afterSanitizeShadowDOM",t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(nt=!e,nt&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Nt(e)){if("function"!=typeof e.toString)throw A("toString is not a function");if("string"!=typeof(e=e.toString()))throw A("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Ue||mt(t),o.removed=[],"string"==typeof e&&(Ye=!1),Ye){if(e.nodeName){const t=lt(e.nodeName);if(!Ne[t]||Ce[t])throw A("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof b)n=Et("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),r.nodeType===V&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!Fe&&!ke&&!Ie&&-1===e.indexOf("<"))return ie&&ze?ie.createHTML(e):e;if(n=Et(e),!n)return Fe?null:ze?ae:""}n&&Pe&&Tt(n.firstChild);const c=_t(Ye?e:n);for(;i=c.nextNode();)St(i)||(i.content instanceof s&&Lt(i.content),Ct(i));if(Ye)return e;if(Fe){if(He)for(l=se.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Se.shadowroot||Se.shadowrootmode)&&(l=me.call(a,l,!0)),l}let m=Ie?n.outerHTML:n.innerHTML;return Ie&&Ne["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&_(q,n.ownerDocument.doctype.name)&&(m="\n"+m),ke&&u([fe,de,he],(e=>{m=g(m,e," ")})),ie&&ze?ie.createHTML(m):m},o.setConfig=function(){mt(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Ue=!0},o.clearConfig=function(){ct=null,Ue=!1},o.isValidAttribute=function(e,t,n){ct||mt({});const o=lt(e),r=lt(t);return Rt(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&(pe[e]=pe[e]||[],p(pe[e],t))},o.removeHook=function(e){if(pe[e])return m(pe[e])},o.removeHooks=function(e){pe[e]&&(pe[e]=[])},o.removeAllHooks=function(){pe={}},o}();return ne})); diff --git a/js/purify-3.2.3.js b/js/purify-3.2.3.js new file mode 100644 index 00000000..4d12880c --- /dev/null +++ b/js/purify-3.2.3.js @@ -0,0 +1,2 @@ +/*! @license DOMPurify 3.2.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.3/LICENSE */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=b(Array.prototype.forEach),m=b(Array.prototype.pop),p=b(Array.prototype.push),f=b(String.prototype.toLowerCase),d=b(String.prototype.toString),h=b(String.prototype.match),g=b(String.prototype.replace),T=b(String.prototype.indexOf),y=b(String.prototype.trim),E=b(Object.prototype.hasOwnProperty),A=b(RegExp.prototype.test),_=(S=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n1?n-1:0),r=1;r2&&void 0!==arguments[2]?arguments[2]:f;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function R(e){for(let t=0;t/gm),B=a(/\$\{[\w\W]*}/gm),W=a(/^data-[\-\w.\u00B7-\uFFFF]+$/),G=a(/^aria-[\-\w]+$/),Y=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),j=a(/^(?:\w+script|data):/i),X=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),q=a(/^html$/i),$=a(/^[a-z][.\w]*(-[.\w]+)+$/i);var K=Object.freeze({__proto__:null,ARIA_ATTR:G,ATTR_WHITESPACE:X,CUSTOM_ELEMENT:$,DATA_ATTR:W,DOCTYPE_NAME:q,ERB_EXPR:F,IS_ALLOWED_URI:Y,IS_SCRIPT_OR_DATA:j,MUSTACHE_EXPR:H,TMPLIT_EXPR:B});const V=1,Z=3,J=7,Q=8,ee=9,te=function(){return"undefined"==typeof window?null:window};var ne=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:te();const o=e=>t(e);if(o.version="3.2.3",o.removed=[],!n||!n.document||n.document.nodeType!==ee)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:S,Node:b,Element:R,NodeFilter:H,NamedNodeMap:F=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:B,DOMParser:W,trustedTypes:G}=n,j=R.prototype,X=O(j,"cloneNode"),$=O(j,"remove"),ne=O(j,"nextSibling"),oe=O(j,"childNodes"),re=O(j,"parentNode");if("function"==typeof S){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let ie,ae="";const{implementation:le,createNodeIterator:ce,createDocumentFragment:se,getElementsByTagName:ue}=r,{importNode:me}=a;let pe={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]};o.isSupported="function"==typeof e&&"function"==typeof re&&le&&void 0!==le.createHTMLDocument;const{MUSTACHE_EXPR:fe,ERB_EXPR:de,TMPLIT_EXPR:he,DATA_ATTR:ge,ARIA_ATTR:Te,IS_SCRIPT_OR_DATA:ye,ATTR_WHITESPACE:Ee,CUSTOM_ELEMENT:Ae}=K;let{IS_ALLOWED_URI:_e}=K,Se=null;const be=N({},[...D,...L,...v,...x,...k]);let Ne=null;const Re=N({},[...I,...U,...z,...P]);let we=Object.seal(l(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Oe=null,De=null,Le=!0,ve=!0,Ce=!1,xe=!0,Me=!1,ke=!0,Ie=!1,Ue=!1,ze=!1,Pe=!1,He=!1,Fe=!1,Be=!0,We=!1,Ge=!0,Ye=!1,je={},Xe=null;const qe=N({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let $e=null;const Ke=N({},["audio","video","img","source","image","track"]);let Ve=null;const Ze=N({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Je="http://www.w3.org/1998/Math/MathML",Qe="http://www.w3.org/2000/svg",et="http://www.w3.org/1999/xhtml";let tt=et,nt=!1,ot=null;const rt=N({},[Je,Qe,et],d);let it=N({},["mi","mo","mn","ms","mtext"]),at=N({},["annotation-xml"]);const lt=N({},["title","style","font","a","script"]);let ct=null;const st=["application/xhtml+xml","text/html"];let ut=null,mt=null;const pt=r.createElement("form"),ft=function(e){return e instanceof RegExp||e instanceof Function},dt=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!mt||mt!==e){if(e&&"object"==typeof e||(e={}),e=w(e),ct=-1===st.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,ut="application/xhtml+xml"===ct?d:f,Se=E(e,"ALLOWED_TAGS")?N({},e.ALLOWED_TAGS,ut):be,Ne=E(e,"ALLOWED_ATTR")?N({},e.ALLOWED_ATTR,ut):Re,ot=E(e,"ALLOWED_NAMESPACES")?N({},e.ALLOWED_NAMESPACES,d):rt,Ve=E(e,"ADD_URI_SAFE_ATTR")?N(w(Ze),e.ADD_URI_SAFE_ATTR,ut):Ze,$e=E(e,"ADD_DATA_URI_TAGS")?N(w(Ke),e.ADD_DATA_URI_TAGS,ut):Ke,Xe=E(e,"FORBID_CONTENTS")?N({},e.FORBID_CONTENTS,ut):qe,Oe=E(e,"FORBID_TAGS")?N({},e.FORBID_TAGS,ut):{},De=E(e,"FORBID_ATTR")?N({},e.FORBID_ATTR,ut):{},je=!!E(e,"USE_PROFILES")&&e.USE_PROFILES,Le=!1!==e.ALLOW_ARIA_ATTR,ve=!1!==e.ALLOW_DATA_ATTR,Ce=e.ALLOW_UNKNOWN_PROTOCOLS||!1,xe=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,Me=e.SAFE_FOR_TEMPLATES||!1,ke=!1!==e.SAFE_FOR_XML,Ie=e.WHOLE_DOCUMENT||!1,Pe=e.RETURN_DOM||!1,He=e.RETURN_DOM_FRAGMENT||!1,Fe=e.RETURN_TRUSTED_TYPE||!1,ze=e.FORCE_BODY||!1,Be=!1!==e.SANITIZE_DOM,We=e.SANITIZE_NAMED_PROPS||!1,Ge=!1!==e.KEEP_CONTENT,Ye=e.IN_PLACE||!1,_e=e.ALLOWED_URI_REGEXP||Y,tt=e.NAMESPACE||et,it=e.MATHML_TEXT_INTEGRATION_POINTS||it,at=e.HTML_INTEGRATION_POINTS||at,we=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&ft(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(we.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&ft(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(we.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(we.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Me&&(ve=!1),He&&(Pe=!0),je&&(Se=N({},k),Ne=[],!0===je.html&&(N(Se,D),N(Ne,I)),!0===je.svg&&(N(Se,L),N(Ne,U),N(Ne,P)),!0===je.svgFilters&&(N(Se,v),N(Ne,U),N(Ne,P)),!0===je.mathMl&&(N(Se,x),N(Ne,z),N(Ne,P))),e.ADD_TAGS&&(Se===be&&(Se=w(Se)),N(Se,e.ADD_TAGS,ut)),e.ADD_ATTR&&(Ne===Re&&(Ne=w(Ne)),N(Ne,e.ADD_ATTR,ut)),e.ADD_URI_SAFE_ATTR&&N(Ve,e.ADD_URI_SAFE_ATTR,ut),e.FORBID_CONTENTS&&(Xe===qe&&(Xe=w(Xe)),N(Xe,e.FORBID_CONTENTS,ut)),Ge&&(Se["#text"]=!0),Ie&&N(Se,["html","head","body"]),Se.table&&(N(Se,["tbody"]),delete Oe.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw _('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw _('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');ie=e.TRUSTED_TYPES_POLICY,ae=ie.createHTML("")}else void 0===ie&&(ie=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}}(G,c)),null!==ie&&"string"==typeof ae&&(ae=ie.createHTML(""));i&&i(e),mt=e}},ht=N({},[...L,...v,...C]),gt=N({},[...x,...M]),Tt=function(e){p(o.removed,{element:e});try{re(e).removeChild(e)}catch(t){$(e)}},yt=function(e,t){try{p(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){p(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e)if(Pe||He)try{Tt(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},Et=function(e){let t=null,n=null;if(ze)e=""+e;else{const t=h(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===ct&&tt===et&&(e=''+e+"");const o=ie?ie.createHTML(e):e;if(tt===et)try{t=(new W).parseFromString(o,ct)}catch(e){}if(!t||!t.documentElement){t=le.createDocument(tt,"template",null);try{t.documentElement.innerHTML=nt?ae:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),tt===et?ue.call(t,Ie?"html":"body")[0]:Ie?t.documentElement:i},At=function(e){return ce.call(e.ownerDocument||e,e,H.SHOW_ELEMENT|H.SHOW_COMMENT|H.SHOW_TEXT|H.SHOW_PROCESSING_INSTRUCTION|H.SHOW_CDATA_SECTION,null)},_t=function(e){return e instanceof B&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof F)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},St=function(e){return"function"==typeof b&&e instanceof b};function bt(e,t,n){u(e,(e=>{e.call(o,t,n,mt)}))}const Nt=function(e){let t=null;if(bt(pe.beforeSanitizeElements,e,null),_t(e))return Tt(e),!0;const n=ut(e.nodeName);if(bt(pe.uponSanitizeElement,e,{tagName:n,allowedTags:Se}),e.hasChildNodes()&&!St(e.firstElementChild)&&A(/<[/\w]/g,e.innerHTML)&&A(/<[/\w]/g,e.textContent))return Tt(e),!0;if(e.nodeType===J)return Tt(e),!0;if(ke&&e.nodeType===Q&&A(/<[/\w]/g,e.data))return Tt(e),!0;if(!Se[n]||Oe[n]){if(!Oe[n]&&wt(n)){if(we.tagNameCheck instanceof RegExp&&A(we.tagNameCheck,n))return!1;if(we.tagNameCheck instanceof Function&&we.tagNameCheck(n))return!1}if(Ge&&!Xe[n]){const t=re(e)||e.parentNode,n=oe(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o){const r=X(n[o],!0);r.__removalCount=(e.__removalCount||0)+1,t.insertBefore(r,ne(e))}}}return Tt(e),!0}return e instanceof R&&!function(e){let t=re(e);t&&t.tagName||(t={namespaceURI:tt,tagName:"template"});const n=f(e.tagName),o=f(t.tagName);return!!ot[e.namespaceURI]&&(e.namespaceURI===Qe?t.namespaceURI===et?"svg"===n:t.namespaceURI===Je?"svg"===n&&("annotation-xml"===o||it[o]):Boolean(ht[n]):e.namespaceURI===Je?t.namespaceURI===et?"math"===n:t.namespaceURI===Qe?"math"===n&&at[o]:Boolean(gt[n]):e.namespaceURI===et?!(t.namespaceURI===Qe&&!at[o])&&!(t.namespaceURI===Je&&!it[o])&&!gt[n]&&(lt[n]||!ht[n]):!("application/xhtml+xml"!==ct||!ot[e.namespaceURI]))}(e)?(Tt(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!A(/<\/no(script|embed|frames)/i,e.innerHTML)?(Me&&e.nodeType===Z&&(t=e.textContent,u([fe,de,he],(e=>{t=g(t,e," ")})),e.textContent!==t&&(p(o.removed,{element:e.cloneNode()}),e.textContent=t)),bt(pe.afterSanitizeElements,e,null),!1):(Tt(e),!0)},Rt=function(e,t,n){if(Be&&("id"===t||"name"===t)&&(n in r||n in pt))return!1;if(ve&&!De[t]&&A(ge,t));else if(Le&&A(Te,t));else if(!Ne[t]||De[t]){if(!(wt(e)&&(we.tagNameCheck instanceof RegExp&&A(we.tagNameCheck,e)||we.tagNameCheck instanceof Function&&we.tagNameCheck(e))&&(we.attributeNameCheck instanceof RegExp&&A(we.attributeNameCheck,t)||we.attributeNameCheck instanceof Function&&we.attributeNameCheck(t))||"is"===t&&we.allowCustomizedBuiltInElements&&(we.tagNameCheck instanceof RegExp&&A(we.tagNameCheck,n)||we.tagNameCheck instanceof Function&&we.tagNameCheck(n))))return!1}else if(Ve[t]);else if(A(_e,g(n,Ee,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==T(n,"data:")||!$e[e]){if(Ce&&!A(ye,g(n,Ee,"")));else if(n)return!1}else;return!0},wt=function(e){return"annotation-xml"!==e&&h(e,Ae)},Ot=function(e){bt(pe.beforeSanitizeAttributes,e,null);const{attributes:t}=e;if(!t||_t(e))return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Ne,forceKeepAttr:void 0};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=ut(a);let p="value"===a?c:y(c);if(n.attrName=s,n.attrValue=p,n.keepAttr=!0,n.forceKeepAttr=void 0,bt(pe.uponSanitizeAttribute,e,n),p=n.attrValue,!We||"id"!==s&&"name"!==s||(yt(a,e),p="user-content-"+p),ke&&A(/((--!?|])>)|<\/(style|title)/i,p)){yt(a,e);continue}if(n.forceKeepAttr)continue;if(yt(a,e),!n.keepAttr)continue;if(!xe&&A(/\/>/i,p)){yt(a,e);continue}Me&&u([fe,de,he],(e=>{p=g(p,e," ")}));const f=ut(e.nodeName);if(Rt(f,s,p)){if(ie&&"object"==typeof G&&"function"==typeof G.getAttributeType)if(l);else switch(G.getAttributeType(f,s)){case"TrustedHTML":p=ie.createHTML(p);break;case"TrustedScriptURL":p=ie.createScriptURL(p)}try{l?e.setAttributeNS(l,a,p):e.setAttribute(a,p),_t(e)?Tt(e):m(o.removed)}catch(e){}}}bt(pe.afterSanitizeAttributes,e,null)},Dt=function e(t){let n=null;const o=At(t);for(bt(pe.beforeSanitizeShadowDOM,t,null);n=o.nextNode();)bt(pe.uponSanitizeShadowNode,n,null),Nt(n),Ot(n),n.content instanceof s&&e(n.content);bt(pe.afterSanitizeShadowDOM,t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(nt=!e,nt&&(e="\x3c!--\x3e"),"string"!=typeof e&&!St(e)){if("function"!=typeof e.toString)throw _("toString is not a function");if("string"!=typeof(e=e.toString()))throw _("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Ue||dt(t),o.removed=[],"string"==typeof e&&(Ye=!1),Ye){if(e.nodeName){const t=ut(e.nodeName);if(!Se[t]||Oe[t])throw _("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof b)n=Et("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),r.nodeType===V&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!Pe&&!Me&&!Ie&&-1===e.indexOf("<"))return ie&&Fe?ie.createHTML(e):e;if(n=Et(e),!n)return Pe?null:Fe?ae:""}n&&ze&&Tt(n.firstChild);const c=At(Ye?e:n);for(;i=c.nextNode();)Nt(i),Ot(i),i.content instanceof s&&Dt(i.content);if(Ye)return e;if(Pe){if(He)for(l=se.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Ne.shadowroot||Ne.shadowrootmode)&&(l=me.call(a,l,!0)),l}let m=Ie?n.outerHTML:n.innerHTML;return Ie&&Se["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&A(q,n.ownerDocument.doctype.name)&&(m="\n"+m),Me&&u([fe,de,he],(e=>{m=g(m,e," ")})),ie&&Fe?ie.createHTML(m):m},o.setConfig=function(){dt(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Ue=!0},o.clearConfig=function(){mt=null,Ue=!1},o.isValidAttribute=function(e,t,n){mt||dt({});const o=ut(e),r=ut(t);return Rt(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&p(pe[e],t)},o.removeHook=function(e){return m(pe[e])},o.removeHooks=function(e){pe[e]=[]},o.removeAllHooks=function(){pe={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},o}();return ne})); diff --git a/lib/Configuration.php b/lib/Configuration.php index 9dd7f4f3..bb348e22 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -109,7 +109,7 @@ class Configuration 'js/legacy.js' => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', 'js/privatebin.js' => 'sha512-JUj/Sbl/bMHlIoIUT1U9e89JU33fDBxCxLSGxwwaeydBFXOBHyfdF7hwSIjgbPxb4d9CO7CSe4meouTIRMy8Vg==', - 'js/purify-3.1.7.js' => 'sha512-LegvqULiMtOfboJZw9MpETN/b+xnLRXZI90gG7oIFHW+yAeHmKvRtEUbiMFx2WvUqQoL9XB3gwU+hWXUT0X+8A==', + 'js/purify-3.2.3.js' => 'sha512-m8Wa/I//YoYMiIahBxDDwYfTnycl+i2DwH58nR8ps1o4KWqXzF8k1K4qHDgAz2HSQFNCNNKH/Qcbfu/jLOuhuQ==', 'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', 'js/zlib-1.3.1.js' => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==', diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 6d7b7483..8c601452 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -71,7 +71,7 @@ if ($MARKDOWN) : - _scriptTag('js/purify-3.1.7.js', 'async'); ?> + _scriptTag('js/purify-3.2.3.js', 'async'); ?> _scriptTag('js/legacy.js', 'async'); ?> _scriptTag('js/privatebin.js', 'defer'); ?> diff --git a/tpl/bootstrap5.php b/tpl/bootstrap5.php index 22909352..7a0e4bb4 100644 --- a/tpl/bootstrap5.php +++ b/tpl/bootstrap5.php @@ -55,7 +55,7 @@ if ($MARKDOWN) : - _scriptTag('js/purify-3.1.7.js', 'defer'); ?> + _scriptTag('js/purify-3.2.3.js', 'defer'); ?> _scriptTag('js/legacy.js', 'async'); ?> _scriptTag('js/privatebin.js', 'defer'); ?> diff --git a/tpl/page.php b/tpl/page.php index 4f42ebe1..0e844e1f 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -49,7 +49,7 @@ if ($MARKDOWN): - _scriptTag('js/purify-3.1.7.js', 'async'); ?> + _scriptTag('js/purify-3.2.3.js', 'async'); ?> _scriptTag('js/legacy.js', 'async'); ?> _scriptTag('js/privatebin.js', 'defer'); ?> From 21b259b5eb2ede4afe2d5788505b3943fe34fab4 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 22 Dec 2024 12:05:55 +0100 Subject: [PATCH 497/783] bump libraries, document change fixes #1301 --- CHANGELOG.md | 2 +- composer.json | 4 +- composer.lock | 16 +++--- vendor/composer/ClassLoader.php | 96 ++++++++++++++++----------------- vendor/composer/installed.php | 4 +- 5 files changed, 58 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d96eabb1..82ec2d3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 1.7.6 (not yet released) * CHANGED: Switched to WASM streaming and replace unsafe-eval with wasm-unsafe-eval CSP declaration (#1464), requires webserver to have `application/wasm` MIME type configured. -* CHANGED: Upgrading libraries to: cloud-storage 1.44.0, aws-sdk-php 3.331.0 +* CHANGED: Upgrading libraries to: cloud-storage 1.45.0, aws-sdk-php 3.336.2 ## 1.7.5 (2024-11-16) * ADDED: Allow non persistent SQL connections, if configured (#1394) diff --git a/composer.json b/composer.json index 10024a08..d3afb5f9 100644 --- a/composer.json +++ b/composer.json @@ -30,8 +30,8 @@ "yzalis/identicon": "2.0.0" }, "suggest" : { - "google/cloud-storage" : "1.44.0", - "aws/aws-sdk-php" : "3.331.0" + "google/cloud-storage" : "1.45.0", + "aws/aws-sdk-php" : "3.336.2" }, "require-dev" : { "phpunit/phpunit" : "^9" diff --git a/composer.lock b/composer.lock index a72fb37c..ec4a2425 100644 --- a/composer.lock +++ b/composer.lock @@ -810,16 +810,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.21", + "version": "9.6.22", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa" + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", - "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", "shasum": "" }, "require": { @@ -830,7 +830,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", + "myclabs/deep-copy": "^1.12.1", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=7.3", @@ -893,7 +893,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.21" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" }, "funding": [ { @@ -909,7 +909,7 @@ "type": "tidelift" } ], - "time": "2024-09-19T10:50:18+00:00" + "time": "2024-12-05T13:48:26+00:00" }, { "name": "sebastian/cli-parser", @@ -1937,5 +1937,5 @@ "platform-overrides": { "php": "7.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index a72151c7..7824d8f7 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -45,35 +45,34 @@ class ClassLoader /** @var \Closure(string):void */ private static $includeFile; - /** @var ?string */ + /** @var string|null */ private $vendorDir; // PSR-4 /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixLengthsPsr4 = array(); /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixDirsPsr4 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr4 = array(); // PSR-0 /** - * @var array[] - * @psalm-var array> + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> */ private $prefixesPsr0 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr0 = array(); @@ -81,8 +80,7 @@ class ClassLoader private $useIncludePath = false; /** - * @var string[] - * @psalm-var array + * @var array */ private $classMap = array(); @@ -90,21 +88,20 @@ class ClassLoader private $classMapAuthoritative = false; /** - * @var bool[] - * @psalm-var array + * @var array */ private $missingClasses = array(); - /** @var ?string */ + /** @var string|null */ private $apcuPrefix; /** - * @var self[] + * @var array */ private static $registeredLoaders = array(); /** - * @param ?string $vendorDir + * @param string|null $vendorDir */ public function __construct($vendorDir = null) { @@ -113,7 +110,7 @@ class ClassLoader } /** - * @return string[] + * @return array> */ public function getPrefixes() { @@ -125,8 +122,7 @@ class ClassLoader } /** - * @return array[] - * @psalm-return array> + * @return array> */ public function getPrefixesPsr4() { @@ -134,8 +130,7 @@ class ClassLoader } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirs() { @@ -143,8 +138,7 @@ class ClassLoader } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirsPsr4() { @@ -152,8 +146,7 @@ class ClassLoader } /** - * @return string[] Array of classname => path - * @psalm-return array + * @return array Array of classname => path */ public function getClassMap() { @@ -161,8 +154,7 @@ class ClassLoader } /** - * @param string[] $classMap Class to filename map - * @psalm-param array $classMap + * @param array $classMap Class to filename map * * @return void */ @@ -179,24 +171,25 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories * * @return void */ public function add($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - (array) $paths + $paths ); } @@ -205,19 +198,19 @@ class ClassLoader $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; + $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - (array) $paths + $paths ); } } @@ -226,9 +219,9 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException * @@ -236,17 +229,18 @@ class ClassLoader */ public function addPsr4($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - (array) $paths + $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -256,18 +250,18 @@ class ClassLoader throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; + $this->prefixDirsPsr4[$prefix] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - (array) $paths + $paths ); } } @@ -276,8 +270,8 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories * * @return void */ @@ -294,8 +288,8 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException * @@ -481,9 +475,9 @@ class ClassLoader } /** - * Returns the currently registered loaders indexed by their corresponding vendor directories. + * Returns the currently registered loaders keyed by their corresponding vendor directories. * - * @return self[] + * @return array */ public static function getRegisteredLoaders() { diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 7c68f160..ead63ad4 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'privatebin/privatebin', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '1c7d63954642b3852177793c0c17963303484051', + 'reference' => '15488d3405cfe28d08ca9662456181d48d550fec', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -31,7 +31,7 @@ 'privatebin/privatebin' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '1c7d63954642b3852177793c0c17963303484051', + 'reference' => '15488d3405cfe28d08ca9662456181d48d550fec', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), From 8b7ccb0fd4165f14ce7eab19c9213fb5c3ea7b80 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 22 Dec 2024 12:14:25 +0100 Subject: [PATCH 498/783] PHP 8.4 is no longer a development release --- .github/workflows/tests.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d668d74e..93f66501 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,11 +22,12 @@ jobs: continue-on-error: "${{ matrix.experimental }}" strategy: matrix: - php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] + php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] experimental: [false] - include: - - php-versions: '8.4' # development release, things can break - experimental: true +# uncomment this to start testing on development release +# include: +# - php-versions: '8.5' # development release, things can break +# experimental: true env: extensions: gd, sqlite3 extensions-cache-key-name: phpextensions From 99e0b7efacb1e7d11fa67a5a38e7fdad3387191e Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 25 Dec 2024 07:27:58 +0100 Subject: [PATCH 499/783] fix brackets, kudos @kanna5 --- js/privatebin.js | 4 ++-- lib/Configuration.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index d11b2355..e34979ec 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2309,10 +2309,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { // show new bootstrap method (if available) if ($passwordModal.length !== 0) { if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION) { - (new bootstrap.Modal($passwordModal[0]), { + (new bootstrap.Modal($passwordModal[0], { backdrop: 'static', keyboard: false - }).show(); + })).show(); } else { $passwordModal.modal({ backdrop: 'static', diff --git a/lib/Configuration.php b/lib/Configuration.php index 010d7aa1..a1afdda7 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -108,7 +108,7 @@ class Configuration 'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==', 'js/legacy.js' => 'sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-rbfSVRLvLB7zcmnDGOopePCL0BUEDH10Yd1sZig/l44MaxQGcMaAG/T5Zeln3it/0LxMOIujZV/By+0ShhwysQ==', + 'js/privatebin.js' => 'sha512-5JuYesxfZ0hS5Auqm5QkDsUy7ZzVabjcfS3zbVLfwkhJVt8ekzU5tYLbhaDTM+wmq3xwV+8N8krpp9fuF5kS3A==', 'js/purify-3.1.7.js' => 'sha512-LegvqULiMtOfboJZw9MpETN/b+xnLRXZI90gG7oIFHW+yAeHmKvRtEUbiMFx2WvUqQoL9XB3gwU+hWXUT0X+8A==', 'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', From 333f0568b64c10ebe511237bd55d9313f5a440a1 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Fri, 27 Dec 2024 09:17:35 +0100 Subject: [PATCH 500/783] fix bootstrap 5 modal usage kudos @kanna5 --- js/privatebin.js | 88 +++++++++++++++++++++---------------------- lib/Configuration.php | 2 +- tpl/bootstrap5.php | 2 +- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index e34979ec..f88753b5 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -2237,8 +2237,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { const me = {}; let $passwordDecrypt, - $passwordForm, $passwordModal, + bootstrap5PasswordModal = null, password = ''; /** @@ -2257,8 +2257,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { password = $passwordDecrypt.val(); // hide modal - if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION) { - (new bootstrap.Modal($passwordModal[0])).hide(); + if (bootstrap5PasswordModal) { + bootstrap5PasswordModal.hide(); } else { $passwordModal.modal('hide'); } @@ -2308,24 +2308,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { { // show new bootstrap method (if available) if ($passwordModal.length !== 0) { - if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION) { - (new bootstrap.Modal($passwordModal[0], { - backdrop: 'static', - keyboard: false - })).show(); + if (bootstrap5PasswordModal) { + bootstrap5PasswordModal.show(); } else { - $passwordModal.modal({ - backdrop: 'static', - keyboard: false - }); $passwordModal.modal('show'); } - // focus password input - $passwordDecrypt.focus(); - // then re-focus it, when modal causes it to loose focus again - setTimeout(function () { - $passwordDecrypt.focus(); - }, 500); return; } @@ -2369,7 +2356,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // and also reset UI $passwordDecrypt.val(''); - } + }; /** * init status manager @@ -2382,11 +2369,26 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.init = function() { $passwordDecrypt = $('#passworddecrypt'); - $passwordForm = $('#passwordform'); $passwordModal = $('#passwordmodal'); // bind events - handle Model password submission - $passwordForm.submit(submitPasswordModal); + if ($passwordModal.length !== 0) { + $('#passwordform').submit(submitPasswordModal); + + const disableClosingConfig = { + backdrop: 'static', + keyboard: false, + show: false + }; + if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION) { + bootstrap5PasswordModal = new bootstrap.Modal($passwordModal[0], disableClosingConfig); + } else { + $passwordModal.modal(disableClosingConfig); + } + $passwordModal.on('shown.bs.modal', () => { + $passwordDecrypt.focus(); + }); + } }; return me; @@ -3985,10 +3987,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { text: window.location.href }); $('#qrcode-display').html(qrCanvas); - // only necessary for bootstrap 5, other templates won't have this - if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION) { - (new bootstrap.Modal('#qrcodemodal')).show(); - } } /** @@ -4077,32 +4075,34 @@ jQuery.PrivateBin = (function($, RawDeflate) { if (expirationDate !== null) { const $emailconfirmTimezoneCurrent = $emailconfirmmodal.find('#emailconfirm-timezone-current'); const $emailconfirmTimezoneUtc = $emailconfirmmodal.find('#emailconfirm-timezone-utc'); - $emailconfirmTimezoneCurrent.off('click.sendEmailCurrentTimezone'); - $emailconfirmTimezoneCurrent.on('click.sendEmailCurrentTimezone', () => { - const emailBody = templateEmailBody(expirationDateRoundedToSecond.toLocaleString(), isBurnafterreading); - if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION) { - (new bootstrap.Modal($emailconfirmmodal[0])).hide(); + let localeConfiguration = { dateStyle: 'long', timeStyle: 'long' }; + const bootstrap5EmailConfirmModal = typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION ? + new bootstrap.Modal($emailconfirmmodal[0]) : null; + + function sendEmailAndHideModal() { + const emailBody = templateEmailBody( + // we don't use Date.prototype.toUTCString() because we would like to avoid GMT + expirationDateRoundedToSecond.toLocaleString( + [], localeConfiguration + ), isBurnafterreading + ); + if (bootstrap5EmailConfirmModal) { + bootstrap5EmailConfirmModal.hide(); } else { $emailconfirmmodal.modal('hide'); } triggerEmailSend(emailBody); - }); + }; + + $emailconfirmTimezoneCurrent.off('click.sendEmailCurrentTimezone'); + $emailconfirmTimezoneCurrent.on('click.sendEmailCurrentTimezone', sendEmailAndHideModal); $emailconfirmTimezoneUtc.off('click.sendEmailUtcTimezone'); $emailconfirmTimezoneUtc.on('click.sendEmailUtcTimezone', () => { - const emailBody = templateEmailBody(expirationDateRoundedToSecond.toLocaleString( - undefined, - // we don't use Date.prototype.toUTCString() because we would like to avoid GMT - { timeZone: 'UTC', dateStyle: 'long', timeStyle: 'long' } - ), isBurnafterreading); - if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION) { - (new bootstrap.Modal($emailconfirmmodal[0])).hide(); - } else { - $emailconfirmmodal.modal('hide'); - } - triggerEmailSend(emailBody); + localeConfiguration.timeZone = 'UTC'; + sendEmailAndHideModal(); }); - if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip.VERSION) { - (new bootstrap.Modal($emailconfirmmodal[0])).show(); + if (bootstrap5EmailConfirmModal) { + bootstrap5EmailConfirmModal.show(); } else { $emailconfirmmodal.modal('show'); } diff --git a/lib/Configuration.php b/lib/Configuration.php index dc1fcb94..6bc95238 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -108,7 +108,7 @@ class Configuration 'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==', 'js/legacy.js' => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-5JuYesxfZ0hS5Auqm5QkDsUy7ZzVabjcfS3zbVLfwkhJVt8ekzU5tYLbhaDTM+wmq3xwV+8N8krpp9fuF5kS3A==', + 'js/privatebin.js' => 'sha512-1RKY0XUEbDtZ6M4/YUwmLsav/qSzteqc/93jvEaH5mFLhCl8f+dItPy6Q8hUcydz10oyCYrB4DFSAtYfcaKZMg==', 'js/purify-3.1.7.js' => 'sha512-LegvqULiMtOfboJZw9MpETN/b+xnLRXZI90gG7oIFHW+yAeHmKvRtEUbiMFx2WvUqQoL9XB3gwU+hWXUT0X+8A==', 'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', diff --git a/tpl/bootstrap5.php b/tpl/bootstrap5.php index 4db055ca..d96aafb6 100644 --- a/tpl/bootstrap5.php +++ b/tpl/bootstrap5.php @@ -193,7 +193,7 @@ if ($EMAIL) : endif; if ($QRCODE) : ?> - Date: Fri, 27 Dec 2024 09:45:22 +0100 Subject: [PATCH 501/783] avoid unnecessary indentation --- lib/I18n.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/I18n.php b/lib/I18n.php index 3737bc46..89693083 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -134,10 +134,8 @@ class I18n if (strpos($args[0], '') !== false) { continue; } - } else { - if (is_int($args[$i])) { - continue; - } + } elseif (is_int($args[$i])) { + continue; } $args[$i] = self::encode($args[$i]); } From 6c39a1441c72bd8ef4c45544d7903a093d4bef28 Mon Sep 17 00:00:00 2001 From: ribas160 Date: Sat, 28 Dec 2024 18:42:46 +0200 Subject: [PATCH 502/783] Copy paste to clipboard button added. Copy paste to clipboard shortcut added --- css/bootstrap/privatebin.css | 39 ++++++++++ css/bootstrap5/privatebin.css | 35 +++++++++ css/privatebin.css | 1 + i18n/ar.json | 4 +- i18n/bg.json | 4 +- i18n/ca.json | 4 +- i18n/co.json | 4 +- i18n/cs.json | 4 +- i18n/de.json | 4 +- i18n/el.json | 4 +- i18n/en.json | 4 +- i18n/es.json | 4 +- i18n/et.json | 4 +- i18n/fi.json | 4 +- i18n/fr.json | 4 +- i18n/he.json | 4 +- i18n/hi.json | 4 +- i18n/hu.json | 4 +- i18n/id.json | 4 +- i18n/it.json | 4 +- i18n/ja.json | 4 +- i18n/jbo.json | 4 +- i18n/ko.json | 4 +- i18n/ku.json | 4 +- i18n/la.json | 4 +- i18n/lt.json | 4 +- i18n/nl.json | 4 +- i18n/no.json | 4 +- i18n/oc.json | 4 +- i18n/pl.json | 4 +- i18n/pt.json | 4 +- i18n/ro.json | 4 +- i18n/ru.json | 4 +- i18n/sk.json | 4 +- i18n/sl.json | 4 +- i18n/sv.json | 4 +- i18n/th.json | 4 +- i18n/tr.json | 4 +- i18n/uk.json | 4 +- i18n/zh.json | 4 +- img/content-copy-icon.svg | 1 + js/privatebin.js | 138 ++++++++++++++++++++++++++++++++++ lib/Configuration.php | 2 +- tpl/bootstrap.php | 9 +++ tpl/bootstrap5.php | 5 ++ 45 files changed, 340 insertions(+), 38 deletions(-) create mode 100644 img/content-copy-icon.svg diff --git a/css/bootstrap/privatebin.css b/css/bootstrap/privatebin.css index a7c0f188..7bb6d286 100644 --- a/css/bootstrap/privatebin.css +++ b/css/bootstrap/privatebin.css @@ -175,3 +175,42 @@ html[dir="rtl"] #language { html[dir="rtl"] #deletelink, html[dir="rtl"] #qrcodemodalClose { float: left; } + +#prettyprint { + padding-right: 30px; +} + +#prettymessageCopyBtn { + position: absolute; + top: 5px; + right: 20px; + width: 25px; + height: 25px; + padding: 0; + background: none; + border: none; + z-index: 1; +} + +#prettymessageCopyBtn svg { + width: 100%; +} + +#copyIcon { + fill: rgb(145, 152, 161); + opacity: 0.4; + transition: all 0.3s ease; +} + +#copyIcon:hover { + opacity: 1; +} + +#copySuccessIcon { + fill: rgb(63, 185, 80); + display: none; +} + +#copyShortcutHint { + margin-bottom: 5px; +} \ No newline at end of file diff --git a/css/bootstrap5/privatebin.css b/css/bootstrap5/privatebin.css index b14768a1..1fa54d70 100644 --- a/css/bootstrap5/privatebin.css +++ b/css/bootstrap5/privatebin.css @@ -84,3 +84,38 @@ li.L0, li.L1, li.L2, li.L3, li.L4, li.L5, li.L6, li.L7, li.L8, li.L9 { html[dir="rtl"] #deletelink, html[dir="rtl"] #qrcodemodalClose { float: left; } + +#prettyprint { + padding-right: 30px; +} + +#prettymessageCopyBtn { + position: absolute; + top: 5px; + right: 5px; + width: 25px; + height: 25px; + padding: 0; + background: none; + border: none; + z-index: 1; +} + +#prettymessageCopyBtn svg { + width: 100%; +} + +#copyIcon { + fill: rgb(145, 152, 161); + opacity: 0.4; + transition: all 0.3s ease; +} + +#copyIcon:hover { + opacity: 1; +} + +#copySuccessIcon { + fill: rgb(63, 185, 80); + display: none; +} diff --git a/css/privatebin.css b/css/privatebin.css index 77824fb6..473875de 100644 --- a/css/privatebin.css +++ b/css/privatebin.css @@ -86,6 +86,7 @@ h3.title { #aboutbox a { color: #94a3b4; } #message, #cleartext, #prettymessage, #attachment, .replymessage { + position: relative; clear: both; color: #000; background-color: #fff; diff --git a/i18n/ar.json b/i18n/ar.json index 5fffac70..a82fdbe0 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -219,5 +219,7 @@ "Yes, see it": "نعم، حمله", "Dark Mode": "الوضع الداكن", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/bg.json b/i18n/bg.json index 44b669a2..2d076bbe 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ca.json b/i18n/ca.json index fca160e7..034f7846 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error de compressió de la nota, no hi ha suport de WebAssembly.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/co.json b/i18n/co.json index d59bdb22..905e41b1 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -219,5 +219,7 @@ "Yes, see it": "Iè, fighjallu", "Dark Mode": "Modu scuru", "Error compressing paste, due to missing WebAssembly support.": "Sbagliu durante a cumpressione di l’appiccicu, perchè WebAssembly ùn hè micca accettatu.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Sbagliu durante a scumpressione di l’appiccicu, perchè u vostru navigatore ùn accetteghja micca WebAssembly. Ci vole à impiegà un altru navigatore per affissà st’appiccicu." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Sbagliu durante a scumpressione di l’appiccicu, perchè u vostru navigatore ùn accetteghja micca WebAssembly. Ci vole à impiegà un altru navigatore per affissà st’appiccicu.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/cs.json b/i18n/cs.json index 5e4b88b2..37ef227a 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/de.json b/i18n/de.json index 8bc311bd..fbf9b864 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -219,5 +219,7 @@ "Yes, see it": "Ja, jetzt einsehen", "Dark Mode": "Nachtmodus", "Error compressing paste, due to missing WebAssembly support.": "Fehler beim Komprimieren des Textes, da WebAssembly-Unterstützung fehlt.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Fehler beim Dekomprimieren des Textes. Dein Browser unterstützt WebAssembly nicht. Bitte verwende einen anderen Browser, um diesen Text anzuzeigen." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Fehler beim Dekomprimieren des Textes. Dein Browser unterstützt WebAssembly nicht. Bitte verwende einen anderen Browser, um diesen Text anzuzeigen.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/el.json b/i18n/el.json index f1278fd5..2d46877d 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -219,5 +219,7 @@ "Yes, see it": "Ναι, δείτε το", "Dark Mode": "Σκοτεινό Θέμα", "Error compressing paste, due to missing WebAssembly support.": "Σφάλμα συμπίεσης επικόλλησης, λόγω έλλειψης υποστήριξης WebAssembly.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Σφάλμα αποσυμπίεσης της επικόλλησης, ο περιηγητής σας δεν υποστηρίζει WebAssembly. Παρακαλούμε χρησιμοποιήστε έναν άλλο περιηγητή για να δείτε αυτή την επικόλληση." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Σφάλμα αποσυμπίεσης της επικόλλησης, ο περιηγητής σας δεν υποστηρίζει WebAssembly. Παρακαλούμε χρησιμοποιήστε έναν άλλο περιηγητή για να δείτε αυτή την επικόλληση.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/en.json b/i18n/en.json index 64bc773f..ac296e1b 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/es.json b/i18n/es.json index ea96caa9..63d221fd 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -219,5 +219,7 @@ "Yes, see it": "Sí, verlo", "Dark Mode": "Modo nocturno", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/et.json b/i18n/et.json index b58ece48..54b9d00f 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Tume režiim", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/fi.json b/i18n/fi.json index 3341555a..3c290ffa 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -219,5 +219,7 @@ "Yes, see it": "Kyllä, näet sen", "Dark Mode": "Tumma tila", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/fr.json b/i18n/fr.json index e4676f2e..21ae376d 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -219,5 +219,7 @@ "Yes, see it": "Oui, le voir", "Dark Mode": "Mode Sombre", "Error compressing paste, due to missing WebAssembly support.": "Erreur lors de la compression du paste, en raison du support de WebAssembly manquant.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Erreur lors de la décompression du paste, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Erreur lors de la décompression du paste, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/he.json b/i18n/he.json index 22a0af1b..bb506b7c 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/hi.json b/i18n/hi.json index 64bc773f..ac296e1b 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/hu.json b/i18n/hu.json index 3f232d97..93d2a13f 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Sötét mód", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/id.json b/i18n/id.json index e4387f95..4ba1baa2 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Mode Gelap", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/it.json b/i18n/it.json index d972a8c5..c0954486 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -219,5 +219,7 @@ "Yes, see it": "Sì, visualizzalo", "Dark Mode": "Tema Scuro", "Error compressing paste, due to missing WebAssembly support.": "Errore nella compressione dell messaggio, a causa del supporto WebAssembly mancante.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Errore nella decompressione dell messaggio, il tuo browser non supporta WebAssembly. Utilizza un altro browser per visualizzare questo messaggio." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Errore nella decompressione dell messaggio, il tuo browser non supporta WebAssembly. Utilizza un altro browser per visualizzare questo messaggio.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ja.json b/i18n/ja.json index 48f91a72..7084cda4 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -219,5 +219,7 @@ "Yes, see it": "はい、使用します", "Dark Mode": "ダークモード", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/jbo.json b/i18n/jbo.json index 7cce9584..37eda35a 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ko.json b/i18n/ko.json index 64bc773f..ac296e1b 100644 --- a/i18n/ko.json +++ b/i18n/ko.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ku.json b/i18n/ku.json index 84d070a7..2e787916 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "جۆری ڕەش", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/la.json b/i18n/la.json index 45e9951c..5174379e 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/lt.json b/i18n/lt.json index 63aeb17f..acbff84e 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -219,5 +219,7 @@ "Yes, see it": "Taip, pamatyti", "Dark Mode": "Tamsi veiksena", "Error compressing paste, due to missing WebAssembly support.": "Klaida glaudinant įdėjimą, nes trūksta WebAssembly palaikymo.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Klaida išglaudinant įdėjimą, jūsų naršyklė nepalaiko WebAssembly. Norėdami peržiūrėti šį įdėjimą, naudokite kitą naršyklę." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Klaida išglaudinant įdėjimą, jūsų naršyklė nepalaiko WebAssembly. Norėdami peržiūrėti šį įdėjimą, naudokite kitą naršyklę.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/nl.json b/i18n/nl.json index 80efa6ad..8efefc27 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -219,5 +219,7 @@ "Yes, see it": "Ja, tonen", "Dark Mode": "Donkere modus", "Error compressing paste, due to missing WebAssembly support.": "Fout bij het comprimeren van notitie door ontbrekende ondersteuning voor WebAssembly.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Fout bij het decomprimeren van de notitie, uw browser ondersteunt WebAssembly niet. Gebruik een andere browser om deze notitie te bekijken." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Fout bij het decomprimeren van de notitie, uw browser ondersteunt WebAssembly niet. Gebruik een andere browser om deze notitie te bekijken.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/no.json b/i18n/no.json index f1850408..17911fde 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -219,5 +219,7 @@ "Yes, see it": "Ja, se det", "Dark Mode": "Mørk modus", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/oc.json b/i18n/oc.json index 3799d86c..97adbb63 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Dark Mode", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/pl.json b/i18n/pl.json index 51f38eed..181ddeef 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Ciemny motyw", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/pt.json b/i18n/pt.json index 34252572..7553fdb7 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -219,5 +219,7 @@ "Yes, see it": "Sim, veja", "Dark Mode": "Modo Noturno", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ro.json b/i18n/ro.json index 5d1d1b3b..698693f4 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -219,5 +219,7 @@ "Yes, see it": "Da, vezi", "Dark Mode": "Mod întunecat", "Error compressing paste, due to missing WebAssembly support.": "Eroare la compresia paste-ului din cauza incompatibilității cu WebAssembly.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Eroare la deschiderea paste-ului, browserul dvs. nu acceptă WebAssembly. Vă rugăm să utilizați un alt browser pentru a vedea acest paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Eroare la deschiderea paste-ului, browserul dvs. nu acceptă WebAssembly. Vă rugăm să utilizați un alt browser pentru a vedea acest paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ru.json b/i18n/ru.json index d7081105..c561a92a 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -219,5 +219,7 @@ "Yes, see it": "Да, загрузить", "Dark Mode": "Тёмная", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Запись скопирована в буфер обмена", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Чтобы скопировать запись нажмите на кнопку скопирования или используйте комбинацию клавиш Ctrl+c/Cmd+c" } diff --git a/i18n/sk.json b/i18n/sk.json index 59390e13..972a40b5 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Tmavý Režim", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/sl.json b/i18n/sl.json index cb0f1e50..a56f79e5 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Temni način", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/sv.json b/i18n/sv.json index 0e24e37b..6e278f84 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "Mörkt Läge", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/th.json b/i18n/th.json index c0aa6803..a1da0993 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -219,5 +219,7 @@ "Yes, see it": "Yes, see it", "Dark Mode": "โหมดมืด", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/tr.json b/i18n/tr.json index 49dcad49..cd98b08e 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -219,5 +219,7 @@ "Yes, see it": "Evet, görüyorum", "Dark Mode": "Koyu Mod", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/uk.json b/i18n/uk.json index cfb8c44e..a8ce1e3c 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -219,5 +219,7 @@ "Yes, see it": "Так, побачити", "Dark Mode": "Темний режим", "Error compressing paste, due to missing WebAssembly support.": "Помилка при стисканні допису, через відсутність підтримки WebAssembly сервера.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте інший браузер для перегляду цього допису." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте інший браузер для перегляду цього допису.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/zh.json b/i18n/zh.json index 80f081c5..07cb05e5 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -219,5 +219,7 @@ "Yes, see it": "是的,加载它", "Dark Mode": "暗黑模式", "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.", - "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste." + "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", + "Paste copied to clipboard": "Paste copied to clipboard", + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/img/content-copy-icon.svg b/img/content-copy-icon.svg new file mode 100644 index 00000000..77b63083 --- /dev/null +++ b/img/content-copy-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js/privatebin.js b/js/privatebin.js index 9c843628..df84f94c 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -4901,6 +4901,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { TopNav.showViewButtons(); + CopyToClipboard.showKeyboardShortcutHint(); + // this cannot be grouped with showViewButtons due to remaining time calculation TopNav.showEmailButton(); @@ -5337,6 +5339,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { // shows the remaining time (until) deletion PasteStatus.showRemainingTime(paste); + CopyToClipboard.showKeyboardShortcutHint(); + Promise.all(decryptionPromises) .then(() => { Alert.hideLoading(); @@ -5366,6 +5370,138 @@ jQuery.PrivateBin = (function($, RawDeflate) { return me; })(); + /** + * + * @name CopyToClipboard + * @class + */ + const CopyToClipboard = (function () { + const me = {}; + + let copyButton = $("#prettymessageCopyBtn"), + copyIcon = $("#copyIcon"), + successIcon = $("#copySuccessIcon"), + shortcutHint = $("#copyShortcutHintText"); + + /** + * Handle copy to clipboard button click + * + * @name CopyToClipboard.handleCopyButtonClick + * @private + * @function + */ + function handleCopyButtonClick() { + $(copyButton).click(function() { + const text = PasteViewer.getText(); + saveToClipboard(text); + }); + }; + + /** + * Handle CTRL+C/CMD+C keyboard shortcut + * + * @name CopyToClipboard.handleKeyboardShortcut + * @private + * @function + */ + function handleKeyboardShortcut() { + $(document).bind('copy', function () { + if (!isUserSelectedTextToCopy()) { + const text = PasteViewer.getText(); + saveToClipboard(text); + } + }); + } + + /** + * Check if user selected some text on the page to copy it + * + * @name CopyToClipboard.isUserSelectedTextToCopy + * @private + * @function + * @returns {boolean} + */ + function isUserSelectedTextToCopy() { + let text = ""; + + if (window.getSelection) { + text = window.getSelection().toString(); + } else if (document.selection && document.selection.type != "Control") { + text = document.selection.createRange().text; + } + + return text.length > 0; + } + + /** + * Save text to the clipboard + * + * @name CopyToClipboard.saveToClipboard + * @private + * @param {string} text + * @function + */ + function saveToClipboard(text) { + navigator.clipboard.writeText(text); + toggleSuccessIcon(); + showAlertMessage(); + }; + + /** + * Show alert message after text copy + * + * @name CopyToClipboard.showAlertMessage + * @private + * @function + */ + function showAlertMessage() { + Alert.showStatus("Paste copied to clipboard"); + } + + /** + * Toogle success icon after copy + * + * @name CopyToClipboard.toggleSuccessIcon + * @private + * @function + */ + function toggleSuccessIcon() { + $(copyIcon).css("display", "none"); + $(successIcon).css("display", "block"); + + setTimeout(function() { + $(copyIcon).css("display", "block"); + $(successIcon).css("display", "none"); + }, 1000); + }; + + /** + * Show keyboard shortcut hint + * + * @name CopyToClipboard.showKeyboardShortcutHint + * @function + */ + me.showKeyboardShortcutHint = function () { + I18n._( + shortcutHint, + 'To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c' + ); + } + + /** + * Initialize + * + * @name CopyToClipboard.init + * @function + */ + me.init = function() { + handleCopyButtonClick(); + handleKeyboardShortcut(); + } + + return me; + })(); + /** * (controller) main PrivateBin logic * @@ -5612,6 +5748,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { Prompt.init(); TopNav.init(); UiHelper.init(); + CopyToClipboard.init(); // check for legacy browsers before going any further if (!Legacy.Check.getInit()) { @@ -5668,6 +5805,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { ServerInteraction: ServerInteraction, PasteEncrypter: PasteEncrypter, PasteDecrypter: PasteDecrypter, + CopyToClipboard: CopyToClipboard, Controller: Controller }; })(jQuery, RawDeflate); diff --git a/lib/Configuration.php b/lib/Configuration.php index 9b2717ca..d246a30b 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -108,7 +108,7 @@ class Configuration 'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==', 'js/legacy.js' => 'sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-cbmXvtZ/5gZPFjQDzP3IEhUAIhFPAoM31gw2kRYCT5xOh8wv9gXeDqI/t798luRW1xdC4gaYodjEFCzrsZR4mA==', + 'js/privatebin.js' => 'sha512-9caF+XTVriuyh86qLZ26dHbL6PfyOnSAB6zC2IhP6V/lifBxi28aJK0tm/t+F0GSdFXprzY0k8Ld3fbkbR0YJg==', 'js/purify-3.1.6.js' => 'sha512-SDwfsqHZFhbcBo/6AN7Te4KoUkWHHw7TzyZCuRkkpl0o8oV4owT/lprznWWe9+qFtigb6MrF81K4CQRLN6be+A==', 'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 901bced7..aaa299c2 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -572,7 +572,16 @@ endif;
+
diff --git a/tpl/bootstrap5.php b/tpl/bootstrap5.php index 298c1684..57ef0a8e 100644 --- a/tpl/bootstrap5.php +++ b/tpl/bootstrap5.php @@ -426,7 +426,12 @@ endif;
+
From 0462da6e8e495799be3c07a4fb911e8ebefa4e09 Mon Sep 17 00:00:00 2001 From: ribas160 Date: Wed, 1 Jan 2025 19:14:58 +0200 Subject: [PATCH 503/783] - used bootstrap 5 CSS icon named copy, bootstrap 3 CSS glyphicon named duplicate - keyboard-shortcuts made more accessible by wrapping the keys into kbd-tags - translate messages may contain allowed HTML tags - added the record to the CHANGELOG.md --- CHANGELOG.md | 1 + css/bootstrap/privatebin.css | 25 +++------ css/bootstrap5/privatebin.css | 40 +++++++------ i18n/ar.json | 2 +- i18n/bg.json | 2 +- i18n/ca.json | 2 +- i18n/co.json | 2 +- i18n/cs.json | 2 +- i18n/de.json | 2 +- i18n/el.json | 2 +- i18n/en.json | 2 +- i18n/es.json | 2 +- i18n/et.json | 2 +- i18n/fi.json | 2 +- i18n/fr.json | 2 +- i18n/he.json | 2 +- i18n/hi.json | 2 +- i18n/hu.json | 2 +- i18n/id.json | 2 +- i18n/it.json | 2 +- i18n/ja.json | 2 +- i18n/jbo.json | 2 +- i18n/ko.json | 2 +- i18n/ku.json | 2 +- i18n/la.json | 2 +- i18n/lt.json | 2 +- i18n/nl.json | 2 +- i18n/no.json | 2 +- i18n/oc.json | 2 +- i18n/pl.json | 2 +- i18n/pt.json | 2 +- i18n/ro.json | 2 +- i18n/ru.json | 2 +- i18n/sk.json | 2 +- i18n/sl.json | 2 +- i18n/sv.json | 2 +- i18n/th.json | 2 +- i18n/tr.json | 2 +- i18n/uk.json | 2 +- i18n/zh.json | 2 +- img/content-copy-icon.svg | 1 - js/privatebin.js | 102 ++++++++++++++++++++++------------ lib/Configuration.php | 2 +- tpl/bootstrap.php | 10 +--- tpl/bootstrap5.php | 6 +- 45 files changed, 141 insertions(+), 120 deletions(-) delete mode 100644 img/content-copy-icon.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index d96eabb1..ae2d426d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.7.6 (not yet released) * CHANGED: Switched to WASM streaming and replace unsafe-eval with wasm-unsafe-eval CSP declaration (#1464), requires webserver to have `application/wasm` MIME type configured. * CHANGED: Upgrading libraries to: cloud-storage 1.44.0, aws-sdk-php 3.331.0 +* ADDED: Ability to copy the paste by clicking the copy icon button or using the keyboard shortcut ctrl+c/cmd+c (#1390) ## 1.7.5 (2024-11-16) * ADDED: Allow non persistent SQL connections, if configured (#1394) diff --git a/css/bootstrap/privatebin.css b/css/bootstrap/privatebin.css index 5f47f6e6..ab2fdebc 100644 --- a/css/bootstrap/privatebin.css +++ b/css/bootstrap/privatebin.css @@ -143,34 +143,23 @@ html[dir="rtl"] #deletelink, html[dir="rtl"] #qrcodemodalClose { padding-right: 30px; } -#prettymessageCopyBtn { +#prettyMessageCopyBtn { position: absolute; - top: 5px; - right: 20px; - width: 25px; - height: 25px; + top: 8px; + right: 25px; + left: auto; padding: 0; background: none; border: none; z-index: 1; } -#prettymessageCopyBtn svg { - width: 100%; -} - -#copyIcon { - fill: rgb(145, 152, 161); - opacity: 0.4; - transition: all 0.3s ease; -} - -#copyIcon:hover { - opacity: 1; +html[dir="rtl"] #prettyMessageCopyBtn { + left: 25px; + right: auto; } #copySuccessIcon { - fill: rgb(63, 185, 80); display: none; } diff --git a/css/bootstrap5/privatebin.css b/css/bootstrap5/privatebin.css index 38bc3fdb..b633dbff 100644 --- a/css/bootstrap5/privatebin.css +++ b/css/bootstrap5/privatebin.css @@ -14,6 +14,15 @@ display: none !important; } +.opacity-05-1-hover { + opacity: 0.5; + transition: all 0.15s ease; +} + +.opacity-05-1-hover:hover { + opacity: 1; +} + .dropdown-menu { --bs-dropdown-min-width: 23rem; } @@ -44,33 +53,30 @@ html[dir="rtl"] #deletelink, html[dir="rtl"] #qrcodemodalClose { padding-right: 30px; } -#prettymessageCopyBtn { +#prettyMessageCopyBtn { position: absolute; - top: 5px; - right: 5px; - width: 25px; - height: 25px; + top: 8px; + right: 8px; + left: auto; + width: 20px; + height: 20px; padding: 0; background: none; border: none; z-index: 1; } -#prettymessageCopyBtn svg { +html[dir="rtl"] #prettyMessageCopyBtn { + left: 8px; + right: auto; +} + +#prettyMessageCopyBtn svg { width: 100%; -} - -#copyIcon { - fill: rgb(145, 152, 161); - opacity: 0.4; - transition: all 0.3s ease; -} - -#copyIcon:hover { - opacity: 1; + height: 100%; + vertical-align: baseline; } #copySuccessIcon { - fill: rgb(63, 185, 80); display: none; } diff --git a/i18n/ar.json b/i18n/ar.json index 4e4e91ba..56b3b8c6 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/bg.json b/i18n/bg.json index d0e1bcda..e8cf177f 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ca.json b/i18n/ca.json index 26a48446..65159327 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/co.json b/i18n/co.json index 496a92e1..f5a7e9c0 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Sbagliu durante a scumpressione di l’appiccicu, perchè u vostru navigatore ùn accetteghja micca WebAssembly. Ci vole à impiegà un altru navigatore per affissà st’appiccicu.", "Start over": "Principià torna", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/cs.json b/i18n/cs.json index f51c6c9f..de42249a 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Chyba při dekomprimování příspěvku, váš prohlížeč nepodporuje WebAssembly. Pro zobrazení tohoto příspěvku prosím použijte jiný prohlížeč.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/de.json b/i18n/de.json index c918baf0..d250e788 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Fehler beim Dekomprimieren des Textes. Dein Browser unterstützt WebAssembly nicht. Bitte verwende einen anderen Browser, um diesen Text anzuzeigen.", "Start over": "Neuen Text erstellen", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/el.json b/i18n/el.json index f64e8d63..f88b702e 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Σφάλμα αποσυμπίεσης της επικόλλησης, ο περιηγητής σας δεν υποστηρίζει WebAssembly. Παρακαλούμε χρησιμοποιήστε έναν άλλο περιηγητή για να δείτε αυτή την επικόλληση.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/en.json b/i18n/en.json index 040a15b7..28f2efbc 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/es.json b/i18n/es.json index 3b312f43..a7e4206b 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/et.json b/i18n/et.json index 9183e7a2..45d868db 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/fi.json b/i18n/fi.json index 1452ea08..fa8de23f 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/fr.json b/i18n/fr.json index a87e453f..99f1d730 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Erreur lors de la décompression du paste, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce paste.", "Start over": "Recommencer", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/he.json b/i18n/he.json index 77ed3e1d..eed6897b 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/hi.json b/i18n/hi.json index 040a15b7..28f2efbc 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/hu.json b/i18n/hu.json index 97e1fc44..c756a989 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/id.json b/i18n/id.json index 32e274c0..e05f5fd0 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/it.json b/i18n/it.json index 3e9f8162..a6c97ffc 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Errore nella decompressione dell messaggio, il tuo browser non supporta WebAssembly. Utilizza un altro browser per visualizzare questo messaggio.", "Start over": "Ricominciare", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ja.json b/i18n/ja.json index d8c7ae01..f1e5d911 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/jbo.json b/i18n/jbo.json index dc992536..1524be0e 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ko.json b/i18n/ko.json index 040a15b7..28f2efbc 100644 --- a/i18n/ko.json +++ b/i18n/ko.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ku.json b/i18n/ku.json index f56f4b8a..71958f36 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/la.json b/i18n/la.json index e17f7c57..9e522e1d 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/lt.json b/i18n/lt.json index 41a07bbc..81cd6154 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Klaida išglaudinant įdėjimą, jūsų naršyklė nepalaiko WebAssembly. Norėdami peržiūrėti šį įdėjimą, naudokite kitą naršyklę.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/nl.json b/i18n/nl.json index a6aaa3e4..8d391029 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Fout bij het decomprimeren van de notitie, uw browser ondersteunt WebAssembly niet. Gebruik een andere browser om deze notitie te bekijken.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/no.json b/i18n/no.json index b793472f..4935887c 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/oc.json b/i18n/oc.json index 4226a4ea..8bb3618b 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error al moment de descompresar l'empegatge, vòstre navegador pren pas en carga WebAssembly. Mercés d'utilizar un autre navigador per visualizar aquesta pega.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/pl.json b/i18n/pl.json index 7707a09c..5c2e38e8 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Błąd dekompresowania wklejenia przez brak obsługi WebAssembly przez przeglądarkę. Użyj innej przeglądarki, aby zobaczyć to wklejenie.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/pt.json b/i18n/pt.json index 95b7f5ee..c84f7cde 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ro.json b/i18n/ro.json index 801019a6..aafa33e0 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Eroare la deschiderea paste-ului, browserul dvs. nu acceptă WebAssembly. Vă rugăm să utilizați un alt browser pentru a vedea acest paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/ru.json b/i18n/ru.json index 3439835a..5b538bc8 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Запись скопирована в буфер обмена", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Чтобы скопировать запись нажмите на кнопку скопирования или используйте комбинацию клавиш Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Чтобы скопировать запись нажмите на кнопку копирования или используйте комбинацию клавиш Ctrl+c/Cmd+c" } diff --git a/i18n/sk.json b/i18n/sk.json index 0441ce78..9136397d 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/sl.json b/i18n/sl.json index 1318735e..84205b49 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/sv.json b/i18n/sv.json index a35c712c..94b10e3c 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/th.json b/i18n/th.json index 21229b43..0dad59dc 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "ไม่สามารถอ่านข้อมูลที่คุณได้ฝากโค้ดไว้ เบราว์เซอร์ของคุณไม่รองรับ WebAssembly กรุณาลองเปลี่ยนใช้เบราว์เซอร์ตัวอื่นเพื่อดูการฝากโค้ดนี้อีกครั้ง", "Start over": "เริ่มใหม่", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/tr.json b/i18n/tr.json index 70d7545c..f06be075 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Yazı açılırken hata oluştu, tarayıcınız WebAssembly'i desteklemiyor. Lütfen bu yazıyı görüntülemek için başka bir tarayıcı kullanın.", "Start over": "Baştan başla", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/uk.json b/i18n/uk.json index 82ba56eb..b4eb3d69 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте в іншому браузері для перегляду цього допису.", "Start over": "Почати знову", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/i18n/zh.json b/i18n/zh.json index f3433912..73b6bc8f 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -222,5 +222,5 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "解压粘贴时出错,您的浏览器不支持 WebAssembly。请使用其他浏览器查看此粘贴。", "Start over": "重新开始", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" } diff --git a/img/content-copy-icon.svg b/img/content-copy-icon.svg deleted file mode 100644 index 77b63083..00000000 --- a/img/content-copy-icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/js/privatebin.js b/js/privatebin.js index a4627647..74e37def 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -757,14 +757,14 @@ jQuery.PrivateBin = (function($, RawDeflate) { args[0] = translations[messageId]; } - // messageID may contain links, but should be from a trusted source (code or translation JSON files) - let containsLinks = args[0].indexOf(' 0) may never contain HTML as they may come from untrusted parties - if ((containsLinks ? i > 1 : i > 0) || !containsLinks) { + if ((containsHtml ? i > 1 : i > 0) || !containsHtml) { args[i] = Helper.htmlEntities(args[i]); } } @@ -772,11 +772,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { // format string let output = Helper.sprintf.apply(this, args); - if (containsLinks) { + if (containsHtml) { // only allow tags/attributes we actually use in translations output = DOMPurify.sanitize( output, { - ALLOWED_TAGS: ['a', 'i', 'span'], + ALLOWED_TAGS: ['a', 'i', 'span', 'kbd'], ALLOWED_ATTR: ['href', 'id'] } ); @@ -784,7 +784,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // if $element is given, insert translation if ($element !== null) { - if (containsLinks) { + if (containsHtml) { $element.html(output); } else { // text node takes care of entity encoding @@ -914,6 +914,25 @@ jQuery.PrivateBin = (function($, RawDeflate) { translations = mockTranslations || {}; }; + /** + * Check if string contains valid HTML code + * + * @name I18n.isStringContainsHtml + * @function + * @private + * @param {string} messageId + * @returns {boolean} + */ + function isStringContainsHtml(messageId) { + // An integer which specifies the type of the node. An Element node like

or

. + const elementNodeType = 1; + + const div = document.createElement('div'); + div.innerHTML = messageId; + + return Array.from(div.childNodes).some(node => node.nodeType === elementNodeType); + } + return me; })(); @@ -3768,7 +3787,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { /** * Clear the password input in the top navigation - * + * * @name TopNav.clearPasswordInput * @function */ @@ -5371,21 +5390,21 @@ jQuery.PrivateBin = (function($, RawDeflate) { })(); /** - * + * * @name CopyToClipboard * @class */ const CopyToClipboard = (function () { const me = {}; - let copyButton = $("#prettymessageCopyBtn"), - copyIcon = $("#copyIcon"), - successIcon = $("#copySuccessIcon"), - shortcutHint = $("#copyShortcutHintText"); + let copyButton = $('#prettyMessageCopyBtn'), + copyIcon = $('#copyIcon'), + successIcon = $('#copySuccessIcon'), + shortcutHint = $('#copyShortcutHintText'); /** * Handle copy to clipboard button click - * + * * @name CopyToClipboard.handleCopyButtonClick * @private * @function @@ -5399,7 +5418,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { /** * Handle CTRL+C/CMD+C keyboard shortcut - * + * * @name CopyToClipboard.handleKeyboardShortcut * @private * @function @@ -5411,31 +5430,31 @@ jQuery.PrivateBin = (function($, RawDeflate) { saveToClipboard(text); } }); - } + }; /** * Check if user selected some text on the page to copy it - * + * * @name CopyToClipboard.isUserSelectedTextToCopy * @private * @function * @returns {boolean} */ function isUserSelectedTextToCopy() { - let text = ""; - + let text = ''; + if (window.getSelection) { text = window.getSelection().toString(); - } else if (document.selection && document.selection.type != "Control") { + } else if (document.selection && document.selection.type != 'Control') { text = document.selection.createRange().text; } - + return text.length > 0; - } + }; /** * Save text to the clipboard - * + * * @name CopyToClipboard.saveToClipboard * @private * @param {string} text @@ -5449,55 +5468,65 @@ jQuery.PrivateBin = (function($, RawDeflate) { /** * Show alert message after text copy - * + * * @name CopyToClipboard.showAlertMessage * @private * @function */ function showAlertMessage() { - Alert.showStatus("Paste copied to clipboard"); - } + Alert.showStatus(I18n._('Paste copied to clipboard')); + }; /** * Toogle success icon after copy - * + * * @name CopyToClipboard.toggleSuccessIcon * @private * @function */ function toggleSuccessIcon() { - $(copyIcon).css("display", "none"); - $(successIcon).css("display", "block"); + $(copyIcon).css('display', 'none'); + $(successIcon).css('display', 'block'); setTimeout(function() { - $(copyIcon).css("display", "block"); - $(successIcon).css("display", "none"); + $(copyIcon).css('display', 'block'); + $(successIcon).css('display', 'none'); }, 1000); }; /** * Show keyboard shortcut hint - * + * * @name CopyToClipboard.showKeyboardShortcutHint * @function */ me.showKeyboardShortcutHint = function () { I18n._( shortcutHint, - 'To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c' + 'To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c' ); - } + }; + + /** + * Hide keyboard shortcut hint + * + * @name CopyToClipboard.showKeyboardShortcutHint + * @function + */ + me.hideKeyboardShortcutHint = function () { + $(shortcutHint).html(''); + }; /** * Initialize - * + * * @name CopyToClipboard.init * @function */ me.init = function() { handleCopyButtonClick(); handleKeyboardShortcut(); - } + }; return me; })(); @@ -5523,6 +5552,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { { PasteStatus.hideMessages(); Alert.hideMessages(); + CopyToClipboard.hideKeyboardShortcutHint(); }; /** diff --git a/lib/Configuration.php b/lib/Configuration.php index ec753793..a262e8fe 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -108,7 +108,7 @@ class Configuration 'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==', 'js/legacy.js' => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-l9FxMcY99yenozSdmWgraPIfGd0TMdAMs3TBRZCKHrBECJqiYS385wfLdN8D3ffpa0HZHvgjRyk2Txs0r+v6FQ==', + 'js/privatebin.js' => 'sha512-4ZwwNQ6GWRx90JqxNJ5SI7qN9A75r1f5vWUd3+GUXEkXvNmygjDGR/unOvKRgGZxXYhW5N42ytNx7CXes0MX/Q==', 'js/purify-3.1.7.js' => 'sha512-LegvqULiMtOfboJZw9MpETN/b+xnLRXZI90gG7oIFHW+yAeHmKvRtEUbiMFx2WvUqQoL9XB3gwU+hWXUT0X+8A==', 'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index e9777a0a..d0a4aa45 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -581,13 +581,9 @@ endif;
diff --git a/tpl/bootstrap5.php b/tpl/bootstrap5.php index ddd9d6ce..fb45ffd7 100644 --- a/tpl/bootstrap5.php +++ b/tpl/bootstrap5.php @@ -437,9 +437,9 @@ endif;
From b86eb93dbe553482fe7003e8a5429bab6b360061 Mon Sep 17 00:00:00 2001 From: ribas160 Date: Fri, 3 Jan 2025 18:19:12 +0200 Subject: [PATCH 504/783] Added the button to copy the paste link to the clipboard --- CREDITS.md | 1 + i18n/ar.json | 4 +++- i18n/bg.json | 4 +++- i18n/ca.json | 4 +++- i18n/co.json | 4 +++- i18n/cs.json | 4 +++- i18n/de.json | 4 +++- i18n/el.json | 4 +++- i18n/en.json | 4 +++- i18n/es.json | 4 +++- i18n/et.json | 4 +++- i18n/fi.json | 4 +++- i18n/fr.json | 4 +++- i18n/he.json | 4 +++- i18n/hi.json | 4 +++- i18n/hu.json | 4 +++- i18n/id.json | 4 +++- i18n/it.json | 4 +++- i18n/ja.json | 4 +++- i18n/jbo.json | 4 +++- i18n/ko.json | 4 +++- i18n/ku.json | 4 +++- i18n/la.json | 4 +++- i18n/lt.json | 4 +++- i18n/nl.json | 4 +++- i18n/no.json | 4 +++- i18n/oc.json | 4 +++- i18n/pl.json | 4 +++- i18n/pt.json | 4 +++- i18n/ro.json | 4 +++- i18n/ru.json | 4 +++- i18n/sk.json | 4 +++- i18n/sl.json | 4 +++- i18n/sv.json | 4 +++- i18n/th.json | 4 +++- i18n/tr.json | 4 +++- i18n/uk.json | 4 +++- i18n/zh.json | 4 +++- js/privatebin.js | 44 ++++++++++++++++++++++++++++++++++++++----- lib/Configuration.php | 2 +- tpl/bootstrap.php | 3 +++ tpl/bootstrap5.php | 3 +++ 42 files changed, 158 insertions(+), 43 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 2ca6fe0b..e5513a1f 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -33,6 +33,7 @@ * Mounir Idrassi & J. Mozdzen - secure YOURLS integration * Felipe Nakandakari - enabled AWS SDK to use default credential provider chain in the S3 Storage backend * Aaron Sherber - cache control headers for API calls & use of `shortenviayourls` in query parameters +* Mikhail Romanov - copying to clipboard ## Translations * Hexalyse - French diff --git a/i18n/ar.json b/i18n/ar.json index 56b3b8c6..16903e72 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/bg.json b/i18n/bg.json index e8cf177f..d8707475 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/ca.json b/i18n/ca.json index 65159327..b24503f3 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/co.json b/i18n/co.json index f5a7e9c0..9a39726d 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Sbagliu durante a scumpressione di l’appiccicu, perchè u vostru navigatore ùn accetteghja micca WebAssembly. Ci vole à impiegà un altru navigatore per affissà st’appiccicu.", "Start over": "Principià torna", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/cs.json b/i18n/cs.json index de42249a..c3510eac 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Chyba při dekomprimování příspěvku, váš prohlížeč nepodporuje WebAssembly. Pro zobrazení tohoto příspěvku prosím použijte jiný prohlížeč.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/de.json b/i18n/de.json index d250e788..4af7d517 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Fehler beim Dekomprimieren des Textes. Dein Browser unterstützt WebAssembly nicht. Bitte verwende einen anderen Browser, um diesen Text anzuzeigen.", "Start over": "Neuen Text erstellen", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/el.json b/i18n/el.json index f88b702e..947909ee 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Σφάλμα αποσυμπίεσης της επικόλλησης, ο περιηγητής σας δεν υποστηρίζει WebAssembly. Παρακαλούμε χρησιμοποιήστε έναν άλλο περιηγητή για να δείτε αυτή την επικόλληση.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/en.json b/i18n/en.json index 28f2efbc..4a30584c 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/es.json b/i18n/es.json index a7e4206b..6520252e 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/et.json b/i18n/et.json index 45d868db..013eef15 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/fi.json b/i18n/fi.json index fa8de23f..328a647a 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/fr.json b/i18n/fr.json index 99f1d730..0f04cd09 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Erreur lors de la décompression du paste, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce paste.", "Start over": "Recommencer", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/he.json b/i18n/he.json index eed6897b..3b01e387 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/hi.json b/i18n/hi.json index 28f2efbc..4a30584c 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/hu.json b/i18n/hu.json index c756a989..333cb80b 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/id.json b/i18n/id.json index e05f5fd0..1cd680b6 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/it.json b/i18n/it.json index a6c97ffc..a33f09c3 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Errore nella decompressione dell messaggio, il tuo browser non supporta WebAssembly. Utilizza un altro browser per visualizzare questo messaggio.", "Start over": "Ricominciare", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/ja.json b/i18n/ja.json index f1e5d911..ec5255c7 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/jbo.json b/i18n/jbo.json index 1524be0e..960ac963 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/ko.json b/i18n/ko.json index 28f2efbc..4a30584c 100644 --- a/i18n/ko.json +++ b/i18n/ko.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/ku.json b/i18n/ku.json index 71958f36..32bff821 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/la.json b/i18n/la.json index 9e522e1d..2d876806 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/lt.json b/i18n/lt.json index 81cd6154..f6b59605 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Klaida išglaudinant įdėjimą, jūsų naršyklė nepalaiko WebAssembly. Norėdami peržiūrėti šį įdėjimą, naudokite kitą naršyklę.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/nl.json b/i18n/nl.json index 8d391029..650c7401 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Fout bij het decomprimeren van de notitie, uw browser ondersteunt WebAssembly niet. Gebruik een andere browser om deze notitie te bekijken.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/no.json b/i18n/no.json index 4935887c..022b12cd 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/oc.json b/i18n/oc.json index 8bb3618b..e7906ff6 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error al moment de descompresar l'empegatge, vòstre navegador pren pas en carga WebAssembly. Mercés d'utilizar un autre navigador per visualizar aquesta pega.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/pl.json b/i18n/pl.json index 5c2e38e8..149682c2 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Błąd dekompresowania wklejenia przez brak obsługi WebAssembly przez przeglądarkę. Użyj innej przeglądarki, aby zobaczyć to wklejenie.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/pt.json b/i18n/pt.json index c84f7cde..618bdff2 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/ro.json b/i18n/ro.json index aafa33e0..055a797e 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Eroare la deschiderea paste-ului, browserul dvs. nu acceptă WebAssembly. Vă rugăm să utilizați un alt browser pentru a vedea acest paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/ru.json b/i18n/ru.json index 5b538bc8..01ad80fa 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Запись скопирована в буфер обмена", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Чтобы скопировать запись нажмите на кнопку копирования или используйте комбинацию клавиш Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Чтобы скопировать запись нажмите на кнопку копирования или используйте комбинацию клавиш Ctrl+c/Cmd+c", + "Copy link": "Скопировать ссылку", + "Link copied to clipboard": "Ссылка скопирована в буфер обмена" } diff --git a/i18n/sk.json b/i18n/sk.json index 9136397d..20f56b96 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/sl.json b/i18n/sl.json index 84205b49..665c057d 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/sv.json b/i18n/sv.json index 94b10e3c..56948010 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.", "Start over": "Start over", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/th.json b/i18n/th.json index 0dad59dc..1629bb9c 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "ไม่สามารถอ่านข้อมูลที่คุณได้ฝากโค้ดไว้ เบราว์เซอร์ของคุณไม่รองรับ WebAssembly กรุณาลองเปลี่ยนใช้เบราว์เซอร์ตัวอื่นเพื่อดูการฝากโค้ดนี้อีกครั้ง", "Start over": "เริ่มใหม่", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/tr.json b/i18n/tr.json index f06be075..0fd28f6f 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Yazı açılırken hata oluştu, tarayıcınız WebAssembly'i desteklemiyor. Lütfen bu yazıyı görüntülemek için başka bir tarayıcı kullanın.", "Start over": "Baştan başla", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/uk.json b/i18n/uk.json index b4eb3d69..ae76312f 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте в іншому браузері для перегляду цього допису.", "Start over": "Почати знову", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/i18n/zh.json b/i18n/zh.json index 73b6bc8f..1c7c5f38 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -222,5 +222,7 @@ "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "解压粘贴时出错,您的浏览器不支持 WebAssembly。请使用其他浏览器查看此粘贴。", "Start over": "重新开始", "Paste copied to clipboard": "Paste copied to clipboard", - "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c" + "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "To copy paste press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "Copy link": "Copy link", + "Link copied to clipboard": "Link copied to clipboard" } diff --git a/js/privatebin.js b/js/privatebin.js index 74e37def..483eb333 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -4920,6 +4920,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { TopNav.showViewButtons(); + CopyToClipboard.setUrl(url); CopyToClipboard.showKeyboardShortcutHint(); // this cannot be grouped with showViewButtons due to remaining time calculation @@ -5398,9 +5399,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { const me = {}; let copyButton = $('#prettyMessageCopyBtn'), + copyLinkButton = $('#copyLink'), copyIcon = $('#copyIcon'), successIcon = $('#copySuccessIcon'), - shortcutHint = $('#copyShortcutHintText'); + shortcutHint = $('#copyShortcutHintText'), + url; /** * Handle copy to clipboard button click @@ -5413,9 +5416,27 @@ jQuery.PrivateBin = (function($, RawDeflate) { $(copyButton).click(function() { const text = PasteViewer.getText(); saveToClipboard(text); + + toggleSuccessIcon(); + showAlertMessage('Paste copied to clipboard'); }); }; + /** + * Handle copy link to clipboard button click + * + * @name CopyToClipboard.handleCopyLinkButtonClick + * @private + * @function + */ + function handleCopyLinkButtonClick() { + $(copyLinkButton).click(function () { + saveToClipboard(url); + + showAlertMessage('Link copied to clipboard'); + }); + } + /** * Handle CTRL+C/CMD+C keyboard shortcut * @@ -5428,6 +5449,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { if (!isUserSelectedTextToCopy()) { const text = PasteViewer.getText(); saveToClipboard(text); + + showAlertMessage('Paste copied to clipboard'); } }); }; @@ -5462,8 +5485,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ function saveToClipboard(text) { navigator.clipboard.writeText(text); - toggleSuccessIcon(); - showAlertMessage(); }; /** @@ -5471,10 +5492,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { * * @name CopyToClipboard.showAlertMessage * @private + * @param {string} message * @function */ - function showAlertMessage() { - Alert.showStatus(I18n._('Paste copied to clipboard')); + function showAlertMessage(message) { + Alert.showStatus(message); }; /** @@ -5517,6 +5539,17 @@ jQuery.PrivateBin = (function($, RawDeflate) { $(shortcutHint).html(''); }; + /** + * Set paste url + * + * @name CopyToClipboard.setUrl + * @param {string} newUrl + * @function + */ + me.setUrl = function (newUrl) { + url = newUrl; + }; + /** * Initialize * @@ -5525,6 +5558,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ me.init = function() { handleCopyButtonClick(); + handleCopyLinkButtonClick(); handleKeyboardShortcut(); }; diff --git a/lib/Configuration.php b/lib/Configuration.php index a262e8fe..2dba64ac 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -108,7 +108,7 @@ class Configuration 'js/kjua-0.9.0.js' => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==', 'js/legacy.js' => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-4ZwwNQ6GWRx90JqxNJ5SI7qN9A75r1f5vWUd3+GUXEkXvNmygjDGR/unOvKRgGZxXYhW5N42ytNx7CXes0MX/Q==', + 'js/privatebin.js' => 'sha512-cCt3Slm10JXtPJhgmYdf1RKO7uWdz6U+k0bdPjTYfdO6WeWfruN9RkJE7tKmpgw8A35H4Xifmrr2KmyVOMbc3g==', 'js/purify-3.1.7.js' => 'sha512-LegvqULiMtOfboJZw9MpETN/b+xnLRXZI90gG7oIFHW+yAeHmKvRtEUbiMFx2WvUqQoL9XB3gwU+hWXUT0X+8A==', 'js/rawinflate-0.3.js' => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index d0a4aa45..f4780797 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -535,6 +535,9 @@ if ($HTTPWARNING) : endif; ?>