Compare commits

..

No commits in common. "master" and "1.7.6" have entirely different histories.

123 changed files with 2221 additions and 2035 deletions

View File

@ -43,7 +43,7 @@ jobs:
actions: read
id-token: write
contents: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
with:
base64-subjects: "${{ needs.release.outputs.hashes }}"
draft-release: true

View File

@ -24,7 +24,7 @@ jobs:
steps:
- name: Download and Extract Artifacts
uses: dawidd6/action-download-artifact@07ab29fd4a977ae4d2b275087cf67563dfdf0295
uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc
with:
run_id: ${{ github.event.workflow_run.id }}
path: artifacts

View File

@ -121,7 +121,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: '20'
cache: 'npm'
cache-dependency-path: 'js/package-lock.json'

View File

@ -2,7 +2,6 @@ RewriteEngine on
RewriteCond !%{HTTP_USER_AGENT} "Let's Encrypt validation server" [NC]
RewriteCond %{HTTP_USER_AGENT} ^.*(bot|spider|crawl|https?://|WhatsApp|SkypeUriPreview|facebookexternalhit) [NC]
RewriteRule .* - [R=403,L]
AddType application/wasm .wasm
<IfModule mod_php7.c>
php_value max_execution_time 30

View File

@ -1,11 +1,5 @@
# PrivateBin version history
## 1.7.7 (not yet released)
* ADDED: Switching templates using the web ui (#1501)
* CHANGED: Passing large data structures by reference to reduce memory consumption (#858)
* CHANGED: Removed use of ctype functions and polyfill library for ctype
* CHANGED: Upgrading libraries to: DOMpurify 3.2.5, ip-lib 1.20.0
## 1.7.6 (2025-02-01)
* ADDED: Ability to copy the paste by clicking the copy icon button or using the keyboard shortcut ctrl+c/cmd+c (#1390 & #12)
* CHANGED: Allow toggling tab-key-support using `[Ctrl]+[m]` or `[Esc]` in textarea for keyboard navigation (#1386)

View File

@ -33,7 +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, UI/UX improvements, templates switching
* Mikhail Romanov - copying to clipboard, UI/UX improvements
## Translations
* Hexalyse - French

View File

@ -14,8 +14,5 @@ a response within a week (usually during the next weekend). The respondee will
reply from their personal address and can offer you their GPG public key to
support end-to-end encrypted communication on sensitive topics or attachments.
You can also [use the corresponding GitHub form](https://github.com/PrivateBin/PrivateBin/security/advisories/new)
to report a new vulnerability directly on GitHub.
You can also contact us via the regular issue tracker if the risk of early
publication is low or you would request input from other PrivateBin users.

View File

@ -42,28 +42,13 @@ defaultformatter = "plaintext"
; size limit per paste or comment in bytes, defaults to 10 Mebibytes
sizelimit = 10485760
; by default PrivateBin use "bootstrap" template (tpl/bootstrap.php).
; Optionally you can enable the template selection menu, which uses
; a session cookie to store the choice until the browser is closed.
templateselection = false
; List of available for selection templates when "templateselection" option is enabled
availabletemplates[] = "bootstrap"
availabletemplates[] = "bootstrap-page"
availabletemplates[] = "bootstrap-dark"
availabletemplates[] = "bootstrap-dark-page"
availabletemplates[] = "bootstrap-compact"
availabletemplates[] = "bootstrap-compact-page"
availabletemplates[] = "bootstrap5"
availabletemplates[] = "page"
; set the template your installs defaults to, defaults to "bootstrap" (tpl/bootstrap.php), also
; template to include, default is "bootstrap" (tpl/bootstrap.php), also
; available are "page" (tpl/page.php), the classic ZeroBin style and several
; bootstrap variants: "bootstrap-dark", "bootstrap-compact", "bootstrap-page",
; which can be combined with "-dark" and "-compact" for "bootstrap-dark-page",
; "bootstrap-compact-page" and finally "bootstrap5" (tpl/bootstrap5.php) - previews at:
; which can be combined with "-dark" and "-compact" for "bootstrap-dark-page"
; and finally "bootstrap-compact-page" - previews at:
; https://privatebin.info/screenshots.html
; template = "bootstrap"
template = "bootstrap"
; (optional) info text to display
; use single, instead of double quotes for HTML attributes

View File

@ -26,8 +26,9 @@
"require" : {
"php": "^7.3 || ^8.0",
"jdenticon/jdenticon": "1.0.2",
"mlocati/ip-lib": "1.20.0",
"symfony/polyfill-php80": "1.31.0",
"mlocati/ip-lib": "1.18.1",
"symfony/polyfill-ctype": "^1.31",
"symfony/polyfill-php80": "^1.31",
"yzalis/identicon": "2.0.0"
},
"suggest" : {

105
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6c7e6dea19e8bfd5641b220cb68c4b65",
"content-hash": "0fdf0f08646fa2a4cf9c076131f529f5",
"packages": [
{
"name": "jdenticon/jdenticon",
@ -57,16 +57,16 @@
},
{
"name": "mlocati/ip-lib",
"version": "1.20.0",
"version": "1.18.1",
"source": {
"type": "git",
"url": "https://github.com/mlocati/ip-lib.git",
"reference": "fd45fc3bf08ed6c7e665e2e70562082ac954afd4"
"reference": "08bb43b4949069c543ebdf099a6b2c322d0172ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mlocati/ip-lib/zipball/fd45fc3bf08ed6c7e665e2e70562082ac954afd4",
"reference": "fd45fc3bf08ed6c7e665e2e70562082ac954afd4",
"url": "https://api.github.com/repos/mlocati/ip-lib/zipball/08bb43b4949069c543ebdf099a6b2c322d0172ab",
"reference": "08bb43b4949069c543ebdf099a6b2c322d0172ab",
"shasum": ""
},
"require": {
@ -112,7 +112,7 @@
],
"support": {
"issues": "https://github.com/mlocati/ip-lib/issues",
"source": "https://github.com/mlocati/ip-lib/tree/1.20.0"
"source": "https://github.com/mlocati/ip-lib/tree/1.18.1"
},
"funding": [
{
@ -124,7 +124,86 @@
"type": "other"
}
],
"time": "2025-02-04T17:30:58+00:00"
"time": "2024-10-29T15:44:19+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php80",
@ -337,16 +416,16 @@
},
{
"name": "myclabs/deep-copy",
"version": "1.13.0",
"version": "1.12.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "024473a478be9df5fdaca2c793f2232fe788e414"
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
"reference": "024473a478be9df5fdaca2c793f2232fe788e414",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845",
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845",
"shasum": ""
},
"require": {
@ -385,7 +464,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
"source": "https://github.com/myclabs/DeepCopy/tree/1.12.1"
},
"funding": [
{
@ -393,7 +472,7 @@
"type": "tidelift"
}
],
"time": "2025-02-12T12:17:51+00:00"
"time": "2024-11-08T17:47:46+00:00"
},
{
"name": "nikic/php-parser",

View File

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

View File

@ -218,14 +218,13 @@
"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.": "خطأ في ضغط اللصق، بسبب فقدان دعم WebAssembly.",
"Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "خطأ في فك ضغط اللصق، متصفحك لا يدعم WebAssembly. الرجاء استخدام متصفح آخر لعرض هذه اللصقة.",
"Start over": "ابدأ من جديد",
"Paste copied to clipboard": "تم نسخ اللصق إلى الحافظة",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "لنسخ اللصق انقر على زر النسخ أو استخدم اختصار الحافظة <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "نسخ الرابط",
"Link copied to clipboard": "تم نسخ الرابط إلى الحافظة",
"Paste text": "لصق النص",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "مفتاح التبويب يعمل كشخصية (انقر <kbd>Ctrl</kbd>+<kbd>m</kbd> أو <kbd>Esc</kbd> للتبديل)",
"Theme": "السمة"
"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",
"Paste copied to clipboard": "Paste copied to clipboard",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Cupià u liame",
"Link copied to clipboard": "U liame hè statu cupiatu in u premepapei",
"Paste text": "Testu di lappiccicu",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "U tastu di tabulazione ghjova cumè un caratteru (Appughjate nantà <kbd>Ctrl</kbd>+<kbd>m</kbd> o <kbd>Scapp</kbd> per scambià)",
"Theme": "Tema"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "U tastu di tabulazione ghjova cumè un caratteru (Appughjate nantà <kbd>Ctrl</kbd>+<kbd>m</kbd> o <kbd>Scapp</kbd> per scambià)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Verknüpfung kopieren",
"Link copied to clipboard": "Verknüpfung wurde in die Zwischenablage kopiert.",
"Paste text": "Text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulatortaste als Zeichen interpretieren (Umschalten durch <kbd>Strg</kbd>+<kbd>m</kbd> oder <kbd>Esc</kbd>)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulatortaste als Zeichen interpretieren (Umschalten durch <kbd>Strg</kbd>+<kbd>m</kbd> oder <kbd>Esc</kbd>)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -215,17 +215,16 @@
"Trying to shorten a URL that isn't pointing at our instance.": "Püüame lühendada URL-i, mis ei viita meie instantsile.",
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Viga YOURLS-i kutsumisel. Tõenäoliselt konfiguratsiooniprobleem, näiteks vale või puuduv \"apiurl\" või \"signature\".",
"Error parsing YOURLS response.": "Viga YOURLS vastuse parsimisel.",
"This secret message can only be displayed once. Would you like to see it now?": "Seda turvalist sõnumit saab kuvada vaid ühe korra. \nKas soovid seda näha nüüd?",
"Yes, see it": "Jah, vaata seda",
"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": "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.",
"Start over": "Alusta uuesti",
"Paste copied to clipboard": "Kleebe kopeeriti lõikelauale",
"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 <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Kopeeri link",
"Link copied to clipboard": "Link kopeeriti lõikelauale",
"Paste text": "Kleebi tekst",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Teema"
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -218,14 +218,13 @@
"This secret message can only be displayed once. Would you like to see it now?": "Tämä salainen viesti voidaan näyttää vain kerran. Haluatko nähdä sen nyt?",
"Yes, see it": "Kyllä, näet sen",
"Dark Mode": "Tumma tila",
"Error compressing paste, due to missing WebAssembly support.": "Virhe pakattaessa pastea, koska WebAssembly-tuki puuttuu.",
"Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Virhe pasten purkamisessa, selaimesi ei tue WebAssemblyä. Ole hyvä ja käytä toista selainta nähdäksesi tämä paste.",
"Start over": "Aloita alusta",
"Paste copied to clipboard": "Paste kopioitu leikepöydälle",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "Voit kopioida pasten painamalla kopioi-painiketta tai käyttämällä leikepöydän oikotietä <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Kopioi linkki",
"Link copied to clipboard": "Linkki kopioitu leikepöydälle",
"Paste text": "Liitä teksti",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulaattori toimii merkkinä (Paina <kbd>Ctrl</kbd>+<kbd>m</kbd> tai <kbd>Esc</kbd> vaihtaaksesi)",
"Theme": "Teema"
"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",
"Paste copied to clipboard": "Paste copied to clipboard",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -151,7 +151,7 @@
"server error or not responding": "Le serveur ne répond pas ou a rencontré une erreur",
"Could not post comment: %s": "Impossible de poster le commentaire : %s",
"Sending paste…": "Envoi du paste…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "Votre paste est disponible à l'adresse <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Appuyez sur <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd> pour copier)</span>",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "Votre paste est disponible à l'adresse <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Appuyez sur <kbd>Ctrl</kbd>+<kbd>c</kbd> pour copier)</span>",
"Delete data": "Supprimer les données du paste",
"Could not create paste: %s": "Impossible de créer le 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?)": "Impossible de déchiffrer le paste : Clé de déchiffrement manquante dans l'URL (Avez-vous utilisé un redirecteur ou un site de réduction d'URL qui supprime une partie de l'URL ?)",
@ -221,11 +221,10 @@
"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.",
"Start over": "Recommencer",
"Paste copied to clipboard": "Paste copié dans le presse-papier",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "Pour copier-coller appuyer sur le bouton To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Paste copied to clipboard": "Paste copied to clipboard",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Copier le lien",
"Link copied to clipboard": "Lien copié dans le presse-papier",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Texte du paste",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "La touche de tabulation sert de caractère (Presser <kbd>Ctrl</kbd>+<kbd>m</kbd> ou <kbd>Esc</kbd> pour basculer)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -1,7 +1,7 @@
{
"PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s הוא שירות pastebin מקוון, מינימליסטי וקוד פתוח, שבו לשרת אין כל ידע על המידע שהודבק. הנתונים מוצפנים ומפוענחים %sבדפדפן%s באמצעות הצפנת AES ב-256 סיביות.",
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "מידע נוסף בדף <a href=\"https://privatebin.info/\">הפרויקט</a>.",
"%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 <a href=\"https://privatebin.info/\">project page</a>.": "More information on the <a href=\"https://privatebin.info/\">project page</a>.",
"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 כדי לפעול.",
@ -29,7 +29,7 @@
"Create": "צור",
"Clone": "שכפול",
"Raw text": "טקסט גולמי",
"Expires": "יפוג ב",
"Expires": "Expires",
"Burn after reading": "קוראים-שורפים",
"Open discussion": "פתיחת דיון",
"Password (recommended)": "ססמה (מומלץ)",
@ -53,11 +53,11 @@
],
"%d hours": [
"שעה אחת",
"%d שעות",
"%d שעות",
"%d שעות",
"%d שעות",
"%d שעות"
"%d hours (1st plural)",
"%d hours (2nd plural)",
"%d hours (3rd plural)",
"%d hours (4th plural)",
"%d hours (5th plural)"
],
"%d days": [
"יום אחד",
@ -94,44 +94,44 @@
"Never": "לעולם לא",
"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.": [
"מסמך זה יפוג בעוד שנייה אחת.",
"מסמך זה יפוג בעוד %d שניות.",
"מסמך זה יפוג בעוד %d שניות.",
"מסמך זה יפוג בעוד %d שניות.",
"מסמך זה יפוג בעוד %d שניות.",
"מסמך זה יפוג בעוד %d שניות."
"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.": [
"מסמך זה יפוג בעוד דקה אחת.",
"מסמך זה יפוג בעוד %d דקות.",
"מסמך זה יפוג בעוד %d דקות.",
"מסמך זה יפוג בעוד %d דקות.",
"מסמך זה יפוג בעוד %d דקות.",
"מסמך זה יפוג בעוד %d דקות."
"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.": [
"מסמך זה יפוג בעוד שעה אחת.",
"מסמך זה יפוג בעוד %d שעות.",
"מסמך זה יפוג בעוד %d שעות.",
"מסמך זה יפוג בעוד %d שעות.",
"מסמך זה יפוג בעוד %d שעות.",
"מסמך זה יפוג בעוד %d שעות."
"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.": [
"מסמך זה יפוג בעוד יום אחד.",
"מסמך זה יפוג בעוד %d ימים.",
"מסמך זה יפוג בעוד %d ימים.",
"מסמך זה יפוג בעוד %d ימים.",
"מסמך זה יפוג בעוד %d ימים.",
"מסמך זה יפוג בעוד %d ימים."
"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.": [
"מסמך זה יפוג בעוד חודש אחד.",
"מסמך זה יפוג בעוד %d חודשים.",
"מסמך זה יפוג בעוד %d חודשים.",
"מסמך זה יפוג בעוד %d חודשים.",
"מסמך זה יפוג בעוד %d חודשים.",
"מסמך זה יפוג בעוד %d חודשים."
"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:": "נא למלא את הססמה להדבקה הזו:",
"Could not decrypt data (Wrong key?)": "לא ניתן לפענח את הנתונים (מפתח שגוי?)",
@ -170,29 +170,29 @@
"Markdown": "Markdown",
"Download attachment": "הורדת קובץ מצורף",
"Cloned: '%s'": "שוכפל: '%s'",
"The cloned file '%s' was attached to this paste.": "הקובץ '%s' שהועתק צורף להדבקה זו.",
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
"Attach a file": "צירוף קובץ",
"alternatively drag & drop a file or paste an image from the clipboard": "לחלופין, ניתן לגרור ולשחרר קובץ או להדביק תמונה מהלוח.",
"File too large, to display a preview. Please download the attachment.": "הקובץ גדול מדי כדי להציג תצוגה מקדימה. אנא הורד את הקובץ המצורף.",
"Remove attachment": "הסר קובץ מצורף",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "הדפדפן שלך אינו תומך בהעלאת קבצים מוצפנים. אנא השתמש בדפדפן עדכני יותר.",
"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.": "קובץ מצורף שגוי.",
"Options": "אפשרויות",
"Shorten URL": "קיצור כתובת",
"Editor": "עורך",
"Preview": "תצוגה מקדימה",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s דורש שה-PATH יסתיים ב-\"%s\". אנא עדכן את ה-PATH בקובץ index.php שלך.",
"%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": "פענוח",
"Enter password": "נא למלא ססמה",
"Loading…": "בטעינה…",
"Decrypting paste…": "ההדבקה מפוענחת…",
"Preparing new paste…": "ההדבקה החדשה בהכנות…",
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "אם הודעה זו לא נעלמת, אנא עיין ב- <a href=\"%s\">שאלות נפוצות אלה למידע לפתרון בעיות</a>.",
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.",
"+++ no paste text +++": "+++ אין טקסט להדבקה +++",
"Could not get paste data: %s": "לא ניתן לקבל את נתוני ההדבקה: %s",
"QR code": "קוד QR",
"This website is using an insecure HTTP connection! Please use it only for testing.": "האתר הזה משתמש בחיבור HTTP בלתי מאובטח! נא להשתמש בזה לבדיקות בלבד.",
"For more information <a href=\"%s\">see this FAQ entry</a>.": "לפרטים נוספים <a href=\"%s\">עיין ברשומת שאלות נפוצות זו</a>.",
"For more information <a href=\"%s\">see this FAQ entry</a>.": "יש מידע נוסף <a href=\"%s\">ברשומה הזאת בשו״ת</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "יכול להיות שהדפדפן שלך ידרוש חיבור HTTPS כדי לתמוך ב־API של WebCrypto. כדי לנסות <a href=\"%s\">לעבור ל־HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "הדפדפן שלך לא תומך ב־WebAssembly שמשמש לדחיסת zlib. אפשר ליצור מסמכים בלתי מוצפנים אך אין אפשרות לקרוא מסמכים מוצפנים.",
"waiting on user to provide a password": "בהמתנה למילוי הססמה מצד המשתמש",
@ -209,23 +209,22 @@
"Close": "סגירה",
"Encrypted note on %s": "%sהערה מוצפנת ב־",
"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 עשוי לחשוף את מפתח הפענוח שלך בכתובת ה-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 שאינה מצביעה על המערכת שלנו.",
"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?": "ההודעה הסודית הזו יכולה להוצג רק פעם אחת. האם תרצה לראות אותה עכשיו?",
"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. אנא השתמש בדפדפן אחר כדי לצפות בהדבקה זו.",
"Start over": "להתחיל מחדש",
"Paste copied to clipboard": "ההדבקה הועתקה ללוח",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "על מנת להעתיק את ההדבקה, לחץ על כפתור ההעתקה או השתמש בקיצור הדרך ללוח <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "העתק קישור",
"Link copied to clipboard": "הקישור הועתק ללוח",
"Paste text": "הדבק טקסט",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "משטח ה-tab פועל כמקש תו (לחץ על <kbd>Ctrl</kbd>+<kbd>m</kbd> או <kbd>Esc</kbd> להחלפה)",
"Theme": "נושא"
"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.",
"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",
"Paste copied to clipboard": "Paste copied to clipboard",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copia il link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Testo del messaggio",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -143,7 +143,7 @@
"Avatar generated from IP address": "Anonieme avatar (van het IP-adres)",
"Add comment": "Commentaar toevoegen",
"Optional nickname…": "Optionele bijnaam…",
"Post comment": "Plaats commentaar",
"Post comment": "Plaats een commentaar",
"Sending comment…": "Commentaar verzenden…",
"Comment posted.": "Commentaar geplaatst.",
"Could not refresh display: %s": "Kon de weergave niet vernieuwen: %s",
@ -220,12 +220,11 @@
"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.",
"Start over": "Opnieuw beginnen",
"Paste copied to clipboard": "Notitie gekopieerd naar klembord",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "Om te kopiëren en plakken druk je op de knop Kopiëren of gebruik je de sneltoets op het klembord <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Kopieer link",
"Link copied to clipboard": "Link gekopieerd naar klembord",
"Paste text": "Tekst plakken",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulatortoets dient als teken (gebruik <kbd>Ctrl</kbd>+<kbd>m</kbd> of <kbd>Esc</kbd> om te schakelen)",
"Theme": "Theme"
"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 <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -220,12 +220,11 @@
"Dark Mode": "Ciemny motyw",
"Error compressing paste, due to missing WebAssembly support.": "Błąd kompresowania wklejenia przez brak obsługi WebAssembly.",
"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": "Zacznij od nowa",
"Paste copied to clipboard": "Wklejka skopiowana do schowka",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "Aby skopiować wklejkę, naciśnij przycisk kopiowania lub użyj skrótu schowka <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Kopiuj link",
"Link copied to clipboard": "Link został skopiowany do schowka",
"Paste text": "Wklej tekst",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Klawisz Tabulatora służy jako znak (przytrzymaj <kbd>Ctrl</kbd>+<kbd>m</kbd> lub <kbd>Esc</kbd> aby przełączać)",
"Theme": "Motyw"
"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 <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Скопировать ссылку",
"Link copied to clipboard": "Ссылка скопирована в буфер обмена",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Тема"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -226,6 +226,5 @@
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
"Theme": "Theme"
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

View File

@ -221,11 +221,10 @@
"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": "重新开始",
"Paste copied to clipboard": "粘贴内容已复制到剪贴板",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "要复制粘贴内容,请点击复制按钮或使用快捷键 <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>。",
"Copy link": "复制链接",
"Link copied to clipboard": "链接已复制到剪贴板",
"Paste text": "粘贴文本",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tab 键可作为字符(按 <kbd>Ctrl</kbd>+<kbd>m</kbd> 或 <kbd>Esc</kbd> 切换开关)",
"Theme": "主题"
"Paste copied to clipboard": "Paste copied to clipboard",
"To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy paste press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Copy link",
"Link copied to clipboard": "Link copied to clipboard",
"Paste text": "Paste text",
"Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 741 B

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 B

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 B

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 B

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 B

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -5,6 +5,7 @@ global.assert = require('assert');
global.jsc = require('jsverify');
global.jsdom = require('jsdom-global');
global.cleanup = global.jsdom();
global.URL = require('jsdom-url').URL;
global.fs = require('fs');
global.WebCrypto = require('@peculiar/webcrypto').Crypto;
@ -16,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.2.5');
global.DOMPurify = require('./purify-3.2.4');
global.baseX = require('./base-x-4.0.0').baseX;
global.Legacy = require('./legacy').Legacy;
require('./bootstrap-3.4.1');
@ -78,16 +79,8 @@ function parseMime(line) {
}
// common testing helper functions
// as of jsDOM 22 the base64 functions provided in the DOM are more restrictive
// than browser implementation and throw when being passed invalid unicode
// codepoints - as we use these in the encryption with binary data, we need
// these to be character encoding agnostic
exports.atob = function(encoded) {
return Buffer.from(encoded, 'base64').toString('binary');
}
exports.btoa = function(text) {
return Buffer.from(text, 'binary').toString('base64');
}
exports.atob = atob;
exports.btoa = btoa;
// provides random lowercase characters from a to z
exports.jscA2zString = function() {

1988
js/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,11 +6,13 @@
"directories": {
"test": "test"
},
"dependencies": {},
"devDependencies": {
"@peculiar/webcrypto": "^1.5.0",
"jsdom": "^26.0.0",
"jsdom-global": "^3.0.2",
"jsverify": "^0.8.3"
"jsdom": "^9.12.0",
"jsdom-global": "^2.1.1",
"jsdom-url": "^2.2.1",
"jsverify": "^0.8.3",
"@peculiar/webcrypto": "^1.1.1"
},
"scripts": {
"test": "mocha",

View File

@ -58,6 +58,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
*/
const purifyHtmlConfig = {
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
SAFE_FOR_JQUERY: true,
USE_PROFILES: {
html: true
}
@ -3932,26 +3933,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
*/
function setLanguage(event)
{
let lang = $(event.target).data('lang') || event.target.value;
document.cookie = 'lang=' + lang + '; SameSite=Lax; Secure';
window.location.reload();
event.preventDefault();
}
/**
* save the template in a cookie and reloads the page
*
* @name TopNav.setTemplate
* @private
* @function
* @param {Event} event
*/
function setTemplate(event)
{
let template = $(event.target).data('template') || event.target.value;
document.cookie = 'template=' + template + '; SameSite=Lax; Secure';
document.cookie = 'lang=' + $(event.target).data('lang') + '; SameSite=Lax; Secure';
window.location.reload();
event.preventDefault();
}
@ -4643,12 +4625,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// bootstrap template drop down
$('#language ul.dropdown-menu li a').click(setLanguage);
// page template drop down
$('#language select').change(setLanguage);
// bootstrap template drop down
$('#template ul.dropdown-menu li a').click(setTemplate);
// page template drop down
$('#template select').change(setTemplate);
$('#language select option').click(setLanguage);
// bind events
$burnAfterReading.change(changeBurnAfterReading);

2
js/purify-3.2.4.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
'use strict';
const common = require('../common');
var common = require('../common');
describe('AttachmentViewer', function () {
describe('setAttachment, showAttachment, removeAttachment, hideAttachment, hideAttachmentPreview, hasAttachment, getAttachment & moveAttachmentTo', function () {
@ -14,12 +14,11 @@ describe('AttachmentViewer', function () {
'string',
function (mimeType, rawdata, filename, prefix, postfix) {
let clean = jsdom(),
data = 'data:' + mimeType + ';base64,' + common.btoa(rawdata),
mimePrefix = mimeType.substring(0, 6),
data = 'data:' + mimeType + ';base64,' + btoa(rawdata),
previewSupported = (
mimePrefix === 'image/' ||
mimePrefix === 'audio/' ||
mimePrefix === 'video/' ||
mimeType.substring(0, 6) === 'image/' ||
mimeType.substring(0, 6) === 'audio/' ||
mimeType.substring(0, 6) === 'video/' ||
mimeType.match(/\/pdf/i)
),
results = [],
@ -49,7 +48,6 @@ describe('AttachmentViewer', function () {
$('#attachment').hasClass('hidden') &&
$('#attachmentPreview').hasClass('hidden')
);
global.atob = common.atob;
if (filename.length) {
$.PrivateBin.AttachmentViewer.setAttachment(data, filename);
} else {

View File

@ -19,9 +19,10 @@ describe('Check', function () {
}
);
Legacy.Check.init();
const result = Legacy.Check.getInit() && !Legacy.Check.getStatus();
const result1 = Legacy.Check.getInit() && !Legacy.Check.getStatus(),
result2 = (document.getElementById('errormessage').className !== 'hidden');
clean();
return result;
return result1 && result2;
}
),
{tests: 10});
@ -66,10 +67,7 @@ describe('Check', function () {
'url': (secureProtocol ? 'https' : 'http' ) + '://' + domain.join('') + '/'
}
);
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
});
window.crypto = new WebCrypto();
Legacy.Check.init();
const result1 = Legacy.Check.getInit() && Legacy.Check.getStatus(),
result2 = secureProtocol === (document.getElementById('httpnotice').className === 'hidden');

View File

@ -4,136 +4,120 @@ const common = require('../common');
describe('CopyToClipboard', function() {
this.timeout(30000);
describe ('Copy paste to clipboard', function () {
jsc.property('Copy with button click',
common.jscFormats(),
'nestring',
async function (format, text) {
var clean = jsdom();
common.enableClipboard();
describe ('Copy paste co clipboard', function () {
jsc.property('Copy with button click', common.jscFormats(), 'nestring', async function (format, text) {
var clean = jsdom();
common.enableClipboard();
$('body').html(
'<div id="placeholder" class="hidden">+++ no paste text ' +
'+++</div><div id="prettymessage" class="hidden">' +
'<button type="button" id="prettyMessageCopyBtn"><svg id="copyIcon"></svg>' +
'<svg id="copySuccessIcon"></svg></button><pre ' +
'id="prettyprint" class="prettyprint linenums:1"></pre>' +
'</div><div id="plaintext" class="hidden"></div>'
);
$.PrivateBin.PasteViewer.init();
$.PrivateBin.PasteViewer.setFormat(format);
$.PrivateBin.PasteViewer.setText(text);
$.PrivateBin.PasteViewer.run();
$.PrivateBin.CopyToClipboard.init();
$('#prettyMessageCopyBtn').trigger('click');
$('body').html(
'<div id="placeholder" class="hidden">+++ no paste text ' +
'+++</div><div id="prettymessage" class="hidden">' +
'<button type="button" id="prettyMessageCopyBtn"><svg id="copyIcon"></svg>' +
'<svg id="copySuccessIcon"></svg></button><pre ' +
'id="prettyprint" class="prettyprint linenums:1"></pre>' +
'</div><div id="plaintext" class="hidden"></div>'
);
$.PrivateBin.PasteViewer.init();
$.PrivateBin.PasteViewer.setFormat(format);
$.PrivateBin.PasteViewer.setText(text);
$.PrivateBin.PasteViewer.run();
$.PrivateBin.CopyToClipboard.init();
$('#prettyMessageCopyBtn').trigger('click');
const savedToClipboardText = await navigator.clipboard.readText();
clean();
return text === savedToClipboardText;
}
);
const savedToClipboardText = await navigator.clipboard.readText();
clean();
return text === savedToClipboardText;
});
/**
* Unfortunately in JSVerify impossible to check if copy with shortcut when user selected some text on the page
* (the copy paste to clipboard should not work in this case) due to lacking window.getSelection() in jsdom.
* (the copy paste to clipboard should not work in this case) due to lucking window.getSelection() in jsdom.
*/
jsc.property('Copy with keyboard shortcut',
common.jscFormats(),
'nestring',
async function (format, text) {
var clean = jsdom();
common.enableClipboard();
$('body').html(
'<div id="placeholder">+++ no paste text ' +
'+++</div><div id="prettymessage" class="hidden">' +
'<button type="button" id="prettyMessageCopyBtn"><svg id="copyIcon"></svg>' +
'<svg id="copySuccessIcon"></svg></button><pre ' +
'id="prettyprint" class="prettyprint linenums:1"></pre>' +
'</div><div id="plaintext" class="hidden"></div>'
);
$.PrivateBin.PasteViewer.init();
$.PrivateBin.PasteViewer.setFormat(format);
$.PrivateBin.PasteViewer.setText(text);
$.PrivateBin.PasteViewer.run();
$.PrivateBin.CopyToClipboard.init();
$('body').trigger('copy');
const copiedTextWithoutSelectedText = await navigator.clipboard.readText();
clean();
return copiedTextWithoutSelectedText === text;
}
);
});
jsc.property('Copy link to clipboard',
'nestring',
async function (text) {
jsc.property('Copy with keyboard shortcut', common.jscFormats(), 'nestring', async function (format, text) {
var clean = jsdom();
common.enableClipboard();
$('body').html('<button id="copyLink"></button>');
$('body').html(
'<div id="placeholder">+++ no paste text ' +
'+++</div><div id="prettymessage" class="hidden">' +
'<button type="button" id="prettyMessageCopyBtn"><svg id="copyIcon"></svg>' +
'<svg id="copySuccessIcon"></svg></button><pre ' +
'id="prettyprint" class="prettyprint linenums:1"></pre>' +
'</div><div id="plaintext" class="hidden"></div>'
);
$.PrivateBin.PasteViewer.init();
$.PrivateBin.PasteViewer.setFormat(format);
$.PrivateBin.PasteViewer.setText(text);
$.PrivateBin.PasteViewer.run();
$.PrivateBin.CopyToClipboard.init();
$.PrivateBin.CopyToClipboard.setUrl(text);
$('#copyLink').trigger('click');
$('body').trigger('copy');
const copiedText = await navigator.clipboard.readText();
const copiedTextWithoutSelectedText = await navigator.clipboard.readText();
clean();
return text === copiedText;
}
);
return copiedTextWithoutSelectedText === text;
});
});
jsc.property('Copy link to clipboard', 'nestring', async function (text) {
var clean = jsdom();
common.enableClipboard();
$('body').html('<button id="copyLink"></button>');
$.PrivateBin.CopyToClipboard.init();
$.PrivateBin.CopyToClipboard.setUrl(text);
$('#copyLink').trigger('click');
const copiedText = await navigator.clipboard.readText();
clean();
return text === copiedText;
});
describe('Keyboard shortcut hint', function () {
jsc.property('Show hint',
'nestring',
function (text) {
var clean = jsdom();
jsc.property('Show hint', 'nestring', function (text) {
var clean = jsdom();
$('body').html('<small id="copyShortcutHintText"></small>');
$.PrivateBin.CopyToClipboard.init();
$.PrivateBin.CopyToClipboard.showKeyboardShortcutHint();
const keyboardShortcutHint = $('#copyShortcutHintText').text();
clean();
return keyboardShortcutHint.length > 0;
});
$('body').html('<small id="copyShortcutHintText"></small>');
$.PrivateBin.CopyToClipboard.init();
$.PrivateBin.CopyToClipboard.showKeyboardShortcutHint();
const keyboardShortcutHint = $('#copyShortcutHintText').text();
clean();
return keyboardShortcutHint.length > 0;
}
);
jsc.property('Hide hint',
'nestring',
function (text) {
var clean = jsdom();
$('body').html('<small id="copyShortcutHintText">' + text + '</small>');
$.PrivateBin.CopyToClipboard.init();
$.PrivateBin.CopyToClipboard.hideKeyboardShortcutHint();
const keyboardShortcutHint = $('#copyShortcutHintText').text();
clean();
return keyboardShortcutHint.length === 0;
}
);
jsc.property('Hide hint', 'nestring', function (text) {
var clean = jsdom();
$('body').html('<small id="copyShortcutHintText">' + text + '</small>');
$.PrivateBin.CopyToClipboard.init();
$.PrivateBin.CopyToClipboard.hideKeyboardShortcutHint();
const keyboardShortcutHint = $('#copyShortcutHintText').text();
clean();
return keyboardShortcutHint.length === 0;
});
});
});

View File

@ -1,5 +1,5 @@
'use strict';
const common = require('../common');
require('../common');
describe('CryptTool', function () {
describe('cipher & decipher', function () {
@ -15,26 +15,21 @@ describe('CryptTool', function () {
'string',
'string',
async function (key, password, message) {
const clean = jsdom();
// pause to let async functions conclude
await new Promise(resolve => setTimeout(resolve, 300));
let clean = jsdom();
// ensure zlib is getting loaded
$.PrivateBin.Controller.initZ();
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
});
global.atob = common.atob;
global.btoa = common.btoa;
window.crypto = new WebCrypto();
message = message.trim();
const cipherMessage = await $.PrivateBin.CryptTool.cipher(
let cipherMessage = await $.PrivateBin.CryptTool.cipher(
key, password, message, []
),
plaintext = await $.PrivateBin.CryptTool.decipher(
key, password, cipherMessage
);
clean();
const result = (message === plaintext);
if (!result) console.log(plaintext, cipherMessage);
return result;
return message === plaintext;
}
),
{tests: 3});
@ -43,19 +38,15 @@ describe('CryptTool', function () {
// The below static unit tests are included to ensure deciphering of "classic"
// SJCL based pastes still works
it(
'supports PrivateBin v1 ciphertext with password (SJCL & browser atob)',
async function () {
'supports PrivateBin v1 ciphertext (SJCL & browser atob)',
function () {
delete global.Base64;
const clean = jsdom();
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
});
global.atob = common.atob;
let clean = jsdom();
window.crypto = new WebCrypto();
// Of course you can easily decipher the following texts, if you like.
// Bonus points for finding their sources and hidden meanings.
const paste = await $.PrivateBin.CryptTool.decipher(
return $.PrivateBin.CryptTool.decipher(
'6t2qsmLyfXIokNCL+3/yl15rfTUBQvm5SOnFPvNE7Q8=',
// -- "That's amazing. I've got the same combination on my luggage."
Array.apply(0, Array(6)).map((_,b) => b + 1).join(''),
@ -86,76 +77,53 @@ describe('CryptTool', function () {
'QUxMXI5htsn2rf0HxCFu7Po8DNYLxTS+67hYjDIYWYaEIc8LXWMLyDm9' +
'C5fARPJ4F2BIWgzgzkNj+dVjusft2XnziamWdbS5u3kuRlVuz5LQj+R5' +
'imnqQAincdZTkTT1nYx+DatlOLllCYIHffpI="}'
);
clean();
const result = typeof paste === 'string' && paste.includes('securely packed in iron');
if (!result) console.log(paste);
assert.ok(result);
}
);
it(
'supports PrivateBin v1 ciphertext no password (SJCL & browser atob)',
async function () {
delete global.Base64;
const clean = jsdom();
// ensure zlib is getting loaded
$.PrivateBin.Controller.initZ();
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
).then(function (paste1) {
$.PrivateBin.CryptTool.decipher(
's9pmKZKOBN7EVvHpTA8jjLFH3Xlz/0l8lB4+ONPACrM=',
'', // no password
'{"iv":"WA42mdxIVXUwBqZu7JYNiw==","v":1,"iter":10000,"ks"' +
':256,"ts":128,"mode":"gcm","adata":"","cipher":"aes","sa' +
'lt":"jN6CjbQMJCM=","ct":"kYYMo5DFG1+w0UHiYXT5pdV0IUuXxzO' +
'lslkW/c3DRCbGFROCVkAskHce7HoRczee1N9c5MhHjVMJUIZE02qIS8U' +
'yHdJ/GqcPVidTUcj9rnDNWsTXkjVv8jCwHS/cwmAjDTWpwp5ThECN+ov' +
'/wNp/NdtTj8Qj7f/T3rfZIOCWfwLH9s4Des35UNcUidfPTNQ1l0Gm0X+' +
'r98CCUSYZjQxkZc6hRZBLPQ8EaNVooUwd5eP4GiYlmSDNA0wOSA+5isP' +
'YxomVCt+kFf58VBlNhpfNi7BLYAUTPpXT4SfH5drR9+C7NTeZ+tTCYjb' +
'U94PzYItOpu8vgnB1/a6BAM5h3m9w+giUb0df4hgTWeZnZxLjo5BN8WV' +
'+kdTXMj3/Vv0gw0DQrDcCuX/cBAjpy3lQGwlAN1vXoOIyZJUjMpQRrOL' +
'dKvLB+zcmVNtGDbgnfP2IYBzk9NtodpUa27ne0T0ZpwOPlVwevsIVZO2' +
'24WLa+iQmmHOWDFFpVDlS0t0fLfOk7Hcb2xFsTxiCIiyKMho/IME1Du3' +
'X4e6BVa3hobSSZv0rRtNgY1KcyYPrUPW2fxZ+oik3y9SgGvb7XpjVIta' +
'8DWlDWRfZ9kzoweWEYqz9IA8Xd373RefpyuWI25zlHoX3nwljzsZU6dC' +
'//h/Dt2DNr+IAvKO3+u23cWoB9kgcZJ2FJuqjLvVfCF+OWcig7zs2pTY' +
'JW6Rg6lqbBCxiUUlae6xJrjfv0pzD2VYCLY7v1bVTagppwKzNI3WaluC' +
'OrdDYUCxUSe56yd1oAoLPRVbYvomRboUO6cjQhEknERyvt45og2kORJO' +
'EJayHW+jZgR0Y0jM3Nk17ubpij2gHxNx9kiLDOiCGSV5mn9mV7qd3HHc' +
'OMSykiBgbyzjobi96LT2dIGLeDXTIdPOog8wyobO4jWq0GGs0vBB8oSY' +
'XhHvixZLcSjX2KQuHmEoWzmJcr3DavdoXZmAurGWLKjzEdJc5dSD/eNr' +
'99gjHX7wphJ6umKMM+fn6PcbYJkhDh2GlJL5COXjXfm/5aj/vuyaRRWZ' +
'MZtmnYpGAtAPg7AUG"}'
).then(function (paste2) {
clean();
assert.ok(
paste1.includes('securely packed in iron') &&
paste2.includes('Sol is right')
);
});
});
global.atob = common.atob;
// Of course you can easily decipher the following texts, if you like.
// Bonus points for finding their sources and hidden meanings.
const paste = await $.PrivateBin.CryptTool.decipher(
's9pmKZKOBN7EVvHpTA8jjLFH3Xlz/0l8lB4+ONPACrM=',
'', // no password
'{"iv":"WA42mdxIVXUwBqZu7JYNiw==","v":1,"iter":10000,"ks"' +
':256,"ts":128,"mode":"gcm","adata":"","cipher":"aes","sa' +
'lt":"jN6CjbQMJCM=","ct":"kYYMo5DFG1+w0UHiYXT5pdV0IUuXxzO' +
'lslkW/c3DRCbGFROCVkAskHce7HoRczee1N9c5MhHjVMJUIZE02qIS8U' +
'yHdJ/GqcPVidTUcj9rnDNWsTXkjVv8jCwHS/cwmAjDTWpwp5ThECN+ov' +
'/wNp/NdtTj8Qj7f/T3rfZIOCWfwLH9s4Des35UNcUidfPTNQ1l0Gm0X+' +
'r98CCUSYZjQxkZc6hRZBLPQ8EaNVooUwd5eP4GiYlmSDNA0wOSA+5isP' +
'YxomVCt+kFf58VBlNhpfNi7BLYAUTPpXT4SfH5drR9+C7NTeZ+tTCYjb' +
'U94PzYItOpu8vgnB1/a6BAM5h3m9w+giUb0df4hgTWeZnZxLjo5BN8WV' +
'+kdTXMj3/Vv0gw0DQrDcCuX/cBAjpy3lQGwlAN1vXoOIyZJUjMpQRrOL' +
'dKvLB+zcmVNtGDbgnfP2IYBzk9NtodpUa27ne0T0ZpwOPlVwevsIVZO2' +
'24WLa+iQmmHOWDFFpVDlS0t0fLfOk7Hcb2xFsTxiCIiyKMho/IME1Du3' +
'X4e6BVa3hobSSZv0rRtNgY1KcyYPrUPW2fxZ+oik3y9SgGvb7XpjVIta' +
'8DWlDWRfZ9kzoweWEYqz9IA8Xd373RefpyuWI25zlHoX3nwljzsZU6dC' +
'//h/Dt2DNr+IAvKO3+u23cWoB9kgcZJ2FJuqjLvVfCF+OWcig7zs2pTY' +
'JW6Rg6lqbBCxiUUlae6xJrjfv0pzD2VYCLY7v1bVTagppwKzNI3WaluC' +
'OrdDYUCxUSe56yd1oAoLPRVbYvomRboUO6cjQhEknERyvt45og2kORJO' +
'EJayHW+jZgR0Y0jM3Nk17ubpij2gHxNx9kiLDOiCGSV5mn9mV7qd3HHc' +
'OMSykiBgbyzjobi96LT2dIGLeDXTIdPOog8wyobO4jWq0GGs0vBB8oSY' +
'XhHvixZLcSjX2KQuHmEoWzmJcr3DavdoXZmAurGWLKjzEdJc5dSD/eNr' +
'99gjHX7wphJ6umKMM+fn6PcbYJkhDh2GlJL5COXjXfm/5aj/vuyaRRWZ' +
'MZtmnYpGAtAPg7AUG"}'
);
clean();
const result = typeof paste === 'string' && paste.includes('Sol is right');
if (!result) console.log(paste);
assert.ok(result);
}
);
it(
'supports ZeroBin ciphertext with password (SJCL & Base64 1.7)',
async function () {
'supports ZeroBin ciphertext (SJCL & Base64 1.7)',
function () {
global.Base64 = require('../base64-1.7').Base64;
const clean = jsdom();
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
});
global.atob = common.atob;
var clean = jsdom();
window.crypto = new WebCrypto();
// Of course you can easily decipher the following texts, if you like.
// Bonus points for finding their sources and hidden meanings.
const paste = await $.PrivateBin.CryptTool.decipher(
return $.PrivateBin.CryptTool.decipher(
'6t2qsmLyfXIokNCL+3/yl15rfTUBQvm5SOnFPvNE7Q8=',
// -- "That's amazing. I've got the same combination on my luggage."
Array.apply(0, Array(6)).map((_,b) => b + 1).join(''),
@ -178,74 +146,54 @@ describe('CryptTool', function () {
'7mNNo7xba/YT9KoPDaniqnYqb+q2pX1WNWE7dLS2wfroMAS3kh8P22DA' +
'V37AeiNoD2PcI6ZcHbRdPa+XRrRcJhSPPW7UQ0z4OvBfjdu/w390QxAx' +
'SxvZewoh49fKKB6hTsRnZb4tpHkjlww=="}'
);
clean();
delete global.Base64;
const result = typeof paste === 'string' && paste.includes('securely packed in iron');
if (!result) console.log(paste);
assert.ok(result);
}
);
it(
'supports ZeroBin ciphertext no password (SJCL & Base64 1.7)',
async function () {
global.Base64 = require('../base64-1.7').Base64;
const clean = jsdom();
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
).then(function (paste1) {
$.PrivateBin.CryptTool.decipher(
's9pmKZKOBN7EVvHpTA8jjLFH3Xlz/0l8lB4+ONPACrM=',
'', // no password
'{"iv":"Z7lAZQbkrqGMvruxoSm6Pw==","v":1,"iter":10000,"ks"' +
':256,"ts":128,"mode":"gcm","adata":"","cipher":"aes","sa' +
'lt":"jN6CjbQMJCM=","ct":"PuOPWB3i2FPcreSrLYeQf84LdE8RHjs' +
'c+MGtiOr4b7doNyWKYtkNorbRadxaPnEee2/Utrp1MIIfY5juJSy8RGw' +
'EPX5ciWcYe6EzsXWznsnvhmpKNj9B7eIIrfSbxfy8E2e/g7xav1nive+' +
'ljToka3WT1DZ8ILQd/NbnJeHWaoSEOfvz8+d8QJPb1tNZvs7zEY95Dum' +
'QwbyOsIMKAvcZHJ9OJNpujXzdMyt6DpcFcqlldWBZ/8q5rAUTw0HNx/r' +
'CgbhAxRYfNoTLIcMM4L0cXbPSgCjwf5FuO3EdE13mgEDhcClW79m0Qvc' +
'nIh8xgzYoxLbp0+AwvC/MbZM8savN/0ieWr2EKkZ04ggiOIEyvfCUuNp' +
'rQBYO+y8kKduNEN6by0Yf4LRCPfmwN+GezDLuzTnZIMhPbGqUAdgV6Ex' +
'qK2ULEEIrQEMoOuQIxfoMhqLlzG79vXGt2O+BY+4IiYfvmuRLks4UXfy' +
'HqxPXTJg48IYbGs0j4TtJPUgp3523EyYLwEGyVTAuWhYAmVIwd/hoV7d' +
'7tmfcF73w9dufDFI3LNca2KxzBnWNPYvIZKBwWbq8ncxkb191dP6mjEi' +
'7NnhqVk5A6vIBbu4AC5PZf76l6yep4xsoy/QtdDxCMocCXeAML9MQ9uP' +
'QbuspOKrBvMfN5igA1kBqasnxI472KBNXsdZnaDddSVUuvhTcETM="}'
).then(function (paste2) {
clean();
delete global.Base64;
assert.ok(
paste1.includes('securely packed in iron') &&
paste2.includes('Sol is right')
);
});
});
global.atob = common.atob;
const paste = await $.PrivateBin.CryptTool.decipher(
's9pmKZKOBN7EVvHpTA8jjLFH3Xlz/0l8lB4+ONPACrM=',
'', // no password
'{"iv":"Z7lAZQbkrqGMvruxoSm6Pw==","v":1,"iter":10000,"ks"' +
':256,"ts":128,"mode":"gcm","adata":"","cipher":"aes","sa' +
'lt":"jN6CjbQMJCM=","ct":"PuOPWB3i2FPcreSrLYeQf84LdE8RHjs' +
'c+MGtiOr4b7doNyWKYtkNorbRadxaPnEee2/Utrp1MIIfY5juJSy8RGw' +
'EPX5ciWcYe6EzsXWznsnvhmpKNj9B7eIIrfSbxfy8E2e/g7xav1nive+' +
'ljToka3WT1DZ8ILQd/NbnJeHWaoSEOfvz8+d8QJPb1tNZvs7zEY95Dum' +
'QwbyOsIMKAvcZHJ9OJNpujXzdMyt6DpcFcqlldWBZ/8q5rAUTw0HNx/r' +
'CgbhAxRYfNoTLIcMM4L0cXbPSgCjwf5FuO3EdE13mgEDhcClW79m0Qvc' +
'nIh8xgzYoxLbp0+AwvC/MbZM8savN/0ieWr2EKkZ04ggiOIEyvfCUuNp' +
'rQBYO+y8kKduNEN6by0Yf4LRCPfmwN+GezDLuzTnZIMhPbGqUAdgV6Ex' +
'qK2ULEEIrQEMoOuQIxfoMhqLlzG79vXGt2O+BY+4IiYfvmuRLks4UXfy' +
'HqxPXTJg48IYbGs0j4TtJPUgp3523EyYLwEGyVTAuWhYAmVIwd/hoV7d' +
'7tmfcF73w9dufDFI3LNca2KxzBnWNPYvIZKBwWbq8ncxkb191dP6mjEi' +
'7NnhqVk5A6vIBbu4AC5PZf76l6yep4xsoy/QtdDxCMocCXeAML9MQ9uP' +
'QbuspOKrBvMfN5igA1kBqasnxI472KBNXsdZnaDddSVUuvhTcETM="}'
);
clean();
delete global.Base64;
const result = typeof paste === 'string' && paste.includes('Sol is right');
if (!result) console.log(paste);
assert.ok(result);
}
);
it('does not truncate messages', async function () {
const message = fs.readFileSync('test/compression-sample.txt', 'ascii').trim(),
let message = fs.readFileSync('test/compression-sample.txt', 'utf8'),
clean = jsdom();
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
});
window.crypto = new WebCrypto();
// ensure zlib is getting loaded
$.PrivateBin.Controller.initZ();
global.atob = common.atob;
global.btoa = common.btoa;
const cipherMessage = await $.PrivateBin.CryptTool.cipher(
let cipherMessage = await $.PrivateBin.CryptTool.cipher(
'foo', 'bar', message, []
),
plaintext = await $.PrivateBin.CryptTool.decipher(
'foo', 'bar', cipherMessage
'foo', 'bar', cipherMessage
);
clean();
const result = (message === plaintext);
if (!result) console.log(plaintext, cipherMessage);
assert.ok(result);
assert.strictEqual(
message,
plaintext
);
});
it('can en- and decrypt a particular message (#260)', function () {
@ -253,6 +201,8 @@ describe('CryptTool', function () {
'string',
'string',
async function (key, password) {
// pause to let async functions conclude
await new Promise(resolve => setTimeout(resolve, 300));
const message = `
1 subgoal
@ -275,23 +225,18 @@ isWhile : interp (while expr sBody) (MemElem mem) =
======================== ( 1 / 1 )
conseq_or_bottom inv (interp (nth_iterate sBody n) (MemElem mem))
`;
const clean = jsdom();
let clean = jsdom();
// ensure zlib is getting loaded
$.PrivateBin.Controller.initZ();
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
});
const cipherMessage = await $.PrivateBin.CryptTool.cipher(
window.crypto = new WebCrypto();
let cipherMessage = await $.PrivateBin.CryptTool.cipher(
key, password, message, []
),
plaintext = await $.PrivateBin.CryptTool.decipher(
key, password, cipherMessage
);
clean();
const result = (message === plaintext);
if (!result) console.log(plaintext, cipherMessage);
return result;
return message === plaintext;
}
),
{tests: 3});
@ -299,27 +244,23 @@ conseq_or_bottom inv (interp (nth_iterate sBody n) (MemElem mem))
});
describe('getSymmetricKey', function () {
this.timeout(10000);
let keys = [];
this.timeout(30000);
var keys = [];
// the parameter is used to ensure the test is run more then one time
it('returns random, non-empty keys', function () {
jsc.assert(jsc.forall(
'integer',
function(counter) {
const clean = jsdom();
Object.defineProperty(window, 'crypto', {
value: new WebCrypto(),
writeable: false,
});
const key = $.PrivateBin.CryptTool.getSymmetricKey(),
result = (key !== '' && keys.indexOf(key) === -1);
keys.push(key);
clean();
return result;
}
),
{tests: 10});
});
jsc.property(
'returns random, non-empty keys',
'integer',
function(counter) {
var clean = jsdom();
window.crypto = new WebCrypto();
var key = $.PrivateBin.CryptTool.getSymmetricKey(),
result = (key !== '' && keys.indexOf(key) === -1);
keys.push(key);
clean();
return result;
}
);
});
});

View File

@ -229,30 +229,30 @@ describe('Helper', function () {
cleanup();
});
/* TODO test fails since jsDOM version 17 - document.cookie remains empty
jsc.property(
'returns the requested cookie',
jsc.nearray(jsc.nearray(common.jscAlnumString())),
jsc.nearray(jsc.nearray(common.jscAlnumString())),
function (labels, values) {
let selectedKey = '', selectedValue = '';
const clean = jsdom();
var selectedKey = '', selectedValue = '',
cookieArray = [];
labels.forEach(function(item, i) {
const key = item.join(''),
var key = item.join(''),
value = (values[i] || values[0]).join('');
document.cookie = key + '=' + value;
cookieArray.push(key + '=' + value);
if (Math.random() < 1 / i || selectedKey === key)
{
selectedKey = key;
selectedValue = value;
}
});
const result = $.PrivateBin.Helper.getCookie(selectedKey);
var clean = jsdom('', {cookie: cookieArray}),
result = $.PrivateBin.Helper.getCookie(selectedKey);
$.PrivateBin.Helper.reset();
clean();
return result === selectedValue;
}
); */
);
});
describe('baseUri', function () {

View File

@ -94,6 +94,7 @@ describe('Model', function () {
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();
@ -106,6 +107,7 @@ describe('Model', function () {
function (url) {
let clean = jsdom('', {url: common.urlToString(url)}),
result = false;
global.URL = require('jsdom-url').URL;
try {
$.PrivateBin.Model.getPasteId();
}
@ -129,7 +131,7 @@ describe('Model', function () {
'returns the fragment of a v1 URL',
common.jscUrl(),
function (url) {
url.fragment = '0OIl'; // any non-base58 string
url.fragment = common.btoa(url.fragment.padStart(32, '\u0000'));
const clean = jsdom('', {url: common.urlToString(url)}),
result = $.PrivateBin.Model.getPasteKey();
$.PrivateBin.Model.reset();
@ -138,17 +140,17 @@ describe('Model', function () {
}
);
jsc.property(
'returns the fragment stripped of trailing query parts',
'returns the v1 fragment stripped of trailing query parts',
common.jscUrl(),
jsc.array(common.jscHashString()),
function (url, trail) {
const fragment = url.fragment.padStart(32, '\u0000');
url.fragment = $.PrivateBin.CryptTool.base58encode(fragment) + '&' + trail.join('');
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();
return fragment === result;
return fragmentString === result;
}
);
jsc.property(

View File

@ -11,7 +11,7 @@ describe('Prompt', function () {
'returns the password fed into the dialog',
'string',
function (password) {
password = password.replace(/\r+|\n+/g, '');
password = password.replace(/\r+/g, '');
var clean = jsdom('', {url: 'ftp://example.com/?0000000000000000'});
$('body').html(
'<div id="passwordmodal" class="modal fade" role="dialog">' +
@ -32,8 +32,7 @@ describe('Prompt', function () {
//var result = $.PrivateBin.Prompt.getPassword();
var result = $('#passworddecrypt').val();
$.PrivateBin.Model.reset();
// TODO triggers error messages in jsDOM since version 11
//clean();
clean();
return result === password;
}
);

View File

@ -621,7 +621,7 @@ describe('TopNav', function () {
'returns the contents of the password input',
'string',
function (password) {
password = password.replace(/\r+|\n+/g, '');
password = password.replace(/\r+/g, '');
var results = [];
$('body').html(
'<nav><div id="navbar"><ul><li><div id="password" ' +
@ -727,11 +727,11 @@ describe('TopNav', function () {
cleanup();
});
// TODO triggers error messages in jsDOM since version 12, but passes
it(
'displays raw text view correctly',
function () {
const clean = jsdom('', {url: 'https://privatebin.net/?0123456789abcdef#0'});
global.URL = require('jsdom-url').URL;
$('body').html('<button id="rawtextbutton"></button>');
const sample = 'example';
$.PrivateBin.PasteViewer.setText(sample);

View File

@ -18,6 +18,11 @@ describe('UiHelper', function () {
const expected = common.urlToString(url),
clean = jsdom('', {url: expected});
// make window.location.href writable
Object.defineProperty(window.location, 'href', {
writable: true,
value: window.location.href
});
$.PrivateBin.UiHelper.mockHistoryChange();
$.PrivateBin.Helper.reset();
var result = window.location.href;
@ -35,6 +40,11 @@ describe('UiHelper', function () {
const expected = common.urlToString(url),
clean = jsdom('', {url: expected});
// make window.location.href writable
Object.defineProperty(window.location, 'href', {
writable: true,
value: window.location.href
});
$.PrivateBin.UiHelper.mockHistoryChange([
{type: 'newpaste'}, '', expected
]);
@ -47,8 +57,6 @@ describe('UiHelper', function () {
});
describe('reloadHome', function () {
// TODO triggers error messages in jsDOM since version 11
/*
this.timeout(30000);
before(function () {
$.PrivateBin.Helper.reset();
@ -63,6 +71,11 @@ describe('UiHelper', function () {
delete(url.fragment);
const expected = common.urlToString(url);
// make window.location.href writable
Object.defineProperty(window.location, 'href', {
writable: true,
value: window.location.href
});
$.PrivateBin.UiHelper.reloadHome();
$.PrivateBin.Helper.reset();
var result = window.location.href;
@ -70,7 +83,6 @@ describe('UiHelper', function () {
return expected === result;
}
);
*/
});
describe('isVisible', function () {

View File

@ -45,18 +45,7 @@ class Configuration
'defaultformatter' => 'plaintext',
'syntaxhighlightingtheme' => '',
'sizelimit' => 10485760,
'templateselection' => false,
'template' => 'bootstrap',
'availabletemplates' => array(
'bootstrap5',
'bootstrap',
'bootstrap-page',
'bootstrap-dark',
'bootstrap-dark-page',
'bootstrap-compact',
'bootstrap-compact-page',
'page',
),
'info' => 'More information on the <a href=\'https://privatebin.info/\'>project page</a>.',
'notice' => '',
'languageselection' => false,
@ -119,8 +108,8 @@ 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-yN0ZaVFrXpiYaeFRcofdCrlHVcw4ZJAXU3K1l6H9rsoY//iLKegX0GdWxRCFWzhd1xO4eDJKCT7qyaA1Vt65bg==',
'js/purify-3.2.5.js' => 'sha512-eLlLLL/zYuf5JuG0x4WQm687MToqOGP9cDQHIdmOy1ZpjiY4J48BBcOM7DtZheKk1UogW920+9RslWYB4KGuuA==',
'js/privatebin.js' => 'sha512-POa+8KNXFFwJFsqp7r9APmR5Rc1w2l363y+OScSzLCySrHN7UhOOgt1VH/o8mVddFvvUozj3FZVmdkTxRlrS5g==',
'js/purify-3.2.4.js' => 'sha512-Mu9BqoHURMeycg6AgqTpokUv9guq88pajfaFqz53fx1OxohyROkydXPLEIbdKCQ7EdDs9hgcrYeZ9zTiPQQ4CA==',
'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==',

View File

@ -112,12 +112,10 @@ class Controller
*
* initializes and runs PrivateBin
*
* @param ?Configuration $config
*
* @access public
* @throws Exception
*/
public function __construct(?Configuration $config = null)
public function __construct()
{
if (version_compare(PHP_VERSION, self::MIN_PHP_VERSION) < 0) {
error_log(I18n::_('%s requires php %s or above to work. Sorry.', I18n::_('PrivateBin'), self::MIN_PHP_VERSION));
@ -128,8 +126,7 @@ class Controller
return;
}
// load config (using ini file by default) & initialize required classes
$this->_conf = $config ?? new Configuration();
// load config from ini file, initialize required classes
$this->_init();
switch ($this->_request->getOperation()) {
@ -177,21 +174,12 @@ class Controller
*/
private function _init()
{
$this->_conf = new Configuration;
$this->_model = new Model($this->_conf);
$this->_request = new Request;
$this->_urlBase = $this->_request->getRequestUri();
$this->_setDefaultLanguage();
$this->_setDefaultTemplate();
}
/**
* Set default language
*
* @access private
*/
private function _setDefaultLanguage()
{
// set default language
$lang = $this->_conf->getKey('languagedefault');
I18n::setLanguageFallback($lang);
// force default language, if language selection is disabled and a default is set
@ -201,25 +189,6 @@ class Controller
}
}
/**
* Set default template
*
* @access private
*/
private function _setDefaultTemplate()
{
$templates = $this->_conf->getKey('availabletemplates');
$template = $this->_conf->getKey('template');
TemplateSwitcher::setAvailableTemplates($templates);
TemplateSwitcher::setTemplateFallback($template);
// force default template, if template selection is disabled and a default is set
if (!$this->_conf->getKey('templateselection') && !empty($template)) {
$_COOKIE['template'] = $template;
setcookie('template', $template, array('SameSite' => 'Lax', 'Secure' => true));
}
}
/**
* Turn off browser caching
*
@ -431,13 +400,6 @@ class Controller
setcookie('lang', $languageselection, array('SameSite' => 'Lax', 'Secure' => true));
}
// set template cookie if that functionality was enabled
$templateselection = '';
if ($this->_conf->getKey('templateselection')) {
$templateselection = TemplateSwitcher::getTemplate();
setcookie('template', $templateselection, array('SameSite' => 'Lax', 'Secure' => true));
}
// strip policies that are unsupported in meta tag
$metacspheader = str_replace(
array(
@ -476,8 +438,6 @@ class Controller
$page->assign('ZEROBINCOMPATIBILITY', $this->_conf->getKey('zerobincompatibility'));
$page->assign('LANGUAGESELECTION', $languageselection);
$page->assign('LANGUAGES', I18n::getLanguageLabels(I18n::getAvailableLanguages()));
$page->assign('TEMPLATESELECTION', $templateselection);
$page->assign('TEMPLATES', TemplateSwitcher::getAvailableTemplates());
$page->assign('EXPIRE', $expire);
$page->assign('EXPIREDEFAULT', $this->_conf->getKey('default', 'expire'));
$page->assign('URLSHORTENER', $this->_conf->getKey('urlshortener'));
@ -487,7 +447,7 @@ class Controller
$page->assign('HTTPSLINK', 'https://' . $this->_request->getHost() . $this->_request->getRequestUri());
$page->assign('COMPRESSION', $this->_conf->getKey('compression'));
$page->assign('SRI', $this->_conf->getSection('sri'));
$page->draw(TemplateSwitcher::getTemplate());
$page->draw($this->_conf->getKey('template'));
}
/**

View File

@ -34,7 +34,7 @@ abstract class AbstractData
* @param array $paste
* @return bool
*/
abstract public function create($pasteid, array &$paste);
abstract public function create($pasteid, array $paste);
/**
* Read a paste.
@ -72,7 +72,7 @@ abstract class AbstractData
* @param array $comment
* @return bool
*/
abstract public function createComment($pasteid, $parentid, $commentid, array &$comment);
abstract public function createComment($pasteid, $parentid, $commentid, array $comment);
/**
* Read all comments of paste.
@ -199,7 +199,7 @@ abstract class AbstractData
* @param array $paste
* @return array
*/
protected static function upgradePreV1Format(array &$paste)
protected static function upgradePreV1Format(array $paste)
{
if (array_key_exists('attachment', $paste['meta'])) {
$paste['attachment'] = $paste['meta']['attachment'];

View File

@ -140,7 +140,7 @@ class Database extends AbstractData
* @param array $paste
* @return bool
*/
public function create($pasteid, array &$paste)
public function create($pasteid, array $paste)
{
$expire_date = 0;
$opendiscussion = $burnafterreading = false;
@ -297,18 +297,14 @@ class Database extends AbstractData
* @param array $comment
* @return bool
*/
public function createComment($pasteid, $parentid, $commentid, array &$comment)
public function createComment($pasteid, $parentid, $commentid, array $comment)
{
if (array_key_exists('data', $comment)) {
$version = 1;
$data = $comment['data'];
} else {
try {
$version = 2;
$data = Json::encode($comment);
} catch (Exception $e) {
return false;
}
$version = 2;
$data = Json::encode($comment);
}
list($createdKey, $iconKey) = $this->_getVersionedKeys($version);
$meta = $comment['meta'];

View File

@ -85,7 +85,7 @@ class Filesystem extends AbstractData
* @param array $paste
* @return bool
*/
public function create($pasteid, array &$paste)
public function create($pasteid, array $paste)
{
$storagedir = $this->_dataid2path($pasteid);
$file = $storagedir . $pasteid . '.php';
@ -188,7 +188,7 @@ class Filesystem extends AbstractData
* @param array $comment
* @return bool
*/
public function createComment($pasteid, $parentid, $commentid, array &$comment)
public function createComment($pasteid, $parentid, $commentid, array $comment)
{
$storagedir = $this->_dataid2discussionpath($pasteid);
$file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid . '.php';
@ -343,11 +343,12 @@ class Filesystem extends AbstractData
*/
private function _get($filename)
{
$data = substr(
file_get_contents($filename),
strlen(self::PROTECTION_LINE . PHP_EOL)
return Json::decode(
substr(
file_get_contents($filename),
strlen(self::PROTECTION_LINE . PHP_EOL)
)
);
return Json::decode($data);
}
/**

View File

@ -105,7 +105,7 @@ class GoogleCloudStorage extends AbstractData
* @param $payload array to store
* @return bool true if successful, otherwise false.
*/
private function _upload($key, &$payload)
private function _upload($key, $payload)
{
$metadata = array_key_exists('meta', $payload) ? $payload['meta'] : array();
unset($metadata['attachment'], $metadata['attachmentname'], $metadata['salt']);
@ -136,7 +136,7 @@ class GoogleCloudStorage extends AbstractData
/**
* @inheritDoc
*/
public function create($pasteid, array &$paste)
public function create($pasteid, array $paste)
{
if ($this->exists($pasteid)) {
return false;
@ -201,7 +201,7 @@ class GoogleCloudStorage extends AbstractData
/**
* @inheritDoc
*/
public function createComment($pasteid, $parentid, $commentid, array &$comment)
public function createComment($pasteid, $parentid, $commentid, array $comment)
{
if ($this->existsComment($pasteid, $parentid, $commentid)) {
return false;
@ -219,8 +219,7 @@ class GoogleCloudStorage extends AbstractData
$prefix = $this->_getKey($pasteid) . '/discussion/';
try {
foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $key) {
$data = $this->_bucket->object($key->name())->downloadAsString();
$comment = Json::decode($data);
$comment = JSON::decode($this->_bucket->object($key->name())->downloadAsString());
$comment['id'] = basename($key->name());
$slot = $this->getOpenSlot($comments, (int) $comment['meta']['created']);
$comments[$slot] = $comment;

View File

@ -165,7 +165,7 @@ class S3Storage extends AbstractData
* @param $payload array to store
* @return bool true if successful, otherwise false.
*/
private function _upload($key, &$payload)
private function _upload($key, $payload)
{
$metadata = array_key_exists('meta', $payload) ? $payload['meta'] : array();
unset($metadata['attachment'], $metadata['attachmentname'], $metadata['salt']);
@ -191,7 +191,7 @@ class S3Storage extends AbstractData
/**
* @inheritDoc
*/
public function create($pasteid, array &$paste)
public function create($pasteid, array $paste)
{
if ($this->exists($pasteid)) {
return false;
@ -263,7 +263,7 @@ class S3Storage extends AbstractData
/**
* @inheritDoc
*/
public function createComment($pasteid, $parentid, $commentid, array &$comment)
public function createComment($pasteid, $parentid, $commentid, array $comment)
{
if ($this->existsComment($pasteid, $parentid, $commentid)) {
return false;

View File

@ -29,7 +29,7 @@ class FormatV2
* @param bool $isComment
* @return bool
*/
public static function isValid(&$message, $isComment = false)
public static function isValid($message, $isComment = false)
{
$required_keys = array('adata', 'v', 'ct');
if ($isComment) {

View File

@ -183,12 +183,9 @@ class I18n
// load translations
self::$_language = $match;
if ($match == 'en') {
self::$_translations = array();
} else {
$data = file_get_contents(self::_getPath($match . '.json'));
self::$_translations = Json::decode($data);
}
self::$_translations = ($match == 'en') ? array() : Json::decode(
file_get_contents(self::_getPath($match . '.json'))
);
}
/**
@ -276,8 +273,7 @@ class I18n
{
$file = self::_getPath('languages.json');
if (count(self::$_languageLabels) == 0 && is_readable($file)) {
$data = file_get_contents($file);
self::$_languageLabels = Json::decode($data);
self::$_languageLabels = Json::decode(file_get_contents($file));
}
if (count($languages) == 0) {
return self::$_languageLabels;

View File

@ -29,7 +29,7 @@ class Json
* @throws Exception
* @return string
*/
public static function encode(&$input)
public static function encode($input)
{
$jsonString = json_encode($input);
self::_detectError();
@ -45,7 +45,7 @@ class Json
* @throws Exception
* @return mixed
*/
public static function decode(&$input)
public static function decode($input)
{
$output = json_decode($input, true);
self::_detectError();

View File

@ -100,9 +100,9 @@ abstract class AbstractModel
* @param array $data
* @throws Exception
*/
public function setData(array &$data)
public function setData(array $data)
{
$this->_sanitize($data);
$data = $this->_sanitize($data);
$this->_validate($data);
$this->_data = $data;
@ -155,7 +155,7 @@ abstract class AbstractModel
*/
public static function isValidId($id)
{
return (bool) preg_match('#\A[a-f0-9]{16}\z#', (string) $id);
return (bool) preg_match('#\A[a-f\d]{16}\z#', (string) $id);
}
/**
@ -163,8 +163,9 @@ abstract class AbstractModel
*
* @access protected
* @param array $data
* @return array
*/
abstract protected function _sanitize(array &$data);
abstract protected function _sanitize(array $data);
/**
* Validate data.
@ -173,7 +174,7 @@ abstract class AbstractModel
* @param array $data
* @throws Exception
*/
protected function _validate(array &$data)
protected function _validate(array $data)
{
}
}

View File

@ -104,7 +104,7 @@ class Comment extends AbstractModel
* @param Paste $paste
* @throws Exception
*/
public function setPaste(Paste &$paste)
public function setPaste(Paste $paste)
{
$this->_paste = $paste;
$this->_data['pasteid'] = $paste->getId();
@ -155,8 +155,9 @@ class Comment extends AbstractModel
*
* @access protected
* @param array $data
* @return array
*/
protected function _sanitize(array &$data)
protected function _sanitize(array $data)
{
// we generate an icon based on a SHA512 HMAC of the users IP, if configured
$icon = $this->_conf->getKey('icon');
@ -189,5 +190,6 @@ class Comment extends AbstractModel
$data['meta']['icon'] = $pngdata;
}
}
return $data;
}
}

View File

@ -219,10 +219,11 @@ class Paste extends AbstractModel
*
* @access protected
* @param array $data
* @return array
*/
protected function _sanitize(array &$data)
protected function _sanitize(array $data)
{
$expiration = $data['meta']['expire'] ?? 0;
$expiration = $data['meta']['expire'];
unset($data['meta']['expire']);
$expire_options = $this->_conf->getSection('expire_options');
if (array_key_exists($expiration, $expire_options)) {
@ -234,6 +235,7 @@ class Paste extends AbstractModel
if ($expire > 0) {
$data['meta']['expire_date'] = time() + $expire;
}
return $data;
}
/**
@ -243,7 +245,7 @@ class Paste extends AbstractModel
* @param array $data
* @throws Exception
*/
protected function _validate(array &$data)
protected function _validate(array $data)
{
// reject invalid or disabled formatters
if (!array_key_exists($data['adata'][1], $this->_conf->getSection('formatter_options'))) {

View File

@ -12,7 +12,6 @@
namespace PrivateBin;
use Exception;
use PrivateBin\Model\Paste;
/**
* Request
@ -85,7 +84,7 @@ class Request
foreach ($_GET as $key => $value) {
// only return if value is empty and key is 16 hex chars
$key = (string) $key;
if (empty($value) && Paste::isValidId($key)) {
if (($value === '') && strlen($key) === 16 && ctype_xdigit($key)) {
return $key;
}
}
@ -111,8 +110,9 @@ class Request
// it might be a creation or a deletion, the latter is detected below
$this->_operation = 'create';
try {
$data = file_get_contents(self::$_inputStream);
$this->_params = Json::decode($data);
$this->_params = Json::decode(
file_get_contents(self::$_inputStream)
);
} catch (Exception $e) {
// ignore error, $this->_params will remain empty
}

View File

@ -1,120 +0,0 @@
<?php declare(strict_types=1);
/**
* PrivateBin
*
* a zero-knowledge paste bin
*
* @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
*/
namespace PrivateBin;
/**
* TemplateSwitcher
*
* Provides tool to change application template
*/
class TemplateSwitcher
{
/**
* template fallback
*
* @access protected
* @static
* @var string
*/
protected static $_templateFallback;
/**
* available templates
*
* @access protected
* @static
* @var array
*/
protected static $_availableTemplates = array();
/**
* set available templates
*
* @access public
* @static
* @param array $templates
*/
public static function setAvailableTemplates(array $templates)
{
self::$_availableTemplates = $templates;
}
/**
* set the default template
*
* @access public
* @static
* @param string $template
*/
public static function setTemplateFallback(string $template)
{
if (self::isTemplateAvailable($template)) {
self::$_templateFallback = $template;
}
}
/**
* get currently loaded template
*
* @access public
* @static
* @return string
*/
public static function getTemplate(): string
{
$selectedTemplate = self::getSelectedByUserTemplate();
return $selectedTemplate ?? self::$_templateFallback;
}
/**
* get list of available templates
*
* @access public
* @static
* @return array
*/
public static function getAvailableTemplates(): array
{
return self::$_availableTemplates;
}
/**
* check if the provided template is available
*
* @access public
* @static
* @return bool
*/
public static function isTemplateAvailable(string $template): bool
{
return in_array($template, self::getAvailableTemplates());
}
/**
* get the template selected by user
*
* @access private
* @static
* @return string|null
*/
private static function getSelectedByUserTemplate(): ?string
{
$selectedTemplate = null;
$templateCookieValue = $_COOKIE['template'] ?? '';
if (self::isTemplateAvailable($templateCookieValue)) {
$selectedTemplate = $templateCookieValue;
}
return $selectedTemplate;
}
}

View File

@ -70,7 +70,7 @@ class View
$sri = array_key_exists($file, $this->_variables['SRI']) ?
' integrity="' . $this->_variables['SRI'][$file] . '"' : '';
// if the file isn't versioned (ends in a digit), add our own version
$cacheBuster = (bool) preg_match('#[0-9]\.js$#', (string) $file) ?
$cacheBuster = ctype_digit(substr($file, -4, 1)) ?
'' : '?' . rawurlencode($this->_variables['VERSION']);
echo '<script ', $attributes,
' type="text/javascript" data-cfasync="false" src="', $file,

View File

@ -71,7 +71,7 @@ if ($MARKDOWN) :
<?php
endif;
?>
<?php $this->_scriptTag('js/purify-3.2.5.js', 'async'); ?>
<?php $this->_scriptTag('js/purify-3.2.4.js', 'async'); ?>
<?php $this->_scriptTag('js/legacy.js', 'async'); ?>
<?php $this->_scriptTag('js/privatebin.js', 'defer'); ?>
<!-- icon -->
@ -457,28 +457,6 @@ if (!empty($LANGUAGESELECTION)) :
</li>
<?php
endif;
?>
<?php
if (!empty($TEMPLATESELECTION)) :
?>
<li id="template" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Theme'); ?>: <?php echo $TEMPLATESELECTION; ?> <span class="caret"></span></a>
<ul class="dropdown-menu dropdown-menu-right">
<?php
foreach ($TEMPLATES as $value) :
?>
<li>
<a href="#" data-template="<?php echo $value; ?>">
<?php echo $value; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<?php
endif;
?>
</ul>
</div>
@ -575,8 +553,8 @@ if (!empty($URLSHORTENER)) :
?>
<p>
<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> btn-block">
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
</p>
<div role="alert" class="alert alert-danger">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>

View File

@ -55,7 +55,7 @@ if ($MARKDOWN) :
<?php
endif;
?>
<?php $this->_scriptTag('js/purify-3.2.5.js', 'defer'); ?>
<?php $this->_scriptTag('js/purify-3.2.4.js', 'defer'); ?>
<?php $this->_scriptTag('js/legacy.js', 'async'); ?>
<?php $this->_scriptTag('js/privatebin.js', 'defer'); ?>
<!-- icon -->
@ -323,30 +323,6 @@ if (!empty($LANGUAGESELECTION)) :
</li>
<?php
endif;
?>
<?php
if (!empty($TEMPLATESELECTION)) :
?>
<li id="template" class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle d-flex align-items-center gap-1" data-bs-toggle="dropdown" role="button" aria-expanded="false">
<?php echo I18n::_('Theme'); ?>: <?php echo $TEMPLATESELECTION, PHP_EOL; ?>
</a>
<ul class="dropdown-menu dropdown-menu-end" role="menu">
<?php
foreach ($TEMPLATES as $value) :
?>
<li>
<a href="#" class="dropdown-item" data-template="<?php echo $value; ?>">
<?php echo $value; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<?php
endif;
?>
</ul>
</div>
@ -442,8 +418,8 @@ if (!empty($URLSHORTENER)) :
?>
<p>
<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>" type="button" class="btn btn-primary btn-block d-flex justify-content-center align-items-center gap-1">
<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#send" /></svg> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#send" /></svg> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
</p>
<div role="alert" class="alert alert-danger">
<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-circle" /></svg>

View File

@ -49,7 +49,7 @@ if ($MARKDOWN):
<?php
endif;
?>
<?php $this->_scriptTag('js/purify-3.2.5.js', 'async'); ?>
<?php $this->_scriptTag('js/purify-3.2.4.js', 'async'); ?>
<?php $this->_scriptTag('js/legacy.js', 'async'); ?>
<?php $this->_scriptTag('js/privatebin.js', 'defer'); ?>
<!-- icon -->
@ -222,27 +222,6 @@ if (!empty($LANGUAGESELECTION)):
</div>
<?php
endif;
?>
<?php
if (!empty($TEMPLATESELECTION)):
?>
<div id="template" class="button"><?php echo I18n::_('Theme'); ?>:
<select name="template">
<?php
foreach ($TEMPLATES as $value):
?>
<option data-template="<?php echo $value; ?>" value="<?php echo $value; ?>"<?php
if ($value == $TEMPLATESELECTION):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
</div>
<?php
endif;
?>
</div>
<?php

View File

@ -1,7 +1,6 @@
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Configuration;
use PrivateBin\Controller;
use PrivateBin\Data\Filesystem;
use PrivateBin\Persistence\ServerSalt;
@ -148,20 +147,6 @@ class ControllerTest extends TestCase
new Controller;
}
/**
* @runInSeparateProcess
*/
public function testNonDefaultConf()
{
$newConfig = new class extends Configuration {};
$configValue = (new ReflectionClass(Controller::class))->getProperty('_conf');
$configValue->setAccessible(true);
ob_start();
$controller = new Controller($newConfig);
ob_end_clean();
$this->assertSame($newConfig, $configValue->getValue($controller));
}
/**
* @runInSeparateProcess
*/
@ -288,8 +273,7 @@ class ControllerTest extends TestCase
$options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0;
Helper::createIniFile(CONF, $options);
$paste = Helper::getPaste();
$this->_data->create(Helper::getPasteId(), $paste);
$this->_data->create(Helper::getPasteId(), Helper::getPaste());
$paste = Helper::getPasteJson();
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, $paste);
@ -539,8 +523,7 @@ class ControllerTest extends TestCase
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REMOTE_ADDR'] = '::1';
$paste = Helper::getPaste();
$this->_data->create(Helper::getPasteId(), $paste);
$this->_data->create(Helper::getPasteId(), Helper::getPaste());
ob_start();
new Controller;
$content = ob_get_contents();
@ -566,8 +549,7 @@ class ControllerTest extends TestCase
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REMOTE_ADDR'] = '::1';
$paste = Helper::getPaste();
$this->_data->create(Helper::getPasteId(), $paste);
$this->_data->create(Helper::getPasteId(), Helper::getPaste());
ob_start();
new Controller;
$content = ob_get_contents();
@ -636,10 +618,8 @@ class ControllerTest extends TestCase
$options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0;
Helper::createIniFile(CONF, $options);
$paste = Helper::getPaste();
$this->_data->create(Helper::getPasteId(), $paste);
$comment = Helper::getComment();
$this->_data->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getPasteId(), $comment);
$this->_data->create(Helper::getPasteId(), Helper::getPaste());
$this->_data->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getPasteId(), Helper::getComment());
$this->assertTrue($this->_data->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getPasteId()), 'comment exists before posting data');
$comment = Helper::getCommentJson();
$file = tempnam(sys_get_temp_dir(), 'FOO');
@ -824,8 +804,7 @@ class ControllerTest extends TestCase
*/
public function testDelete()
{
$paste = Helper::getPaste();
$this->_data->create(Helper::getPasteId(), $paste);
$this->_data->create(Helper::getPasteId(), Helper::getPaste());
$this->assertTrue($this->_data->exists(Helper::getPasteId()), 'paste exists before deleting data');
$paste = $this->_data->read(Helper::getPasteId());
$_GET['pasteid'] = Helper::getPasteId();
@ -847,8 +826,7 @@ class ControllerTest extends TestCase
*/
public function testDeleteInvalidId()
{
$paste = Helper::getPaste();
$this->_data->create(Helper::getPasteId(), $paste);
$this->_data->create(Helper::getPasteId(), Helper::getPaste());
$_GET['pasteid'] = 'foo';
$_GET['deletetoken'] = 'bar';
ob_start();
@ -886,8 +864,7 @@ class ControllerTest extends TestCase
*/
public function testDeleteInvalidToken()
{
$paste = Helper::getPaste();
$this->_data->create(Helper::getPasteId(), $paste);
$this->_data->create(Helper::getPasteId(), Helper::getPaste());
$_GET['pasteid'] = Helper::getPasteId();
$_GET['deletetoken'] = 'bar';
ob_start();
@ -907,8 +884,7 @@ class ControllerTest extends TestCase
*/
public function testDeleteInvalidBurnAfterReading()
{
$paste = Helper::getPaste();
$this->_data->create(Helper::getPasteId(), $paste);
$this->_data->create(Helper::getPasteId(), Helper::getPaste());
$this->assertTrue($this->_data->exists(Helper::getPasteId()), 'paste exists before deleting data');
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, json_encode(array(

View File

@ -60,22 +60,18 @@ class DatabaseTest extends TestCase
$this->assertEquals($paste, $this->_model->read(Helper::getPasteId()));
// storing comments
$comment1 = Helper::getComment(1);
$comment2 = Helper::getComment(2);
$meta1 = $comment1['meta'];
$meta2 = $comment2['meta'];
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'v1 comment does not yet exist');
$this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), $comment1) !== false, 'store v1 comment');
$this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment(1)) !== false, 'store v1 comment');
$this->assertTrue($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'v1 comment exists after storing it');
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getPasteId()), 'v2 comment does not yet exist');
$this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getPasteId(), $comment2) !== false, 'store v2 comment');
$this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getPasteId(), Helper::getComment(2)) !== false, 'store v2 comment');
$this->assertTrue($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getPasteId()), 'v2 comment exists after storing it');
$comment1 = Helper::getComment(1);
$comment1['id'] = Helper::getCommentId();
$comment1['parentid'] = Helper::getPasteId();
$comment1['meta'] = $meta1;
$comment2 = Helper::getComment(2);
$comment2['id'] = Helper::getPasteId();
$comment2['parentid'] = Helper::getPasteId();
$comment2['meta'] = $meta2;
$this->assertEquals(
array(
$comment1['meta']['postdate'] => $comment1,
@ -124,8 +120,7 @@ class DatabaseTest extends TestCase
if (in_array($key, array('y', 'z'))) {
$this->assertTrue($this->_model->create($ids[$key], $paste), "store $key paste");
} elseif ($key === 'x') {
$data = Helper::getPaste();
$this->assertTrue($this->_model->create($ids[$key], $data), "store $key paste");
$this->assertTrue($this->_model->create($ids[$key], Helper::getPaste()), "store $key paste");
} else {
$this->assertTrue($this->_model->create($ids[$key], $expired), "store $key paste");
}
@ -142,28 +137,6 @@ class DatabaseTest extends TestCase
}
}
public function testErrorDetection()
{
$this->_model->delete(Helper::getPasteId());
$paste = Helper::getPaste(2, array('expire' => "Invalid UTF-8 sequence: \xB1\x31"));
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
$this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store broken paste');
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does still not exist');
}
public function testCommentErrorDetection()
{
$this->_model->delete(Helper::getPasteId());
$data = Helper::getPaste();
$comment = Helper::getComment(2, array('nickname' => "Invalid UTF-8 sequence: \xB1\x31"));
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
$this->assertTrue($this->_model->create(Helper::getPasteId(), $data), 'store new paste');
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does not yet exist');
$this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), $comment), 'unable to store broken comment');
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does still not exist');
}
public function testGetIbmInstance()
{
$this->expectException(PDOException::class);

Some files were not shown because too many files have changed in this diff Show More