Compare commits

..

63 Commits
2.0.1 ... 2.0.3

Author SHA1 Message Date
El RIDO
19ca6d3dab incrementing version 2025-11-12 08:00:50 +01:00
El RIDO
f48544978b apply StyleCI suggestion 2025-11-12 07:57:30 +01:00
El RIDO
4434dbf73a Merge commit from fork
Fix arbitrary PHP file inclusion when enabling template switching
2025-11-12 07:54:10 +01:00
El RIDO
bddfb173da Merge branch 'master' into advisory-fix-1 2025-11-12 07:47:43 +01:00
El RIDO
f9550e5133 Merge commit from fork
Insert drag and drop file names as a text, not html
2025-11-12 07:46:35 +01:00
El RIDO
5b85d63942 Merge branch 'master' into advisory-fix-1 2025-11-12 07:18:43 +01:00
El RIDO
e427458cd0 Merge branch 'master' into advisory-fix-1 2025-11-11 22:00:09 +01:00
Mikhail Romanov
1fbaba732e Merge pull request #1702 from PrivateBin/create_cloned_paste_error
fix: error fetching attachments from blob
2025-11-11 20:15:00 +02:00
Ribas160
08b3244314 privatebin.js SRI and CHANGELOG.md updated 2025-11-11 20:13:10 +02:00
Mikhail Romanov
ff5aee85b4 Insert file names as break-separated text nodes
Co-authored-by: El RIDO <elrido@gmx.net>
2025-11-11 20:05:32 +02:00
El RIDO
2e11b13464 remove dead code 2025-11-11 17:56:49 +01:00
El RIDO
c35fc4f790 use more straight forward in_array check
kudos @Ribas160 for the suggestion
2025-11-11 17:53:50 +01:00
El RIDO
f456fb576e ensure template cookie cannot be a path 2025-11-11 17:52:48 +01:00
Ribas160
9c71fbcc70 Use pure JavaScript to create a div element 2025-11-11 17:45:27 +02:00
El RIDO
a371f5cab5 remove dead code 2025-11-11 12:49:37 +01:00
El RIDO
51bb637411 document the change 2025-11-11 11:00:19 +01:00
El RIDO
94a854faca do add the configured template to the available ones, if missing 2025-11-11 10:59:55 +01:00
El RIDO
ea73300e15 don't always set the cookie, having to unset it later
but still unset it, if it currently should not be in use (templateselection = false)
2025-11-11 09:45:51 +01:00
El RIDO
be6a3702fc simplify logic and improve readability
function was only used in one place and only indirectly tested, so it could be inlined, which also makes the test for null and the extra variable allocation unnecessary
2025-11-11 09:43:41 +01:00
El RIDO
f2164353c3 use realpath and validate tpl directory contents
to ensure only php files inside the tpl dir can get used as templates
2025-11-11 09:34:54 +01:00
El RIDO
dae5f7fd61 partially revert #1559
Instead of automatically adding custom templates, we log an error if
that template is missing in the available templates. Still mitigates
arbitrary file inclusion, as the string is now checked against a fixed
allow list.
2025-11-10 17:31:35 +01:00
Ribas160
14b68af528 Insert drag and drop file names as a text, not html 2025-11-10 17:59:18 +02:00
El RIDO
a479d75405 belt and braces: reset the template cookie, if function is not enabled 2025-11-10 12:25:19 +01:00
El RIDO
17ff44037a prevent use of paths in template names, only file names inside tpl directory are allowed 2025-11-10 12:23:50 +01:00
El RIDO
13949349af improve readability of logic 2025-11-10 12:22:29 +01:00
El RIDO
5f6c2beb3b Unit test on escaping the template directory 2025-11-10 12:00:29 +01:00
El RIDO
591d2d40e1 Merge pull request #1708 from calvinbui/patch-1
Fix typo in Shlink config docs
2025-11-09 07:46:23 +01:00
Calvin Bui
ec178e0c38 Fix typo in Shlink config docs 2025-11-09 10:00:48 +11:00
PrivateBin Translator Bot
697753ab91 New Crowdin updates (#1706)
* New translations en.json (Lithuanian)
2025-11-08 06:00:28 +01:00
Ribas160
a7b253a43a fix: error fetching attachments from blob 2025-11-05 17:33:08 +02:00
El RIDO
5e10469ffc Merge pull request #1700 from HariZalanPrivateBin/master
Update hu.json
2025-11-05 07:45:54 +01:00
HariZalanPrivateBin
feeac849c4 Update hu.json
My own translations currently used at privbin.harizalan.hu, enhanced at various points
2025-11-05 06:29:42 +01:00
El RIDO
0dd275db5c Merge pull request #1699 from PrivateBin/crowdin-translation
New Crowdin updates
2025-11-02 08:09:09 +01:00
PrivateBin Translator Bot
cadfe65bfa New translations en.json (Finnish) 2025-11-01 12:52:40 +01:00
El RIDO
9d7508f44f chore: prepare for next release 2025-10-28 16:54:42 +01:00
El RIDO
5018c963f9 chore: prepare for next release 2025-10-28 16:53:07 +01:00
El RIDO
a91d0afebd ensure there is still a space between commenter icon and name 2025-10-28 16:35:58 +01:00
El RIDO
2f70456e9a incrementing version 2025-10-28 16:08:13 +01:00
El RIDO
392e160006 Merge pull request #1688 from PrivateBin/purify-3.3.0
update DOMpurify library from 3.2.7 to 3.3.0
2025-10-28 11:44:34 +01:00
El RIDO
8293d1fb5d apply ESLint recommendation 2025-10-28 11:33:47 +01:00
El RIDO
43cf8b53ac Merge branch 'master' into purify-3.3.0 2025-10-28 11:27:17 +01:00
El RIDO
2d8af1f31e Merge commit from fork
Sanitize file name in attachment file size hints
2025-10-28 11:24:11 +01:00
El RIDO
0a6e7ef4f7 Merge pull request #1692 from PrivateBin/dependabot/github_actions/actions/upload-artifact-5
Bump actions/upload-artifact from 4 to 5
2025-10-27 13:38:15 +01:00
dependabot[bot]
8526816468 Bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 12:00:40 +00:00
El RIDO
85ae5cf676 Merge pull request #1691 from PrivateBin/crowdin-translation
New Crowdin updates
2025-10-26 18:31:34 +01:00
El RIDO
d27d63584f Merge branch 'master' into crowdin-translation 2025-10-26 18:26:06 +01:00
PrivateBin Translator Bot
99e0d5ca4e New translations en.json (Ukrainian) 2025-10-26 15:38:32 +01:00
PrivateBin Translator Bot
5a3125ff19 New translations en.json (Chinese Simplified) 2025-10-26 14:31:47 +01:00
El RIDO
ca10d47da0 Merge pull request #1690 from nykula/master
Update Ukrainian translation
2025-10-26 14:28:01 +01:00
Denys Nykula
3522ec07ce Update Ukrainian translation 2025-10-26 11:45:10 +02:00
El RIDO
c4f8482b30 Refactored jQuery DOM element creation
using plain JavaScript, to ensure text nodes are sanitized
2025-10-25 12:56:55 +02:00
El RIDO
fd2c2ae0c5 update DOMpurify library from 3.2.7 to 3.3.0 2025-10-25 10:52:40 +02:00
El RIDO
ca70c7555d Add tests of malicious file names 2025-10-24 15:00:56 +02:00
El RIDO
5c5fe333a0 Merge pull request #1679 from PrivateBin/opcache
Make OPcache optional
2025-10-22 06:50:38 +02:00
El RIDO
8c21a2275a Merge pull request #1684 from PrivateBin/doc-patch-readme
Fix links in doc/README.md
2025-10-22 06:49:46 +02:00
rugk
ca1f0d092e Fix links in doc/README.md
* Fixing the last link, which was totally broken
* Updated links in README to use relative paths.
2025-10-21 22:46:54 +02:00
El RIDO
508904dfac Merge pull request #1681 from PrivateBin/dependabot/github_actions/actions/setup-node-6
Bump actions/setup-node from 5 to 6
2025-10-14 13:33:17 +02:00
dependabot[bot]
3b45d8fa79 Bump actions/setup-node from 5 to 6
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-14 11:05:10 +00:00
El RIDO
b7286cf99a fix bootstrap template password peek display 2025-10-13 18:51:15 +02:00
El RIDO
0bfa300c59 apply StyleCI recommendation 2025-10-12 18:40:48 +02:00
El RIDO
d76796adf3 deduplicate logic 2025-10-12 18:39:36 +02:00
El RIDO
60bab2badb make OPcache optional, resolves #1678 2025-10-12 18:19:46 +02:00
El RIDO
a5d71d855f chore: prepare for next release 2025-10-12 12:03:07 +02:00
30 changed files with 368 additions and 351 deletions

View File

@@ -23,7 +23,7 @@ jobs:
uses: actions/checkout@v5 uses: actions/checkout@v5
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v5 uses: actions/setup-node@v6
with: with:
node-version: '20' node-version: '20'

View File

@@ -112,7 +112,7 @@ jobs:
- name: Upload Test Results - name: Upload Test Results
if: always() if: always()
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: Test Results (PHP ${{ matrix.php-versions }}) name: Test Results (PHP ${{ matrix.php-versions }})
path: tst/results.xml path: tst/results.xml
@@ -203,7 +203,7 @@ jobs:
- name: Upload Test Results - name: Upload Test Results
if: always() if: always()
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: Test Results name: Test Results
path: tst/results.xml path: tst/results.xml
@@ -216,7 +216,7 @@ jobs:
uses: actions/checkout@v5 uses: actions/checkout@v5
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v5 uses: actions/setup-node@v6
with: with:
node-version: '18' node-version: '18'
cache: 'npm' cache: 'npm'
@@ -235,7 +235,7 @@ jobs:
- name: Upload Test Results - name: Upload Test Results
if: always() if: always()
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: Test Results (Mocha) name: Test Results (Mocha)
path: js/mocha-results.xml path: js/mocha-results.xml
@@ -245,7 +245,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Upload - name: Upload
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v5
with: with:
name: Event File name: Event File
path: "${{ github.event_path }}" path: "${{ github.event_path }}"

View File

@@ -1,5 +1,17 @@
# PrivateBin version history # PrivateBin version history
## 2.0.3 (not yet released)
* FIXED: Prevent arbitrary PHP file inclusion when enabling template switching
* FIXED: Malicious filename can be used for self-XSS / HTML injection locally for users
* FIXED: Unable to create a new paste from the cloned one when a JSON file attached (#1585)
## 2.0.2 (2025-10-28)
* CHANGED: Upgrading libraries to: DOMpurify 3.3.0
* CHANGED: Refactored jQuery DOM element creation into plain JavaScript
* FIXED: Sanitize file name in attachment size hint
* FIXED: PHP OPcache module is optional again (#1679)
* FIXED: bootstrap template password peek input group display
## 2.0.1 (2025-10-12) ## 2.0.1 (2025-10-12)
* ADDED: Auto shorten URLs with config option `shortenbydefault` (#1627) * ADDED: Auto shorten URLs with config option `shortenbydefault` (#1627)
* ADDED: Added `shortenviashlink` endpoint with an `shlink` configuration section * ADDED: Added `shortenviashlink` endpoint with an `shlink` configuration section
@@ -35,7 +47,7 @@
* FIXED: Page template scripts loading order (#1579) * FIXED: Page template scripts loading order (#1579)
## 1.7.7 (2025-06-28) ## 1.7.7 (2025-06-28)
* ADDED: Switching templates using the web ui (#1501) * ADDED: Switching templates using the web UI (#1501)
* ADDED: Show file name and size on download page (#603) * ADDED: Show file name and size on download page (#603)
* CHANGED: Passing large data structures by reference to reduce memory consumption (#858) * CHANGED: Passing large data structures by reference to reduce memory consumption (#858)
* CHANGED: Removed use of ctype functions and polyfill library for ctype * CHANGED: Removed use of ctype functions and polyfill library for ctype

View File

@@ -1,7 +1,7 @@
.PHONY: all coverage coverage-js coverage-php doc doc-js doc-php increment sign test test-js test-php help .PHONY: all coverage coverage-js coverage-php doc doc-js doc-php increment sign test test-js test-php help
CURRENT_VERSION = 2.0.1 CURRENT_VERSION = 2.0.3
VERSION ?= 2.0.1 VERSION ?= 2.0.3
VERSION_FILES = README.md SECURITY.md doc/Installation.md js/package.json lib/Controller.php Makefile VERSION_FILES = README.md SECURITY.md doc/Installation.md js/package.json lib/Controller.php Makefile
REGEX_CURRENT_VERSION := $(shell echo $(CURRENT_VERSION) | sed "s/\./\\\./g") REGEX_CURRENT_VERSION := $(shell echo $(CURRENT_VERSION) | sed "s/\./\\\./g")
REGEX_VERSION := $(shell echo $(VERSION) | sed "s/\./\\\./g") REGEX_VERSION := $(shell echo $(VERSION) | sed "s/\./\\\./g")

View File

@@ -1,6 +1,6 @@
# [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/) # [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/)
*Current version: 2.0.1* *Current version: 2.0.3*
**PrivateBin** is a minimalist, open source online **PrivateBin** is a minimalist, open source online
[pastebin](https://en.wikipedia.org/wiki/Pastebin) [pastebin](https://en.wikipedia.org/wiki/Pastebin)

View File

@@ -4,8 +4,8 @@
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ------- | ------------------ |
| 2.0.1 | :heavy_check_mark: | | 2.0.3 | :heavy_check_mark: |
| < 2.0.1 | :x: | | < 2.0.3 | :x: |
## Reporting a Vulnerability ## Reporting a Vulnerability

View File

@@ -280,7 +280,7 @@ dir = PATH "data"
; "urlshortener" needs to point to the base URL of your PrivateBin ; "urlshortener" needs to point to the base URL of your PrivateBin
; instance with "?shortenviashlink&link=" appended. For example: ; instance with "?shortenviashlink&link=" appended. For example:
; urlshortener = "${basepath}?shortenviashlink&link=" ; urlshortener = "${basepath}?shortenviashlink&link="
; This URL will in turn call YOURLS on the server side, using the URL from ; This URL will in turn call Shlink on the server side, using the URL from
; "apiurl" and the API Key from the "apikey" parameters below. ; "apiurl" and the API Key from the "apikey" parameters below.
; apiurl = "https://shlink.example.com/rest/v3/short-urls" ; apiurl = "https://shlink.example.com/rest/v3/short-urls"
; apikey = "your_api_key" ; apikey = "your_api_key"

View File

@@ -30,7 +30,7 @@ for more information.
### Optional Requirements ### Optional Requirements
- PHP with GD extension (when using identicon or vizhash icons, jdenticon works - PHP with GD extension (when using identicon or vizhash icons, jdenticon works
without it) without it) and OPcache (for better performance)
- a database supported by [PHP PDO](https://php.net/manual/book.pdo.php) and the - a database supported by [PHP PDO](https://php.net/manual/book.pdo.php) and the
PHP PDO extension (when using database storage) PHP PDO extension (when using database storage)
- a Ceph cluster with Rados gateway or AWS S3 storage (when using S3 storage) - a Ceph cluster with Rados gateway or AWS S3 storage (when using S3 storage)
@@ -203,7 +203,7 @@ CREATE INDEX parent ON prefix_comment(pasteid);
CREATE TABLE prefix_config ( CREATE TABLE prefix_config (
id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id) id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id)
); );
INSERT INTO prefix_config VALUES('VERSION', '2.0.1'); INSERT INTO prefix_config VALUES('VERSION', '2.0.3');
``` ```
In **PostgreSQL**, the `data`, `attachment`, `nickname` and `vizhash` columns In **PostgreSQL**, the `data`, `attachment`, `nickname` and `vizhash` columns

View File

@@ -4,7 +4,7 @@
Please have a look at these questions *before* opening an issue in this repo. Please have a look at these questions *before* opening an issue in this repo.
## [Installation guide](https://github.com/PrivateBin/PrivateBin/blob/master/doc/Installation.md#installation) ## [Installation guide](Installation.md#installation)
Minimal requirements, hardening and securing your installation and initial Minimal requirements, hardening and securing your installation and initial
configuration. configuration.
@@ -26,12 +26,12 @@ How to help translate PrivateBin and technical background on it's implementation
Know how for participating in PrivateBins development. Know how for participating in PrivateBins development.
### [Generating Source Code Documentation](https://github.com/PrivateBin/PrivateBin/blob/master/doc/Generating%20Source%20Code%20Documentation.md#generating-source-code-documentation) ### [Generating Source Code Documentation](Generating%20Source%20Code%20Documentation.md#generating-source-code-documentation)
How to generate the source code API documentation, as found on the project How to generate the source code API documentation, as found on the project
website for [PHP](https://privatebin.info/codedoc/) and [JS](https://privatebin.info/jsdoc/) website for [PHP](https://privatebin.info/codedoc/) and [JS](https://privatebin.info/jsdoc/)
### [Running Unit Tests](https://github.com/PrivateBin/PrivateBin/blob/master/doc/Running Unit Tests.md#running-all-unit-tests) ### [Running Unit Tests](Running%20Unit%20Tests.md#running-all-unit-tests)
How to run the PHP & JS unit tests, including a brief introduction to property How to run the PHP & JS unit tests, including a brief introduction to property
based unit testing. based unit testing.

View File

@@ -210,13 +210,13 @@
"Encrypted note on %s": "Salattu viesti %sissä", "Encrypted note on %s": "Salattu viesti %sissä",
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Vieraile tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomaan viestiä.", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Vieraile tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomaan viestiä.",
"URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.", "URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.",
"URL shortener is enabled by default.": "URL shortener is enabled by default.", "URL shortener is enabled by default.": "URL-lyhennys on oletuksena käytössä.",
"Save document": "Tallenna asiakirja", "Save document": "Tallenna asiakirja",
"Your IP is not authorized to create documents.": "IP:llesi ei ole annettu oikeutta luoda pasteja.", "Your IP is not authorized to create documents.": "IP:llesi ei ole annettu oikeutta luoda pasteja.",
"Trying to shorten a URL that isn't pointing at our instance.": "Yritetään lyhentää URL-osoite, joka ei osoita meidän instanssiiin.", "Trying to shorten a URL that isn't pointing at our instance.": "Yritetään lyhentää URL-osoite, joka ei osoita meidän instanssiiin.",
"Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Virhe kutsuttaessa YOURLS. Luultavasti asetusongelma kuten väärä tai puuttuuva \"apiurl\" tai \"signature\".", "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Virhe kutsuttaessa YOURLS. Luultavasti asetusongelma kuten väärä tai puuttuuva \"apiurl\" tai \"signature\".",
"Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Virhe jäsennettäessä YOURLS-vastausta.", "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Virhe jäsennettäessä YOURLS-vastausta.",
"Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.", "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Välityspalvelinvirhe: Virheellinen vastaus. Tämä voi olla asetusongelma, kuten väärä tai puuttuva asetus, tai väliaikainen katkos.",
"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?", "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", "Yes, see it": "Kyllä, näet sen",
"Dark Mode": "Tumma tila", "Dark Mode": "Tumma tila",
@@ -229,7 +229,7 @@
"Link copied to clipboard": "Linkki kopioitu leikepöydälle", "Link copied to clipboard": "Linkki kopioitu leikepöydälle",
"Document text": "Liitä teksti", "Document 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)", "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)",
"Show password": "Show password", "Show password": "Näytä salasana",
"Hide password": "Hide password", "Hide password": "Piilota salasana",
"Theme": "Teema" "Theme": "Teema"
} }

View File

@@ -1,10 +1,10 @@
{ {
"PrivateBin": "PrivateBin", "PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "A %s egy minimalista, nyílt forráskódú adattároló szoftver, ahol a szerver semmilyen információt nem tárol a feltett adatról. Azt ugyanis a %sböngésződ%s segítségével titkosítja és oldja fel 256 bit hosszú titkosítási kulcsú AES-t használva.", "%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "A %s minimalista, nyílt forráskódú adattároló szoftver, ahol a szerver semmilyen információt nem tárol a rábízott adatról. Azt ugyanis a %sböngésződ%s segítségével titkosítja és oldja fel 256 bit hosszú titkosítási kulcsú AES-t használva.",
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "További információt a <a href=\"https://privatebin.info/\">projekt oldalán</a> találsz.", "More information on the <a href=\"https://privatebin.info/\">project page</a>.": "További információt a <a href=\"https://privatebin.info/\">projekt oldalán</a> találsz.",
"Because ignorance is bliss": "A titok egyfajta hatalom.", "Because ignorance is bliss": "A titok egyfajta hatalom.",
"Document does not exist, has expired or has been deleted.": "A bejegyzés nem létezik, lejárt vagy törölve lett.", "Document does not exist, has expired or has been deleted.": "A bejegyzés nem létezik, lejárt vagy törölve lett.",
"%s requires php %s or above to work. Sorry.": "Bocs, de a %s működéséhez %s vagy ezt meghaladó verziójú php-s környezet szükséges.", "%s requires php %s or above to work. Sorry.": "Sajnáljuk, de a %s működéséhez %s vagy ezt meghaladó verziójú php-s környezet szükséges.",
"%s requires configuration section [%s] to be present in configuration file.": "A %s megfelelő működéséhez a konfigurációs fájlban a [%s] résznek léteznie kell.", "%s requires configuration section [%s] to be present in configuration file.": "A %s megfelelő működéséhez a konfigurációs fájlban a [%s] résznek léteznie kell.",
"Please wait %d seconds between each post.": [ "Please wait %d seconds between each post.": [
"Kérlek várj %d másodpercet két beküldés között.", "Kérlek várj %d másodpercet két beküldés között.",
@@ -92,7 +92,7 @@
"%d év" "%d év"
], ],
"Never": "Soha", "Never": "Soha",
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Megjegyzés: ez egy teszt szolgáltatás, az adatok bármikor törlődhetnek. Ha visszaélsz vele, kiscicák bánhatják! :)", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Megjegyzés: ezen szolgáltatás egy teszt, az adatok bármikor törlődhetnek. Ha visszaélsz vele, kiscicák bánhatják.",
"This document will expire in %d seconds.": [ "This document will expire in %d seconds.": [
"Ez a bejegyzés %d másodperc múlva megsemmisül.", "Ez a bejegyzés %d másodperc múlva megsemmisül.",
"Ez a bejegyzés %d másodperc múlva megsemmisül.", "Ez a bejegyzés %d másodperc múlva megsemmisül.",
@@ -142,7 +142,7 @@
"Anonymous": "Névtelen", "Anonymous": "Névtelen",
"Avatar generated from IP address": "Avatar (az IP cím alapján generáljuk)", "Avatar generated from IP address": "Avatar (az IP cím alapján generáljuk)",
"Add comment": "Hozzászólok", "Add comment": "Hozzászólok",
"Optional nickname…": "Becenév (már ha meg akarod adni)", "Optional nickname…": "Becenév (amennyiben meg akarod adni)",
"Post comment": "Beküld", "Post comment": "Beküld",
"Sending comment…": "Beküldés alatt...", "Sending comment…": "Beküldés alatt...",
"Comment posted.": "A hozzászólás beküldve.", "Comment posted.": "A hozzászólás beküldve.",
@@ -154,7 +154,7 @@
"Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "A bejegyzésed a <a id=\"pasteurl\" href=\"%s\">%s</a> címen elérhető. <span id=\"copyhint\"> <kbd>Ctrl</kbd>+<kbd>c</kbd>-vel tudod vágólapra másolni.</span>", "Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "A bejegyzésed a <a id=\"pasteurl\" href=\"%s\">%s</a> címen elérhető. <span id=\"copyhint\"> <kbd>Ctrl</kbd>+<kbd>c</kbd>-vel tudod vágólapra másolni.</span>",
"Delete data": "Adat törlése", "Delete data": "Adat törlése",
"Could not create document: %s": "Nem tudtuk létrehozni a bejegyzést: %s", "Could not create document: %s": "Nem tudtuk létrehozni a bejegyzést: %s",
"Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nem tudjuk visszafejteni a bejegyzést: a dekódoláshoz szükséges kulcs hiányzik a címből. Talán URL rövidítőt használtál ami kivágta azt belőle?", "Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nem tudjuk visszafejteni a bejegyzést: a dekódoláshoz szükséges kulcs hiányzik a címből. Talán URL rövidítőt használtál, amely azt kivágta belőle?",
"B": "B", "B": "B",
"kB": "kB", "kB": "kB",
"MB": "MB", "MB": "MB",
@@ -190,13 +190,13 @@
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "Abban az esetben, ha ez az üzenet mindig látható lenne, látogass el a <a href=\"%s\">Gyakran Ismételt Kérdések szekcióba a megoldásához</a>.", "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "Abban az esetben, ha ez az üzenet mindig látható lenne, látogass el a <a href=\"%s\">Gyakran Ismételt Kérdések szekcióba a megoldásához</a>.",
"+++ no document text +++": "+++ nincs beillesztett szöveg +++", "+++ no document text +++": "+++ nincs beillesztett szöveg +++",
"Could not get document data: %s": "Az adat megszerzése nem sikerült: %s", "Could not get document data: %s": "Az adat megszerzése nem sikerült: %s",
"QR code": "QR kód", "QR code": "QR-kód",
"This website is using an insecure HTTP connection! Please use it only for testing.": "Ez a weboldal nem biztonságos HTTP kapcsolatot használ! Emiatt csak teszt célokra ajánljuk.", "This website is using an insecure HTTP connection! Please use it only for testing.": "Ez a weboldal nem biztonságos (HTTP) kapcsolatot használ! Emiatt csak teszt célra ajánljuk.",
"For more information <a href=\"%s\">see this FAQ entry</a>.": "További információ <a href=\"%s\">ebben a GyIK bejegyzésben</a> található (angolul).", "For more information <a href=\"%s\">see this FAQ entry</a>.": "További információ <a href=\"%s\">ebben a GyIK bejegyzésben</a> található (angolul).",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "A WebCrypto API használatához a böngésződ számára esetleg HTTPS kapcsolat szükséges. Ezért próbálj meg <a href=\"%s\">HTTPS-re váltani</a>.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "A WebCrypto API használatához a böngésződ számára esetleg HTTPS kapcsolat szükséges. Ezért próbálj meg <a href=\"%s\">HTTPS-re váltani</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "A böngésződ nem támogatja a WebAssemblyt, ami a zlib tömörítéshez kell. Létre tudsz hozni tömörítetlen dokumentumokat, de tömörítetteket nem tudsz olvasni.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "A böngésződ nem támogatja a WebAssemblyt, amely zlib-tömörítéshez szükséges. Létrehozhatsz tömörítetlen bejegyzést, de tömörítetteket nem tudsz elolvasni.",
"waiting on user to provide a password": "Várakozás a felhasználóra jelszó megadása okán", "waiting on user to provide a password": "Várakozás jelszó megadására",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Nem lehetett visszafejteni az adatot. Rossz jelszót ütöttél be? Ismételd meg a fent található gombbal.", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Nem sikerült visszafejteni az adatot. Rossz jelszót ütöttél be? Ismételd meg a fentebbi gombbal.",
"Retry": "Újrapróbálkozás", "Retry": "Újrapróbálkozás",
"Showing raw text…": "Nyers szöveg mutatása…", "Showing raw text…": "Nyers szöveg mutatása…",
"Notice:": "Megjegyzés:", "Notice:": "Megjegyzés:",
@@ -209,27 +209,27 @@
"Close": "Bezárás", "Close": "Bezárás",
"Encrypted note on %s": "Titkosított jegyzet a %s", "Encrypted note on %s": "Titkosított jegyzet a %s",
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Látogasd meg ezt a hivatkozást a bejegyzés megtekintéséhez. Ha mások számára is megadod ezt a linket, azzal hozzáférnek ők is.", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Látogasd meg ezt a hivatkozást a bejegyzés megtekintéséhez. Ha mások számára is megadod ezt a linket, azzal hozzáférnek ők is.",
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "URL shortener may expose your decrypt key in URL.": "Az URL-rövidítő kiszolgáltathatja dekódolókulcsod.",
"URL shortener is enabled by default.": "URL shortener is enabled by default.", "URL shortener is enabled by default.": "Az URL-rövidítő alapértelmezetten engedélyezett.",
"Save document": "Save document", "Save document": "Bejegyzés mentése",
"Your IP is not authorized to create documents.": "Your IP is not authorized to create documents.", "Your IP is not authorized to create documents.": "Your IP is not authorized to create documents.",
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
"Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.", "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.",
"Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.", "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.",
"Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.", "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.",
"This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?", "This secret message can only be displayed once. Would you like to see it now?": "Ez az üzenet csak egyszer jeleníthető meg. Szeretnéd megnézni?",
"Yes, see it": "Yes, see it", "Yes, see it": "Igen",
"Dark Mode": "Sötét mód", "Dark Mode": "Sötét mód",
"Error compressing document, due to missing WebAssembly support.": "Error compressing document, due to missing WebAssembly support.", "Error compressing document, due to missing WebAssembly support.": "WebAssembly-támogatás hiánya miatt nem tömöríthetjük a dokumentumot.",
"Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.", "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.",
"Start over": "Start over", "Start over": "Újrakezdés",
"Document copied to clipboard": "Document copied to clipboard", "Document copied to clipboard": "Bejegyzés másolva",
"To copy document press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy document press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>", "To copy document press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "Másoláshoz használd a <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd> billentyűkombinációt",
"Copy link": "Copy link", "Copy link": "Link másolása",
"Link copied to clipboard": "Link copied to clipboard", "Link copied to clipboard": "Link másolva",
"Document text": "Document text", "Document text": "Bejegyzés szövege",
"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)", "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "A tabulátor karakternek használható (nyomd le a <kbd>Ctrl</kbd>+<kbd>m</kbd> vagy az <kbd>Esc</kbd> to billentyűket ennek megszüntetéséhez).",
"Show password": "Show password", "Show password": "Jelszó megjelenítése",
"Hide password": "Hide password", "Hide password": "Jelszó elrejtése",
"Theme": "Theme" "Theme": "Téma"
} }

View File

@@ -3,7 +3,7 @@
"%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s yra minimalistinis, atvirojo kodo internetinis įdėjimų dėklas, kurį naudojant, serveris nieko nenutuokia apie įdėtus duomenis. Duomenys yra šifruojami/iššifruojami %snaršyklėje%s naudojant 256 bitų AES.", "%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s yra minimalistinis, atvirojo kodo internetinis įdėjimų dėklas, kurį naudojant, serveris nieko nenutuokia apie įdėtus duomenis. Duomenys yra šifruojami/iššifruojami %snaršyklėje%s naudojant 256 bitų AES.",
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Daugiau informacijos rasite <a href=\"https://privatebin.info/\">projekto puslapyje</a>.", "More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Daugiau informacijos rasite <a href=\"https://privatebin.info/\">projekto puslapyje</a>.",
"Because ignorance is bliss": "Nes nežinojimas yra palaima", "Because ignorance is bliss": "Nes nežinojimas yra palaima",
"Document does not exist, has expired or has been deleted.": "Įdėjimo nėra, jis nebegalioja arba buvo ištrintas.", "Document does not exist, has expired or has been deleted.": "Dokumento nėra, jis nebegalioja arba buvo ištrintas.",
"%s requires php %s or above to work. Sorry.": "%s savo darbui reikalauja php %s arba naujesnės versijos. Apgailestaujame.", "%s requires php %s or above to work. Sorry.": "%s savo darbui reikalauja php %s arba naujesnės versijos. Apgailestaujame.",
"%s requires configuration section [%s] to be present in configuration file.": "%s reikalauja, kad konfigūracijos faile būtų [%s] konfigūracijos sekcija.", "%s requires configuration section [%s] to be present in configuration file.": "%s reikalauja, kad konfigūracijos faile būtų [%s] konfigūracijos sekcija.",
"Please wait %d seconds between each post.": [ "Please wait %d seconds between each post.": [
@@ -14,15 +14,15 @@
"Tarp kiekvieno įrašo palaukite %d sekundžių.", "Tarp kiekvieno įrašo palaukite %d sekundžių.",
"Tarp kiekvieno įrašo palaukite %d sekundžių." "Tarp kiekvieno įrašo palaukite %d sekundžių."
], ],
"Document is limited to %s of encrypted data.": "Įdėjimas yra apribotas iki %s šifruotų duomenų.", "Document is limited to %s of encrypted data.": "Dokumentas yra apribotas iki %s šifruotų duomenų.",
"Invalid data.": "Neteisingi duomenys.", "Invalid data.": "Neteisingi duomenys.",
"You are unlucky. Try again.": "Jums nesiseka. Bandykite dar kartą.", "You are unlucky. Try again.": "Jums nesiseka. Bandykite dar kartą.",
"Error saving comment. Sorry.": "Klaida įrašant komentarą. Apgailestaujame.", "Error saving comment. Sorry.": "Klaida įrašant komentarą. Apgailestaujame.",
"Error saving document. Sorry.": "Klaida įrašant įdėjimą. Apgailestaujame.", "Error saving document. Sorry.": "Klaida įrašant dokumentą. Apgailestaujame.",
"Invalid document ID.": "Neteisingas įdėjimo ID.", "Invalid document ID.": "Neteisingas dokumento ID.",
"Document is not of burn-after-reading type.": "Įdėjimo tipas nėra „Perskaičius sudeginti“.", "Document is not of burn-after-reading type.": "Dokumento tipas nėra „Perskaičius sudeginti“.",
"Wrong deletion token. Document was not deleted.": "Neteisingas ištrynimo prieigos raktas. Įdėjimas nebuvo ištrintas.", "Wrong deletion token. Document was not deleted.": "Neteisingas ištrynimo prieigos raktas. Dokumentas nebuvo ištrintas.",
"Document was properly deleted.": "Įdėjimas buvo tinkamai ištrintas.", "Document was properly deleted.": "Dokumentas buvo tinkamai ištrintas.",
"JavaScript is required for %s to work. Sorry for the inconvenience.": "%s darbui reikalinga JavaScript. Atsiprašome už nepatogumus.", "JavaScript is required for %s to work. Sorry for the inconvenience.": "%s darbui reikalinga JavaScript. Atsiprašome už nepatogumus.",
"%s requires a modern browser to work.": "%s savo darbui reikalauja šiuolaikinės naršyklės.", "%s requires a modern browser to work.": "%s savo darbui reikalauja šiuolaikinės naršyklės.",
"New": "Naujas", "New": "Naujas",
@@ -133,9 +133,9 @@
"Šis dokumentas nustos galioti po %d mėnesių.", "Šis dokumentas nustos galioti po %d mėnesių.",
"Šis dokumentas nustos galioti po %d mėnesių." "Šis dokumentas nustos galioti po %d mėnesių."
], ],
"Please enter the password for this document:": "Įveskite šio įdėjimo slaptažodį:", "Please enter the password for this document:": "Įveskite šio dokumento slaptažodį:",
"Could not decrypt data (Wrong key?)": "Nepavyko iššifruoti duomenų (Neteisingas raktas?)", "Could not decrypt data (Wrong key?)": "Nepavyko iššifruoti duomenų (Neteisingas raktas?)",
"Could not delete the document, it was not stored in burn after reading mode.": "Nepavyko ištrinti įdėjimo, jis nebuvo saugomas „Perskaičius sudeginti“ veiksenoje.", "Could not delete the document, it was not stored in burn after reading mode.": "Nepavyko ištrinti dokumento, jis nebuvo saugomas „Perskaičius sudeginti“ veiksenoje.",
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "SKIRTA TIK JŪSŲ AKIMS. Neužverkite šio lango, šis pranešimas negalės būti rodomas dar kartą.", "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "SKIRTA TIK JŪSŲ AKIMS. Neužverkite šio lango, šis pranešimas negalės būti rodomas dar kartą.",
"Could not decrypt comment; Wrong key?": "Nepavyko iššifruoti komentaro; Neteisingas raktas?", "Could not decrypt comment; Wrong key?": "Nepavyko iššifruoti komentaro; Neteisingas raktas?",
"Reply": "Atsakyti", "Reply": "Atsakyti",
@@ -150,11 +150,11 @@
"unknown status": "nežinoma būsena", "unknown status": "nežinoma būsena",
"server error or not responding": "serverio klaida arba jis neatsako", "server error or not responding": "serverio klaida arba jis neatsako",
"Could not post comment: %s": "Nepavyko paskelbti komentaro: %s", "Could not post comment: %s": "Nepavyko paskelbti komentaro: %s",
"Sending document…": "Siunčiamas įdėjimas…", "Sending document…": "Siunčiamas dokumentas…",
"Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "Jūsų įdėjimas yra <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Paspauskite <kbd>Vald</kbd>+<kbd>c</kbd> norėdami nukopijuoti)</span>", "Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "Jūsų dokumentas yra <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Paspauskite <kbd>Ctrl</kbd>+<kbd>c</kbd> norėdami nukopijuoti)</span>",
"Delete data": "Ištrinti duomenis", "Delete data": "Ištrinti duomenis",
"Could not create document: %s": "Nepavyko sukurti įdėjimo: %s", "Could not create document: %s": "Nepavyko sukurti dokumento: %s",
"Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nepavyksta iššifruoti įdėjimo: URL adrese trūksta iššifravimo rakto (Ar naudojote peradresavimo ar URL trumpinimo įrankį, kuris pašalina URL dalį?)", "Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nepavyksta iššifruoti dokumento: URL adrese trūksta iššifravimo rakto (Ar naudojote peradresavimo ar URL trumpinimo įrankį, kuris pašalina URL dalį?)",
"B": "B", "B": "B",
"kB": "kB", "kB": "kB",
"MB": "MB", "MB": "MB",
@@ -170,7 +170,7 @@
"Markdown": "„Markdown“", "Markdown": "„Markdown“",
"Download attachment": "Atsisiųsti priedą", "Download attachment": "Atsisiųsti priedą",
"Cloned: '%s'": "Dubliuota: „%s“", "Cloned: '%s'": "Dubliuota: „%s“",
"The cloned file '%s' was attached to this document.": "Dubliuotas failas „%s“ buvo pridėtas į šį įdėjimą.", "The cloned file '%s' was attached to this document.": "Dubliuotas failas „%s“ buvo pridėtas į šį dokumentą.",
"Attach a file": "Pridėti failą", "Attach a file": "Pridėti failą",
"alternatively drag & drop a file or paste an image from the clipboard": "arba kitaip - tempkite failą arba įdėkite paveikslą iš iškarpinės", "alternatively drag & drop a file or paste an image from the clipboard": "arba kitaip - tempkite failą arba įdėkite paveikslą iš iškarpinės",
"File too large, to display a preview. Please download the attachment.": "Failas per didelis, kad būtų rodoma peržiūra. Atsisiųskite priedą.", "File too large, to display a preview. Please download the attachment.": "Failas per didelis, kad būtų rodoma peržiūra. Atsisiųskite priedą.",
@@ -185,11 +185,11 @@
"Decrypt": "Iššifruoti", "Decrypt": "Iššifruoti",
"Enter password": "Įveskite slaptažodį", "Enter password": "Įveskite slaptažodį",
"Loading…": "Įkeliama…", "Loading…": "Įkeliama…",
"Decrypting document…": "Iššifruojamas įdėjimas…", "Decrypting document…": "Iššifruojamas dokumentas…",
"Preparing new document…": "Ruošiamas naujas įdėjimas…", "Preparing new document…": "Ruošiamas naujas dokumentas…",
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "Jeigu šis pranešimas niekada nedingsta, pasižiūrėkite <a href=\"%s\">šį DUK skyrių, kuriame yra informacija apie nesklandumų šalinimą</a>.", "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "Jeigu šis pranešimas niekada nedingsta, pasižiūrėkite <a href=\"%s\">šį DUK skyrių, kuriame yra informacija apie nesklandumų šalinimą</a>.",
"+++ no document text +++": "+++ nėra įdėjimo teksto +++", "+++ no document text +++": "+++ nėra dokumento teksto +++",
"Could not get document data: %s": "Nepavyko gauti įdėjimo duomenų: %s", "Could not get document data: %s": "Nepavyko gauti dokumento duomenų: %s",
"QR code": "QR kodas", "QR code": "QR kodas",
"This website is using an insecure HTTP connection! Please use it only for testing.": "Ši internetinė svetainė naudoja nesaugų HTTP ryšį! Naudokite ją tik bandymams.", "This website is using an insecure HTTP connection! Please use it only for testing.": "Ši internetinė svetainė naudoja nesaugų HTTP ryšį! Naudokite ją tik bandymams.",
"For more information <a href=\"%s\">see this FAQ entry</a>.": "Išsamesnei informacijai, <a href=\"%s\">žiūrėkite šį DUK įrašą</a>.", "For more information <a href=\"%s\">see this FAQ entry</a>.": "Išsamesnei informacijai, <a href=\"%s\">žiūrėkite šį DUK įrašą</a>.",
@@ -210,26 +210,26 @@
"Encrypted note on %s": "Šifruoti užrašai ties %s", "Encrypted note on %s": "Šifruoti užrašai ties %s",
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.",
"URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.", "URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.",
"URL shortener is enabled by default.": "URL shortener is enabled by default.", "URL shortener is enabled by default.": "URL trumpinimo įrankis pagal numatymą įjungtas.",
"Save document": "Įrašyti įdėjimą", "Save document": "Įrašyti dokumentą",
"Your IP is not authorized to create documents.": "Jūsų IP adresas neturi įgaliojimų kurti įdėjimų.", "Your IP is not authorized to create documents.": "Jūsų IP adresas neturi įgaliojimų kurti dokumentus.",
"Trying to shorten a URL that isn't pointing at our instance.": "Bandoma sutrumpinti URL adresą, kuris nenurodo į mūsų egzempliorių.", "Trying to shorten a URL that isn't pointing at our instance.": "Bandoma sutrumpinti URL adresą, kuris nenurodo į mūsų egzempliorių.",
"Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Klaida iškviečiant YOURLS. Tikriausiai, konfigūracijos klaida, pavyzdžiui, neteisingi „apiurl“ ar „signature“, arba jų nėra.", "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Įgaliotojo serverio klaida: Įgaliotojo serverio URL yra tuščias. Tai gali būti konfigūracijos sukelta problema, pavyzdžiui, neteisingi arba trūkstami konfigūracijos raktai.",
"Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Klaida nagrinėjant YOURLS atsaką.", "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Įgaliotojo serverio klaida: Klaida nagrinėjant įgaliotojo serverio atsaką. Tai gali būti konfigūracijos sukelta problema, pavyzdžiui, neteisingi arba trūkstami konfigūracijos raktai.",
"Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.", "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Įgaliotojo serverio klaida: Blogas atsakas. Tai gali būti konfigūracijos sukelta problema, pavyzdžiui, neteisingi arba trūkstami konfigūracijos raktai, arba laikinas avarinis atjungimas.",
"This secret message can only be displayed once. Would you like to see it now?": "Ši slapta žinutė gali būti parodyta tik vieną kartą. Ar norėtumėte ją dabar pamatyti?", "This secret message can only be displayed once. Would you like to see it now?": "Ši slapta žinutė gali būti parodyta tik vieną kartą. Ar norėtumėte ją dabar pamatyti?",
"Yes, see it": "Taip, pamatyti", "Yes, see it": "Taip, pamatyti",
"Dark Mode": "Tamsi veiksena", "Dark Mode": "Tamsi veiksena",
"Error compressing document, due to missing WebAssembly support.": "Klaida glaudinant įdėjimą, nes trūksta WebAssembly palaikymo.", "Error compressing document, due to missing WebAssembly support.": "Klaida glaudinant dokumentą, nes trūksta WebAssembly palaikymo.",
"Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Klaida išglaudinant įdėjimą, jūsų naršyklė nepalaiko WebAssembly. Norėdami peržiūrėti šį įdėjimą, naudokite kitą naršyklę.", "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Klaida išglaudinant dokumentą, jūsų naršyklė nepalaiko WebAssembly. Norėdami peržiūrėti šį dokumentą, naudokite kitą naršyklę.",
"Start over": "Start over", "Start over": "Pradėti iš naujo",
"Document copied to clipboard": "Document copied to clipboard", "Document copied to clipboard": "Dokumentas nukopijuotas į iškarpinę",
"To copy document press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy document press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>", "To copy document press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "Norėdami nukopijuoti dokumentą paspauskite kopijavimo mygtuką arba naudokite iškarpinės sparčiuosius klavišus <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>",
"Copy link": "Copy link", "Copy link": "Kopijuoti nuorodą",
"Link copied to clipboard": "Link copied to clipboard", "Link copied to clipboard": "Nuoroda nukopijuota į iškarpinę",
"Document text": "Document text", "Document text": "Dokumento tekstas",
"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)", "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabuliatoriaus klavišas tarnauja kaip simbolis (Paspauskite <kbd>Ctrl</kbd>+<kbd>m</kbd> arba <kbd>Esc</kbd> norėdami perjungti)",
"Show password": "Show password", "Show password": "Rodyti slaptažodį",
"Hide password": "Hide password", "Hide password": "Slėpti slaptažodį",
"Theme": "Theme" "Theme": "Apipavidalinimas"
} }

View File

@@ -1,10 +1,10 @@
{ {
"PrivateBin": "PrivateBin", "PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s це мінімалістичний Open Source проєкт для створення нотаток, де сервер не знає нічого про дані, що зберігаються. Дані шифруються/розшифровуються %sу браузері%s з використанням 256-бітного шифрування AES.", "%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s мінімалістична вільна програма для створення нотаток, сервер якої не знає нічого про дані, що зберігаються. Дані шифруються/розшифровуються %sу браузері%s з використанням 256-бітного шифрування AES.",
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Подробиці можна дізнатися на <a href=\"https://privatebin.info/\">сайті проєкту</a>.", "More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Докладніше — на <a href=\"https://privatebin.info/\">сайті проєкту</a>.",
"Because ignorance is bliss": "Бо незнання - благо", "Because ignorance is bliss": "Менше знаєш — краще спиш",
"Document does not exist, has expired or has been deleted.": "Допис не існує, протермінований чи був видалений.", "Document does not exist, has expired or has been deleted.": "Документ не існує. Можливо, його протерміновано чи видалено.",
"%s requires php %s or above to work. Sorry.": "Для роботи %s потрібен php %s и вище. Вибачте.", "%s requires php %s or above to work. Sorry.": "Для роботи %s потрібен php %s чи вище. Вибачте.",
"%s requires configuration section [%s] to be present in configuration file.": "%s потрібна секція [%s] в конфігураційному файлі.", "%s requires configuration section [%s] to be present in configuration file.": "%s потрібна секція [%s] в конфігураційному файлі.",
"Please wait %d seconds between each post.": [ "Please wait %d seconds between each post.": [
"Будь ласка, зачекайте %d секунду між створеннями.", "Будь ласка, зачекайте %d секунду між створеннями.",
@@ -14,18 +14,18 @@
"Будь ласка, зачекайте %d секунд між створеннями.", "Будь ласка, зачекайте %d секунд між створеннями.",
"Будь ласка, зачекайте %d секунд між створеннями." "Будь ласка, зачекайте %d секунд між створеннями."
], ],
"Document is limited to %s of encrypted data.": "Розмір допису обмежений %s зашифрованих даних.", "Document is limited to %s of encrypted data.": "Розмір документа обмежено %s зашифрованих даних.",
"Invalid data.": "Неправильні дані.", "Invalid data.": "Неправильні дані.",
"You are unlucky. Try again.": "Якась халепа! Спробуйте ще раз.", "You are unlucky. Try again.": "Якась халепа! Спробуйте ще раз.",
"Error saving comment. Sorry.": "Помилка при збереженні коментаря. Вибачте.", "Error saving comment. Sorry.": "Не вдалося зберегти коментар. Вибачте.",
"Error saving document. Sorry.": "Помилка при збереженні допису. Вибачте.", "Error saving document. Sorry.": "Не вдалося зберегти документ. Вибачте.",
"Invalid document ID.": "Неправильний ID допису.", "Invalid document ID.": "Хибний ідентифікатор документа.",
"Document is not of burn-after-reading type.": "Тип допису не \"Знищити після прочитання\".", "Document is not of burn-after-reading type.": "Тип документа не «Знищити після прочитання».",
"Wrong deletion token. Document was not deleted.": "Неправильний жетон вилучення допису. Допис не вилучено.", "Wrong deletion token. Document was not deleted.": "Хибний токен видалення. Документ не видалено.",
"Document was properly deleted.": "Допис був вилучений повністю.", "Document was properly deleted.": "Документ видалено повністю.",
"JavaScript is required for %s to work. Sorry for the inconvenience.": "Для роботи %s потрібен увімкнутий JavaScript. Вибачте.", "JavaScript is required for %s to work. Sorry for the inconvenience.": "Для роботи %s потрібен увімкнутий JavaScript. Вибачте.",
"%s requires a modern browser to work.": "Для роботи %s потрібен більш сучасний браузер.", "%s requires a modern browser to work.": "Для роботи %s потрібен більш сучасний браузер.",
"New": "Новий допис", "New": "Новий документ",
"Create": "Створити", "Create": "Створити",
"Clone": "Дублювати", "Clone": "Дублювати",
"Raw text": "Початковий текст", "Raw text": "Початковий текст",
@@ -36,8 +36,8 @@
"Discussion": "Обговорення", "Discussion": "Обговорення",
"Toggle navigation": "Перемкнути навігацію", "Toggle navigation": "Перемкнути навігацію",
"%d seconds": [ "%d seconds": [
"%d секунд", "%d секунду",
"%d секунд", "%d секунди",
"%d секунд", "%d секунд",
"%d секунд", "%d секунд",
"%d секунд", "%d секунд",
@@ -92,144 +92,144 @@
"%d років" "%d років"
], ],
"Never": "Ніколи", "Never": "Ніколи",
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Примітка: Це тестовий сервіс: Дані можуть бути вилучені в будь який момент. Кошенята помруть, якщо ви будете зловживати сервісом.", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Примітка: це тестовий сервіс, і дані можуть бути видалені в будь-який момент. Будете зловживати — пси вам марша зіграють.",
"This document will expire in %d seconds.": [ "This document will expire in %d seconds.": [
"Документ буде вилучений через %d секунду.", "Документ буде видалено через %d секунду.",
"Документ буде вилучений через %d секунди.", "Документ буде видалено через %d секунди.",
"Документ буде вилучений через %d секунд.", "Документ буде видалено через %d секунд.",
"Документ буде вилучений через %d секунд.", "Документ буде видалено через %d секунд.",
"Документ буде вилучений через %d секунд.", "Документ буде видалено через %d секунд.",
"Документ буде вилучений через %d секунд." "Документ буде видалено через %d секунд."
], ],
"This document will expire in %d minutes.": [ "This document will expire in %d minutes.": [
"Документ буде вилучений через %d хвилину.", "Документ буде видалено через %d хвилину.",
"Документ буде вилучений через %d хвилини.", "Документ буде видалено через %d хвилини.",
"Документ буде вилучений через %d хвилин.", "Документ буде видалено через %d хвилин.",
"Документ буде вилучений через %d хвилин.", "Документ буде видалено через %d хвилин.",
"Документ буде вилучений через %d хвилин.", "Документ буде видалено через %d хвилин.",
"Документ буде вилучений через %d хвилин." "Документ буде видалено через %d хвилин."
], ],
"This document will expire in %d hours.": [ "This document will expire in %d hours.": [
"Документ буде вилучений через %d годину.", "Документ буде видалено через %d годину.",
"Документ буде вилучений через %d години.", "Документ буде видалено через %d години.",
"Документ буде вилучений через %d годин.", "Документ буде видалено через %d годин.",
"Документ буде вилучений через %d годин.", "Документ буде видалено через %d годин.",
"Документ буде вилучений через %d годин.", "Документ буде видалено через %d годин.",
"Документ буде вилучений через %d годин." "Документ буде видалено через %d годин."
], ],
"This document will expire in %d days.": [ "This document will expire in %d days.": [
"Документ буде вилучений через %d день.", "Документ буде видалено через %d день.",
"Документ буде вилучений через %d дні.", "Документ буде видалено через %d дні.",
"Документ буде вилучений через %d днів.", "Документ буде видалено через %d днів.",
"Документ буде вилучений через %d днів.", "Документ буде видалено через %d днів.",
"Документ буде вилучений через %d днів.", "Документ буде видалено через %d днів.",
"Документ буде вилучений через %d днів." "Документ буде видалено через %d днів."
], ],
"This document will expire in %d months.": [ "This document will expire in %d months.": [
"Документ буде вилучений через %d місяць.", "Документ буде видалено через %d місяць.",
"Документ буде вилучений через %d місяці.", "Документ буде видалено через %d місяці.",
"Документ буде вилучений через %d місяців.", "Документ буде видалено через %d місяців.",
"Документ буде вилучений через %d місяців.", "Документ буде видалено через %d місяців.",
"Документ буде вилучений через %d місяців.", "Документ буде видалено через %d місяців.",
"Документ буде вилучений через %d місяців." "Документ буде видалено через %d місяців."
], ],
"Please enter the password for this document:": "Будь ласка, введіть пароль від допису:", "Please enter the password for this document:": "Введіть пароль від документа:",
"Could not decrypt data (Wrong key?)": "Неможливо розшифрувати дані (можливо, невірний ключ?)", "Could not decrypt data (Wrong key?)": "Неможливо розшифрувати дані (хибний ключ?)",
"Could not delete the document, it was not stored in burn after reading mode.": "Неможливо вилучити допис, він не був збережений в режимі знищити після прочитання.", "Could not delete the document, it was not stored in burn after reading mode.": "Неможливо видалити документ, його не збережено в режимі «Знищити після прочитання».",
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ЛИШЕ ДЛЯ ВАШИХ ОЧЕЙ. Не закривайте це вікно, це повідомлення не може бути показано знову.", "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ЛИШЕ ДЛЯ ВАС. Не закривайте вікно, це повідомлення одноразове.",
"Could not decrypt comment; Wrong key?": "Неможливо розшифрувати коментар; Неправильний ключ?", "Could not decrypt comment; Wrong key?": "Неможливо розшифрувати коментар. Хибний ключ?",
"Reply": "Відповісти", "Reply": "Відповісти",
"Anonymous": "Анонім", "Anonymous": "Анонім",
"Avatar generated from IP address": "Аватар зґенерований з IP-адреси", "Avatar generated from IP address": "Аватар зґенеровано з IP-адреси",
"Add comment": "Додати коментар", "Add comment": "Додати коментар",
"Optional nickname…": "Необов’язкове прізвисько…", "Optional nickname…": "Необов’язкове прізвисько…",
"Post comment": "Відправити коментар", "Post comment": "Надіслати коментар",
"Sending comment…": "Відправка коментаря…", "Sending comment…": "Надсилання коментаря…",
"Comment posted.": "Коментар опублікований.", "Comment posted.": "Коментар опубліковано.",
"Could not refresh display: %s": "Не вдалося оновити екран: %s", "Could not refresh display: %s": "Не вдалося оновити екран: %s",
"unknown status": "невідома причина", "unknown status": "невідома причина",
"server error or not responding": "помилка на сервері чи немає відповіді", "server error or not responding": "помилка на сервері чи немає відповіді",
"Could not post comment: %s": "Не вдалося опублікувати коментар: %s", "Could not post comment: %s": "Не вдалося опублікувати коментар: %s",
"Sending document…": "Відправка допису…", "Sending document…": "Надсилання документа…",
"Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "Посилання на допис <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Тисніть <kbd>Ctrl</kbd>+<kbd>c</kbd>, щоб скопіювати посилання)</span>", "Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "Документ: <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(копіювати: <kbd>Ctrl</kbd>+<kbd>c</kbd>)</span>",
"Delete data": "Видалити допис", "Delete data": "Видалити дані",
"Could not create document: %s": "Не вдалося опублікувати допис: %s", "Could not create document: %s": "Не вдалося опублікувати документ: %s",
"Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Неможливо розшифрувати запис: Ключ дешифрування відсутній в посиланні (Можливо, ви використовуєте скорочувач посилань, що видаляє частину посилання?)", "Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Не вдається розшифрувати документ: ключ дешифрування відсутній у посиланні (можливо, ваш сервіс переспрямування чи скорочення посилань видаляє частину посилання?)",
"B": "байт", "B": "Б",
"kB": байт", "kB": Б",
"MB": "Мбайт", "MB": "МБ",
"GB": байт", "GB": Б",
"TB": "Тбайт", "TB": "ТБ",
"PB": байт", "PB": Б",
"EB": "Ебайт", "EB": "ЕБ",
"ZB": "Збайт", "ZB": "ЗБ",
"YB": байт", "YB": Б",
"Format": "Формат", "Format": "Формат",
"Plain Text": "Звичайний текст", "Plain Text": "Звичайний текст",
"Source Code": "Вихідний код", "Source Code": "Вихідний код",
"Markdown": "Мова розмітки", "Markdown": "Мова розмітки",
"Download attachment": "Звантажити прикріплений файл", "Download attachment": "Завантажити вкладення",
"Cloned: '%s'": "Дубльовано: '%s'", "Cloned: '%s'": "Дубльовано: «%s»",
"The cloned file '%s' was attached to this document.": "Дублікат файлу '%s' був прикріплений до цього запису.", "The cloned file '%s' was attached to this document.": "Дублікат файлу «%s» вкладено до цього документа.",
"Attach a file": "Прикріпити файл", "Attach a file": "Вкласти файл",
"alternatively drag & drop a file or paste an image from the clipboard": "також можна перенести файл у вікно переглядача чи вставити зображення з буфера", "alternatively drag & drop a file or paste an image from the clipboard": "також можна перенести файл у вікно браузера чи вставити зображення з буфера",
"File too large, to display a preview. Please download the attachment.": "Файл завеликий для відображення передогляду. Будь ласка, звантажте прикріплений файл.", "File too large, to display a preview. Please download the attachment.": "Файл завеликий для передогляду. Будь ласка, завантажте вкладення.",
"Remove attachment": "Видалити вкладення", "Remove attachment": "Видалити вкладення",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Ваш переглядач не підтримує відправлення зашифрованих файлів. Використовуйте сучасніший переглядач.", "Your browser does not support uploading encrypted files. Please use a newer browser.": "Ваш браузер не підтримує надсилання зашифрованих файлів. Використовуйте сучасніший браузер.",
"Invalid attachment.": "Невідоме вкладення.", "Invalid attachment.": "Непідтримуване вкладення.",
"Options": "Опції", "Options": "Опції",
"Shorten URL": "Коротке посилання", "Shorten URL": "Коротке посилання",
"Editor": "Редактор", "Editor": "Редактор",
"Preview": "Передогляд", "Preview": "Передогляд",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "Змінна PATH необхідна %s в конці \"%s\". Будь ласка, оновіть змінну PATH у вашому index.php.", "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "Для роботи %s у кінці змінної PATH має бути «%s». Будь ласка, оновіть змінну PATH у вашому index.php.",
"Decrypt": "Розшифрувати", "Decrypt": "Розшифрувати",
"Enter password": "Введіть пароль", "Enter password": "Введіть пароль",
"Loading…": "Завантаження…", "Loading…": "Завантаження…",
"Decrypting document…": "Розшифровування допису…", "Decrypting document…": "Розшифрування документа…",
"Preparing new document…": риготування нового допису…", "Preparing new document…": ідготовка нового документа…",
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "Якщо це повідомлення не зникатиме тривалий час, подивіться <a href=\"%s\">цей FAQ з інформацією про можливе вирішення проблеми</a>.", "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "Якщо це повідомлення не зникатиме тривалий час, подивіться <a href=\"%s\">цей FAQ з інформацією про можливе вирішення проблеми</a>.",
"+++ no document text +++": "+++ у дописі немає тексту +++", "+++ no document text +++": "+++ документ без тексту +++",
"Could not get document data: %s": "Не вдалося отримати дані допису: %s", "Could not get document data: %s": "Не вдалося отримати дані документа: %s",
"QR code": "QR код", "QR code": "QR код",
"This website is using an insecure HTTP connection! Please use it only for testing.": "Цей сайт використовує незахищене HTTP підключення! Будь ласка, використовуйте його лише для тестування.", "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\">дивіться інформацію в FAQ</a>.", "For more information <a href=\"%s\">see this FAQ entry</a>.": окладніше — <a href=\"%s\">в FAQ</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Ваш переглядач вимагає підключення HTTPS для підтримки WebCrypto API. Спробуйте <a href=\"%s\">перемкнутися на HTTPS</a>.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "WebCrypto API може не працювати у вашому браузері без HTTPS-з'єднання. Спробуйте <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. Ви можете створювати нестиснені документи, але не зможете читати стиснені.", "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": "очікування користувача для вводу паролю", "waiting on user to provide a password": "очікування користувача для вводу пароля",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Не вдалося розшифрувати дані. Може, ви ввели неправильний пароль? Спробуйте знову за допомогою верхньої кнопки.", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Не вдалося розшифрувати дані. Може, ви ввели неправильний пароль? Спробуйте знову за допомогою верхньої кнопки.",
"Retry": "Спробуйте ще раз", "Retry": "Спробуйте ще раз",
"Showing raw text…": "Відображається неформатований текст…", "Showing raw text…": "Показано неформатований текст…",
"Notice:": "Зверніть увагу:", "Notice:": "Зверніть увагу:",
"This link will expire after %s.": "Термін дії цього посилання сплине через %s.", "This link will expire after %s.": "Термін дії цього посилання сплине через %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.": "Дане посилання доступна тільки один раз, не натискайте кнопку назад та не обновляйте сторінку браузера.", "This link can only be accessed once, do not use back or refresh button in your browser.": "Посилання доступне тільки один раз, не натискайте кнопку «Назад» і не оновлюйте сторінку браузера.",
"Link:": "Посилання:", "Link:": "Посилання:",
"Recipient may become aware of your timezone, convert time to UTC?": "Отримувач дізнається ваш часовий пояс, перетворити час в UTC?", "Recipient may become aware of your timezone, convert time to UTC?": "Отримувач дізнається ваш часовий пояс, перетворити час в UTC?",
"Use Current Timezone": "Використовувати поточний часовий пояс", "Use Current Timezone": "Використовувати поточний часовий пояс",
"Convert To UTC": "Конвертувати в UTC", "Convert To UTC": "Конвертувати в UTC",
"Close": "Закрити", "Close": "Закрити",
"Encrypted note on %s": "Зашифрована нотатка на %s", "Encrypted note on %s": "Зашифрована нотатка в %s",
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Відвідайте посилання, щоб переглянути нотатку. Передача посилання будь-кому дозволить їм переглянути нотатку.", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Відвідайте посилання, щоб переглянути нотатку. Передача посилання будь-кому дозволить їм переглянути нотатку.",
"URL shortener may expose your decrypt key in URL.": "Сервіс скорочення посилань може викрити ваш ключ дешифрування з URL.", "URL shortener may expose your decrypt key in URL.": "Сервіс скорочення посилань може викрити ваш ключ дешифрування з URL.",
"URL shortener is enabled by default.": "URL shortener is enabled by default.", "URL shortener is enabled by default.": "Скорочення посилань типово увімкнено.",
"Save document": "Зберегти вставку", "Save document": "Зберегти документ",
"Your IP is not authorized to create documents.": "Вашому IP не дозволено створювати вставки.", "Your IP is not authorized to create documents.": "Вашій IP-адресі не дозволено створювати документи.",
"Trying to shorten a URL that isn't pointing at our instance.": "Спроба скоротити URL, який не вказує на наш екземпляр.", "Trying to shorten a URL that isn't pointing at our instance.": "Спроба скоротити URL, який не вказує на наш сервер.",
"Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Помилка виклику YOURLS. Ймовірно проблема з налаштуванням, наприклад \"apiurl\" чи \"signature\".", "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Помилка проксі: не вказано URL-адреси проксі. Ймовірно, проблема в налаштуваннях: ключі конфігурації можуть бути відсутні або містити одрук.",
"Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Помилка розбору відповіді YOURLS.", "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Помилка проксі: не вдається розпізнати відповідь проксі. Ймовірно, проблема в налаштуваннях: ключі конфігурації можуть бути відсутні або містити одрук",
"Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.", "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Помилка проксі: хибна відповідь. Ймовірно, проблема в налаштуваннях: ключі конфігурації можуть бути відсутні або містити одрук.",
"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 document, due to missing WebAssembly support.": "Помилка при стисканні допису, через відсутність підтримки WebAssembly сервера.", "Error compressing document, due to missing WebAssembly support.": "Помилка стиснення документа: сервер не підтримує WebAssembly.",
"Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте в іншому браузері для перегляду цього допису.", "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Помилка розпакування документа: браузер не підтримує WebAssembly. Спробуйте відкрити документ в іншому браузері.",
"Start over": "Почати знову", "Start over": "Почати знову",
"Document copied to clipboard": "Document copied to clipboard", "Document copied to clipboard": "Документ скопійовано до буфера",
"To copy document press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>": "To copy document press on the copy button or use the clipboard shortcut <kbd>Ctrl</kbd>+<kbd>c</kbd>/<kbd>Cmd</kbd>+<kbd>c</kbd>", "To copy document 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": "Copy link", "Copy link": "Копіювати посилання",
"Link copied to clipboard": "Link copied to clipboard", "Link copied to clipboard": "Посилання скопійовано до буфера",
"Document text": "Document text", "Document 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)", "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>)",
"Show password": "Show password", "Show password": "Показати пароль",
"Hide password": "Hide password", "Hide password": "Сховати пароль",
"Theme": "Theme" "Theme": "Тема"
} }

View File

@@ -229,7 +229,7 @@
"Link copied to clipboard": "链接已复制到剪贴板", "Link copied to clipboard": "链接已复制到剪贴板",
"Document text": "粘贴文本", "Document 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> 切换开关)", "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> 切换开关)",
"Show password": "Show password", "Show password": "显示密码",
"Hide password": "Hide password", "Hide password": "隐藏密码",
"Theme": "主题" "Theme": "主题"
} }

View File

@@ -15,7 +15,7 @@ require('./prettify');
global.prettyPrint = window.PR.prettyPrint; global.prettyPrint = window.PR.prettyPrint;
global.prettyPrintOne = window.PR.prettyPrintOne; global.prettyPrintOne = window.PR.prettyPrintOne;
global.showdown = require('./showdown-2.1.0'); global.showdown = require('./showdown-2.1.0');
global.DOMPurify = require('./purify-3.2.7'); global.DOMPurify = require('./purify-3.3.0');
global.baseX = require('./base-x-5.0.1').baseX; global.baseX = require('./base-x-5.0.1').baseX;
global.Legacy = require('./legacy').Legacy; global.Legacy = require('./legacy').Legacy;
require('./privatebin'); require('./privatebin');

View File

@@ -1,6 +1,6 @@
{ {
"name": "privatebin", "name": "privatebin",
"version": "2.0.1", "version": "2.0.3",
"description": "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted in the browser using 256 bit AES in Galois Counter mode (GCM).", "description": "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted in the browser using 256 bit AES in Galois Counter mode (GCM).",
"main": "privatebin.js", "main": "privatebin.js",
"directories": { "directories": {

View File

@@ -2992,7 +2992,8 @@ jQuery.PrivateBin = (function($) {
attachmentLink.attr('download', fileName); attachmentLink.attr('download', fileName);
const fileSize = Helper.formatBytes(decodedData.length); const fileSize = Helper.formatBytes(decodedData.length);
template.append(`(${fileName}, ${fileSize})`); const fileInfo = document.createTextNode(` (${fileName}, ${fileSize})`);
template[0].appendChild(fileInfo);
} }
// sanitize SVG preview // sanitize SVG preview
@@ -3085,10 +3086,15 @@ jQuery.PrivateBin = (function($) {
* @name AttachmentViewer.printDragAndDropFileNames * @name AttachmentViewer.printDragAndDropFileNames
* @private * @private
* @function * @function
* @param {array} fileNames * @param {string[]} fileNames
*/ */
function printDragAndDropFileNames(fileNames) { function printDragAndDropFileNames(fileNames) {
$dragAndDropFileNames.html(fileNames.join('<br>')); $dragAndDropFileNames.empty();
fileNames.forEach(fileName => {
const name = document.createTextNode(fileName);
$dragAndDropFileNames[0].appendChild(name);
$dragAndDropFileNames[0].appendChild(document.createElement('br'));
});
} }
/** /**
@@ -3287,44 +3293,38 @@ jQuery.PrivateBin = (function($) {
const alreadyIncludesCurrentAttachment = $targetElement.find(`[src='${blobUrl}']`).length > 0; const alreadyIncludesCurrentAttachment = $targetElement.find(`[src='${blobUrl}']`).length > 0;
if (blobUrl && !alreadyIncludesCurrentAttachment) { if (blobUrl && !alreadyIncludesCurrentAttachment) {
if (mimeType.match(/^image\//i)) { if (mimeType.toLowerCase().startsWith('image/')) {
$targetElement.append( const image = document.createElement('img');
$(document.createElement('img')) image.setAttribute('src', blobUrl);
.attr('src', blobUrl) image.setAttribute('class', 'img-thumbnail');
.attr('class', 'img-thumbnail') $targetElement[0].appendChild(image);
); } else if (mimeType.toLowerCase().startsWith('video/')) {
} else if (mimeType.match(/^video\//i)) { const video = document.createElement('video');
$targetElement.append( video.setAttribute('controls', 'true');
$(document.createElement('video')) video.setAttribute('autoplay', 'true');
.attr('controls', 'true') video.setAttribute('class', 'img-thumbnail');
.attr('autoplay', 'true') const source = document.createElement('source');
.attr('class', 'img-thumbnail') source.setAttribute('type', mimeType);
source.setAttribute('src', blobUrl);
.append($(document.createElement('source')) video.appendChild(source);
.attr('type', mimeType) $targetElement[0].appendChild(video);
.attr('src', blobUrl)) } else if (mimeType.toLowerCase().startsWith('audio/')) {
); const audio = document.createElement('audio');
} else if (mimeType.match(/^audio\//i)) { audio.setAttribute('controls', 'true');
$targetElement.append( audio.setAttribute('autoplay', 'true');
$(document.createElement('audio')) const source = document.createElement('source');
.attr('controls', 'true') source.setAttribute('type', mimeType);
.attr('autoplay', 'true') source.setAttribute('src', blobUrl);
audio.appendChild(source);
.append($(document.createElement('source')) $targetElement[0].appendChild(audio);
.attr('type', mimeType) } else if (mimeType.toLowerCase().endsWith('/pdf')) {
.attr('src', blobUrl)) const embed = document.createElement('embed');
); embed.setAttribute('src', blobUrl);
} else if (mimeType.match(/\/pdf/i)) { embed.setAttribute('type', 'application/pdf');
embed.setAttribute('class', 'pdfPreview');
// Fallback for browsers, that don't support the vh unit // Fallback for browsers, that don't support the vh unit
const clientHeight = $(window).height(); embed.style.height = window.innerHeight + 'px';
$targetElement[0].appendChild(embed);
$targetElement.append(
$(document.createElement('embed'))
.attr('src', blobUrl)
.attr('type', 'application/pdf')
.attr('class', 'pdfPreview')
.css('height', clientHeight)
);
} }
} }
}; };
@@ -3603,8 +3603,10 @@ jQuery.PrivateBin = (function($) {
if (nickname.length > 0) { if (nickname.length > 0) {
$commentEntry.find('span.nickname').text(nickname); $commentEntry.find('span.nickname').text(nickname);
} else { } else {
$commentEntry.find('span.nickname').html('<i></i>'); const anonCommenter = document.createElement('em');
I18n._($commentEntry.find('span.nickname i'), 'Anonymous'); anonCommenter.textContent = I18n._('Anonymous');
$commentEntry.find('span.nickname')[0].innerHTML = '';
$commentEntry.find('span.nickname')[0].appendChild(anonCommenter);
} }
// set date // set date
@@ -3617,14 +3619,10 @@ jQuery.PrivateBin = (function($) {
// if an avatar is available, display it // if an avatar is available, display it
const icon = comment.getIcon(); const icon = comment.getIcon();
if (icon) { if (icon) {
$commentEntry.find('span.nickname') const image = document.createElement('img');
.before( image.setAttribute('src', icon);
'<img src="' + icon + '" class="vizhash" /> ' image.setAttribute('class', 'vizhash');
); $commentEntry.find('span.nickname').prepend(' ').prepend(image);
$(document).on('languageLoaded', function () {
$commentEntry.find('img.vizhash')
.prop('title', I18n._('Avatar generated from IP address'));
});
} }
// starting point (default value/fallback) // starting point (default value/fallback)
@@ -5221,22 +5219,23 @@ jQuery.PrivateBin = (function($) {
cipherMessage['attachment'] = attachments.map(attachment => attachment[0]); cipherMessage['attachment'] = attachments.map(attachment => attachment[0]);
cipherMessage['attachment_name'] = attachments.map(attachment => attachment[1]); cipherMessage['attachment_name'] = attachments.map(attachment => attachment[1]);
cipherMessage['attachment'] = await Promise.all(cipherMessage['attachment'].map(async (attachment) => { cipherMessage['attachment'] = await Promise.all(cipherMessage['attachment'].map(async (attachment, i) => {
// we need to retrieve data from blob if browser already parsed it in memory // we need to retrieve data from blob if browser already parsed it in memory
if (typeof attachment === 'string' && attachment.startsWith('blob:')) { if (typeof attachment === 'string' && attachment.startsWith('blob:')) {
Alert.showStatus( Alert.showStatus(
[ [
'Retrieving cloned file \'%s\' from memory...', 'Retrieving cloned file \'%s\' from memory...',
attachment[1] cipherMessage['attachment_name'][i]
], ],
'copy' 'copy'
); );
try { try {
const blobData = await $.ajax({ const blobData = await $.ajax({
type: 'GET', type: 'GET',
url: `${attachment}`, url: attachment,
processData: false, processData: false,
timeout: 10000, timeout: 10000,
dataType: 'binary',
xhrFields: { xhrFields: {
withCredentials: false, withCredentials: false,
responseType: 'blob' responseType: 'blob'
@@ -5418,6 +5417,10 @@ jQuery.PrivateBin = (function($) {
plaintexts[i][1] plaintexts[i][1]
); );
} }
$(document).on('languageLoaded', function () {
$('#commentcontainer').find('img.vizhash')
.prop('title', I18n._('Avatar generated from IP address'));
});
}); });
} }

File diff suppressed because one or more lines are too long

2
js/purify-3.3.0.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -129,5 +129,46 @@ describe('AttachmentViewer', function () {
return results.every(element => element); return results.every(element => element);
} }
); );
it(
'sanitizes file names in attachments',
function() {
const clean = jsdom();
$('body').html(
'<div id="attachmentPreview" class="col-md-12 text-center hidden"></div>' +
'<div id="attachment" class="hidden"></div>' +
'<div id="templates">' +
'<div id="attachmenttemplate" role="alert" class="attachment hidden alert alert-info">' +
'<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>' +
'<a class="alert-link">Download attachment</a>' +
'</div>' +
'</div>'
);
// mock createObjectURL for jsDOM
if (typeof window.URL.createObjectURL === 'undefined') {
Object.defineProperty(
window.URL,
'createObjectURL',
{value: function(blob) {
return 'blob:' + location.origin + '/1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed';
}}
)
}
$.PrivateBin.AttachmentViewer.init();
$.PrivateBin.Model.init();
global.atob = common.atob;
const maliciousFileNames = [
'<script>alert("☹️");//<a',
'"><meta http-equiv="refresh" content="0;url=http://example.com/">.txt'
];
for (const filename of maliciousFileNames) {
$.PrivateBin.AttachmentViewer.setAttachment('data:;base64,', filename);
assert.ok(!$('body').html().includes(filename));
}
clean();
}
);
}); });
}); });

View File

@@ -121,8 +121,8 @@ class Configuration
'js/kjua-0.10.0.js' => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==', 'js/kjua-0.10.0.js' => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==',
'js/legacy.js' => 'sha512-rGXYUpIqbFoHAgBXZ0UlJBdNAIMOC9EQ67MG0X46D5uRB8LvwzgKirbSQRGdYfk8I2jsUcm+tvHXYboUnC6DUg==', 'js/legacy.js' => 'sha512-rGXYUpIqbFoHAgBXZ0UlJBdNAIMOC9EQ67MG0X46D5uRB8LvwzgKirbSQRGdYfk8I2jsUcm+tvHXYboUnC6DUg==',
'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
'js/privatebin.js' => 'sha512-2F02E/UQoQyCNk0FvwaOLD9MvDhtuYqTtGKdqwsbDjY4O0jMZjn/EtiP2wvS0uxYojkxeUitF0HWb+RDFUwQXg==', 'js/privatebin.js' => 'sha512-ZwoUDxBdEE+zNoGqr9o7X7CJYS4JStEeNvcOnhz69YVbXjiibNoYSY7i3vc6MLI3M/K1K6sIUmSFm8sjoUdF5Q==',
'js/purify-3.2.7.js' => 'sha512-2H9wzIiPQCOsh7T3hK/WuqWIwSQ2oYq91doyrp1LcnXuPyxzehopypz16wiWqxmMjx2cVIqAWCoRp1gNZAsFEQ==', 'js/purify-3.3.0.js' => 'sha512-lsHD5zxs4lu/NDzaaibe27Vd2t7Cy9JQ3qDHUvDfb4oZvKoWDNEhwUY+4bT3R68cGgpgCYp8U1x2ifeVxqurdQ==',
'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
'js/zlib-1.3.1-1.js' => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==', 'js/zlib-1.3.1-1.js' => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==',
), ),

View File

@@ -30,7 +30,7 @@ class Controller
* *
* @const string * @const string
*/ */
const VERSION = '2.0.1'; const VERSION = '2.0.3';
/** /**
* minimal required PHP version * minimal required PHP version
@@ -216,13 +216,17 @@ class Controller
{ {
$templates = $this->_conf->getKey('availabletemplates'); $templates = $this->_conf->getKey('availabletemplates');
$template = $this->_conf->getKey('template'); $template = $this->_conf->getKey('template');
if (!in_array($template, $templates, true)) {
$templates[] = $template;
}
TemplateSwitcher::setAvailableTemplates($templates); TemplateSwitcher::setAvailableTemplates($templates);
TemplateSwitcher::setTemplateFallback($template); TemplateSwitcher::setTemplateFallback($template);
// force default template, if template selection is disabled and a default is set // force default template, if template selection is disabled
if (!$this->_conf->getKey('templateselection') && !empty($template)) { if (!$this->_conf->getKey('templateselection') && array_key_exists('template', $_COOKIE)) {
$_COOKIE['template'] = $template; unset($_COOKIE['template']); // ensure value is not re-used in template switcher
setcookie('template', $template, array('SameSite' => 'Lax', 'Secure' => true)); $expiredInAllTimezones = time() - 86400;
setcookie('template', '', array('expires' => $expiredInAllTimezones, 'SameSite' => 'Lax', 'Secure' => true));
} }
} }

View File

@@ -267,27 +267,25 @@ class Filesystem extends AbstractData
*/ */
public function setValue($value, $namespace, $key = '') public function setValue($value, $namespace, $key = '')
{ {
$file = $this->_path . DIRECTORY_SEPARATOR . $namespace . '.php';
if (function_exists('opcache_invalidate')) {
opcache_invalidate($file);
}
switch ($namespace) { switch ($namespace) {
case 'purge_limiter': case 'purge_limiter':
opcache_invalidate($this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php'); $content = '<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . var_export($value, true) . ';';
return $this->_storeString( break;
$this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php',
'<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . var_export($value, true) . ';'
);
case 'salt': case 'salt':
return $this->_storeString( $content = '<?php # |' . $value . '|';
$this->_path . DIRECTORY_SEPARATOR . 'salt.php', break;
'<?php # |' . $value . '|'
);
case 'traffic_limiter': case 'traffic_limiter':
$this->_last_cache[$key] = $value; $this->_last_cache[$key] = $value;
opcache_invalidate($this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php'); $content = '<?php' . PHP_EOL . '$GLOBALS[\'traffic_limiter\'] = ' . var_export($this->_last_cache, true) . ';';
return $this->_storeString( break;
$this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php', default:
'<?php' . PHP_EOL . '$GLOBALS[\'traffic_limiter\'] = ' . var_export($this->_last_cache, true) . ';' return false;
);
} }
return false; return $this->_storeString($file, $content);
} }
/** /**

View File

@@ -59,16 +59,13 @@ class TemplateSwitcher
{ {
if (self::isTemplateAvailable($template)) { if (self::isTemplateAvailable($template)) {
self::$_templateFallback = $template; self::$_templateFallback = $template;
} else {
if (!in_array($template, self::getAvailableTemplates())) { error_log('failed to set "' . $template . '" as a fallback, it needs to be added to the list of `availabletemplates` in the configuration file');
// Add custom template to the available templates list
self::$_availableTemplates[] = $template;
}
} }
} }
/** /**
* get currently loaded template * get user selected template or fallback
* *
* @access public * @access public
* @static * @static
@@ -76,8 +73,13 @@ class TemplateSwitcher
*/ */
public static function getTemplate(): string public static function getTemplate(): string
{ {
$selectedTemplate = self::getSelectedByUserTemplate(); if (array_key_exists('template', $_COOKIE)) {
return $selectedTemplate ?? self::$_templateFallback; $template = basename($_COOKIE['template']);
if (self::isTemplateAvailable($template)) {
return $template;
}
}
return self::$_templateFallback;
} }
/** /**
@@ -101,32 +103,10 @@ class TemplateSwitcher
*/ */
public static function isTemplateAvailable(string $template): bool public static function isTemplateAvailable(string $template): bool
{ {
$available = in_array($template, self::getAvailableTemplates()); if (in_array($template, self::getAvailableTemplates(), true)) {
return true;
if (!$available && !View::isBootstrapTemplate($template)) {
$path = View::getTemplateFilePath($template);
$available = file_exists($path);
} }
error_log('template "' . $template . '" is not in the list of `availabletemplates` in the configuration file');
return $available; return false;
}
/**
* 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

@@ -49,39 +49,19 @@ class View
*/ */
public function draw($template) public function draw($template)
{ {
$path = self::getTemplateFilePath($template); $dir = PATH . 'tpl' . DIRECTORY_SEPARATOR;
if (!file_exists($path)) { $file = substr($template, 0, 10) === 'bootstrap-' ? 'bootstrap' : $template;
throw new Exception('Template ' . $template . ' not found!', 80); $path = $dir . $file . '.php';
if (!is_file($path)) {
throw new Exception('Template ' . $template . ' not found in file ' . $path . '!', 80);
}
if (!in_array($path, glob($dir . '*.php', GLOB_NOSORT | GLOB_ERR), true)) {
throw new Exception('Template ' . $file . '.php not found in ' . $dir . '!', 81);
} }
extract($this->_variables); extract($this->_variables);
include $path; include $path;
} }
/**
* Get template file path
*
* @access public
* @param string $template
* @return string
*/
public static function getTemplateFilePath(string $template): string
{
$file = self::isBootstrapTemplate($template) ? 'bootstrap' : $template;
return PATH . 'tpl' . DIRECTORY_SEPARATOR . $file . '.php';
}
/**
* Is the template a variation of the bootstrap template
*
* @access public
* @param string $template
* @return bool
*/
public static function isBootstrapTemplate(string $template): bool
{
return substr($template, 0, 10) === 'bootstrap-';
}
/** /**
* echo script tag incl. SRI hash for given script file * echo script tag incl. SRI hash for given script file
* *

View File

@@ -65,7 +65,7 @@ if ($MARKDOWN) :
<?php <?php
endif; endif;
?> ?>
<?php $this->_scriptTag('js/purify-3.2.7.js', 'defer'); ?> <?php $this->_scriptTag('js/purify-3.3.0.js', 'defer'); ?>
<?php $this->_scriptTag('js/legacy.js', 'defer'); ?> <?php $this->_scriptTag('js/legacy.js', 'defer'); ?>
<?php $this->_scriptTag('js/privatebin.js', 'defer'); ?> <?php $this->_scriptTag('js/privatebin.js', 'defer'); ?>
<!-- icon --> <!-- icon -->
@@ -373,7 +373,7 @@ if ($PASSWORD) :
?> ?>
<li> <li>
<div id="password" class="navbar-form hidden"> <div id="password" class="navbar-form hidden">
<div class="password-peek-container"> <div class="input-group">
<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control input-password" size="23" /> <input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control input-password" size="23" />
<div class="input-group-addon toggle-password" type="button" title="<?php echo I18n::_('Show password'); ?>" aria-label="<?php echo I18n::_('Show password'); ?>"> <div class="input-group-addon toggle-password" type="button" title="<?php echo I18n::_('Show password'); ?>" aria-label="<?php echo I18n::_('Show password'); ?>">
<span class="glyphicon glyphicon-eye-open"></span> <span class="glyphicon glyphicon-eye-open"></span>

View File

@@ -49,7 +49,7 @@ if ($MARKDOWN) :
<?php <?php
endif; endif;
?> ?>
<?php $this->_scriptTag('js/purify-3.2.7.js', 'defer'); ?> <?php $this->_scriptTag('js/purify-3.3.0.js', 'defer'); ?>
<?php $this->_scriptTag('js/legacy.js', 'defer'); ?> <?php $this->_scriptTag('js/legacy.js', 'defer'); ?>
<?php $this->_scriptTag('js/privatebin.js', 'defer'); ?> <?php $this->_scriptTag('js/privatebin.js', 'defer'); ?>
<!-- icon --> <!-- icon -->

View File

@@ -6,7 +6,9 @@ use Google\Cloud\Storage\Bucket;
use Google\Cloud\Storage\Connection\ConnectionInterface; use Google\Cloud\Storage\Connection\ConnectionInterface;
use Google\Cloud\Storage\StorageClient; use Google\Cloud\Storage\StorageClient;
use Google\Cloud\Storage\StorageObject; use Google\Cloud\Storage\StorageObject;
use PrivateBin\Configuration;
use PrivateBin\Persistence\ServerSalt; use PrivateBin\Persistence\ServerSalt;
use PrivateBin\TemplateSwitcher;
error_reporting(E_ALL | E_STRICT); error_reporting(E_ALL | E_STRICT);
@@ -26,6 +28,7 @@ if (!defined('CONF_SAMPLE')) {
require PATH . 'vendor/autoload.php'; require PATH . 'vendor/autoload.php';
Helper::updateSubresourceIntegrity(); Helper::updateSubresourceIntegrity();
TemplateSwitcher::setAvailableTemplates(Configuration::getDefaults()['main']['availabletemplates']);
/** /**
* Class Helper provides unit tests pastes and comments of various formats * Class Helper provides unit tests pastes and comments of various formats

View File

@@ -41,6 +41,7 @@ class TemplateSwitcherTest extends TestCase
$defaultTemplateFallback = 'bootstrap5'; $defaultTemplateFallback = 'bootstrap5';
$customTemplate = 'bootstrap-dark'; $customTemplate = 'bootstrap-dark';
$customWrongTemplate = 'bootstrap-wrong'; $customWrongTemplate = 'bootstrap-wrong';
$escapeTemplateDirectory = '../index';
TemplateSwitcher::setTemplateFallback($defaultTemplateFallback); TemplateSwitcher::setTemplateFallback($defaultTemplateFallback);
@@ -49,6 +50,9 @@ class TemplateSwitcherTest extends TestCase
$_COOKIE['template'] = $customTemplate; $_COOKIE['template'] = $customTemplate;
$this->assertEquals($customTemplate, TemplateSwitcher::getTemplate(), 'Custom template'); $this->assertEquals($customTemplate, TemplateSwitcher::getTemplate(), 'Custom template');
$_COOKIE['template'] = $escapeTemplateDirectory;
$this->assertEquals($defaultTemplateFallback, TemplateSwitcher::getTemplate(), 'Fallback on escaping template directory');
} }
public function testGetAvailableTemplates() public function testGetAvailableTemplates()

View File

@@ -142,19 +142,11 @@ class ViewTest extends TestCase
$test->draw('123456789 does not exist!'); $test->draw('123456789 does not exist!');
} }
public function testTemplateFilePath() public function testInvalidTemplate()
{ {
$template = 'bootstrap'; $test = new View;
$templatePath = PATH . 'tpl' . DIRECTORY_SEPARATOR . $template . '.php'; $this->expectException(Exception::class);
$path = View::getTemplateFilePath($template); $this->expectExceptionCode(81);
$this->assertEquals($templatePath, $path, 'Template file path'); $test->draw('../index');
}
public function testIsBootstrapTemplate()
{
$bootstrapTemplate = 'bootstrap-dark';
$nonBootstrapTemplate = 'bootstrap5';
$this->assertTrue(View::isBootstrapTemplate($bootstrapTemplate), 'Is bootstrap template');
$this->assertFalse(View::isBootstrapTemplate($nonBootstrapTemplate), 'Is not bootstrap template');
} }
} }