Compare commits
1 Commits
master
...
siftleft-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79c0ad1670 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -19,8 +19,6 @@ js/test/ export-ignore
|
||||
.scrutinizer.yml export-ignore
|
||||
.styleci.yml export-ignore
|
||||
.travis.yml export-ignore
|
||||
codacy-analysis.yml export-ignore
|
||||
crowdin.yml export-ignore
|
||||
composer.json export-ignore
|
||||
composer.lock export-ignore
|
||||
BADGES.md export-ignore
|
||||
|
||||
14
.github/dependabot.yml
vendored
14
.github/dependabot.yml
vendored
@@ -1,14 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
# Maintain dependencies for GitHub Actions
|
||||
# src: https://github.com/marketplace/actions/build-and-push-docker-images#keep-up-to-date-with-github-dependabot
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
# Also keep PHP (Composer) dependencies up-to-date
|
||||
# see: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
|
||||
- package-ecosystem: "composer"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@@ -33,11 +33,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -46,4 +46,4 @@ jobs:
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
||||
37
.github/workflows/refresh-php8.yml
vendored
37
.github/workflows/refresh-php8.yml
vendored
@@ -1,37 +0,0 @@
|
||||
name: Refresh PHP 8 branch
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '42 2 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout php8 branch
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# directly checkout the php8 branch
|
||||
ref: php8
|
||||
# Number of commits to fetch. 0 indicates all history for all branches and tags.
|
||||
# Default: 1
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Merge master changes into php8
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git merge origin/master
|
||||
|
||||
- name: Push new changes
|
||||
uses: github-actions-x/commit@v2.9
|
||||
with:
|
||||
name: github-actions[bot]
|
||||
email: 41898282+github-actions[bot]@users.noreply.github.com
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
push-branch: 'php8'
|
||||
|
||||
35
.github/workflows/shiftleft-analysis.yml
vendored
Normal file
35
.github/workflows/shiftleft-analysis.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# This workflow integrates Scan with GitHub's code scanning feature
|
||||
# Scan is a free open-source security tool for modern DevOps teams from ShiftLeft
|
||||
# Visit https://slscan.io/en/latest/integrations/code-scan for help
|
||||
name: SL Scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '16 22 * * 4'
|
||||
|
||||
jobs:
|
||||
Scan-Build:
|
||||
# Scan runs on ubuntu, mac and windows
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
# potentially add composer install steo here
|
||||
- name: Perform Scan
|
||||
uses: ShiftLeftSecurity/scan-action@master
|
||||
env:
|
||||
WORKSPACE: ""
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SCAN_AUTO_BUILD: true
|
||||
with:
|
||||
output: reports
|
||||
# Scan auto-detects the languages.
|
||||
|
||||
- name: Upload report
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
with:
|
||||
sarif_file: reports
|
||||
29
.github/workflows/snyk-scan.yml
vendored
29
.github/workflows/snyk-scan.yml
vendored
@@ -1,29 +0,0 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: Snyk scan
|
||||
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
jobs:
|
||||
# https://github.com/snyk/actions/tree/master/php
|
||||
snyk-php:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Google Cloud Storage
|
||||
run: composer require --no-update google/cloud-storage && composer update --no-dev
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
uses: snyk/actions/php@master
|
||||
continue-on-error: true # To make sure that SARIF upload gets called
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
args: --sarif-file-output=snyk.sarif
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: snyk.sarif
|
||||
82
.github/workflows/tests.yml
vendored
82
.github/workflows/tests.yml
vendored
@@ -2,119 +2,53 @@ name: Tests
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
|
||||
Composer:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-dev
|
||||
|
||||
PHPunit:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4']
|
||||
name: PHP ${{ matrix.php-versions }} unit tests on ${{ matrix.operating-system }}
|
||||
env:
|
||||
extensions: gd, sqlite3
|
||||
extensions-cache-key-name: phpextensions
|
||||
|
||||
steps:
|
||||
|
||||
# let's get started!
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# cache PHP extensions
|
||||
- name: Setup cache environment
|
||||
id: extcache
|
||||
uses: shivammathur/cache-extensions@v1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: ${{ env.extensions }}
|
||||
key: ${{ runner.os }}-${{ env.extensions-cache-key }}
|
||||
|
||||
- name: Cache extensions
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.extcache.outputs.dir }}
|
||||
key: ${{ steps.extcache.outputs.key }}
|
||||
restore-keys: ${{ runner.os }}-${{ env.extensions-cache-key }}
|
||||
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: ${{ env.extensions }}
|
||||
|
||||
# Setup GitHub CI PHP problem matchers
|
||||
# https://github.com/shivammathur/setup-php#problem-matchers
|
||||
- name: Setup problem matchers for PHP
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
|
||||
|
||||
- name: Setup problem matchers for PHPUnit
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
# composer cache
|
||||
extensions: gd, sqlite3
|
||||
- name: Remove composer lock
|
||||
run: rm composer.lock
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composer-cache
|
||||
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
# http://man7.org/linux/man-pages/man1/date.1.html
|
||||
# https://github.com/actions/cache#creating-a-cache-key
|
||||
- name: Get Date
|
||||
id: get-date
|
||||
run: echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}-${{ hashFiles('**/composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}-
|
||||
|
||||
# composer installation
|
||||
- name: Setup PHPunit
|
||||
run: composer install -n
|
||||
|
||||
- name: Install Google Cloud Storage
|
||||
run: composer require google/cloud-storage
|
||||
|
||||
# testing
|
||||
- name: Run unit tests
|
||||
run: ../vendor/bin/phpunit --no-coverage
|
||||
working-directory: tst
|
||||
|
||||
Mocha:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'js/package-lock.json'
|
||||
|
||||
node-version: '12'
|
||||
- name: Setup Mocha
|
||||
run: npm install -g mocha
|
||||
|
||||
- name: Setup Node modules
|
||||
run: npm ci
|
||||
run: npm install
|
||||
working-directory: js
|
||||
|
||||
- name: Run unit tests
|
||||
run: npm test
|
||||
run: mocha
|
||||
working-directory: js
|
||||
|
||||
|
||||
@@ -29,9 +29,3 @@ disabled:
|
||||
- short_array_syntax
|
||||
- single_line_after_imports
|
||||
- unalign_equals
|
||||
|
||||
finder:
|
||||
path:
|
||||
- "lib/"
|
||||
- "tpl/"
|
||||
- "tst/"
|
||||
|
||||
39
CHANGELOG.md
39
CHANGELOG.md
@@ -1,35 +1,16 @@
|
||||
# PrivateBin version history
|
||||
|
||||
* **1.4.1 (not yet released)**
|
||||
* ADDED: script for data storage backend migrations (#1012)
|
||||
* ADDED: Translations for Turkish, Slovak, Greek and Thai
|
||||
* ADDED: S3 Storage backend (#994)
|
||||
* CHANGED: Switched to Jdenticons as the default for comment icons (#793)
|
||||
* CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919)
|
||||
* CHANGED: Upgrading libraries to: zlib 1.2.13
|
||||
* FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943)
|
||||
* FIXED: Apply table prefix to indexes as well, to support multiple instances sharing a single database (#943)
|
||||
* FIXED: YOURLS integration via new proxy, storing signature in configuration (#725)
|
||||
* **1.4 (2022-04-09)**
|
||||
* ADDED: Translations for Corsican, Estonian, Finnish and Lojban
|
||||
* **1.4 (not yet released)**
|
||||
* ADDED: Translation for Estonian
|
||||
* ADDED: new HTTP headers improving security (#765)
|
||||
* ADDED: Download button for paste text (#774)
|
||||
* ADDED: Opt-out of federated learning of cohorts (FLoC) (#776)
|
||||
* ADDED: Configuration option to exempt IPs from the rate-limiter (#787)
|
||||
* ADDED: Google Cloud Storage backend support (#795)
|
||||
* ADDED: Oracle database support (#868)
|
||||
* ADDED: Configuration option to limit paste creation and commenting to certain IPs (#883)
|
||||
* ADDED: Set CSP also as meta tag, to deal with misconfigured webservers mangling the HTTP header
|
||||
* ADDED: Sanitize SVG preview, preventing script execution in instance context
|
||||
* CHANGED: Language selection cookie only transmitted over HTTPS (#472)
|
||||
* CHANGED: Upgrading libraries to: base-x 4.0.0, bootstrap 3.4.1 (JS), DOMpurify 2.3.6, ip-lib 1.18.0, jQuery 3.6.0, random_compat 2.0.21, Showdown 2.0.3 & zlib 1.2.12
|
||||
* CHANGED: Removed automatic `.ini` configuration file migration (#808)
|
||||
* CHANGED: Removed configurable `dir` for `traffic` & `purge` limiters (#419)
|
||||
* CHANGED: Server salt, traffic and purge limiter now stored in the storage backend (#419)
|
||||
* CHANGED: Drop support for attachment download in IE
|
||||
* FIXED: Error when attachments are disabled, but paste with attachment gets displayed
|
||||
* CHANGED: Upgrading libraries to: random_compat 2.0.20
|
||||
* **1.3.5 (2021-04-05)**
|
||||
* ADDED: Translations for Hebrew, Lithuanian, Indonesian and Catalan
|
||||
* ADDED: Translation for Hebrew, Lithuanian, Indonesian and Catalan
|
||||
* ADDED: Make the project info configurable (#681)
|
||||
* CHANGED: Upgrading libraries to: DOMpurify 2.2.7, kjua 0.9.0 & random_compat 2.0.18
|
||||
* CHANGED: Open all links in new window (#630)
|
||||
@@ -70,7 +51,7 @@
|
||||
* FIXED: HTML injection via unescaped attachment filename (#554)
|
||||
* FIXED: Password disabling option (#527)
|
||||
* **1.2.2 (2020-01-11)**
|
||||
* CHANGED: Upgrading libraries to: bootstrap 3.4.1 (CSS), DOMpurify 2.0.7, jQuery 3.4.1, kjua 0.6.0, Showdown 1.9.1 & SJCL 1.0.8
|
||||
* CHANGED: Upgrading libraries to: bootstrap 3.4.1, DOMpurify 2.0.7, jQuery 3.4.1, kjua 0.6.0, Showdown 1.9.1 & SJCL 1.0.8
|
||||
* FIXED: HTML injection via unescaped attachment filename (#554)
|
||||
* **1.3.1 (2019-09-22)**
|
||||
* ADDED: Translation for Bulgarian (#455)
|
||||
@@ -81,7 +62,7 @@
|
||||
* CHANGED: Upgrading libraries to: DOMpurify 2.0.1
|
||||
* FIXED: Enabling browsers without WASM to create pastes and read uncompressed ones (#454)
|
||||
* FIXED: Cloning related issues (#489, #491, #493, #494)
|
||||
* FIXED: Enable file operation only when editing (#497)
|
||||
* FIXED: Enable file operation only when editing (#497)
|
||||
* FIXED: Clicking 'New' on a previously submitted paste does not blank address bar (#354)
|
||||
* FIXED: Clear address bar when create new paste from existing paste (#479)
|
||||
* FIXED: Discussion section not hiding when new/clone paste is clicked on (#484)
|
||||
@@ -244,7 +225,7 @@ encryption), i18n (translation, counterpart of i18n.php) and helper (stateless u
|
||||
* FIXED: 2 minor corrections to avoid notices in php log.
|
||||
* FIXED: Sources converted to UTF-8.
|
||||
* **Alpha 0.14 (2012-04-20):**
|
||||
* ADDED: GD presence is checked.
|
||||
* ADDED: GD presence is checked.
|
||||
* CHANGED: Traffic limiter data files moved to data/ (→easier rights management)
|
||||
* ADDED: "Burn after reading" implemented. Opening the URL will display the paste and immediately destroy it on server.
|
||||
* **Alpha 0.13 (2012-04-18):**
|
||||
@@ -252,16 +233,16 @@ encryption), i18n (translation, counterpart of i18n.php) and helper (stateless u
|
||||
* FIXED: $error not properly initialized in index.php
|
||||
* **Alpha 0.12 (2012-04-18):**
|
||||
* **DISCUSSIONS !** Now you can enable discussions on your pastes. Of course, posted comments and nickname are also encrypted and the server cannot see them.
|
||||
* This feature implies a change in storage format. You will have to delete all previous pastes in your ZeroBin.
|
||||
* This feature implies a change in storage format. You will have to delete all previous pastes in your ZeroBin.
|
||||
* Added [[php:vizhash_gd|Vizhash]] as avatars, so you can match posters IP addresses without revealing them. (Same image = same IP). Of course the IP address cannot be deduced from the Vizhash.
|
||||
* Remaining time before expiration is now displayed.
|
||||
* Explicit tags were added to CSS and jQuery selectors (eg. div#aaa instead of #aaa) to speed up browser.
|
||||
* Explicit tags were added to CSS and jQuery selectors (eg. div#aaa instead of #aaa) to speed up browser.
|
||||
* Better cleaning of the URL (to make sure the key is not broken by some stupid redirection service)
|
||||
* **Alpha 0.11 (2012-04-12):**
|
||||
* Automatically ignore parameters (such as &utm_source=...) added //after// the anchor by some stupid Web 2.0 services.
|
||||
* First public release.
|
||||
* **Alpha 0.10 (2012-04-12):**
|
||||
* IE9 does not seem to correctly support ''pre-wrap'' either. Special handling mode activated for all version of IE<10. (Note: **ALL other browsers** correctly support this feature.)
|
||||
* IE9 does not seem to correctly support ''pre-wrap'' either. Special handling mode activated for all version of IE<10. (Note: **ALL other browsers** correctly support this feature.)
|
||||
* **Alpha 0.9 (2012-04-11):**
|
||||
* Oh bummer... IE 8 is as shitty as IE6/7: Its does not seem to support ''white-space:pre-wrap'' correctly. I had to activate the special handling mode. I still have to test IE 9.
|
||||
* **Alpha 0.8 (2012-04-11):**
|
||||
|
||||
22
CREDITS.md
22
CREDITS.md
@@ -2,17 +2,18 @@
|
||||
|
||||
## Active contributors
|
||||
|
||||
* Simon Rupf - current developer and maintainer
|
||||
* rugk - security review, doc improvment, JS refactoring & various other stuff
|
||||
* R4SAS - python client, compression, blob URI to support larger attachments
|
||||
Simon Rupf - current developer and maintainer
|
||||
rugk - security review, doc improvment, JS refactoring & various other stuff
|
||||
R4SAS - python client, compression, blob URI to support larger attachments
|
||||
|
||||
## Past contributions
|
||||
|
||||
* Sébastien Sauvage - original idea and main developer
|
||||
Sébastien Sauvage - original idea and main developer
|
||||
|
||||
* Alexey Gladkov - syntax highlighting
|
||||
* Greg Knaddison - robots.txt
|
||||
* MrKooky - HTML5 markup, CSS cleanup
|
||||
* Simon Rupf - WebCrypto, unit tests, container images, database backend, MVC, configuration, i18n
|
||||
* Simon Rupf - WebCrypto, unit tests, containers images, database backend, MVC, configuration, i18n
|
||||
* Hexalyse - Password protection
|
||||
* Viktor Stanchev - File upload support
|
||||
* azlux - Tab character input support
|
||||
@@ -28,10 +29,6 @@
|
||||
* Lucas Savva - configurable config file location, NixOS packaging
|
||||
* rodehoed - option to exempt ips from the rate-limiter
|
||||
* Mark van Holsteijn - Google Cloud Storage backend
|
||||
* Austin Huang - Oracle database support
|
||||
* Felix J. Ogris - S3 Storage backend
|
||||
* Mounir Idrassi & J. Mozdzen - secure YOURLS integration
|
||||
* Felix J. Ogris - script for data backend migrations, dropped singleton behaviour of data backends
|
||||
|
||||
## Translations
|
||||
* Hexalyse - French
|
||||
@@ -56,10 +53,3 @@
|
||||
* whenwesober - Indonesian
|
||||
* retiolus - Catalan
|
||||
* sarnane - Estonian
|
||||
* foxsouns - Lojban
|
||||
* Patriccollu di Santa Maria è Sichè - Corsican
|
||||
* Markus Mikkonen - Finnish
|
||||
* Emir Ensar Rahmanlar - Turkish
|
||||
* Stevo984 - Slovak
|
||||
* Christos Karamolegkos - Greek
|
||||
* jaideejung007 - Thai
|
||||
|
||||
177
INSTALL.md
177
INSTALL.md
@@ -2,46 +2,38 @@
|
||||
|
||||
**TL;DR:** Download the
|
||||
[latest release archive](https://github.com/PrivateBin/PrivateBin/releases/latest)
|
||||
(with the link labelled as "Source code (…)") and extract it in your web hosts
|
||||
folder where you want to install your PrivateBin instance. We try to provide a
|
||||
mostly safe default configuration, but we urge you to check the
|
||||
[security section](#hardening-and-security) below and the
|
||||
[configuration options](#configuration) to adjust as you see fit.
|
||||
and extract it in your web hosts folder where you want to install your PrivateBin
|
||||
instance. We try to provide a mostly safe default configuration, but we urge you to
|
||||
check the [security section](#hardening-and-security) below and the [configuration
|
||||
options](#configuration) to adjust as you see fit.
|
||||
|
||||
**NOTE:** See our [FAQ entry on securely downloading release files](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-can-i-securely-clonedownload-your-project)
|
||||
for more information.
|
||||
**NOTE:** See [our FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-can-i-securely-clonedownload-your-project) for information how to securely download the PrivateBin release files.
|
||||
|
||||
**NOTE:** There is a [ansible](https://ansible.com) role by @e1mo available to
|
||||
install and configure PrivateBin on your server. It's available on
|
||||
[ansible galaxy](https://galaxy.ansible.com/e1mo/privatebin)
|
||||
([source code](https://git.sr.ht/~e1mo/ansible-role-privatebin)).
|
||||
**NOTE:** There is a [ansible](https://ansible.com) role by @e1mo available to install and configure PrivateBin on your server. It's available on [ansible galaxy](https://galaxy.ansible.com/e1mo/privatebin) ([source code](https://git.sr.ht/~e1mo/ansible-role-privatebin)).
|
||||
|
||||
### Minimal Requirements
|
||||
### Minimal requirements
|
||||
|
||||
- PHP version 7.0 or above
|
||||
- Or PHP version 5.6 AND _one_ of the following sources of cryptographically
|
||||
safe randomness:
|
||||
- [Libsodium](https://download.libsodium.org/libsodium/content/installation/)
|
||||
and it's [PHP extension](https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium)
|
||||
- `open_basedir` access to `/dev/urandom`
|
||||
- mcrypt extension AND `open_basedir` access to `/dev/urandom`
|
||||
- Or PHP version 5.6 AND _one_ of the following sources of cryptographically safe randomness:
|
||||
- [Libsodium](https://download.libsodium.org/libsodium/content/installation/) and it's [PHP extension](https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium)
|
||||
- open_basedir access to `/dev/urandom`
|
||||
- mcrypt extension (mcrypt needs to be able to access `/dev/urandom`. This means if `open_basedir` is set, it must include this file.)
|
||||
- com_dotnet extension
|
||||
- GD extension
|
||||
- zlib extension
|
||||
- some disk space or a database supported by [PDO](https://php.net/manual/book.pdo.php)
|
||||
- ability to create files and folders in the installation directory and the PATH
|
||||
defined in index.php
|
||||
- A web browser with JavaScript and (optional) WebAssembly support
|
||||
- some disk space or (optionally) a database supported by [PDO](https://php.net/manual/book.pdo.php)
|
||||
- ability to create files and folders in the installation directory and the PATH defined in index.php
|
||||
- A web browser with JavaScript support
|
||||
|
||||
## Hardening and Security
|
||||
## Hardening and security
|
||||
|
||||
### Changing the Path
|
||||
### Changing the path
|
||||
|
||||
In the index.php you can define a different `PATH`. This is useful to secure
|
||||
your installation. You can move the utilities, configuration, data files,
|
||||
templates and PHP libraries (directories bin, cfg, doc, data, lib, tpl, tst and
|
||||
vendor) outside of your document root. This new location must still be
|
||||
accessible to your webserver and PHP process (see also
|
||||
In the index.php you can define a different `PATH`. This is useful to secure your
|
||||
installation. You can move the configuration, data files, templates and PHP
|
||||
libraries (directories cfg, doc, data, lib, tpl, tst and vendor) outside of your
|
||||
document root. This new location must still be accessible to your webserver / PHP
|
||||
process (see also
|
||||
[open_basedir setting](https://secure.php.net/manual/en/ini.core.php#ini.open-basedir)).
|
||||
|
||||
> #### PATH Example
|
||||
@@ -50,25 +42,24 @@ accessible to your webserver and PHP process (see also
|
||||
> http://example.com/paste/
|
||||
>
|
||||
> The full path of PrivateBin on your webserver is:
|
||||
> /srv/example.com/htdocs/paste
|
||||
> /home/example.com/htdocs/paste
|
||||
>
|
||||
> When setting the path like this:
|
||||
> define('PATH', '../../secret/privatebin/');
|
||||
>
|
||||
> PrivateBin will look for your includes and data here:
|
||||
> /srv/example.com/secret/privatebin
|
||||
> PrivateBin will look for your includes / data here:
|
||||
> /home/example.com/secret/privatebin
|
||||
|
||||
### Changing the config path only
|
||||
|
||||
In situations where you want to keep the PrivateBin static files separate from the
|
||||
rest of your data, or you want to reuse the installation files on multiple vhosts,
|
||||
you may only want to change the `conf.php`. In this case, you can set the
|
||||
you may only want to change the `conf.php`. In this instance, you can set the
|
||||
`CONFIG_PATH` environment variable to the absolute path to the `conf.php` file.
|
||||
This can be done in your web server's virtual host config, the PHP config, or in
|
||||
the index.php, if you choose to customize it.
|
||||
the index.php if you choose to customize it.
|
||||
|
||||
Note that your PHP process will need read access to the configuration file,
|
||||
wherever it may be.
|
||||
Note that your PHP process will need read access to the config wherever it may be.
|
||||
|
||||
> #### CONFIG_PATH example
|
||||
> Setting the value in an Apache Vhost:
|
||||
@@ -82,27 +73,23 @@ wherever it may be.
|
||||
|
||||
### Transport security
|
||||
|
||||
When setting up PrivateBin, also set up HTTPS, if you haven't already. Without
|
||||
HTTPS PrivateBin is not secure, as the JavaScript or WebAssembly files could be
|
||||
manipulated during transmission. For more information on this, see our
|
||||
[FAQ entry on HTTPS setup recommendations](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-should-i-setup-https).
|
||||
When setting up PrivateBin, also set up HTTPS, if you haven't already. Without HTTPS
|
||||
PrivateBin is not secure, as the JavaScript files could be manipulated during transmission.
|
||||
For more information on this, see our [FAQ entry on HTTPS setup](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-should-i-setup-https).
|
||||
|
||||
### File-level permissions
|
||||
|
||||
After completing the installation, you should make sure, that other users on the
|
||||
system cannot read the config file or the `data/` directory, as – depending on
|
||||
your configuration – potentially sensitive information may be stored in there.
|
||||
After completing the installation, you should make sure, other users on the system cannot read the config file or the `data/` directory, as – depending on your configuration – potential secret information are saved there.
|
||||
|
||||
See our [FAQ entry on permissions](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#what-are-the-recommended-file-and-folder-permissions-for-privatebin)
|
||||
for a detailed guide on how to "harden" access to files and folders.
|
||||
See [this FAQ item](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#what-are-the-recommended-file-and-folder-permissions-for-privatebin) for a detailed guide on how to "harden" the permissions of files and folders.
|
||||
|
||||
## Configuration
|
||||
|
||||
In the file `cfg/conf.php` you can configure PrivateBin. A `cfg/conf.sample.php`
|
||||
is provided containing all options and their default values. You can copy it to
|
||||
`cfg/conf.php` and change it as needed. Alternatively you can copy it anywhere
|
||||
and set the `CONFIG_PATH` environment variable (see above notes). The config
|
||||
file is divided into multiple sections, which are enclosed in square brackets.
|
||||
is provided containing all options and default values. You can copy it to
|
||||
`cfg/conf.php` and adapt it as needed. Alternatively you can copy it anywhere and
|
||||
set the `CONFIG_PATH` environment variable (see above notes). The config file is
|
||||
divided into multiple sections, which are enclosed in square brackets.
|
||||
|
||||
In the `[main]` section you can enable or disable the discussion feature, set
|
||||
the limit of stored pastes and comments in bytes. The `[traffic]` section lets
|
||||
@@ -120,28 +107,28 @@ A `robots.txt` file is provided in the root dir of PrivateBin. It disallows all
|
||||
robots from accessing your pastes. It is recommend to place it into the root of
|
||||
your web directory if you have installed PrivateBin in a subdirectory. Make sure
|
||||
to adjust it, so that the file paths match your installation. Of course also
|
||||
adjust the file, if you already use a `robots.txt`.
|
||||
adjust the file if you already use a `robots.txt`.
|
||||
|
||||
A `.htaccess.disabled` file is provided in the root dir of PrivateBin. It blocks
|
||||
some known robots and link-scanning bots. If you use Apache, you can rename the
|
||||
file to `.htaccess` to enable this feature. If you use another webserver, you
|
||||
have to configure it manually to do the same.
|
||||
|
||||
### On using Cloudflare
|
||||
### When using Cloudflare
|
||||
|
||||
If you want to use PrivateBin behind Cloudflare, make sure you have disabled the
|
||||
Rocket loader and unchecked "Javascript" for Auto Minify, found in your domain
|
||||
settings, under "Speed". More information can be found in our
|
||||
[FAQ entry on Cloudflare related issues](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#user-content-how-to-make-privatebin-work-when-using-cloudflare-for-ddos-protection).
|
||||
If you want to use PrivateBin behind Cloudflare, make sure you have disabled the Rocket
|
||||
loader and unchecked "Javascript" for Auto Minify, found in your domain settings,
|
||||
under "Speed". (More information
|
||||
[in this FAQ entry](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#user-content-how-to-make-privatebin-work-when-using-cloudflare-for-ddos-protection))
|
||||
|
||||
### Using a Database Instead of Flat Files
|
||||
### Using a database instead of flat files
|
||||
|
||||
In the configuration file the `[model]` and `[model_options]` sections let you
|
||||
configure your favourite way of storing the pastes and discussions on your
|
||||
server.
|
||||
|
||||
`Filesystem` is the default model, which stores everything in files in the
|
||||
data folder. This is the recommended setup for most sites on single hosts.
|
||||
data folder. This is the recommended setup for most sites.
|
||||
|
||||
Under high load, in distributed setups or if you are not allowed to store files
|
||||
locally, you might want to switch to the `Database` model. This lets you
|
||||
@@ -155,26 +142,21 @@ to use a prefix for
|
||||
The table prefix option is called `tbl`.
|
||||
|
||||
> #### Note
|
||||
> The `Database` model has only been tested with SQLite, MariaDB/MySQL and
|
||||
> PostgreSQL, although it would not be recommended to use SQLite in a production
|
||||
> environment. If you gain any experience running PrivateBin on other RDBMS,
|
||||
> please let us know.
|
||||
> The `Database` model has only been tested with SQLite, MySQL and PostgreSQL,
|
||||
> although it would not be recommended to use SQLite in a production environment.
|
||||
> If you gain any experience running PrivateBin on other RDBMS, please let us
|
||||
> know.
|
||||
|
||||
The following GRANTs (privileges) are required for the PrivateBin user in
|
||||
**MariaDB/MySQL**. In normal operation:
|
||||
The following GRANTs (privileges) are required for the PrivateBin user in **MySQL**. In normal operation:
|
||||
- INSERT, SELECT, DELETE on the paste and comment tables
|
||||
- SELECT on the config table
|
||||
|
||||
If you want PrivateBin to handle table creation (when you create the first paste)
|
||||
and updates (after you update PrivateBin to a new release), you need to give the
|
||||
user these additional privileges:
|
||||
If you want PrivateBin to handle table creation (when you create the first paste) and updates (after you update PrivateBin to a new release), you need to give the user these additional privileges:
|
||||
- CREATE, INDEX and ALTER on the database
|
||||
- INSERT and UPDATE on the config table
|
||||
|
||||
For reference or if you want to create the table schema for yourself to avoid
|
||||
having to give PrivateBin too many permissions (replace `prefix_` with your own
|
||||
table prefix and create the table schema with your favourite MariaDB/MySQL
|
||||
client):
|
||||
For reference or if you want to create the table schema for yourself to avoid having to give PrivateBin too many permissions (replace
|
||||
`prefix_` with your own table prefix and create the table schema with your favourite MySQL console):
|
||||
|
||||
```sql
|
||||
CREATE TABLE prefix_paste (
|
||||
@@ -205,23 +187,17 @@ CREATE INDEX parent ON prefix_comment(pasteid);
|
||||
CREATE TABLE prefix_config (
|
||||
id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id)
|
||||
);
|
||||
INSERT INTO prefix_config VALUES('VERSION', '1.4.0');
|
||||
INSERT INTO prefix_config VALUES('VERSION', '1.3.5');
|
||||
```
|
||||
|
||||
In **PostgreSQL**, the `data`, `attachment`, `nickname` and `vizhash` columns
|
||||
need to be `TEXT` and not `BLOB` or `MEDIUMBLOB`. The key names in brackets,
|
||||
after `PRIMARY KEY`, need to be removed.
|
||||
In **PostgreSQL**, the data, attachment, nickname and vizhash columns needs to
|
||||
be TEXT and not BLOB or MEDIUMBLOB.
|
||||
|
||||
In **Oracle**, the `data`, `attachment`, `nickname` and `vizhash` columns need
|
||||
to be `CLOB` and not `BLOB` or `MEDIUMBLOB`, the `id` column in the `config`
|
||||
table needs to be `VARCHAR2(16)` and the `meta` column in the `paste` table
|
||||
and the `value` column in the `config` table need to be `VARCHAR2(4000)`.
|
||||
|
||||
#### Using Google Cloud Storage
|
||||
### Using Google Cloud Storage
|
||||
If you want to deploy PrivateBin in a serverless manner in the Google Cloud, you
|
||||
can choose the `GoogleCloudStorage` as backend. To use this backend, you create
|
||||
a GCS bucket and specify the name as the model option `bucket`. Alternatively,
|
||||
you can set the name through the environment variable `PRIVATEBIN_GCS_BUCKET`.
|
||||
you can set the name through the environment variable PASTEBIN_GCS_BUCKET.
|
||||
|
||||
The default prefix for pastes stored in the bucket is `pastes`. To change the
|
||||
prefix, specify the option `prefix`.
|
||||
@@ -232,42 +208,3 @@ Platform using Google Cloud Run is easy and cheap.
|
||||
|
||||
To use the Google Cloud Storage backend you have to install the suggested
|
||||
library using the command `composer require google/cloud-storage`.
|
||||
|
||||
#### Using S3 Storage
|
||||
Similar to Google Cloud Storage, you can choose S3 as storage backend. It uses
|
||||
the AWS SDK for PHP, but can also talk to a Rados gateway as part of a CEPH
|
||||
cluster. To use this backend, you first have to install the SDK in the
|
||||
document root of PrivateBin: `composer require aws/aws-sdk-php`. You have to
|
||||
create the S3 bucket on the CEPH cluster before using the S3 backend.
|
||||
|
||||
In the `[model]` section of cfg/conf.php, set `class` to `S3Storage`.
|
||||
|
||||
You can set any combination of the following options in the `[model_options]`
|
||||
section:
|
||||
|
||||
* region
|
||||
* version
|
||||
* endpoint
|
||||
* bucket
|
||||
* prefix
|
||||
* accesskey
|
||||
* secretkey
|
||||
* use_path_style_endpoint
|
||||
|
||||
By default, prefix is empty. If set, the S3 backend will place all PrivateBin
|
||||
data beneath this prefix.
|
||||
|
||||
For AWS, you have to provide at least `region`, `bucket`, `accesskey`, and
|
||||
`secretkey`.
|
||||
|
||||
For CEPH, follow this example:
|
||||
|
||||
```
|
||||
region = ""
|
||||
version = "2006-03-01"
|
||||
endpoint = "https://s3.my-ceph.invalid"
|
||||
use_path_style_endpoint = true
|
||||
bucket = "my-bucket"
|
||||
accesskey = "my-rados-user"
|
||||
secretkey = "my-rados-pass"
|
||||
```
|
||||
|
||||
11
Makefile
11
Makefile
@@ -1,8 +1,8 @@
|
||||
.PHONY: all coverage coverage-js coverage-php doc doc-js doc-php increment sign test test-js test-php help
|
||||
|
||||
CURRENT_VERSION = 1.4.0
|
||||
VERSION ?= 1.4.1
|
||||
VERSION_FILES = index.php cfg/ *.md css/ i18n/ img/ js/package.json js/privatebin.js lib/ Makefile tpl/ tst/
|
||||
CURRENT_VERSION = 1.3.5
|
||||
VERSION ?= 1.3.6
|
||||
VERSION_FILES = index.php cfg/ *.md css/ i18n/ img/ js/privatebin.js lib/ Makefile tpl/ tst/
|
||||
REGEX_CURRENT_VERSION := $(shell echo $(CURRENT_VERSION) | sed "s/\./\\\./g")
|
||||
REGEX_VERSION := $(shell echo $(VERSION) | sed "s/\./\\\./g")
|
||||
|
||||
@@ -33,13 +33,12 @@ increment: ## Increment and commit new version number, set target version using
|
||||
do \
|
||||
sed -i "s/$(REGEX_CURRENT_VERSION)/$(REGEX_VERSION)/g" $$F; \
|
||||
done
|
||||
cd tst && phpunit --no-coverage && cd ..
|
||||
git add $(VERSION_FILES) tpl/
|
||||
git add $(VERSION_FILES)
|
||||
git commit -m "incrementing version"
|
||||
|
||||
sign: ## Sign a release.
|
||||
git tag $(VERSION)
|
||||
git push origin $(VERSION)
|
||||
git push --tags
|
||||
signrelease.sh
|
||||
|
||||
test: test-js test-php ## Run all unit tests.
|
||||
|
||||
53
README.md
53
README.md
@@ -1,27 +1,25 @@
|
||||
# [](https://privatebin.info/)
|
||||
|
||||
*Current version: 1.4.0*
|
||||
*Current version: 1.3.5*
|
||||
|
||||
**PrivateBin** is a minimalist, open source online
|
||||
[pastebin](https://en.wikipedia.org/wiki/Pastebin)
|
||||
**PrivateBin** is a minimalist, open source online [pastebin](https://en.wikipedia.org/wiki/Pastebin)
|
||||
where the server has zero knowledge of pasted data.
|
||||
|
||||
Data is encrypted and decrypted in the browser using 256bit AES in
|
||||
[Galois Counter mode](https://en.wikipedia.org/wiki/Galois/Counter_Mode).
|
||||
Data is encrypted and decrypted in the browser using 256bit AES in [Galois Counter mode](https://en.wikipedia.org/wiki/Galois/Counter_Mode).
|
||||
|
||||
This is a fork of ZeroBin, originally developed by
|
||||
[Sébastien Sauvage](https://github.com/sebsauvage/ZeroBin). PrivateBin was
|
||||
refactored to allow easier and cleaner extensions and has many additional
|
||||
features. It is, however, still fully compatible to the original ZeroBin 0.19
|
||||
[Sébastien Sauvage](https://github.com/sebsauvage/ZeroBin). ZeroBin was refactored
|
||||
to allow easier and cleaner extensions. PrivateBin has many more features than the
|
||||
original ZeroBin. It is, however, still fully compatible to the original ZeroBin 0.19
|
||||
data storage scheme. Therefore, such installations can be upgraded to PrivateBin
|
||||
without losing any data.
|
||||
|
||||
## What PrivateBin provides
|
||||
|
||||
+ As a server administrator you don't have to worry if your users post content
|
||||
that is considered illegal in your country. You have plausible deniability of
|
||||
any of the pastes content. If requested or enforced, you can delete any paste
|
||||
from your system.
|
||||
that is considered illegal in your country. You have no knowledge of any
|
||||
of the pastes content. If requested or enforced, you can delete any paste from
|
||||
your system.
|
||||
|
||||
+ Pastebin-like system to store text documents, code samples, etc.
|
||||
|
||||
@@ -33,13 +31,13 @@ without losing any data.
|
||||
|
||||
## What it doesn't provide
|
||||
|
||||
- As a user you have to trust the server administrator not to inject any
|
||||
malicious code. For security, a PrivateBin installation *has to be used over*
|
||||
*HTTPS*! Otherwise you would also have to trust your internet provider, and
|
||||
any jurisdiction the traffic passes through. Additionally the instance should
|
||||
be secured by
|
||||
[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security). It can
|
||||
use traditional certificate authorities and/or use a
|
||||
- As a user you have to trust the server administrator not to inject any malicious
|
||||
javascript code.
|
||||
For basic security, the PrivateBin installation *has to provide HTTPS*!
|
||||
Otherwise you would also have to trust your internet provider, and any country
|
||||
the traffic passes through.
|
||||
Additionally the instance should be secured by
|
||||
[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security). It can use traditional certificate authorities and/or use
|
||||
[DNSSEC](https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions)
|
||||
protected
|
||||
[DANE](https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities)
|
||||
@@ -47,17 +45,18 @@ without losing any data.
|
||||
|
||||
- The "key" used to encrypt the paste is part of the URL. If you publicly post
|
||||
the URL of a paste that is not password-protected, anyone can read it.
|
||||
Use a password if you want your paste to remain private. In that case, make
|
||||
sure to use a strong password and share it privately and end-to-end-encrypted.
|
||||
Use a password if you want your paste to be private. In this case, make sure to
|
||||
use a strong password and only share it privately and end-to-end-encrypted.
|
||||
|
||||
- A server admin can be forced to hand over access logs to the authorities.
|
||||
- A server admin might be forced to hand over access logs to the authorities.
|
||||
PrivateBin encrypts your text and the discussion contents, but who accessed a
|
||||
paste (first) might still be disclosed via access logs.
|
||||
|
||||
- In case of a server breach your data is secure as it is only stored encrypted
|
||||
on the server. However, the server could be absused or the server admin could
|
||||
be legally forced into sending malicious code to their users, which logs
|
||||
the decryption key and sends it to a server when a user accesses a paste.
|
||||
on the server. However, the server could be misused or the server admin could
|
||||
be legally forced into sending malicious JavaScript to all web users, which
|
||||
grabs the decryption key and sends it to the server when a user accesses a
|
||||
PrivateBin.
|
||||
Therefore, do not access any PrivateBin instance if you think it has been
|
||||
compromised. As long as no user accesses this instance with a previously
|
||||
generated URL, the content can't be decrypted.
|
||||
@@ -78,8 +77,8 @@ file](https://github.com/PrivateBin/PrivateBin/wiki/Configuration):
|
||||
* Syntax highlighting for source code using prettify.js, including 4 prettify
|
||||
themes
|
||||
|
||||
* File upload support, image, media and PDF preview (disabled by default, size
|
||||
limit adjustable)
|
||||
* File upload support, images get displayed (disabled by default, possibility
|
||||
to adjust size limit)
|
||||
|
||||
* Templates: By default there are bootstrap CSS, darkstrap and "classic ZeroBin"
|
||||
to choose from and it is easy to adapt these to your own websites layout or
|
||||
@@ -90,7 +89,7 @@ file](https://github.com/PrivateBin/PrivateBin/wiki/Configuration):
|
||||
|
||||
* Language selection (disabled by default, as it uses a session cookie)
|
||||
|
||||
* QR code for paste URLs, to easily transfer them over to mobile devices
|
||||
* QR code generation of URL, to easily transfer pastes over to a mobile device
|
||||
|
||||
## Further resources
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.4.0 | :heavy_check_mark: |
|
||||
| < 1.4.0 | :x: |
|
||||
| 1.3.5 | :heavy_check_mark: |
|
||||
| < 1.3.5 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
||||
194
bin/migrate.php
194
bin/migrate.php
@@ -1,194 +0,0 @@
|
||||
<?php
|
||||
|
||||
// change this, if your php files and data is outside of your webservers document root
|
||||
define('PATH', '..' . DIRECTORY_SEPARATOR);
|
||||
|
||||
define('PUBLIC_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||
require PATH . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||
|
||||
use PrivateBin\Configuration;
|
||||
use PrivateBin\Model;
|
||||
|
||||
|
||||
$longopts = array(
|
||||
"delete-after",
|
||||
"delete-during"
|
||||
);
|
||||
$opts_arr = getopt("fhnv", $longopts, $rest);
|
||||
if ($opts_arr === false) {
|
||||
dieerr("Erroneous command line options. Please use -h");
|
||||
}
|
||||
if (array_key_exists("h", $opts_arr)) {
|
||||
helpexit();
|
||||
}
|
||||
|
||||
$delete_after = array_key_exists("delete-after", $opts_arr);
|
||||
$delete_during = array_key_exists("delete-during", $opts_arr);
|
||||
$force_overwrite = array_key_exists("f", $opts_arr);
|
||||
$dryrun = array_key_exists("n", $opts_arr);
|
||||
$verbose = array_key_exists("v", $opts_arr);
|
||||
|
||||
if ($rest >= $argc) {
|
||||
dieerr("Missing source configuration directory");
|
||||
}
|
||||
if ($delete_after && $delete_during) {
|
||||
dieerr("--delete-after and --delete-during are mutually exclusive");
|
||||
}
|
||||
|
||||
$srcconf = getConfig("source", $argv[$rest]);
|
||||
$rest++;
|
||||
$dstconf = getConfig("destination", ($rest < $argc ? $argv[$rest] : ""));
|
||||
|
||||
if (($srcconf->getSection("model") == $dstconf->getSection("model")) &&
|
||||
($srcconf->getSection("model_options") == $dstconf->getSection("model_options"))) {
|
||||
dieerr("Source and destination storage configurations are identical");
|
||||
}
|
||||
|
||||
$srcmodel = new Model($srcconf);
|
||||
$srcstore = $srcmodel->getStore();
|
||||
$dstmodel = new Model($dstconf);
|
||||
$dststore = $dstmodel->getStore();
|
||||
$ids = $srcstore->getAllPastes();
|
||||
|
||||
foreach ($ids as $id) {
|
||||
debug("Reading paste id " . $id);
|
||||
$paste = $srcstore->read($id);
|
||||
$comments = $srcstore->readComments($id);
|
||||
|
||||
savePaste($force_overwrite, $dryrun, $id, $paste, $dststore);
|
||||
foreach ($comments as $comment) {
|
||||
saveComment($force_overwrite, $dryrun, $id, $comment, $dststore);
|
||||
}
|
||||
if ($delete_during) {
|
||||
deletePaste($dryrun, $id, $srcstore);
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete_after) {
|
||||
foreach ($ids as $id) {
|
||||
deletePaste($dryrun, $id, $srcstore);
|
||||
}
|
||||
}
|
||||
|
||||
debug("Done.");
|
||||
|
||||
|
||||
function deletePaste($dryrun, $pasteid, $srcstore)
|
||||
{
|
||||
if (!$dryrun) {
|
||||
debug("Deleting paste id " . $pasteid);
|
||||
$srcstore->delete($pasteid);
|
||||
} else {
|
||||
debug("Would delete paste id " . $pasteid);
|
||||
}
|
||||
}
|
||||
|
||||
function saveComment ($force_overwrite, $dryrun, $pasteid, $comment, $dststore)
|
||||
{
|
||||
$parentid = $comment["parentid"];
|
||||
$commentid = $comment["id"];
|
||||
|
||||
if (!$dststore->existsComment($pasteid, $parentid, $commentid)) {
|
||||
if (!$dryrun) {
|
||||
debug("Saving paste id " . $pasteid . ", parent id " .
|
||||
$parentid . ", comment id " . $commentid);
|
||||
$dststore->createComment($pasteid, $parentid, $commentid, $comment);
|
||||
} else {
|
||||
debug("Would save paste id " . $pasteid . ", parent id " .
|
||||
$parentid . ", comment id " . $commentid);
|
||||
}
|
||||
} else if ($force_overwrite) {
|
||||
if (!$dryrun) {
|
||||
debug("Overwriting paste id " . $pasteid . ", parent id " .
|
||||
$parentid . ", comment id " . $commentid);
|
||||
$dststore->createComment($pasteid, $parentid, $commentid, $comment);
|
||||
} else {
|
||||
debug("Would overwrite paste id " . $pasteid . ", parent id " .
|
||||
$parentid . ", comment id " . $commentid);
|
||||
}
|
||||
} else {
|
||||
if (!$dryrun) {
|
||||
dieerr("Not overwriting paste id " . $pasteid . ", parent id " .
|
||||
$parentid . ", comment id " . $commentid);
|
||||
} else {
|
||||
dieerr("Would not overwrite paste id " . $pasteid . ", parent id " .
|
||||
$parentid . ", comment id " . $commentid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function savePaste ($force_overwrite, $dryrun, $pasteid, $paste, $dststore)
|
||||
{
|
||||
if (!$dststore->exists($pasteid)) {
|
||||
if (!$dryrun) {
|
||||
debug("Saving paste id " . $pasteid);
|
||||
$dststore->create($pasteid, $paste);
|
||||
} else {
|
||||
debug("Would save paste id " . $pasteid);
|
||||
}
|
||||
} else if ($force_overwrite) {
|
||||
if (!$dryrun) {
|
||||
debug("Overwriting paste id " . $pasteid);
|
||||
$dststore->create($pasteid, $paste);
|
||||
} else {
|
||||
debug("Would overwrite paste id " . $pasteid);
|
||||
}
|
||||
} else {
|
||||
if (!$dryrun) {
|
||||
dieerr("Not overwriting paste id " . $pasteid);
|
||||
} else {
|
||||
dieerr("Would not overwrite paste id " . $pasteid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getConfig ($target, $confdir)
|
||||
{
|
||||
debug("Trying to load " . $target . " conf.php" .
|
||||
($confdir === "" ? "" : " from " . $confdir));
|
||||
|
||||
putenv("CONFIG_PATH=" . $confdir);
|
||||
$conf = new Configuration;
|
||||
putenv("CONFIG_PATH=");
|
||||
|
||||
return $conf;
|
||||
}
|
||||
|
||||
function dieerr ($text)
|
||||
{
|
||||
fprintf(STDERR, "ERROR: %s" . PHP_EOL, $text);
|
||||
die(1);
|
||||
}
|
||||
|
||||
function debug ($text) {
|
||||
if ($GLOBALS["verbose"]) {
|
||||
printf("DEBUG: %s" . PHP_EOL, $text);
|
||||
}
|
||||
}
|
||||
|
||||
function helpexit ()
|
||||
{
|
||||
print("migrate.php - Copy data between PrivateBin backends
|
||||
|
||||
Usage:
|
||||
php migrate.php [--delete-after] [--delete-during] [-f] [-n] [-v] srcconfdir
|
||||
[<dstconfdir>]
|
||||
php migrate.php [-h]
|
||||
|
||||
Options:
|
||||
--delete-after delete data from source after all pastes and comments have
|
||||
successfully been copied to the destination
|
||||
--delete-during delete data from source after the current paste and its
|
||||
comments have successfully been copied to the destination
|
||||
-f forcefully overwrite data which already exists at the
|
||||
destination
|
||||
-n dry run, do not copy data
|
||||
-v be verbose
|
||||
<srcconfdir> use storage backend configration from conf.php found in
|
||||
this directory as source
|
||||
<dstconfdir> optionally, use storage backend configration from conf.php
|
||||
found in this directory as destination; defaults to:
|
||||
" . PATH . "cfg" . DIRECTORY_SEPARATOR . "conf.php
|
||||
");
|
||||
exit();
|
||||
}
|
||||
@@ -7,10 +7,9 @@
|
||||
; (optional) set a project name to be displayed on the website
|
||||
; name = "PrivateBin"
|
||||
|
||||
; The full URL, with the domain name and directories that point to the
|
||||
; PrivateBin files, including an ending slash (/). This URL is essential to
|
||||
; allow Opengraph images to be displayed on social networks.
|
||||
; basepath = "https://privatebin.example.com/"
|
||||
; The full URL, with the domain name and directories that point to the PrivateBin files
|
||||
; This URL is essential to allow Opengraph images to be displayed on social networks
|
||||
; basepath = ""
|
||||
|
||||
; enable or disable the discussion feature, defaults to true
|
||||
discussion = true
|
||||
@@ -56,9 +55,9 @@ languageselection = false
|
||||
; if this is set and language selection is disabled, this will be the only language
|
||||
; languagedefault = "en"
|
||||
|
||||
; (optional) URL shortener address to offer after a new paste is created.
|
||||
; It is suggested to only use this with self-hosted shorteners as this will leak
|
||||
; the pastes encryption key.
|
||||
; (optional) URL shortener address to offer after a new paste is created
|
||||
; it is suggested to only use this with self-hosted shorteners as this will leak
|
||||
; the pastes encryption key
|
||||
; urlshortener = "https://shortener.example.com/api?link="
|
||||
|
||||
; (optional) Let users create a QR code for sharing the paste URL with one click.
|
||||
@@ -66,11 +65,10 @@ languageselection = false
|
||||
; qrcode = true
|
||||
|
||||
; (optional) IP based icons are a weak mechanism to detect if a comment was from
|
||||
; a different user when the same username was used in a comment. It might get
|
||||
; used to get the IP of a comment poster if the server salt is leaked and a
|
||||
; SHA512 HMAC rainbow table is generated for all (relevant) IPs.
|
||||
; Can be set to one these values:
|
||||
; "none" / "vizhash" / "identicon" / "jdenticon" (default).
|
||||
; a different user when the same username was used in a comment. It might be
|
||||
; used to get the IP of a non anonymous comment poster if the server salt is
|
||||
; leaked and a SHA256 HMAC rainbow table is generated for all (relevant) IPs.
|
||||
; Can be set to one these values: "none" / "vizhash" / "identicon" (default).
|
||||
; icon = "none"
|
||||
|
||||
; Content Security Policy headers allow a website to restrict what sources are
|
||||
@@ -89,7 +87,7 @@ languageselection = false
|
||||
; async functions and display an error if not and for Chrome to enable
|
||||
; webassembly support (used for zlib compression). You can remove it if Chrome
|
||||
; doesn't need to be supported and old browsers don't need to be warned.
|
||||
; cspheader = "default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval'; style-src 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads"
|
||||
; cspheader = "default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval' resource:; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads"
|
||||
|
||||
; stay compatible with PrivateBin Alpha 0.19, less secure
|
||||
; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of
|
||||
@@ -137,22 +135,17 @@ markdown = "Markdown"
|
||||
; Set this to 0 to disable rate limiting.
|
||||
limit = 10
|
||||
|
||||
; (optional) Set IPs addresses (v4 or v6) or subnets (CIDR) which are exempted
|
||||
; from the rate-limit. Invalid IPs will be ignored. If multiple values are to
|
||||
; be exempted, the list needs to be comma separated. Leave unset to disable
|
||||
; exemptions.
|
||||
; exempted = "1.2.3.4,10.10.10/24"
|
||||
|
||||
; (optional) If you want only some source IP addresses (v4 or v6) or subnets
|
||||
; (CIDR) to be allowed to create pastes, set these here. Invalid IPs will be
|
||||
; ignored. If multiple values are to be exempted, the list needs to be comma
|
||||
; separated. Leave unset to allow anyone to create pastes.
|
||||
; creators = "1.2.3.4,10.10.10/24"
|
||||
; Set ips (v4|v6) which should be exempted for the rate-limit. CIDR also supported. Needed to be comma separated.
|
||||
; Unset for enabling and invalid values will be ignored
|
||||
; eg: exemptedIp = '1.2.3.4,10.10.10/24'
|
||||
|
||||
; (optional) if your website runs behind a reverse proxy or load balancer,
|
||||
; set the HTTP header containing the visitors IP address, i.e. X_FORWARDED_FOR
|
||||
; header = "X_FORWARDED_FOR"
|
||||
|
||||
; directory to store the traffic limits in
|
||||
dir = PATH "data"
|
||||
|
||||
[purge]
|
||||
; minimum time limit between two purgings of expired pastes, it is only
|
||||
; triggered when pastes are created
|
||||
@@ -164,6 +157,9 @@ limit = 300
|
||||
; site
|
||||
batchsize = 10
|
||||
|
||||
; directory to store the purge limit in
|
||||
dir = PATH "data"
|
||||
|
||||
[model]
|
||||
; name of data model class to load and directory for storage
|
||||
; the default model "Filesystem" stores everything in the filesystem
|
||||
@@ -171,13 +167,12 @@ class = Filesystem
|
||||
[model_options]
|
||||
dir = PATH "data"
|
||||
|
||||
;[model]
|
||||
[model]
|
||||
; example of a Google Cloud Storage configuration
|
||||
;class = GoogleCloudStorage
|
||||
;[model_options]
|
||||
;bucket = "my-private-bin"
|
||||
;prefix = "pastes"
|
||||
;uniformacl = false
|
||||
|
||||
;[model]
|
||||
; example of DB configuration for MySQL
|
||||
@@ -197,52 +192,3 @@ dir = PATH "data"
|
||||
;usr = null
|
||||
;pwd = null
|
||||
;opt[12] = true ; PDO::ATTR_PERSISTENT
|
||||
|
||||
;[model]
|
||||
; example of DB configuration for PostgreSQL
|
||||
;class = Database
|
||||
;[model_options]
|
||||
;dsn = "pgsql:host=localhost;dbname=privatebin"
|
||||
;tbl = "privatebin_" ; table prefix
|
||||
;usr = "privatebin"
|
||||
;pwd = "Z3r0P4ss"
|
||||
;opt[12] = true ; PDO::ATTR_PERSISTENT
|
||||
|
||||
;[model]
|
||||
; example of S3 configuration for Rados gateway / CEPH
|
||||
;class = S3Storage
|
||||
;[model_options]
|
||||
;region = ""
|
||||
;version = "2006-03-01"
|
||||
;endpoint = "https://s3.my-ceph.invalid"
|
||||
;use_path_style_endpoint = true
|
||||
;bucket = "my-bucket"
|
||||
;accesskey = "my-rados-user"
|
||||
;secretkey = "my-rados-pass"
|
||||
|
||||
;[model]
|
||||
; example of S3 configuration for AWS
|
||||
;class = S3Storage
|
||||
;[model_options]
|
||||
;region = "eu-central-1"
|
||||
;version = "latest"
|
||||
;bucket = "my-bucket"
|
||||
;accesskey = "access key id"
|
||||
;secretkey = "secret access key"
|
||||
|
||||
[yourls]
|
||||
; When using YOURLS as a "urlshortener" config item:
|
||||
; - By default, "urlshortener" will point to the YOURLS API URL, with or without
|
||||
; credentials, and will be visible in public on the PrivateBin web page.
|
||||
; Only use this if you allow short URL creation without credentials.
|
||||
; - Alternatively, using the parameters in this section ("signature" and
|
||||
; "apiurl"), "urlshortener" needs to point to the base URL of your PrivateBin
|
||||
; instance with "shortenviayourls?link=" appended. For example:
|
||||
; urlshortener = "${basepath}shortenviayourls?link="
|
||||
; This URL will in turn call YOURLS on the server side, using the URL from
|
||||
; "apiurl" and the "access signature" from the "signature" parameters below.
|
||||
|
||||
; (optional) the "signature" (access key) issued by YOURLS for the using account
|
||||
; signature = ""
|
||||
; (optional) the URL of the YOURLS API, called to shorten a PrivateBin URL
|
||||
; apiurl = "https://yourls.example.com/yourls-api.php"
|
||||
@@ -25,14 +25,12 @@
|
||||
},
|
||||
"require" : {
|
||||
"php" : "^5.6.0 || ^7.0 || ^8.0",
|
||||
"paragonie/random_compat" : "2.0.21",
|
||||
"paragonie/random_compat" : "2.0.20",
|
||||
"yzalis/identicon" : "2.0.0",
|
||||
"mlocati/ip-lib" : "1.18.0",
|
||||
"jdenticon/jdenticon": "^1.0"
|
||||
"mlocati/ip-lib" : "1.14.0"
|
||||
},
|
||||
"suggest" : {
|
||||
"google/cloud-storage" : "1.26.1",
|
||||
"aws/aws-sdk-php" : "3.239.0"
|
||||
"google/cloud-storage" : "1.23.1"
|
||||
},
|
||||
"require-dev" : {
|
||||
"phpunit/phpunit" : "^4.6 || ^5.0"
|
||||
@@ -45,4 +43,4 @@
|
||||
"config" : {
|
||||
"autoloader-suffix" : "DontChange"
|
||||
}
|
||||
}
|
||||
}
|
||||
487
composer.lock
generated
487
composer.lock
generated
@@ -4,69 +4,20 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "17bceced29627163f7aa330a0697f68b",
|
||||
"content-hash": "217f0ba9bdac1014a332a8ba390be949",
|
||||
"packages": [
|
||||
{
|
||||
"name": "jdenticon/jdenticon",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dmester/jdenticon-php.git",
|
||||
"reference": "cabb7a44c413c318392a341c5d3ca30fcdd57a6f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dmester/jdenticon-php/zipball/cabb7a44c413c318392a341c5d3ca30fcdd57a6f",
|
||||
"reference": "cabb7a44c413c318392a341c5d3ca30fcdd57a6f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Jdenticon\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Daniel Mester Pirttijärvi"
|
||||
}
|
||||
],
|
||||
"description": "Render PNG and SVG identicons.",
|
||||
"homepage": "https://jdenticon.com/",
|
||||
"keywords": [
|
||||
"avatar",
|
||||
"identicon",
|
||||
"jdenticon"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://jdenticon.com/php-api.html",
|
||||
"issues": "https://github.com/dmester/jdenticon-php/issues",
|
||||
"source": "https://github.com/dmester/jdenticon-php"
|
||||
},
|
||||
"time": "2022-10-30T17:15:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mlocati/ip-lib",
|
||||
"version": "1.18.0",
|
||||
"version": "1.14.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mlocati/ip-lib.git",
|
||||
"reference": "c77bd0b1f3e3956c7e9661e75cb1f54ed67d95d2"
|
||||
"reference": "882bc0e115970a536b13bcfa59f312783fce08c8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mlocati/ip-lib/zipball/c77bd0b1f3e3956c7e9661e75cb1f54ed67d95d2",
|
||||
"reference": "c77bd0b1f3e3956c7e9661e75cb1f54ed67d95d2",
|
||||
"url": "https://api.github.com/repos/mlocati/ip-lib/zipball/882bc0e115970a536b13bcfa59f312783fce08c8",
|
||||
"reference": "882bc0e115970a536b13bcfa59f312783fce08c8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -74,7 +25,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-pdo_sqlite": "*",
|
||||
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.5 || ^9.5"
|
||||
"phpunit/dbunit": "^1.4 || ^2 || ^3 || ^4",
|
||||
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -110,10 +62,6 @@
|
||||
"range",
|
||||
"subnet"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/mlocati/ip-lib/issues",
|
||||
"source": "https://github.com/mlocati/ip-lib/tree/1.18.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/mlocati",
|
||||
@@ -124,27 +72,27 @@
|
||||
"type": "other"
|
||||
}
|
||||
],
|
||||
"time": "2022-01-13T18:05:33+00:00"
|
||||
"time": "2020-12-31T11:30:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "v2.0.21",
|
||||
"version": "v2.0.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/random_compat.git",
|
||||
"reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae"
|
||||
"reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/96c132c7f2f7bc3230723b66e89f8f150b29d5ae",
|
||||
"reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
|
||||
"reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "*"
|
||||
"phpunit/phpunit": "4.*|5.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||
@@ -173,12 +121,7 @@
|
||||
"pseudorandom",
|
||||
"random"
|
||||
],
|
||||
"support": {
|
||||
"email": "info@paragonie.com",
|
||||
"issues": "https://github.com/paragonie/random_compat/issues",
|
||||
"source": "https://github.com/paragonie/random_compat"
|
||||
},
|
||||
"time": "2022-02-16T17:07:03+00:00"
|
||||
"time": "2021-04-17T09:33:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "yzalis/identicon",
|
||||
@@ -230,10 +173,6 @@
|
||||
"identicon",
|
||||
"image"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/yzalis/Identicon/issues",
|
||||
"source": "https://github.com/yzalis/Identicon/tree/master"
|
||||
},
|
||||
"abandoned": true,
|
||||
"time": "2019-10-14T09:30:57+00:00"
|
||||
}
|
||||
@@ -241,34 +180,31 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.0.5",
|
||||
"version": "1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/instantiator.git",
|
||||
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
|
||||
"reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
|
||||
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b",
|
||||
"reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3,<8.0-DEV"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"athletic/athletic": "~0.1.8",
|
||||
"doctrine/coding-standard": "^8.0",
|
||||
"ext-pdo": "*",
|
||||
"ext-phar": "*",
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"squizlabs/php_codesniffer": "~2.0"
|
||||
"phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
|
||||
@@ -282,51 +218,64 @@
|
||||
{
|
||||
"name": "Marco Pivetta",
|
||||
"email": "ocramius@gmail.com",
|
||||
"homepage": "http://ocramius.github.com/"
|
||||
"homepage": "https://ocramius.github.io/"
|
||||
}
|
||||
],
|
||||
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
|
||||
"homepage": "https://github.com/doctrine/instantiator",
|
||||
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
|
||||
"keywords": [
|
||||
"constructor",
|
||||
"instantiate"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/instantiator/issues",
|
||||
"source": "https://github.com/doctrine/instantiator/tree/master"
|
||||
},
|
||||
"time": "2015-06-14T21:17:01+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.doctrine-project.org/sponsorship.html",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/phpdoctrine",
|
||||
"type": "patreon"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-11-10T18:47:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.7.0",
|
||||
"version": "1.10.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e"
|
||||
"reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
|
||||
"reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220",
|
||||
"reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"replace": {
|
||||
"myclabs/deep-copy": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/collections": "^1.0",
|
||||
"doctrine/common": "^2.6",
|
||||
"phpunit/phpunit": "^4.1"
|
||||
"phpunit/phpunit": "^7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/DeepCopy/deep_copy.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"DeepCopy\\": "src/DeepCopy/"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src/DeepCopy/deep_copy.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@@ -340,43 +289,40 @@
|
||||
"object",
|
||||
"object graph"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.x"
|
||||
},
|
||||
"time": "2017-10-19T19:58:43+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-11-13T09:40:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
"version": "1.0.1",
|
||||
"version": "2.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
|
||||
"reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
|
||||
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
|
||||
"reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
|
||||
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.6"
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
"dev-2.x": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpDocumentor\\Reflection\\": [
|
||||
"src"
|
||||
]
|
||||
"phpDocumentor\\Reflection\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@@ -398,94 +344,90 @@
|
||||
"reflection",
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
|
||||
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master"
|
||||
},
|
||||
"time": "2017-09-11T18:02:19+00:00"
|
||||
"time": "2020-06-27T09:03:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
"version": "3.3.2",
|
||||
"version": "5.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||
"reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2"
|
||||
"reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2",
|
||||
"reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
|
||||
"reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0",
|
||||
"phpdocumentor/reflection-common": "^1.0.0",
|
||||
"phpdocumentor/type-resolver": "^0.4.0",
|
||||
"webmozart/assert": "^1.0"
|
||||
"ext-filter": "*",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpdocumentor/reflection-common": "^2.2",
|
||||
"phpdocumentor/type-resolver": "^1.3",
|
||||
"webmozart/assert": "^1.9.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^0.9.4",
|
||||
"phpunit/phpunit": "^4.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpDocumentor\\Reflection\\": [
|
||||
"src/"
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mike van Riel",
|
||||
"email": "me@mikevanriel.com"
|
||||
}
|
||||
],
|
||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
|
||||
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/3.x"
|
||||
},
|
||||
"time": "2017-11-10T14:09:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
"version": "0.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
|
||||
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5 || ^7.0",
|
||||
"phpdocumentor/reflection-common": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^0.9.4",
|
||||
"phpunit/phpunit": "^5.2||^4.8.24"
|
||||
"mockery/mockery": "~1.3.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
"dev-master": "5.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpDocumentor\\Reflection\\": [
|
||||
"src/"
|
||||
]
|
||||
"phpDocumentor\\Reflection\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mike van Riel",
|
||||
"email": "me@mikevanriel.com"
|
||||
},
|
||||
{
|
||||
"name": "Jaap van Otterdijk",
|
||||
"email": "account@ijaap.nl"
|
||||
}
|
||||
],
|
||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||
"time": "2020-09-03T19:13:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
"version": "1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||
"reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
|
||||
"reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpdocumentor/reflection-common": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-tokenizer": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-1.x": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpDocumentor\\Reflection\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@@ -498,11 +440,8 @@
|
||||
"email": "me@mikevanriel.com"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/master"
|
||||
},
|
||||
"time": "2017-07-14T14:27:02+00:00"
|
||||
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
||||
"time": "2020-09-17T18:55:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
@@ -565,10 +504,6 @@
|
||||
"spy",
|
||||
"stub"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpspec/prophecy/issues",
|
||||
"source": "https://github.com/phpspec/prophecy/tree/v1.10.3"
|
||||
},
|
||||
"time": "2020-03-05T15:02:03+00:00"
|
||||
},
|
||||
{
|
||||
@@ -632,11 +567,6 @@
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"support": {
|
||||
"irc": "irc://irc.freenode.net/phpunit",
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/4.0"
|
||||
},
|
||||
"time": "2017-04-02T07:44:40+00:00"
|
||||
},
|
||||
{
|
||||
@@ -684,11 +614,6 @@
|
||||
"filesystem",
|
||||
"iterator"
|
||||
],
|
||||
"support": {
|
||||
"irc": "irc://irc.freenode.net/phpunit",
|
||||
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5"
|
||||
},
|
||||
"time": "2017-11-27T13:52:08+00:00"
|
||||
},
|
||||
{
|
||||
@@ -730,10 +655,6 @@
|
||||
"keywords": [
|
||||
"template"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1"
|
||||
},
|
||||
"time": "2015-06-21T13:50:34+00:00"
|
||||
},
|
||||
{
|
||||
@@ -783,37 +704,33 @@
|
||||
"keywords": [
|
||||
"timer"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-timer/tree/master"
|
||||
},
|
||||
"time": "2017-02-26T11:10:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-token-stream",
|
||||
"version": "1.4.12",
|
||||
"version": "2.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
|
||||
"reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16"
|
||||
"reference": "791198a2c6254db10131eecfe8c06670700904db"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16",
|
||||
"reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db",
|
||||
"reference": "791198a2c6254db10131eecfe8c06670700904db",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-tokenizer": "*",
|
||||
"php": ">=5.3.3"
|
||||
"php": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.2"
|
||||
"phpunit/phpunit": "^6.2.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -836,12 +753,8 @@
|
||||
"keywords": [
|
||||
"tokenizer"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4"
|
||||
},
|
||||
"abandoned": true,
|
||||
"time": "2017-12-04T08:55:13+00:00"
|
||||
"time": "2017-11-27T05:48:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
@@ -923,10 +836,6 @@
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/5.7.27"
|
||||
},
|
||||
"time": "2018-02-01T05:50:59+00:00"
|
||||
},
|
||||
{
|
||||
@@ -986,11 +895,6 @@
|
||||
"mock",
|
||||
"xunit"
|
||||
],
|
||||
"support": {
|
||||
"irc": "irc://irc.freenode.net/phpunit",
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/3.4"
|
||||
},
|
||||
"abandoned": true,
|
||||
"time": "2017-06-30T09:13:00+00:00"
|
||||
},
|
||||
@@ -1037,10 +941,6 @@
|
||||
],
|
||||
"description": "Looks up which function or method a line of code belongs to",
|
||||
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
|
||||
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
@@ -1111,10 +1011,6 @@
|
||||
"compare",
|
||||
"equality"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/1.2"
|
||||
},
|
||||
"time": "2017-01-29T09:50:25+00:00"
|
||||
},
|
||||
{
|
||||
@@ -1167,10 +1063,6 @@
|
||||
"keywords": [
|
||||
"diff"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/1.4"
|
||||
},
|
||||
"time": "2017-05-22T07:24:03+00:00"
|
||||
},
|
||||
{
|
||||
@@ -1221,10 +1113,6 @@
|
||||
"environment",
|
||||
"hhvm"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/environment/issues",
|
||||
"source": "https://github.com/sebastianbergmann/environment/tree/master"
|
||||
},
|
||||
"time": "2016-11-26T07:53:53+00:00"
|
||||
},
|
||||
{
|
||||
@@ -1292,10 +1180,6 @@
|
||||
"export",
|
||||
"exporter"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/master"
|
||||
},
|
||||
"time": "2016-11-19T08:54:04+00:00"
|
||||
},
|
||||
{
|
||||
@@ -1347,10 +1231,6 @@
|
||||
"keywords": [
|
||||
"global state"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/global-state/issues",
|
||||
"source": "https://github.com/sebastianbergmann/global-state/tree/1.1.1"
|
||||
},
|
||||
"time": "2015-10-12T03:26:01+00:00"
|
||||
},
|
||||
{
|
||||
@@ -1397,10 +1277,6 @@
|
||||
],
|
||||
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
|
||||
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
|
||||
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/master"
|
||||
},
|
||||
"time": "2017-02-18T15:18:39+00:00"
|
||||
},
|
||||
{
|
||||
@@ -1454,10 +1330,6 @@
|
||||
],
|
||||
"description": "Provides functionality to recursively process PHP variables",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
|
||||
"source": "https://github.com/sebastianbergmann/recursion-context/tree/master"
|
||||
},
|
||||
"time": "2016-11-19T07:33:16+00:00"
|
||||
},
|
||||
{
|
||||
@@ -1500,10 +1372,6 @@
|
||||
],
|
||||
"description": "Provides a list of PHP built-in functions that operate on resources",
|
||||
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
|
||||
"source": "https://github.com/sebastianbergmann/resource-operations/tree/master"
|
||||
},
|
||||
"time": "2015-07-28T20:34:47+00:00"
|
||||
},
|
||||
{
|
||||
@@ -1547,28 +1415,24 @@
|
||||
],
|
||||
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
||||
"homepage": "https://github.com/sebastianbergmann/version",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/version/issues",
|
||||
"source": "https://github.com/sebastianbergmann/version/tree/master"
|
||||
},
|
||||
"time": "2016-10-03T07:35:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.19.0",
|
||||
"version": "v1.23.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b"
|
||||
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b",
|
||||
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
|
||||
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "For best performance"
|
||||
@@ -1576,7 +1440,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.19-dev"
|
||||
"dev-main": "1.23-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -1584,12 +1448,12 @@
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@@ -1613,9 +1477,6 @@
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
@@ -1630,31 +1491,31 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-23T09:01:57+00:00"
|
||||
"time": "2021-02-19T12:13:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v3.4.47",
|
||||
"version": "v4.4.24",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "88289caa3c166321883f67fe5130188ebbb47094"
|
||||
"reference": "8b6d1b97521e2f125039b3fcb4747584c6dfa0ef"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094",
|
||||
"reference": "88289caa3c166321883f67fe5130188ebbb47094",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/8b6d1b97521e2f125039b3fcb4747584c6dfa0ef",
|
||||
"reference": "8b6d1b97521e2f125039b3fcb4747584c6dfa0ef",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"php": ">=7.1.3",
|
||||
"symfony/polyfill-ctype": "~1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<3.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "~3.4|~4.0"
|
||||
"symfony/console": "^3.4|^4.0|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "For validating YAML files using the lint command"
|
||||
@@ -1682,11 +1543,8 @@
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v3.4.47"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
@@ -1701,34 +1559,39 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-24T10:57:07+00:00"
|
||||
"time": "2021-05-16T09:52:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "1.9.1",
|
||||
"version": "1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozarts/assert.git",
|
||||
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389"
|
||||
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
|
||||
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
|
||||
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3.3 || ^7.0 || ^8.0",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan": "<0.12.20",
|
||||
"vimeo/psalm": "<3.9.1"
|
||||
"vimeo/psalm": "<4.6.1 || 4.6.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.36 || ^7.5.13"
|
||||
"phpunit/phpunit": "^8.5.13"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.10-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Webmozart\\Assert\\": "src/"
|
||||
@@ -1750,11 +1613,7 @@
|
||||
"check",
|
||||
"validate"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/webmozarts/assert/issues",
|
||||
"source": "https://github.com/webmozarts/assert/tree/1.9.1"
|
||||
},
|
||||
"time": "2020-07-08T17:02:28+00:00"
|
||||
"time": "2021-03-09T10:59:23+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
@@ -1766,5 +1625,5 @@
|
||||
"php": "^5.6.0 || ^7.0 || ^8.0"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "1.1.0"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
body {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
/* When there is no script at all other */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
158
i18n/ca.json
158
i18n/ca.json
@@ -8,126 +8,126 @@
|
||||
"%s requires php %s or above to work. Sorry.": "%s requereix php %s o superior per funcionar. Ho sento.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s requereix que la secció de configuració [%s] sigui present al fitxer de configuració.",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Espereu %d segon entre cada entrada.",
|
||||
"Espereu %d segons entre cada entrada.",
|
||||
"Please wait %d second between each post. (singular)",
|
||||
"Please wait %d seconds between each post. (1st plural)",
|
||||
"Please wait %d seconds between each post. (2nd plural)",
|
||||
"Please wait %d seconds between each post. (3rd plural)"
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "L'enganxat està limitat a %s de dades encriptades.",
|
||||
"Invalid data.": "Dades no vàlides.",
|
||||
"You are unlucky. Try again.": "Mala sort. Torna-ho a provar.",
|
||||
"Error saving comment. Sorry.": "S'ha produït un error en desar el comentari. Ho sento.",
|
||||
"Error saving paste. Sorry.": "S'ha produït un error en desar l'enganxat. Ho sento.",
|
||||
"Invalid paste ID.": "Identificador d'enganxament no vàlid.",
|
||||
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.",
|
||||
"Invalid data.": "Invalid data.",
|
||||
"You are unlucky. Try again.": "You are unlucky. Try again.",
|
||||
"Error saving comment. Sorry.": "Error saving comment. Sorry.",
|
||||
"Error saving paste. Sorry.": "Error saving paste. Sorry.",
|
||||
"Invalid paste ID.": "Invalid paste ID.",
|
||||
"Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.",
|
||||
"Wrong deletion token. Paste was not deleted.": "El token d'eliminació és incorrecte. El Paste no s'ha eliminat.",
|
||||
"Paste was properly deleted.": "El Paste s'ha esborrat correctament.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "Cal JavaScript perquè %s funcioni. Em sap greu les molèsties.",
|
||||
"%s requires a modern browser to work.": "%s requereix un navegador modern per funcionar.",
|
||||
"New": "Nou",
|
||||
"Send": "Enviar",
|
||||
"Clone": "Clona",
|
||||
"Raw text": "Text sense processar",
|
||||
"Expires": "Caducitat",
|
||||
"Burn after reading": "Esborra després de ser llegit",
|
||||
"Open discussion": "Discussió oberta",
|
||||
"Password (recommended)": "Contrasenya (recomanat)",
|
||||
"Discussion": "Discussió",
|
||||
"Toggle navigation": "Alternar navegació",
|
||||
"Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.",
|
||||
"Paste was properly deleted.": "Paste was properly deleted.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.",
|
||||
"%s requires a modern browser to work.": "%s requires a modern browser to work.",
|
||||
"New": "New",
|
||||
"Send": "Send",
|
||||
"Clone": "Clone",
|
||||
"Raw text": "Raw text",
|
||||
"Expires": "Expires",
|
||||
"Burn after reading": "Burn after reading",
|
||||
"Open discussion": "Open discussion",
|
||||
"Password (recommended)": "Password (recommended)",
|
||||
"Discussion": "Discussion",
|
||||
"Toggle navigation": "Toggle navigation",
|
||||
"%d seconds": [
|
||||
"%d segon",
|
||||
"%d segons",
|
||||
"%d second (singular)",
|
||||
"%d seconds (1st plural)",
|
||||
"%d seconds (2nd plural)",
|
||||
"%d seconds (3rd plural)"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d minut",
|
||||
"%d minuts",
|
||||
"%d minute (singular)",
|
||||
"%d minutes (1st plural)",
|
||||
"%d minutes (2nd plural)",
|
||||
"%d minutes (3rd plural)"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d hora",
|
||||
"%d hores",
|
||||
"%d hour (singular)",
|
||||
"%d hours (1st plural)",
|
||||
"%d hours (2nd plural)",
|
||||
"%d hours (3rd plural)"
|
||||
],
|
||||
"%d days": [
|
||||
"%d dia",
|
||||
"%d dies",
|
||||
"%d day (singular)",
|
||||
"%d days (1st plural)",
|
||||
"%d days (2nd plural)",
|
||||
"%d days (3rd plural)"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d setmana",
|
||||
"%d setmanes",
|
||||
"%d week (singular)",
|
||||
"%d weeks (1st plural)",
|
||||
"%d weeks (2nd plural)",
|
||||
"%d weeks (3rd plural)"
|
||||
],
|
||||
"%d months": [
|
||||
"%d mes",
|
||||
"%d mesos",
|
||||
"%d month (singular)",
|
||||
"%d months (1st plural)",
|
||||
"%d months (2nd plural)",
|
||||
"%d months (3rd plural)"
|
||||
],
|
||||
"%d years": [
|
||||
"%d any",
|
||||
"%d anys",
|
||||
"%d year (singular)",
|
||||
"%d years (1st plural)",
|
||||
"%d years (2nd plural)",
|
||||
"%d years (3rd plural)"
|
||||
],
|
||||
"Never": "Mai",
|
||||
"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.": [
|
||||
"Aquest document caducarà d'aquí %d segon.",
|
||||
"Aquest document caducarà d'aquí %d segons.",
|
||||
"Aquest document caducarà d'aquí %d segons.",
|
||||
"Aquest document caducarà d'aquí %d segons."
|
||||
"This document will expire in %d second. (singular)",
|
||||
"This document will expire in %d seconds. (1st plural)",
|
||||
"This document will expire in %d seconds. (2nd plural)",
|
||||
"This document will expire in %d seconds. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"Aquest document caducarà d'aquí %d minut.",
|
||||
"Aquest document caducarà d'aquí %d minuts.",
|
||||
"Aquest document caducarà d'aquí %d minuts.",
|
||||
"Aquest document caducarà d'aquí %d minuts."
|
||||
"This document will expire in %d minute. (singular)",
|
||||
"This document will expire in %d minutes. (1st plural)",
|
||||
"This document will expire in %d minutes. (2nd plural)",
|
||||
"This document will expire in %d minutes. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"Aquest document caducarà d'aquí %d hora.",
|
||||
"Aquest document caducarà d'aquí %d hores.",
|
||||
"Aquest document caducarà d'aquí %d hores.",
|
||||
"Aquest document caducarà d'aquí %d hores."
|
||||
"This document will expire in %d hour. (singular)",
|
||||
"This document will expire in %d hours. (1st plural)",
|
||||
"This document will expire in %d hours. (2nd plural)",
|
||||
"This document will expire in %d hours. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"Aquest document caducarà d'aquí %d dia.",
|
||||
"Aquest document caducarà d'aquí %d dies.",
|
||||
"Aquest document caducarà d'aquí %d dies.",
|
||||
"Aquest document caducarà d'aquí %d dies."
|
||||
"This document will expire in %d day. (singular)",
|
||||
"This document will expire in %d days. (1st plural)",
|
||||
"This document will expire in %d days. (2nd plural)",
|
||||
"This document will expire in %d days. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"Aquest document caducarà d'aquí %d mes.",
|
||||
"Aquest document caducarà d'aquí %d mesos.",
|
||||
"Aquest document caducarà d'aquí %d mesos.",
|
||||
"Aquest document caducarà d'aquí %d mesos."
|
||||
"This document will expire in %d month. (singular)",
|
||||
"This document will expire in %d months. (1st plural)",
|
||||
"This document will expire in %d months. (2nd plural)",
|
||||
"This document will expire in %d months. (3rd plural)"
|
||||
],
|
||||
"Please enter the password for this paste:": "Si us plau, introdueix la contrasenya per aquest paste:",
|
||||
"Could not decrypt data (Wrong key?)": "No s'han pogut desxifrar les dades (Clau incorrecte?)",
|
||||
"Please enter the password for this paste:": "Please enter the password for this paste:",
|
||||
"Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.",
|
||||
"Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?",
|
||||
"Reply": "Respondre",
|
||||
"Anonymous": "Anònim",
|
||||
"Avatar generated from IP address": "Avatar generat a partir de l'adreça IP",
|
||||
"Add comment": "Afegir comentari",
|
||||
"Optional nickname…": "Pseudònim opcional…",
|
||||
"Post comment": "Publicar comentari",
|
||||
"Sending comment…": "Enviant comentari…",
|
||||
"Comment posted.": "Comentari publicat.",
|
||||
"Reply": "Reply",
|
||||
"Anonymous": "Anonymous",
|
||||
"Avatar generated from IP address": "Avatar generated from IP address",
|
||||
"Add comment": "Add comment",
|
||||
"Optional nickname…": "Optional nickname…",
|
||||
"Post comment": "Post comment",
|
||||
"Sending comment…": "Sending comment…",
|
||||
"Comment posted.": "Comment posted.",
|
||||
"Could not refresh display: %s": "Could not refresh display: %s",
|
||||
"unknown status": "estat desconegut",
|
||||
"unknown status": "unknown status",
|
||||
"server error or not responding": "server error or not responding",
|
||||
"Could not post comment: %s": "No s'ha pogut publicar el comentari: %s",
|
||||
"Sending paste…": "Enviant paste…",
|
||||
"Could not post comment: %s": "Could not post comment: %s",
|
||||
"Sending paste…": "Sending paste…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>",
|
||||
"Delete data": "Esborrar les dades",
|
||||
"Delete data": "Delete data",
|
||||
"Could not create paste: %s": "Could not create paste: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
|
||||
"B": "B",
|
||||
@@ -140,13 +140,13 @@
|
||||
"ZiB": "ZiB",
|
||||
"YiB": "YiB",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Text sense format",
|
||||
"Source Code": "Codi font",
|
||||
"Plain Text": "Plain Text",
|
||||
"Source Code": "Source Code",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Baixar els adjunts",
|
||||
"Download attachment": "Download attachment",
|
||||
"Cloned: '%s'": "Cloned: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Adjuntar un fitxer",
|
||||
"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",
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
193
i18n/co.json
193
i18n/co.json
@@ -1,193 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s hè un serviziu in linea di tipu « pastebin » (ghjestiunariu d’appiccicu di pezzi di testu è di codice di fonte) minimalistu è à fonte aperta induve u servitore ùn hà micca cunnuscenza di i dati mandati. I dati sò cifrati è dicifrati %sin u navigatore%s cù una cifratura AES di 256 bit.",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Più d’infurmazione annant’à a <a href=\"https://privatebin.info/\">pagina di u prughjettu</a>.",
|
||||
"Because ignorance is bliss": "Perchè l’ignurenza hè una campa",
|
||||
"en": "co",
|
||||
"Paste does not exist, has expired or has been deleted.": "L’appiccicu ùn esiste micca, hè scadutu o hè statu squassatu.",
|
||||
"%s requires php %s or above to work. Sorry.": "Per disgrazzia, %s richiede php %s o più recente per funziunà.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s richiede a presenza di a sezzione di cunfigurazione [%s] in a schedariu di cunfigurazione.",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Aspettate %d seconda trà dui publicazioni.",
|
||||
"Aspettate %d seconde trà dui publicazioni.",
|
||||
"Aspettate %d seconde trà dui publicazioni.",
|
||||
"Aspettate %d seconde trà dui publicazioni."
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "L’appiccicu hè limitatu à %s di dati cifrati.",
|
||||
"Invalid data.": "Dati inaccetevule.",
|
||||
"You are unlucky. Try again.": "Pruvate torna, Serete più furtunati.",
|
||||
"Error saving comment. Sorry.": "Per disgrazzia, ci hè un sbagliu à l’arregistramentu di u cummentu.",
|
||||
"Error saving paste. Sorry.": "Per disgrazzia, ci hè un sbagliu à l’arregistramentu di l’appiccicu.",
|
||||
"Invalid paste ID.": "N° di l’appiccicu inaccettevule.",
|
||||
"Paste is not of burn-after-reading type.": "L’appiccicu ùn hè micca di tipu « Squassà dopu a lettura ».",
|
||||
"Wrong deletion token. Paste was not deleted.": "Gettone di squassatura incurrettu. L’appiccicu ùn hè micca statu squassatu.",
|
||||
"Paste was properly deleted.": "L’appiccicu hè statu squassatu currettamente.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript hè richiestu per fà funziunà %s. Scusate per stu penseru.",
|
||||
"%s requires a modern browser to work.": "%s richiede un navigatore mudernu per funziunà.",
|
||||
"New": "Novu",
|
||||
"Send": "Mandà",
|
||||
"Clone": "Duppione",
|
||||
"Raw text": "Testu grossu",
|
||||
"Expires": "Scadenza",
|
||||
"Burn after reading": "Squassà dopu a lettura",
|
||||
"Open discussion": "Apre una chjachjarata",
|
||||
"Password (recommended)": "Parolla d’intesa (ricumandata)",
|
||||
"Discussion": "Chjachjarata",
|
||||
"Toggle navigation": "Invertisce a navigazione",
|
||||
"%d seconds": [
|
||||
"%d seconda",
|
||||
"%d seconde",
|
||||
"%d seconde",
|
||||
"%d seconde"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d minutu",
|
||||
"%d minuti",
|
||||
"%d minuti",
|
||||
"%d minuti"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d ora",
|
||||
"%d ore",
|
||||
"%d ore",
|
||||
"%d ore"
|
||||
],
|
||||
"%d days": [
|
||||
"%d ghjornu",
|
||||
"%d ghjorni",
|
||||
"%d ghjorni",
|
||||
"%d ghjorni"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d settimana",
|
||||
"%d settimane",
|
||||
"%d settimane",
|
||||
"%d settimane"
|
||||
],
|
||||
"%d months": [
|
||||
"%d mese",
|
||||
"%d mesi",
|
||||
"%d mesi",
|
||||
"%d mesi"
|
||||
],
|
||||
"%d years": [
|
||||
"%d annu",
|
||||
"%d anni",
|
||||
"%d anni",
|
||||
"%d anni"
|
||||
],
|
||||
"Never": "Mai",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Nota : Què hè un serviziu di prova ; i dati ponu esse squassati à ogni mumentu. Parechji catorni anu da esse tombi s’è vò impiegate troppu stu serviziu.",
|
||||
"This document will expire in %d seconds.": [
|
||||
"Stu ducumentu serà scadutu in %d seconda.",
|
||||
"Stu ducumentu serà scadutu in %d seconde.",
|
||||
"Stu ducumentu serà scadutu in %d seconde.",
|
||||
"Stu ducumentu serà scadutu in %d seconde."
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"Stu ducumentu serà scadutu in %d minutu.",
|
||||
"Stu ducumentu serà scadutu in %d minuti.",
|
||||
"Stu ducumentu serà scadutu in %d minuti.",
|
||||
"Stu ducumentu serà scadutu in %d minuti."
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"Stu ducumentu serà scadutu in %d ora.",
|
||||
"Stu ducumentu serà scadutu in %d ore.",
|
||||
"Stu ducumentu serà scadutu in %d ore.",
|
||||
"Stu ducumentu serà scadutu in %d ore."
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"Stu ducumentu serà scadutu in %d ghjornu.",
|
||||
"Stu ducumentu serà scadutu in %d ghjorni.",
|
||||
"Stu ducumentu serà scadutu in %d ghjorni.",
|
||||
"Stu ducumentu serà scadutu in %d ghjorni."
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"Stu ducumentu serà scadutu in %d mese.",
|
||||
"Stu ducumentu serà scadutu in %d mesi.",
|
||||
"Stu ducumentu serà scadutu in %d mesi.",
|
||||
"Stu ducumentu serà scadutu in %d mesi."
|
||||
],
|
||||
"Please enter the password for this paste:": "Stampittate a parolla d’intesa per st’appiccicu :",
|
||||
"Could not decrypt data (Wrong key?)": "Ùn si pò micca dicifrà i dati ; seria incurretta a chjave ?",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Ùn si pò micca squassà l’appiccicu, ùn hè micca statu in u modu « Squassà dopu a lettura ».",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "SOLU CÙ L’OCHJI. Ùn chjudite micca sta finestra, stu messaghju un puderà più esse affissatu torna.",
|
||||
"Could not decrypt comment; Wrong key?": "Ùn si pò micca dicifrà u cummentu. Seria incurretta a chjave ?",
|
||||
"Reply": "Risponde",
|
||||
"Anonymous": "Anonimu",
|
||||
"Avatar generated from IP address": "Avatar ingeneratu da l’indirizzu IP",
|
||||
"Add comment": "Aghjunghje un cummentu",
|
||||
"Optional nickname…": "Cugnome ozzionale…",
|
||||
"Post comment": "Impustà u cummentu",
|
||||
"Sending comment…": "Inviu di u cummentu…",
|
||||
"Comment posted.": "Cummentu inviatu.",
|
||||
"Could not refresh display: %s": "Ùn si pò micca attualizà l’affissera : %s",
|
||||
"unknown status": "statu scunnisciutu",
|
||||
"server error or not responding": "sbagliu di u servitore o u servitore ùn risponde micca",
|
||||
"Could not post comment: %s": "Ùn si pò micca impustà u cummentu : %s",
|
||||
"Sending paste…": "Inviu di l’appiccicu…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "U vostru appiccicu si trova à l’indirizzu<a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Appughjate [Ctrl]+[c] per cupià u liame)</span>",
|
||||
"Delete data": "Squassà i dati",
|
||||
"Could not create paste: %s": "Ùn si pò micca creà l’appiccicu : %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Ùn si pò micca dicifrà l’appiccicu : A chjave di dicifratura hè assente in l’indirizzu. Averiate impiegatu un orientadore d’indirizzu o un riduttore chì ammuzzeghja una parte di l’indirizzu ?",
|
||||
"B": "o",
|
||||
"KiB": "Ko",
|
||||
"MiB": "Mo",
|
||||
"GiB": "Go",
|
||||
"TiB": "To",
|
||||
"PiB": "Po",
|
||||
"EiB": "Eo",
|
||||
"ZiB": "Zo",
|
||||
"YiB": "Yo",
|
||||
"Format": "Furmatu",
|
||||
"Plain Text": "Testu in chjaru",
|
||||
"Source Code": "Codice di fonte",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Scaricà a pezza aghjunta",
|
||||
"Cloned: '%s'": "Duppiatu : « %s »",
|
||||
"The cloned file '%s' was attached to this paste.": "U schedariu duppiatu « %s » hè statu aghjuntu à st’appiccicu.",
|
||||
"Attach a file": "Aghjunghje un schedariu",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "in alternanza, sguillà è depone un schedariu o incullà una fiura da u preme’papei",
|
||||
"File too large, to display a preview. Please download the attachment.": "Schedariu troppu maiò per affissà una fighjulata. Scaricate a pezza aghjunta.",
|
||||
"Remove attachment": "Caccià a pezza aghjunta",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "U vostru navigatore ùn accetta micca l’inviu di i schedarii cifrati. Impiegate un navigatore più recente.",
|
||||
"Invalid attachment.": "A pezza aghjunta hè inaccettevule.",
|
||||
"Options": "Ozzioni",
|
||||
"Shorten URL": "Ammuzzà l’indirizzu",
|
||||
"Editor": "Editore",
|
||||
"Preview": "Fighjulata",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s richiede chì a variabile PATH si compii cù « %s ». Mudificate a variabile PATH in u vostru index.php.",
|
||||
"Decrypt": "Dicifrà",
|
||||
"Enter password": "Stampittate a parolla d’intesa",
|
||||
"Loading…": "Caricamentu…",
|
||||
"Decrypting paste…": "Dicifratura di l’appiccicu…",
|
||||
"Preparing new paste…": "Approntu di u novu appiccicu…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "S’è stu messaghju ùn smarisce micca, lighjite <a href=\"%s\">sta FAQ per ottene infurmazioni annant’à a risuluzione di i prublemi</a>.",
|
||||
"+++ no paste text +++": "+++ nisunu testu incullatu +++",
|
||||
"Could not get paste data: %s": "Ùn si pò micca ottene i dati di l’appiccicu : %s",
|
||||
"QR code": "Codice QR",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "Stu situ web impiegheghja una cunnessione HTTP non sicura ! impiegatelu solu per una prova.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "Per sapene di più, <a href=\"%s\">lighjite sta rubrica di a FAQ</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "U vostru navigatore pò richiede una cunnessione HTTPS per permette l’usu di l’API WebCrypto. Pruvate di <a href=\"%s\">passà à HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "U vostru navigatore ùn accetta micca WebAssembly, impiegatu per a cumpressione zlib. Pudete creà ducumenti micca cumpressi, ma ùn pudete micca leghje quelli chì sò cumpressi.",
|
||||
"waiting on user to provide a password": "in attesa di l’utilizatore per furnisce una parolla d’intesa",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Ùn si pò micca dicifrà i dati. Avete stampittatu una parolla d’intesa incurretta ? Pruvate torna cù u buttone insù.",
|
||||
"Retry": "Pruvà torna",
|
||||
"Showing raw text…": "Affissera di u testu grossu…",
|
||||
"Notice:": "Avertimentu :",
|
||||
"This link will expire after %s.": "Stu liame hà da scade dopu à %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Stu liame pò esse accessu solu una volta, ùn impiegate micca i buttoni Precedente o Attualizà di u vostru navigatore.",
|
||||
"Link:": "Liame :",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "U destinatariu pò cunnnosce u vostru fusu orariu. Vulete cunvertisce l’ora in u furmatu UTC ?",
|
||||
"Use Current Timezone": "Impiegà u fusu orariu attuale",
|
||||
"Convert To UTC": "Cunvertisce in UTC",
|
||||
"Close": "Chjode",
|
||||
"Encrypted note on %s": "Nota cifrata nant’à %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitate stu liame per vede a nota. Date l’indirizzu à qualunque li permette d’accede à a nota dinù.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Un ammuzzatore d’indirizzu pò palisà a vostra chjave di dicifratura in l’indirizzu.",
|
||||
"Save paste": "Arregistrà l’appiccicu",
|
||||
"Your IP is not authorized to create pastes.": "U vostru indirizzu IP ùn hè micca auturizatu à creà l’appiccichi.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Pruvate d’ammuzzà un indirizzu web chì ùn punta micca versu a vostra instanza.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Sbagliu à a chjama di YOURLS. Seria forse una cunfigurazione gattiva, tale una \"apiurl\" o \"signature\" falsa o assente.",
|
||||
"Error parsing YOURLS response.": "Sbagliu durante l’analisa di a risposta di YOURLS."
|
||||
}
|
||||
94
i18n/cs.json
94
i18n/cs.json
@@ -6,7 +6,7 @@
|
||||
"en": "cs",
|
||||
"Paste does not exist, has expired or has been deleted.": "Vložený text neexistuje, expiroval nebo byl odstraněn.",
|
||||
"%s requires php %s or above to work. Sorry.": "%s vyžaduje php %s nebo vyšší. Lituji.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s vyžaduje, aby byla v konfiguračním souboru přítomna sekce [%s].",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Počet sekund do dalšího příspěvku: %d.",
|
||||
"Počet sekund do dalšího příspěvku: %d.",
|
||||
@@ -19,10 +19,10 @@
|
||||
"Error saving comment. Sorry.": "Chyba při ukládání komentáře.",
|
||||
"Error saving paste. Sorry.": "Chyba při ukládání příspěvku.",
|
||||
"Invalid paste ID.": "Chybně vložené ID.",
|
||||
"Paste is not of burn-after-reading type.": "Příspěvek není nastaven na smazaní po přečtení.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Chybný token pro odstranění. Příspěvek nebyl smazán.",
|
||||
"Paste was properly deleted.": "Příspěvek byl řádně smazán.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "Pro fungování %s je vyžadován JavaScript. Omlouváme se za nepříjemnosti.",
|
||||
"Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.",
|
||||
"Paste was properly deleted.": "Paste was properly deleted.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.",
|
||||
"%s requires a modern browser to work.": "%%s requires a modern browser to work.",
|
||||
"New": "Nový",
|
||||
"Send": "Odeslat",
|
||||
@@ -33,7 +33,7 @@
|
||||
"Open discussion": "Povolit komentáře",
|
||||
"Password (recommended)": "Heslo (doporučeno)",
|
||||
"Discussion": "Komentáře",
|
||||
"Toggle navigation": "Přepnout navigaci",
|
||||
"Toggle navigation": "Toggle navigation",
|
||||
"%d seconds": [
|
||||
"%d sekuda",
|
||||
"%d sekundy",
|
||||
@@ -77,7 +77,7 @@
|
||||
"%d years (3rd plural)"
|
||||
],
|
||||
"Never": "Nikdy",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Poznámka: Tato služba slouží k vyzkoušení: Data mohou být kdykoliv smazána. Při zneužití této služby zemřou koťátka.",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "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.": [
|
||||
"Tento dokument expiruje za %d sekundu.",
|
||||
"Tento dokument expiruje za %d sekundy.",
|
||||
@@ -109,19 +109,19 @@
|
||||
"Tento dokument expiruje za %d měsíců."
|
||||
],
|
||||
"Please enter the password for this paste:": "Zadejte prosím heslo:",
|
||||
"Could not decrypt data (Wrong key?)": "Nepodařilo se dešifrovat data (Špatný klíč?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Nepodařilo se odstranit příspěvek, nebyl uložen v režimu smazání po přečtení.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "POUZE PRO VAŠE OČI. Nezavírejte toto okno, tuto zprávu nelze znovu zobrazit.",
|
||||
"Could not decrypt comment; Wrong key?": "Nepodařilo se dešifrovat komentář; Špatný klíč?",
|
||||
"Reply": "Odpovědět",
|
||||
"Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.",
|
||||
"Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?",
|
||||
"Reply": "Reply",
|
||||
"Anonymous": "Anonym",
|
||||
"Avatar generated from IP address": "Avatar vygenerován z IP adresy",
|
||||
"Avatar generated from IP address": "Avatar generated from IP address",
|
||||
"Add comment": "Přidat komentář",
|
||||
"Optional nickname…": "Volitelný nickname…",
|
||||
"Post comment": "Odeslat komentář",
|
||||
"Sending comment…": "Odesílání komentáře…",
|
||||
"Comment posted.": "Komentář odeslán.",
|
||||
"Could not refresh display: %s": "Nepodařilo se obnovit zobrazení: %s",
|
||||
"Could not refresh display: %s": "Could not refresh display: %s",
|
||||
"unknown status": "neznámý stav",
|
||||
"server error or not responding": "Chyba na serveru nebo server neodpovídá",
|
||||
"Could not post comment: %s": "Nelze odeslat komentář: %s",
|
||||
@@ -145,49 +145,45 @@
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Stáhnout přílohu",
|
||||
"Cloned: '%s'": "Klonováno: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "Naklonovaný soubor '%s' byl připojen k tomuto příspěvku.",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Připojit soubor",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "alternativně přetáhněte soubor nebo vložte obrázek ze schránky",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
|
||||
"File too large, to display a preview. Please download the attachment.": "Soubor je příliš velký pro zobrazení náhledu. Stáhněte si přílohu.",
|
||||
"Remove attachment": "Odstranit přílohu",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Váš prohlížeč nepodporuje nahrávání šifrovaných souborů. Použijte modernější verzi prohlížeče.",
|
||||
"Invalid attachment.": "Chybná příloha.",
|
||||
"Options": "Volby",
|
||||
"Shorten URL": "Zkrátit URL",
|
||||
"Shorten URL": "Shorten URL",
|
||||
"Editor": "Editor",
|
||||
"Preview": "Náhled",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH skončil s \"%s\". Aktualizujte PATH ve vašem souboru index.php.",
|
||||
"Decrypt": "Dešifrovat",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
|
||||
"Decrypt": "Decrypt",
|
||||
"Enter password": "Zadejte heslo",
|
||||
"Loading…": "Načítání…",
|
||||
"Decrypting paste…": "Dešifruji příspěvek…",
|
||||
"Preparing new paste…": "Připravuji nový příspěvek…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "V případě, že tato zpráva nezmizí, se podívejte na <a href=\"%s\">tyto často kladené otázky pro řešení</a>.",
|
||||
"Loading…": "Loading…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.",
|
||||
"+++ no paste text +++": "+++ žádný vložený text +++",
|
||||
"Could not get paste data: %s": "Nepodařilo se získat data příspěvku: %s",
|
||||
"QR code": "QR kód",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "Tato stránka používá nezabezpečený připojení HTTP! Použijte ji prosím jen pro testování.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "Více informací naleznete <a href=\"%s\">v této položce FAQ</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Váš prohlížeč může vyžadovat připojení HTTPS pro podporu WebCrypto API. Zkuste <a href=\"%s\">přepnout na HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Váš prohlížeč nepodporuje WebAssembly, který se používá pro zlib kompresi. Můžete vytvořit nekomprimované dokumenty, ale nebudete moct číst ty komprimované.",
|
||||
"waiting on user to provide a password": "čekám na zadání hesla",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Nepodařilo se dešifrovat data. Zadali jste špatné heslo? Zkuste to znovu pomocí tlačítka nahoře.",
|
||||
"Retry": "Opakovat",
|
||||
"Showing raw text…": "Zobrazuji surový text…",
|
||||
"Notice:": "Upozornění:",
|
||||
"This link will expire after %s.": "Tento odkaz vyprší za %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Tento odkaz je přístupný pouze jednou, nepoužívejte tlačítko zpět ani neobnovujte tuto stránku ve vašem prohlížeči.",
|
||||
"Link:": "Odkaz:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Příjemce se může dozvědět o vašem časovém pásmu, převést čas na UTC?",
|
||||
"Use Current Timezone": "Použít aktuální časové pásmo",
|
||||
"Convert To UTC": "Převést na UTC",
|
||||
"Close": "Zavřít",
|
||||
"Encrypted note on %s": "Šifrovaná poznámka ve službě %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.",
|
||||
"Save paste": "Uložit příspěvek",
|
||||
"Your IP is not authorized to create pastes.": "Vaše IP adresa nemá oprávnění k vytvoření vložení.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Could not get paste data: %s": "Could not get paste data: %s",
|
||||
"QR code": "QR code",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "For more information <a href=\"%s\">see this FAQ entry</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
|
||||
"waiting on user to provide a password": "waiting on user to provide a password",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
|
||||
"Retry": "Retry",
|
||||
"Showing raw text…": "Showing raw text…",
|
||||
"Notice:": "Notice:",
|
||||
"This link will expire after %s.": "This link will expire after %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.",
|
||||
"Link:": "Link:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?",
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
16
i18n/de.json
16
i18n/de.json
@@ -175,19 +175,15 @@
|
||||
"Retry": "Wiederholen",
|
||||
"Showing raw text…": "Rohtext wird angezeigt…",
|
||||
"Notice:": "Hinweis:",
|
||||
"This link will expire after %s.": "Dieser Link wird am %s ablaufen.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Dieser Link kann nur einmal geöffnet werden, verwende nicht den Zurück- oder Neu-laden-Knopf Deines Browsers.",
|
||||
"Link:": "Link:",
|
||||
"This link will expire after %s.": "Diese Verknüpfung wird in %s ablaufen.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Diese Verknüpfung kann nur einmal geöffnet werden, verwende nicht den Zurück- oder Neu-laden-Knopf Deines Browsers.",
|
||||
"Link:": "Verknüpfung:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Der Empfänger könnte Deine Zeitzone erfahren, möchtest Du die Zeit in UTC umwandeln?",
|
||||
"Use Current Timezone": "Aktuelle Zeitzone verwenden",
|
||||
"Convert To UTC": "In UTC umwandeln",
|
||||
"Close": "Schliessen",
|
||||
"Encrypted note on %s": "Verschlüsselte Notiz auf %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besuche diesen Link um das Dokument zu sehen. Wird die URL an eine andere Person gegeben, so kann diese Person ebenfalls auf dieses Dokument zugreifen.",
|
||||
"Encrypted note on PrivateBin": "Verschlüsselte Notiz auf PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besuche diese Verknüpfung um das Dokument zu sehen. Wird die URL an eine andere Person gegeben, so kann diese Person ebenfalls auf dieses Dokument zugreifen.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Der URL-Verkürzer kann den Schlüssel in der URL enthüllen.",
|
||||
"Save paste": "Text speichern",
|
||||
"Your IP is not authorized to create pastes.": "Deine IP ist nicht berechtigt, Texte zu erstellen.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Versuch eine URL zu verkürzen, die nicht auf unsere Instanz zeigt.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Fehler beim Aufruf von YOURLS. Wahrscheinlich ein Konfigurationsproblem, wie eine falsche oder fehlende \"apiurl\" oder \"signature\".",
|
||||
"Error parsing YOURLS response.": "Fehler beim Verarbeiten der YOURLS-Antwort."
|
||||
"Save paste": "Text speichern"
|
||||
}
|
||||
|
||||
302
i18n/el.json
302
i18n/el.json
@@ -1,135 +1,135 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s είναι ένα λιτό, ανοικτού λογισμικού διαδικτυακής υπηρεσίας επικόλλησης όπου ο διακομιστής έχει πλήρη άγνια του περιεχομένου που επικολλήθηκαν. Τα Δεδομένα κρυπτογραφούνται και αποκρυπτογραφούνται %sστον φιλομετρητή (browser)%s χρησιμοποιόντας 256 bits AES.",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Περισσότερες πληροφορίες στον <a href=\"https://privatebin.info/\">ιστότοπο του εργαλείου</a>.",
|
||||
"Because ignorance is bliss": "Επειδή η άγνοια είναι ευτυχία",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "More information on the <a href=\"https://privatebin.info/\">project page</a>.",
|
||||
"Because ignorance is bliss": "Because ignorance is bliss",
|
||||
"en": "el",
|
||||
"Paste does not exist, has expired or has been deleted.": "Η επικόλληση δεν υπάρχει, έληξε ή διαγράφηκε",
|
||||
"%s requires php %s or above to work. Sorry.": "%s απαιτεί php %s ή νεότερη για να λειτουργήσει. Συγγνώμη.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s απαιτεί οι ρυθμίσεις [%s] να υπάρχουν στο αρχείο ρυθμίσεων.",
|
||||
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.",
|
||||
"%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Παρακαλώ περιμένετε %d δευτερόλεπτο μεταξύ κάθε επικόλλησης.",
|
||||
"Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης.",
|
||||
"Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης.",
|
||||
"Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης."
|
||||
"Please wait %d second between each post. (singular)",
|
||||
"Please wait %d seconds between each post. (1st plural)",
|
||||
"Please wait %d seconds between each post. (2nd plural)",
|
||||
"Please wait %d seconds between each post. (3rd plural)"
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "Η επικόλληση είναι περιορισμένη σε %s κρυπτογραφημένων δεδομένων.",
|
||||
"Invalid data.": "Λάθος δεδομένα.",
|
||||
"You are unlucky. Try again.": "Ατυχήσατε. Προσπαθήστε πάλι.",
|
||||
"Error saving comment. Sorry.": "Λάθος στην αποθήκευση του σχόλιου. Συγγνώμη.",
|
||||
"Error saving paste. Sorry.": "Λάθος στην αποθήκευση της επικόλλησης. Συγγνώμη.",
|
||||
"Invalid paste ID.": "Λάθος αναγνωριστικό επικόλλησης.",
|
||||
"Paste is not of burn-after-reading type.": "Η επικόληση δεν είναι τύπου καταστροφή-μετά-το-διάβασμα.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Λάθος αναγνωριστικό διαγραφής. Η επικόλληση δεν διαγράφηκε.",
|
||||
"Paste was properly deleted.": "Η επικόλληση διαγράφηκε επιτυχώς.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "Η JavaScript είναι απαραίτητη για να λειτουργήσει το %s. Συγγνώμη για την ταλαιπωρία.",
|
||||
"%s requires a modern browser to work.": "%s απαιτεί σύγχρονο φυλλομετρητή (browser) για να λειτουργήσει.",
|
||||
"New": "Νέο",
|
||||
"Send": "Αποστολή",
|
||||
"Clone": "Κλωνοποίηση",
|
||||
"Raw text": "Κείμενο",
|
||||
"Expires": "Λήγει",
|
||||
"Burn after reading": "Διαγραφή μετά την ανάγνωση",
|
||||
"Open discussion": "Ανοικτή συζήτηση",
|
||||
"Password (recommended)": "Κωδικός (προτείνεται)",
|
||||
"Discussion": "Συζήτηση",
|
||||
"Toggle navigation": "Εναλλαγή πλοήγησης",
|
||||
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.",
|
||||
"Invalid data.": "Invalid data.",
|
||||
"You are unlucky. Try again.": "You are unlucky. Try again.",
|
||||
"Error saving comment. Sorry.": "Error saving comment. Sorry.",
|
||||
"Error saving paste. Sorry.": "Error saving paste. Sorry.",
|
||||
"Invalid paste ID.": "Invalid paste ID.",
|
||||
"Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.",
|
||||
"Paste was properly deleted.": "Paste was properly deleted.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.",
|
||||
"%s requires a modern browser to work.": "%s requires a modern browser to work.",
|
||||
"New": "New",
|
||||
"Send": "Send",
|
||||
"Clone": "Clone",
|
||||
"Raw text": "Raw text",
|
||||
"Expires": "Expires",
|
||||
"Burn after reading": "Burn after reading",
|
||||
"Open discussion": "Open discussion",
|
||||
"Password (recommended)": "Password (recommended)",
|
||||
"Discussion": "Discussion",
|
||||
"Toggle navigation": "Toggle navigation",
|
||||
"%d seconds": [
|
||||
"%d δευτερόλεπτο",
|
||||
"%d δευτερόλεπτα",
|
||||
"%d δευτερόλεπτα",
|
||||
"%d δευτερόλεπτα"
|
||||
"%d second (singular)",
|
||||
"%d seconds (1st plural)",
|
||||
"%d seconds (2nd plural)",
|
||||
"%d seconds (3rd plural)"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d λεπτό",
|
||||
"%d λεπτά",
|
||||
"%d λεπτά",
|
||||
"%d λεπτά"
|
||||
"%d minute (singular)",
|
||||
"%d minutes (1st plural)",
|
||||
"%d minutes (2nd plural)",
|
||||
"%d minutes (3rd plural)"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d ώρα",
|
||||
"%d ώρες",
|
||||
"%d ώρες",
|
||||
"%d ώρες"
|
||||
"%d hour (singular)",
|
||||
"%d hours (1st plural)",
|
||||
"%d hours (2nd plural)",
|
||||
"%d hours (3rd plural)"
|
||||
],
|
||||
"%d days": [
|
||||
"%d ημέρα",
|
||||
"%d ημέρες",
|
||||
"%d ημέρες",
|
||||
"%d ημέρες"
|
||||
"%d day (singular)",
|
||||
"%d days (1st plural)",
|
||||
"%d days (2nd plural)",
|
||||
"%d days (3rd plural)"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d εβδομάδα",
|
||||
"%d εβδομάδες",
|
||||
"%d εβδομάδες",
|
||||
"%d εβδομάδες"
|
||||
"%d week (singular)",
|
||||
"%d weeks (1st plural)",
|
||||
"%d weeks (2nd plural)",
|
||||
"%d weeks (3rd plural)"
|
||||
],
|
||||
"%d months": [
|
||||
"%d μήνας",
|
||||
"%d μήνες",
|
||||
"%d μήνες",
|
||||
"%d μήνες"
|
||||
"%d month (singular)",
|
||||
"%d months (1st plural)",
|
||||
"%d months (2nd plural)",
|
||||
"%d months (3rd plural)"
|
||||
],
|
||||
"%d years": [
|
||||
"%d χρόνο",
|
||||
"%d χρόνια",
|
||||
"%d χρόνια",
|
||||
"%d χρόνια"
|
||||
"%d year (singular)",
|
||||
"%d years (1st plural)",
|
||||
"%d years (2nd plural)",
|
||||
"%d years (3rd plural)"
|
||||
],
|
||||
"Never": "Ποτέ",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Σημείωση: αυτή είναι μία δοκιμαστική υπηρεσία. Τα δεδομένα μπορεί να σβηστούν ανά πάσα στιγμή.",
|
||||
"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.": [
|
||||
"Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτο.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα."
|
||||
"This document will expire in %d second. (singular)",
|
||||
"This document will expire in %d seconds. (1st plural)",
|
||||
"This document will expire in %d seconds. (2nd plural)",
|
||||
"This document will expire in %d seconds. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"Αυτό το έγγραφο θα λήξει σε %d λεπτό.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d λεπτά.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d λεπτά.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d λεπτά."
|
||||
"This document will expire in %d minute. (singular)",
|
||||
"This document will expire in %d minutes. (1st plural)",
|
||||
"This document will expire in %d minutes. (2nd plural)",
|
||||
"This document will expire in %d minutes. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"Αυτό το έγγραφο θα λήξει σε %d ώρα.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d ώρες.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d ώρες.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d ώρες."
|
||||
"This document will expire in %d hour. (singular)",
|
||||
"This document will expire in %d hours. (1st plural)",
|
||||
"This document will expire in %d hours. (2nd plural)",
|
||||
"This document will expire in %d hours. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"Αυτό το έγγραφο θα λήξει σε %d ημέρα.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d ημέρες.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d ημέρες.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d ημέρες."
|
||||
"This document will expire in %d day. (singular)",
|
||||
"This document will expire in %d days. (1st plural)",
|
||||
"This document will expire in %d days. (2nd plural)",
|
||||
"This document will expire in %d days. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"Αυτό το έγγραφο θα λήξει σε %d μήνα.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d μήνες.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d μήνες.",
|
||||
"Αυτό το έγγραφο θα λήξει σε %d μήνες."
|
||||
"This document will expire in %d month. (singular)",
|
||||
"This document will expire in %d months. (1st plural)",
|
||||
"This document will expire in %d months. (2nd plural)",
|
||||
"This document will expire in %d months. (3rd plural)"
|
||||
],
|
||||
"Please enter the password for this paste:": "Παρακαλώ εισάγετε τον κωδικό για αυτή την επικόληση:",
|
||||
"Could not decrypt data (Wrong key?)": "Δεν ήταν δυνατή η αποκρυπτογράφηση των δεδομένων (πιθανώς λανθασμένο κλειδί;)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Δεν ήταν δυνατή η διαγραφή της επικόλλησης, δεν ήταν αποθηκευμένη σε μορφή διαγραφής μετά την ανάγνωση.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ΜΟΝΟ ΓΙΑ ΕΣΑΣ. Μην κλείσετε το αυτό το παράθυρο, αυτό το μήνυμα δεν μπορεί να εμφανιστεί ξανά.",
|
||||
"Could not decrypt comment; Wrong key?": "Δεν ήταν δυνατή η αποκρυπτογράφηση του σχολίου. Λάθος κλειδί;",
|
||||
"Reply": "Απάντηση",
|
||||
"Anonymous": "Ανώνυμος",
|
||||
"Avatar generated from IP address": "το avatar δημιουργήθηκε από τη διεύθυνση IP",
|
||||
"Add comment": "Σχολιάστε",
|
||||
"Optional nickname…": "Προαιρετικό ψευδώνυμο…",
|
||||
"Post comment": "Αποστολή σχολίου",
|
||||
"Sending comment…": "Το σχόλιο αποστέλλεται…",
|
||||
"Comment posted.": "Το σχόλιο δημοσιεύτηκε.",
|
||||
"Could not refresh display: %s": "Δεν ήταν δυνατή η ανανέωση της σελίδας: %s",
|
||||
"unknown status": "άγνωστη κατάσταση",
|
||||
"server error or not responding": "Πρόβλημα του διακομιστή ή δεν υπάρχει απάντηση",
|
||||
"Could not post comment: %s": "Δεν ήταν δυνατή η δημοσίευση του σχολίου: %s",
|
||||
"Sending paste…": "Η επικόλληση αποστέλλεται…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Η επικόλλησή σας είναι <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Πληκτρολογήστε [Ctrl]+[c] για αντιγραφή)</span>",
|
||||
"Delete data": "Διαγραφή δεδομένων",
|
||||
"Could not create paste: %s": "Δεν ήταν δυνατή η δημιουργία επικόλλησης: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Δεν ήταν δυνατή η αποκρυπτογράφηση της επικόλλησης: Το κλειδί αποκρυπτογράφησης λείπει από τον σύνδεσμο (Μήπως χρησιμοποιήσατε ανακατεύθυνση συνδέσμου ή υπηρεσία συντόμευσης συνδέσμου;)",
|
||||
"Please enter the password for this paste:": "Please enter the password for this paste:",
|
||||
"Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.",
|
||||
"Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?",
|
||||
"Reply": "Reply",
|
||||
"Anonymous": "Anonymous",
|
||||
"Avatar generated from IP address": "Avatar generated from IP address",
|
||||
"Add comment": "Add comment",
|
||||
"Optional nickname…": "Optional nickname…",
|
||||
"Post comment": "Post comment",
|
||||
"Sending comment…": "Sending comment…",
|
||||
"Comment posted.": "Comment posted.",
|
||||
"Could not refresh display: %s": "Could not refresh display: %s",
|
||||
"unknown status": "unknown status",
|
||||
"server error or not responding": "server error or not responding",
|
||||
"Could not post comment: %s": "Could not post comment: %s",
|
||||
"Sending paste…": "Sending paste…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>",
|
||||
"Delete data": "Delete data",
|
||||
"Could not create paste: %s": "Could not create paste: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
|
||||
"B": "B",
|
||||
"KiB": "KiB",
|
||||
"MiB": "MiB",
|
||||
@@ -139,55 +139,51 @@
|
||||
"EiB": "EiB",
|
||||
"ZiB": "ZiB",
|
||||
"YiB": "YiB",
|
||||
"Format": "Μορφοποίηση",
|
||||
"Plain Text": "Απλό κείμενο",
|
||||
"Source Code": "Πηγαίος Κώδικας",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Plain Text",
|
||||
"Source Code": "Source Code",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Λήψη επισυναπτόμενου",
|
||||
"Cloned: '%s'": "Κλώνος: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "Το κλωνοποιημένο αρχείο '%s' επισυνάφθηκε στ αυτή την επικόλληση.",
|
||||
"Attach a file": "Επισύναψη αρχείου",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "εναλλακτικά σύρετε το αρχείο ή επικολλήστε μία εικόνα από το clipboard",
|
||||
"File too large, to display a preview. Please download the attachment.": "Πολύ μεγάλο αρχείο για προεπισκόπηση. Παρακαλώ κατεβάστε το επισυναπτόμενο.",
|
||||
"Remove attachment": "Αφαίρεση επισυναπτόμενου",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Ο φυλλομετρητής (browser) σας δεν υποστηρίζει κρυπτογραφημένα αρχεία. Παρακαλώ χρησιμοποιήστε νεότερο φιλομετρητή.",
|
||||
"Invalid attachment.": "Λάθος επισυναπτόμενο.",
|
||||
"Options": "Επιλογές",
|
||||
"Shorten URL": "Συντόμευση σύνδεσμου",
|
||||
"Editor": "Διορθωτής",
|
||||
"Preview": "Προεπισκόπηση",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s απαιτεί το PATH να τελειώνει σε \"%s\". Παρακαλώ ενημερώστε το PATH στο index.php σας.",
|
||||
"Decrypt": "Αποκρυπτογράφηση",
|
||||
"Enter password": "Εισαγωγή κωδικού",
|
||||
"Loading…": "Φόρτωση…",
|
||||
"Decrypting paste…": "Η επικόλληση αποκρυπτογραφείται…",
|
||||
"Preparing new paste…": "Προετοιμασία νέας επικόλλησης…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "Σε περίπτωση που αυτό το μήνυμα δεν εξαφανίζεται παρακαλώ κοιτάξτε στις <a href=\"%s\">Ερωταποκρίσεις για πληροφορίες στην αντιμετώπιση προβλημάτων</a>.",
|
||||
"+++ no paste text +++": "+++ Δεν υπάρχει επικόλληση +++",
|
||||
"Could not get paste data: %s": "Δεν ήταν δυνατή η λήψη της επικόλλησης: %s",
|
||||
"QR code": "QR εικονοστοιχειοσειρά",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "Αυτός ο ιστότοπος χρησιμοποιεί μη ασφαλή HTTP σύνδεση! Παρακαλώ χρησιμοποιήστε το μόνο δοκιμαστικά.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "Για περισσότερες πληροφορίες <a href=\"%s\">δείτε τις ερωταπαντήσεις</a>.",
|
||||
"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 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": "Αναμονή ο χρήστης να δώσει τον κωδικό",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Δεν ήταν δυνατή η αποκρυπτογράφηση των δεδομένων. Μήπως εισάγατε λάθος κωδικό; Προσπαθήστε με το κουμπί στο επάνω μέρος.",
|
||||
"Retry": "Επαναπροσπάθεια",
|
||||
"Showing raw text…": "Προβολή κειμένου…",
|
||||
"Notice:": "Επισήμανση:",
|
||||
"This link will expire after %s.": "Ο σύνδεσμος θα λήξει σε %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Αυτός ο σύνδεσμος μπορεί να προσπελαστεί μόνο μία φορά, μην χρησιμοποιήσετε το κουμπί επιστροφή ή ανανέωση στον φυλλομετρητή σας.",
|
||||
"Link:": "Σύνδεσμος:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Ο παραλήπτης μπορεί να αναγνωρίσει τη ζώνη ώρας σας, θέλετε μετατροπή της ώρας σε UTC;",
|
||||
"Use Current Timezone": "Χρήση τρέχουσας ζώνης ώρας",
|
||||
"Convert To UTC": "Μετατροπή σε UTC",
|
||||
"Close": "Κλείσιμο",
|
||||
"Encrypted note on %s": "Κρυπτογραφημένο μήνυμα από το %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφτείτε αυτόν τον σύνδεσμο για να δείτε το μήνυμα. Δίνοντας τον σύνδεσμο σε οποιονδήποτε, του επιτρέπετε να επισκεφτεί το μήνυμα επίσης.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Συντομευτές συνδέσμων πιθανώς να δημοσιοποιήσουν το κλειδί αποκρυπτογράφισης στον σύνδεσμο.",
|
||||
"Save paste": "Αποθήκευση επικόλλησης",
|
||||
"Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Download attachment": "Download attachment",
|
||||
"Cloned: '%s'": "Cloned: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Attach a file",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
|
||||
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
|
||||
"Remove attachment": "Remove attachment",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.",
|
||||
"Invalid attachment.": "Invalid attachment.",
|
||||
"Options": "Options",
|
||||
"Shorten URL": "Shorten URL",
|
||||
"Editor": "Editor",
|
||||
"Preview": "Preview",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
|
||||
"Decrypt": "Decrypt",
|
||||
"Enter password": "Enter password",
|
||||
"Loading…": "Loading…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.",
|
||||
"+++ no paste text +++": "+++ no paste text +++",
|
||||
"Could not get paste data: %s": "Could not get paste data: %s",
|
||||
"QR code": "QR code",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "For more information <a href=\"%s\">see this FAQ entry</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
|
||||
"waiting on user to provide a password": "waiting on user to provide a password",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
|
||||
"Retry": "Retry",
|
||||
"Showing raw text…": "Showing raw text…",
|
||||
"Notice:": "Notice:",
|
||||
"This link will expire after %s.": "This link will expire after %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.",
|
||||
"Link:": "Link:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?",
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
10
i18n/es.json
10
i18n/es.json
@@ -2,7 +2,7 @@
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s es un \"pastebin\" en línea minimalista de código abierto, donde el servidor no tiene ningún conocimiento de los datos guardados. Los datos son cifrados/descifrados %sen el navegador%s usando 256 bits AES.",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Más información en la <a href=\"https://privatebin.info/\">página del proyecto</a>.",
|
||||
"Because ignorance is bliss": "Porque la ignorancia es felicidad",
|
||||
"Because ignorance is bliss": "Porque la ignorancia es dicha",
|
||||
"en": "es",
|
||||
"Paste does not exist, has expired or has been deleted.": "El \"paste\" no existe, ha caducado o ha sido eliminado.",
|
||||
"%s requires php %s or above to work. Sorry.": "%s requiere php %s o superior para funcionar. Lo siento.",
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Usar Zona Horaria Actual",
|
||||
"Convert To UTC": "Convertir A UTC",
|
||||
"Close": "Cerrar",
|
||||
"Encrypted note on %s": "Nota cifrada en %s",
|
||||
"Encrypted note on PrivateBin": "Nota cifrada en PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite este enlace para ver la nota. Dar la URL a cualquier persona también les permite acceder a la nota.",
|
||||
"URL shortener may expose your decrypt key in URL.": "El acortador de URL puede exponer su clave de descifrado en el URL.",
|
||||
"Save paste": "Guardar \"paste\"",
|
||||
"Your IP is not authorized to create pastes.": "Tu IP no está autorizada para crear contenido.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Guardar \"paste\""
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Kasuta praegust ajavööndit",
|
||||
"Convert To UTC": "Teisenda UTC-ks",
|
||||
"Close": "Sulge",
|
||||
"Encrypted note on %s": "Krüpteeritud kiri %s-is",
|
||||
"Encrypted note on PrivateBin": "Krüpteeritud kiri PrivateBin-is",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kirja nägemiseks külasta seda linki. Teistele URL-i andmine lubab ka neil ligi pääseda kirjale.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL-i lühendaja võib paljastada sinu dekrüpteerimisvõtme URL-is.",
|
||||
"Save paste": "Salvesta kleebe",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Salvesta kleebe"
|
||||
}
|
||||
|
||||
193
i18n/fi.json
193
i18n/fi.json
@@ -1,193 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s on minimalistinen, avoimen lähdekoodin online pastebin jossa palvelimella ei ole tietoa syötetystä datasta. Data salataan/puretaan %sselaimessa%s käyttäen 256-bittistä AES:ää.",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Enemmän tietoa <a href=\"https://privatebin.info/\">projektisivulla</a>.",
|
||||
"Because ignorance is bliss": "Koska tieto lisää tuskaa",
|
||||
"en": "fi",
|
||||
"Paste does not exist, has expired or has been deleted.": "Pastea ei ole olemassa, se on vanhentunut, tai se on poistettu.",
|
||||
"%s requires php %s or above to work. Sorry.": "%s tarvitsee php %s-versiota tai uudempaa toimiakseen. Anteeksi.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s vaatii konfiguraatio-osion [%s] olevan läsnä konfiguraatiotiedostossa.",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Odotathan %d sekuntin jokaisen lähetyksen välillä.",
|
||||
"Odotathan %d sekuntia jokaisen lähetyksen välillä.",
|
||||
"Odotathan %d sekuntia jokaisen lähetyksen välillä.",
|
||||
"Odotathan %d sekuntia jokaisen lähetyksen välillä."
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "Paste on rajoitettu kokoon %s salattua dataa.",
|
||||
"Invalid data.": "Virheellinen data.",
|
||||
"You are unlucky. Try again.": "Olet epäonnekas. Yritä uudelleen.",
|
||||
"Error saving comment. Sorry.": "Virhe kommenttia tallentaessa. Anteeksi.",
|
||||
"Error saving paste. Sorry.": "Virhe pastea tallentaessa. Anteeksi.",
|
||||
"Invalid paste ID.": "Virheellinen paste ID.",
|
||||
"Paste is not of burn-after-reading type.": "Paste ei ole polta-lukemisen-jälkeen-tyyppiä.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Virheellinen poistotunniste. Pastea ei poistettu.",
|
||||
"Paste was properly deleted.": "Paste poistettiin kunnolla.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScriptiä tarvitaan jotta %s toimisi. Anteeksi haitasta.",
|
||||
"%s requires a modern browser to work.": "%s tarvitsee modernia selainta toimiakseen.",
|
||||
"New": "Uusi",
|
||||
"Send": "Lähetä",
|
||||
"Clone": "Kloonaa",
|
||||
"Raw text": "Raaka teksti",
|
||||
"Expires": "Vanhenee",
|
||||
"Burn after reading": "Polta lukemisen jälkeen",
|
||||
"Open discussion": "Avaa keskustelu",
|
||||
"Password (recommended)": "Salasana (suositeltu)",
|
||||
"Discussion": "Keskustelu",
|
||||
"Toggle navigation": "Navigointi päällä/pois",
|
||||
"%d seconds": [
|
||||
"%d sekunti",
|
||||
"%d sekuntia",
|
||||
"%d sekuntia",
|
||||
"%d sekuntia"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d minuutti",
|
||||
"%d minuuttia",
|
||||
"%d minuuttia",
|
||||
"%d minuuttia"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d tunti",
|
||||
"%d tuntia",
|
||||
"%d tuntia",
|
||||
"%d tuntia"
|
||||
],
|
||||
"%d days": [
|
||||
"%d päivä",
|
||||
"%d päivää",
|
||||
"%d päivää",
|
||||
"%d päivää"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d viikko",
|
||||
"%d viikkoa",
|
||||
"%d viikkoa",
|
||||
"%d viikkoa"
|
||||
],
|
||||
"%d months": [
|
||||
"%d kuukausi",
|
||||
"%d kuukautta",
|
||||
"%d kuukautta",
|
||||
"%d kuukautta"
|
||||
],
|
||||
"%d years": [
|
||||
"%d vuosi",
|
||||
"%d vuotta",
|
||||
"%d vuotta",
|
||||
"%d vuotta"
|
||||
],
|
||||
"Never": "Ei koskaan",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Huomaa: Tämä on testipalvelu: Data voidaan poistaa milloin tahansa. Kissanpennut kuolevat jos väärinkäytät tätä palvelua.",
|
||||
"This document will expire in %d seconds.": [
|
||||
"Tämä dokumentti vanhenee %d sekuntissa.",
|
||||
"Tämä dokumentti vanhenee %d sekunnissa.",
|
||||
"Tämä dokumentti vanhenee %d sekunnissa.",
|
||||
"Tämä dokumentti vanhenee %d sekunnissa."
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"Tämä dokumentti vanhenee %d minuutissa.",
|
||||
"Tämä dokumentti vanhenee %d minuutissa.",
|
||||
"Tämä dokumentti vanhenee %d minuutissa.",
|
||||
"Tämä dokumentti vanhenee %d minuutissa."
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"Tämä dokumentti vanhenee %d tunnissa.",
|
||||
"Tämä dokumentti vanhenee %d tunnissa.",
|
||||
"Tämä dokumentti vanhenee %d tunnissa.",
|
||||
"Tämä dokumentti vanhenee %d tunnissa."
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"Tämä dokumentti vanhenee %d päivässä.",
|
||||
"Tämä dokumentti vanhenee %d päivässä.",
|
||||
"Tämä dokumentti vanhenee %d päivässä.",
|
||||
"Tämä dokumentti vanhenee %d päivässä."
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"Tämä dokumentti vanhenee %d kuukaudessa.",
|
||||
"Tämä dokumentti vanhenee %d kuukaudessa.",
|
||||
"Tämä dokumentti vanhenee %d kuukaudessa.",
|
||||
"Tämä dokumentti vanhenee %d kuukaudessa."
|
||||
],
|
||||
"Please enter the password for this paste:": "Syötä salasana tälle pastelle:",
|
||||
"Could not decrypt data (Wrong key?)": "Dataa ei voitu purkaa (Väärä avain?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Pastea ei voitu poistaa, sitä ei säilytetty \"Polta lukemisen jälkeen\" -tilassa.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "VAIN SINUN SILMILLESI. Älä sulje tätä ikkunaa, tätä viestiä ei voida näyttää uudelleen.",
|
||||
"Could not decrypt comment; Wrong key?": "Kommenttia ei voitu purkaa; väärä avain?",
|
||||
"Reply": "Vastaa",
|
||||
"Anonymous": "Anonyymi",
|
||||
"Avatar generated from IP address": "Avatar generoitu IP-osoitteesta",
|
||||
"Add comment": "Lisää kommentti",
|
||||
"Optional nickname…": "Valinnainen nimimerkki…",
|
||||
"Post comment": "Lähetä kommentti",
|
||||
"Sending comment…": "Lähetetään kommenttia…",
|
||||
"Comment posted.": "Kommentti lähetetty.",
|
||||
"Could not refresh display: %s": "Näyttöä ei voitu päivittää: %s",
|
||||
"unknown status": "tuntematon status",
|
||||
"server error or not responding": "palvelinvirhe tai palvelin ei vastaa",
|
||||
"Could not post comment: %s": "Kommenttia ei voitu lähettää: %s",
|
||||
"Sending paste…": "Lähetetään pastea…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Pastesi on <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Paina [Ctrl]+[c] kopioidaksesi)</span>",
|
||||
"Delete data": "Poista data",
|
||||
"Could not create paste: %s": "Pastea ei voitu luoda: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Pastea ei voitu purkaa: Purkausavain puuttuu URL:stä (Käytitkö uudelleenohjaajaa tai URL-lyhentäjää joka poistaa osan URL:stä?)",
|
||||
"B": "B",
|
||||
"KiB": "KiB",
|
||||
"MiB": "MiB",
|
||||
"GiB": "GiB",
|
||||
"TiB": "TiB",
|
||||
"PiB": "PiB",
|
||||
"EiB": "EiB",
|
||||
"ZiB": "ZiB",
|
||||
"YiB": "YiB",
|
||||
"Format": "Formaatti",
|
||||
"Plain Text": "Perusteksti",
|
||||
"Source Code": "Lähdekoodi",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Lataa liite",
|
||||
"Cloned: '%s'": "Kloonattu: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "Kloonattu tiedosto '%s' liitettiin tähän pasteen",
|
||||
"Attach a file": "Liitä tiedosto",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "vaihtoehtoisesti vedä & pudota tiedosto tai liitä kuva leikepöydältä",
|
||||
"File too large, to display a preview. Please download the attachment.": "Tiedosto on liian iso esikatselun näyttämiseksi. Lataathan liitteen.",
|
||||
"Remove attachment": "Poista liite",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Selaimesi ei tue salattujen tiedostojen lataamista. Käytäthän uudempaa selainta.",
|
||||
"Invalid attachment.": "Virheellinen liite.",
|
||||
"Options": "Asetukset",
|
||||
"Shorten URL": "Lyhennä URL",
|
||||
"Editor": "Muokkaaja",
|
||||
"Preview": "Esikatselu",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vaatii PATH:in loppuvan \"%s\"-merkkiin. Päivitäthän PATH:in index.php:ssäsi.",
|
||||
"Decrypt": "Pura",
|
||||
"Enter password": "Syötä salasana",
|
||||
"Loading…": "Ladataan…",
|
||||
"Decrypting paste…": "Puretaan pastea…",
|
||||
"Preparing new paste…": "Valmistellaan uutta pastea",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "Jos tämä viesti ei katoa koskaan, katsothan <a href=\"%s\">tämän FAQ:n ongelmanratkaisutiedon löytämiseksi</a>.",
|
||||
"+++ no paste text +++": "+++ ei paste-tekstiä +++",
|
||||
"Could not get paste data: %s": "Paste-tietoja ei löydetty: %s",
|
||||
"QR code": "QR-koodi",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "Tämä sivusto käyttää epäturvallista HTTP-yhteyttä! Käytäthän sitä vain testaukseen.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "Lisätietoja varten <a href=\"%s\">lue tämä FAQ-kohta</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Selaimesi ehkä tarvitsee HTTPS-yhteyden tukeakseen WebCrypto API:a. Yritä <a href=\"%s\">vaihtamista HTTPS:ään</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Selaimesi ei tue WebAssemblyä jota käytetään zlib-pakkaamiseen. Voit luoda pakkaamattomia dokumentteja, mutta et voi lukea pakattuja dokumentteja.",
|
||||
"waiting on user to provide a password": "odotetaan käyttäjän antavan salasanan",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Dataa ei voitu purkaa. Syötitkö väärän salasanan? Yritä uudelleen ylhäällä olevalla painikkeella.",
|
||||
"Retry": "Yritä uudelleen",
|
||||
"Showing raw text…": "Näytetään raaka reksti…",
|
||||
"Notice:": "Huomautus:",
|
||||
"This link will expire after %s.": "Tämä linkki vanhenee ajan %s jälkeen.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Tätä linkkiä voidaan käyttää vain kerran, älä käytä taaksepäin- tai päivityspainiketta selaimessasi.",
|
||||
"Link:": "Linkki:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Vastaanottaja saattaa tulla tietoiseksi aikavyöhykkeestäsi, muutetaanko aika UTC:ksi?",
|
||||
"Use Current Timezone": "Käytä nykyistä aikavyöhykettä",
|
||||
"Convert To UTC": "Muuta UTC:ksi",
|
||||
"Close": "Sulje",
|
||||
"Encrypted note on %s": "Salattu viesti %sissä",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Käy tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomeen viestiä. ",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.",
|
||||
"Save paste": "Tallenna paste",
|
||||
"Your IP is not authorized to create pastes.": "IP:llesi ei ole annettu oikeutta luoda pasteja.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
}
|
||||
10
i18n/fr.json
10
i18n/fr.json
@@ -2,7 +2,7 @@
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s est un 'pastebin' (ou gestionnaire d'extraits de texte et de code source) minimaliste et open source, dans lequel le serveur n'a aucune connaissance des données envoyées. Les données sont chiffrées/déchiffrées %sdans le navigateur%s par un chiffrement AES 256 bits.",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Plus d'informations sur <a href=\"https://privatebin.info/\">la page du projet</a>.",
|
||||
"Because ignorance is bliss": "Vivons heureux, vivons cachés",
|
||||
"Because ignorance is bliss": "Parce que l'ignorance c'est le bonheur",
|
||||
"en": "fr",
|
||||
"Paste does not exist, has expired or has been deleted.": "Le paste n'existe pas, a expiré, ou a été supprimé.",
|
||||
"%s requires php %s or above to work. Sorry.": "Désolé, %s nécessite php %s ou supérieur pour fonctionner.",
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Conserver l'actuel",
|
||||
"Convert To UTC": "Convertir en UTC",
|
||||
"Close": "Fermer",
|
||||
"Encrypted note on %s": "Message chiffré sur %s",
|
||||
"Encrypted note on PrivateBin": "Message chiffré sur PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visiter ce lien pour voir la note. Donner l'URL à une autre personne lui permet également d'accéder à la note.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.",
|
||||
"Save paste": "Sauver le paste",
|
||||
"Your IP is not authorized to create pastes.": "Votre adresse IP n'est pas autorisée à créer des pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Sauver le paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "להשתמש באזור הזמן הנוכחי",
|
||||
"Convert To UTC": "המרה ל־UTC",
|
||||
"Close": "סגירה",
|
||||
"Encrypted note on %s": "%sהערה מוצפנת ב־",
|
||||
"Encrypted note on PrivateBin": "הערה מוצפנת ב־PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "נא לבקר בקישור כדי לצפות בהערה. מסירת הקישור לאנשים כלשהם תאפשר גם להם לגשת להערה.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Az aktuális időzóna használata",
|
||||
"Convert To UTC": "Átalakítás UTC időzónára",
|
||||
"Close": "Bezárás",
|
||||
"Encrypted note on %s": "Titkosított jegyzet a %s",
|
||||
"Encrypted note on PrivateBin": "Titkosított jegyzet a PrivateBinen",
|
||||
"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.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Gunakan Zonawaktu Saat Ini",
|
||||
"Convert To UTC": "Konversi Ke UTC",
|
||||
"Close": "Tutup",
|
||||
"Encrypted note on %s": "Catatan ter-ekrip di %s",
|
||||
"Encrypted note on PrivateBin": "Catatan ter-ekrip di PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kunjungi tautan ini untuk melihat catatan. Memberikan alamat URL pada siapapun juga, akan mengizinkan mereka untuk mengakses catatan, so pasti gitu loh Kaka.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Pemendek URL mungkin akan menampakkan kunci dekrip Anda dalam URL.",
|
||||
"Save paste": "Simpan paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Simpan paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Usa Fuso Orario Corrente",
|
||||
"Convert To UTC": "Converti a UTC",
|
||||
"Close": "Chiudi",
|
||||
"Encrypted note on %s": "Nota crittografata su %s",
|
||||
"Encrypted note on PrivateBin": "Nota crittografata su PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visita questo collegamento per vedere la nota. Dare l'URL a chiunque consente anche a loro di accedere alla nota.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener può esporre la tua chiave decrittografata nell'URL.",
|
||||
"Save paste": "Salva il messagio",
|
||||
"Your IP is not authorized to create pastes.": "Il tuo IP non è autorizzato a creare dei messaggi.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Salva il messagio"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
193
i18n/jbo.json
193
i18n/jbo.json
@@ -1,193 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "sivlolnitvanku'a",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": ".i la %s mupli lo sorcu lo'e se setca kibro .i ji'a zo'e se zancari gi'e fingubni .i lo samse'u na djuno lo datni selru'e cu .i ba'e %sle brauzero%s ku mipri le do datni ku fi la'oi AES poi bitni li 256",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "More information on the <a href=\"https://privatebin.info/\">project page</a>.",
|
||||
"Because ignorance is bliss": ".i ki'u le ka na djuno cu ka saxfri",
|
||||
"en": "jbo",
|
||||
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.",
|
||||
"%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Please wait %d second between each post. (singular)",
|
||||
"Please wait %d seconds between each post. (1st plural)",
|
||||
"Please wait %d seconds between each post. (2nd plural)",
|
||||
"Please wait %d seconds between each post. (3rd plural)"
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.",
|
||||
"Invalid data.": ".i le selru'e cu na drani",
|
||||
"You are unlucky. Try again.": "You are unlucky. Try again.",
|
||||
"Error saving comment. Sorry.": "Error saving comment. Sorry.",
|
||||
"Error saving paste. Sorry.": "Error saving paste. Sorry.",
|
||||
"Invalid paste ID.": "Invalid paste ID.",
|
||||
"Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.",
|
||||
"Paste was properly deleted.": "Paste was properly deleted.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.",
|
||||
"%s requires a modern browser to work.": "%s requires a modern browser to work.",
|
||||
"New": "cnino",
|
||||
"Send": "benji",
|
||||
"Clone": "fukpi",
|
||||
"Raw text": "vlapoi nalselrucyzu'e",
|
||||
"Expires": "vimcu",
|
||||
"Burn after reading": "vimcu ba la tcidu",
|
||||
"Open discussion": "lo zbasu cu casnu",
|
||||
"Password (recommended)": "japyvla (nelti'i)",
|
||||
"Discussion": "casnu",
|
||||
"Toggle navigation": "Toggle navigation",
|
||||
"%d seconds": [
|
||||
"%d second (singular)",
|
||||
"%d seconds (1st plural)",
|
||||
"%d seconds (2nd plural)",
|
||||
"%d seconds (3rd plural)"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d minute (singular)",
|
||||
"%d minutes (1st plural)",
|
||||
"%d minutes (2nd plural)",
|
||||
"%d minutes (3rd plural)"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d hour (singular)",
|
||||
"%d hours (1st plural)",
|
||||
"%d hours (2nd plural)",
|
||||
"%d hours (3rd plural)"
|
||||
],
|
||||
"%d days": [
|
||||
"%d day (singular)",
|
||||
"%d days (1st plural)",
|
||||
"%d days (2nd plural)",
|
||||
"%d days (3rd plural)"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d week (singular)",
|
||||
"%d weeks (1st plural)",
|
||||
"%d weeks (2nd plural)",
|
||||
"%d weeks (3rd plural)"
|
||||
],
|
||||
"%d months": [
|
||||
"%d month (singular)",
|
||||
"%d months (1st plural)",
|
||||
"%d months (2nd plural)",
|
||||
"%d months (3rd plural)"
|
||||
],
|
||||
"%d years": [
|
||||
"%d year (singular)",
|
||||
"%d years (1st plural)",
|
||||
"%d years (2nd plural)",
|
||||
"%d years (3rd plural)"
|
||||
],
|
||||
"Never": "Never",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.",
|
||||
"This document will expire in %d seconds.": [
|
||||
"This document will expire in %d second. (singular)",
|
||||
"This document will expire in %d seconds. (1st plural)",
|
||||
"This document will expire in %d seconds. (2nd plural)",
|
||||
"This document will expire in %d seconds. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"This document will expire in %d minute. (singular)",
|
||||
"This document will expire in %d minutes. (1st plural)",
|
||||
"This document will expire in %d minutes. (2nd plural)",
|
||||
"This document will expire in %d minutes. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"This document will expire in %d hour. (singular)",
|
||||
"This document will expire in %d hours. (1st plural)",
|
||||
"This document will expire in %d hours. (2nd plural)",
|
||||
"This document will expire in %d hours. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"This document will expire in %d day. (singular)",
|
||||
"This document will expire in %d days. (1st plural)",
|
||||
"This document will expire in %d days. (2nd plural)",
|
||||
"This document will expire in %d days. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"This document will expire in %d month. (singular)",
|
||||
"This document will expire in %d months. (1st plural)",
|
||||
"This document will expire in %d months. (2nd plural)",
|
||||
"This document will expire in %d months. (3rd plural)"
|
||||
],
|
||||
"Please enter the password for this paste:": "Please enter the password for this paste:",
|
||||
"Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.",
|
||||
"Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?",
|
||||
"Reply": "Reply",
|
||||
"Anonymous": "Anonymous",
|
||||
"Avatar generated from IP address": "Avatar generated from IP address",
|
||||
"Add comment": "Add comment",
|
||||
"Optional nickname…": "Optional nickname…",
|
||||
"Post comment": "Post comment",
|
||||
"Sending comment…": "Sending comment…",
|
||||
"Comment posted.": "Comment posted.",
|
||||
"Could not refresh display: %s": "Could not refresh display: %s",
|
||||
"unknown status": "unknown status",
|
||||
"server error or not responding": "server error or not responding",
|
||||
"Could not post comment: %s": "Could not post comment: %s",
|
||||
"Sending paste…": "Sending paste…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>",
|
||||
"Delete data": "Delete data",
|
||||
"Could not create paste: %s": "Could not create paste: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
|
||||
"B": "B",
|
||||
"KiB": "KiB",
|
||||
"MiB": "MiB",
|
||||
"GiB": "GiB",
|
||||
"TiB": "TiB",
|
||||
"PiB": "PiB",
|
||||
"EiB": "EiB",
|
||||
"ZiB": "ZiB",
|
||||
"YiB": "YiB",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Plain Text",
|
||||
"Source Code": "Source Code",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Download attachment",
|
||||
"Cloned: '%s'": "Cloned: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Attach a file",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
|
||||
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
|
||||
"Remove attachment": "Remove attachment",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.",
|
||||
"Invalid attachment.": "Invalid attachment.",
|
||||
"Options": "Options",
|
||||
"Shorten URL": "Shorten URL",
|
||||
"Editor": "Editor",
|
||||
"Preview": "Preview",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
|
||||
"Decrypt": "Decrypt",
|
||||
"Enter password": "Enter password",
|
||||
"Loading…": "Loading…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.",
|
||||
"+++ no paste text +++": "+++ no paste text +++",
|
||||
"Could not get paste data: %s": "Could not get paste data: %s",
|
||||
"QR code": "ky.bu ry termifra",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "For more information <a href=\"%s\">see this FAQ entry</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
|
||||
"waiting on user to provide a password": "waiting on user to provide a password",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
|
||||
"Retry": "refcfa",
|
||||
"Showing raw text…": "Showing raw text…",
|
||||
"Notice:": "Notice:",
|
||||
"This link will expire after %s.": "This link will expire after %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.",
|
||||
"Link:": "urli:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?",
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "galfi lo cabni la utc",
|
||||
"Close": "ganlo",
|
||||
"Encrypted note on %s": ".i lo lo notci ku mifra cu zvati %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "rejgau fukpi",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
}
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -89,7 +89,6 @@
|
||||
"ku": ["Kurdî", "Kurdish"],
|
||||
"kj": ["Kuanyama", "Kwanyama"],
|
||||
"la": ["lingua latina", "Latin"],
|
||||
"jbo":["jbobau", "Lojban"],
|
||||
"lb": ["Lëtzebuergesch", "Luxembourgish"],
|
||||
"lg": ["Luganda", "Ganda"],
|
||||
"li": ["Limburgs", "Limburgish"],
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Naudoti esamą laiko juostą",
|
||||
"Convert To UTC": "Konvertuoti į UTC",
|
||||
"Close": "Užverti",
|
||||
"Encrypted note on %s": "Šifruoti užrašai ties %s",
|
||||
"Encrypted note on PrivateBin": "Šifruoti užrašai ties PrivateBin",
|
||||
"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ą.",
|
||||
"Save paste": "Įrašyti įdėjimą",
|
||||
"Your IP is not authorized to create pastes.": "Jūsų IP adresas neturi įgaliojimų kurti įdėjimų.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
56
i18n/nl.json
56
i18n/nl.json
@@ -35,7 +35,7 @@
|
||||
"Discussion": "Discussie",
|
||||
"Toggle navigation": "Navigatie openen/sluiten",
|
||||
"%d seconds": [
|
||||
"%d seconde",
|
||||
"%d second",
|
||||
"%d seconden",
|
||||
"%d seconds (2nd plural)",
|
||||
"%d seconds (3rd plural)"
|
||||
@@ -72,14 +72,14 @@
|
||||
],
|
||||
"%d years": [
|
||||
"%d jaar",
|
||||
"%d jaren",
|
||||
"%d jaaren",
|
||||
"%d years (2nd plural)",
|
||||
"%d years (3rd plural)"
|
||||
],
|
||||
"Never": "Nooit",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Opmerking: Dit is een testservice: Gegevens kunnen op elk gegeven moment verwijderd worden.",
|
||||
"This document will expire in %d seconds.": [
|
||||
"Dit document verloopt over %d seconde.",
|
||||
"Dit document verloopt over %d second.",
|
||||
"Dit document verloopt over %d seconden.",
|
||||
"Dit document verloopt over %d seconden.",
|
||||
"Dit document verloopt over %d seconden."
|
||||
@@ -108,7 +108,7 @@
|
||||
"Dit document verloopt over %d maanden.",
|
||||
"Dit document verloopt over %d maanden."
|
||||
],
|
||||
"Please enter the password for this paste:": "Voer het wachtwoord in voor deze geplakte tekst:",
|
||||
"Please enter the password for this paste:": "Voer het wachtwoord in voor deze geplakte tekst:",
|
||||
"Could not decrypt data (Wrong key?)": "Kon de gegevens niet decoderen (verkeerde sleutel?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Verwijderen van de geplakte tekst niet mogelijk, deze werd niet opgeslagen in 'vernietig na lezen' modus.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Sluit dit venster niet, dit bericht kan niet opnieuw worden weergegeven.",
|
||||
@@ -129,7 +129,7 @@
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Uw geplakte tekst is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Druk [Ctrl]+[c] om te kopiëren)</span>",
|
||||
"Delete data": "Gegevens wissen",
|
||||
"Could not create paste: %s": "Kon de geplakte tekst niet aanmaken: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Kon de geplakte tekst niet decoderen: Decoderingssleutel ontbreekt in URL (Hebt u een redirector of een URL-verkorter gebruikt die een deel van de URL verwijdert?)",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Kon de geplakte tekst niet decoderen: Decoderingssleutel ontbreekt in URL (Hebt u een redirector of een URL-verkorter gebruikt die een deel van de URL verwijdert?)",
|
||||
"B": "B",
|
||||
"KiB": "KiB",
|
||||
"MiB": "MiB",
|
||||
@@ -164,30 +164,26 @@
|
||||
"Preparing new paste…": "Nieuwe geplakte tekst voorbereiden…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "In het geval dat dit bericht nooit verdwijnt, kijkt u dan eens naar <a href=\"%s\"> veelgestelde vragen voor informatie over het oplossen van problemen </a>.",
|
||||
"+++ no paste text +++": "+++ geen geplakte tekst +++",
|
||||
"Could not get paste data: %s": "Kon geen klembordgegevens verkrijgen: %s",
|
||||
"QR code": "QR-code",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "Deze website gebruikt een onveilige HTTP-verbinding! Gelieve deze enkel te gebruiken om te testen.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "Voor meer informatie <a href=\"%s\">zie dit FAQ-artikel</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Uw browser kan een HTTPS-verbinding nodig hebben om de WebCrypto API te ondersteunen. Probeer <a href=\"%s\">het met HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Uw browser ondersteunt WebAssembly niet, wat wordt gebruikt voor zlib compressie. U kunt niet-gecomprimeerde documenten maken, maar geen gecomprimeerde documenten lezen.",
|
||||
"waiting on user to provide a password": "wachtend op gebruiker om een wachtwoord te geven",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Kon de gegevens niet decoderen. Heeft u een verkeerd wachtwoord ingevoerd? Probeer het opnieuw met de knop bovenaan.",
|
||||
"Retry": "Opnieuw proberen",
|
||||
"Showing raw text…": "Platte tekst tonen…",
|
||||
"Notice:": "Let op:",
|
||||
"This link will expire after %s.": "Deze link vervalt na %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Deze link kan slechts eenmaal worden geopend, gebruik niet de terug- of verversknop in uw browser.",
|
||||
"Could not get paste data: %s": "Could not get paste data: %s",
|
||||
"QR code": "QR code",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "For more information <a href=\"%s\">see this FAQ entry</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
|
||||
"waiting on user to provide a password": "waiting on user to provide a password",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
|
||||
"Retry": "Retry",
|
||||
"Showing raw text…": "Showing raw text…",
|
||||
"Notice:": "Notice:",
|
||||
"This link will expire after %s.": "This link will expire after %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.",
|
||||
"Link:": "Link:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Ontvanger kan zich bewust worden van uw tijdzone, tijd omzetten naar UTC?",
|
||||
"Use Current Timezone": "Gebruik huidige tijdzone",
|
||||
"Convert To UTC": "Omzetten naar UTC",
|
||||
"Close": "Sluiten",
|
||||
"Encrypted note on %s": "Versleutelde notitie op %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Bezoek deze link om de notitie te bekijken. Als je de URL aan iemand geeft, kan die de notitie ook bekijken.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL-verkorter kan uw ontcijferingssleutel in URL blootleggen.",
|
||||
"Save paste": "Notitie opslaan",
|
||||
"Your IP is not authorized to create pastes.": "Uw IP-adres is niet gemachtigd om geplakte tekst te maken.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?",
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Bruk gjeldende tidssone",
|
||||
"Convert To UTC": "Konverter til UTC",
|
||||
"Close": "Steng",
|
||||
"Encrypted note on %s": "Kryptert notat på %s",
|
||||
"Encrypted note on PrivateBin": "Kryptert notat på PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besøk denne lenken for å se notatet. Hvis lenken deles med andre, vil de også kunne se notatet.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL forkorter kan avsløre dekrypteringsnøkkelen.",
|
||||
"Save paste": "Lagre utklipp",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Lagre utklipp"
|
||||
}
|
||||
|
||||
80
i18n/oc.json
80
i18n/oc.json
@@ -37,76 +37,76 @@
|
||||
"%d seconds": [
|
||||
"%d segonda",
|
||||
"%d segondas",
|
||||
"%d segondas",
|
||||
"%d segondas"
|
||||
"%d seconds (2nd plural)",
|
||||
"%d seconds (3rd plural)"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d minuta",
|
||||
"%d minutas",
|
||||
"%d minutas",
|
||||
"%d minutas"
|
||||
"%d minutes (2nd plural)",
|
||||
"%d minutes (3rd plural)"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d ora",
|
||||
"%d oras",
|
||||
"%d oras",
|
||||
"%d oras"
|
||||
"%d hours (2nd plural)",
|
||||
"%d hours (3rd plural)"
|
||||
],
|
||||
"%d days": [
|
||||
"%d jorn",
|
||||
"%d jorns",
|
||||
"%d jorns",
|
||||
"%d jorns"
|
||||
"%d days (2nd plural)",
|
||||
"%d days (3rd plural)"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d setmana",
|
||||
"%d setmanas",
|
||||
"%d setmanas",
|
||||
"%d setmanas"
|
||||
"%d weeks (2nd plural)",
|
||||
"%d weeks (3rd plural)"
|
||||
],
|
||||
"%d months": [
|
||||
"%d mes",
|
||||
"%d meses",
|
||||
"%d meses",
|
||||
"%d meses"
|
||||
"%d months (2nd plural)",
|
||||
"%d months (3rd plural)"
|
||||
],
|
||||
"%d years": [
|
||||
"%d an",
|
||||
"%d ans",
|
||||
"%d ans",
|
||||
"%d ans"
|
||||
"%d years (2nd plural)",
|
||||
"%d years (3rd plural)"
|
||||
],
|
||||
"Never": "Jamai",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Nota : Aquò es un servici d’espròva : las donadas pòdon èsser suprimidas a cada moment. De catons moriràn s’abusatz d’aqueste servici.",
|
||||
"This document will expire in %d seconds.": [
|
||||
"Aqueste document expirarà d’aquí %d segonda.",
|
||||
"Aqueste document expirarà d’aquí %d segondas.",
|
||||
"Aqueste document expirarà d’aquí %d segondas.",
|
||||
"Aqueste document expirarà d’aquí %d segondas."
|
||||
"Ce document expirera dans %d seconde.",
|
||||
"Aqueste document expirarà dins %d segondas.",
|
||||
"Aqueste document expirarà dins %d segondas.",
|
||||
"Aqueste document expirarà dins %d segondas."
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"Aqueste document expirarà d’aquí %d minuta.",
|
||||
"Aqueste document expirarà d’aquí %d minutas.",
|
||||
"Aqueste document expirarà d’aquí %d minutas.",
|
||||
"Aqueste document expirarà d’aquí %d minutas."
|
||||
"Ce document expirera dans %d minute.",
|
||||
"Aqueste document expirarà dins %d minutas.",
|
||||
"Aqueste document expirarà dins %d minutas.",
|
||||
"Aqueste document expirarà dins %d minutas."
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"Aqueste document expirarà d’aquí %d ora.",
|
||||
"Aqueste document expirarà d’aquí %d oras.",
|
||||
"Aqueste document expirarà d’aquí %d oras.",
|
||||
"Aqueste document expirarà d’aquí %d oras."
|
||||
"Ce document expirera dans %d heure.",
|
||||
"Aqueste document expirarà dins %d oras.",
|
||||
"Aqueste document expirarà dins %d oras.",
|
||||
"Aqueste document expirarà dins %d oras."
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"Aqueste document expirarà d’aquí %d jorn.",
|
||||
"Aqueste document expirarà d’aquí %d jorns.",
|
||||
"Aqueste document expirarà d’aquí %d jorns.",
|
||||
"Aqueste document expirarà d’aquí %d jorns."
|
||||
"Ce document expirera dans %d jour.",
|
||||
"Aqueste document expirarà dins %d jorns.",
|
||||
"Aqueste document expirarà dins %d jorns.",
|
||||
"Aqueste document expirarà dins %d jorns."
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"Aqueste document expirarà d’aquí %d mes.",
|
||||
"Aqueste document expirarà d’aquí %d meses.",
|
||||
"Aqueste document expirarà d’aquí %d meses.",
|
||||
"Aqueste document expirarà d’aquí %d meses."
|
||||
"Ce document expirera dans %d mois.",
|
||||
"Aqueste document expirarà dins %d meses.",
|
||||
"Aqueste document expirarà dins %d meses.",
|
||||
"Aqueste document expirarà dins %d meses."
|
||||
],
|
||||
"Please enter the password for this paste:": "Picatz lo senhal per aqueste tèxte :",
|
||||
"Could not decrypt data (Wrong key?)": "Impossible de deschifrar las donadas (marrida clau ?)",
|
||||
@@ -156,7 +156,7 @@
|
||||
"Shorten URL": "Acorchir l’URL",
|
||||
"Editor": "Editar",
|
||||
"Preview": "Previsualizar",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s demanda que lo PATH termine en « %s ». Mercés de metre a jorn lo PATH dins vòstre index.php.",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s demanda que lo PATH termine en \"%s\". Mercés de metre a jorn lo PATH dins vòstre index.php.",
|
||||
"Decrypt": "Deschifrar",
|
||||
"Enter password": "Picatz lo senhal",
|
||||
"Loading…": "Cargament…",
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Utilizar l’actual",
|
||||
"Convert To UTC": "Convertir en UTC",
|
||||
"Close": "Tampar",
|
||||
"Encrypted note on %s": "Nòtas chifradas sus %s",
|
||||
"Encrypted note on PrivateBin": "Nòtas chifradas sus PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitatz aqueste ligam per veire la nòta. Fornir lo ligam a qualqu’un mai li permet tanben d’accedir a la nòta.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Los espleches d’acorchiment d’URL pòdon expausar la clau de deschiframent dins l’URL.",
|
||||
"Save paste": "Enregistrar lo tèxt",
|
||||
"Your IP is not authorized to create pastes.": "Vòstra adreça IP a pas l’autorizacion de crear de tèxtes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Usar Fuso Horário Atual",
|
||||
"Convert To UTC": "Converter para UTC",
|
||||
"Close": "Fechar",
|
||||
"Encrypted note on %s": "Nota criptografada no %s",
|
||||
"Encrypted note on PrivateBin": "Nota criptografada no PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite esse link para ver a nota. Dar a URL para qualquer um permite que eles também acessem a nota.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Использовать текущий часовой пояс",
|
||||
"Convert To UTC": "Конвертировать в UTC",
|
||||
"Close": "Закрыть",
|
||||
"Encrypted note on %s": "Зашифрованная запись на %s",
|
||||
"Encrypted note on PrivateBin": "Зашифрованная запись на PrivateBin",
|
||||
"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.": "Сервис сокращения ссылок может получить ваш ключ расшифровки из ссылки.",
|
||||
"Save paste": "Сохранить запись",
|
||||
"Your IP is not authorized to create pastes.": "Вашему IP адресу не разрешено создавать записи.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Сохранить запись"
|
||||
}
|
||||
|
||||
193
i18n/sk.json
193
i18n/sk.json
@@ -1,193 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s je minimalistický, open source online pastebin, kde server nemá žiadne znalosti o vložených údajoch. Údaje sú šifrované/dešifrované %sv prehliadači%s pomocou 256-bitového AES.",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Viac informácií na <a href=\"https://privatebin.info/\">stránke projektu</a>.",
|
||||
"Because ignorance is bliss": "Pretože nevedomosť je sladká",
|
||||
"en": "sk",
|
||||
"Paste does not exist, has expired or has been deleted.": "Vložený text neexistuje, jeho platnosť vypršala alebo bol vymazaný.",
|
||||
"%s requires php %s or above to work. Sorry.": "%s vyžaduje php %s alebo vyššie. Prepáčte.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s vyžaduje, aby bola v konfiguračnom súbore prítomná sekcia [%s].",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Počet sekúnd do ďalšieho príspevku: %d",
|
||||
"Počet sekúnd do ďalšieho príspevku: %d",
|
||||
"Počet sekúnd do ďalšieho príspevku: %d",
|
||||
"Počet sekúnd do ďalšieho príspevku: %d"
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "Príspevok je obmedzený na %s zašifrovaných údajov.",
|
||||
"Invalid data.": "Neplatné údaje.",
|
||||
"You are unlucky. Try again.": "Ľutujem. Skúste to znova.",
|
||||
"Error saving comment. Sorry.": "Pri ukladaní komentára sa vyskytla chyba.",
|
||||
"Error saving paste. Sorry.": "Pri ukladaní príspevku sa vyskytla chyba.",
|
||||
"Invalid paste ID.": "Chybne vložené ID.",
|
||||
"Paste is not of burn-after-reading type.": "Príspevok nieje nastavený na zmazanie po prečítaní.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Nesprávny token odstránenia. Príspevok nebol odstránený.",
|
||||
"Paste was properly deleted.": "Príspevok bol správne vymazaný.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "Na fungovanie %s je potrebný JavaScript. Ospravedlňujeme sa za nepríjemnosti.",
|
||||
"%s requires a modern browser to work.": "%s vyžaduje na fungovanie moderný prehliadač.",
|
||||
"New": "Nový",
|
||||
"Send": "Odoslať",
|
||||
"Clone": "Klonovať",
|
||||
"Raw text": "Surový text",
|
||||
"Expires": "Expirácia",
|
||||
"Burn after reading": "Po prečítaní zmazať",
|
||||
"Open discussion": "Povoliť komentáre",
|
||||
"Password (recommended)": "Heslo (doporučené)",
|
||||
"Discussion": "Komentáre",
|
||||
"Toggle navigation": "Prepnúť navigáciu",
|
||||
"%d seconds": [
|
||||
"%d sekunda",
|
||||
"%d sekundy",
|
||||
"%d sekúnd",
|
||||
"%d sekúnd"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d minúta",
|
||||
"%d minúty",
|
||||
"%d minút",
|
||||
"%d minút"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d hodina",
|
||||
"%d hodiny",
|
||||
"%d hodín",
|
||||
"%d hodín"
|
||||
],
|
||||
"%d days": [
|
||||
"%d deň",
|
||||
"%d dni",
|
||||
"%d dní",
|
||||
"%d dní"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d týždeň",
|
||||
"%d týždne",
|
||||
"%d týždňov",
|
||||
"%d týždňov"
|
||||
],
|
||||
"%d months": [
|
||||
"%d mesiac",
|
||||
"%d mesiace",
|
||||
"%d mesiacov",
|
||||
"%d mesiacov"
|
||||
],
|
||||
"%d years": [
|
||||
"%d rok",
|
||||
"%d roky",
|
||||
"%d rokov",
|
||||
"%d rokov"
|
||||
],
|
||||
"Never": "Nikdy",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Poznámka: Toto je testovacia služba: Údaje môžu byť kedykoľvek vymazané. Pri zneužití tejto služby zomrú mačiatka.",
|
||||
"This document will expire in %d seconds.": [
|
||||
"Platnosť tohto dokumentu vyprší o %d sekundu.",
|
||||
"Platnosť tohto dokumentu vyprší o %d sekundy.",
|
||||
"Platnosť tohto dokumentu vyprší o %d sekúnd.",
|
||||
"Platnosť tohto dokumentu vyprší o %d sekúnd."
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"Platnosť tohto dokumentu vyprší o %d minútu.",
|
||||
"Platnosť tohto dokumentu vyprší o %d minúty.",
|
||||
"Platnosť tohto dokumentu vyprší o %d minút.",
|
||||
"Platnosť tohto dokumentu vyprší o %d minút."
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"Platnosť tohto dokumentu vyprší o %d hodinu.",
|
||||
"Platnosť tohto dokumentu vyprší o %d hodiny.",
|
||||
"Platnosť tohto dokumentu vyprší o %d hodín.",
|
||||
"Platnosť tohto dokumentu vyprší o %d hodín."
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"Platnosť tohto dokumentu vyprší o %d deň.",
|
||||
"Platnosť tohto dokumentu vyprší o %d dni.",
|
||||
"Platnosť tohto dokumentu vyprší o %d dní.",
|
||||
"Platnosť tohto dokumentu vyprší o %d dní."
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"Platnosť tohto dokumentu vyprší o %d mesiac.",
|
||||
"Platnosť tohto dokumentu vyprší o %d mesiace.",
|
||||
"Platnosť tohto dokumentu vyprší o %d mesiacov.",
|
||||
"Platnosť tohto dokumentu vyprší o %d mesiacov."
|
||||
],
|
||||
"Please enter the password for this paste:": "Zadajte prosím heslo:",
|
||||
"Could not decrypt data (Wrong key?)": "Nepodarilo sa dešifrovať údaje (nesprávny kľúč?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Nepodarilo sa odstrániť príspevok, nebol uložený v režime zmazania po prečítaní.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "IBA PRE VAŠE OČI. Toto okno nezatvárajte, táto správa sa nedá znova zobraziť.",
|
||||
"Could not decrypt comment; Wrong key?": "Nepodarilo sa dešifrovať komentár. Nesprávny kľúč?",
|
||||
"Reply": "Odpovedať",
|
||||
"Anonymous": "Anonymný",
|
||||
"Avatar generated from IP address": "Avatar vygenerovaný z IP adresy",
|
||||
"Add comment": "Pridať komentár",
|
||||
"Optional nickname…": "Voliteľná prezývka…",
|
||||
"Post comment": "Odoslať komentár",
|
||||
"Sending comment…": "Odosielanie komentára…",
|
||||
"Comment posted.": "Komentár odoslaný.",
|
||||
"Could not refresh display: %s": "Nepodarilo sa obnoviť zobrazenie: %s",
|
||||
"unknown status": "neznámy stav",
|
||||
"server error or not responding": "chyba servera alebo server neodpovedá",
|
||||
"Could not post comment: %s": "Nepodarilo sa pridať komentár: %s",
|
||||
"Sending paste…": "Odosiela sa príspevok…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Váš príspevok je <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(skopírujte stlačením [Ctrl]+[c])</span>",
|
||||
"Delete data": "Odstrániť dáta",
|
||||
"Could not create paste: %s": "Nepodarilo sa vytvoriť príspevok: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nie je možné dešifrovať príspevok: V URL adrese chýba dešifrovací kľúč (Použili ste presmerovač alebo skracovač adresy, ktorý odstráni časť adresy URL?)",
|
||||
"B": "B",
|
||||
"KiB": "KiB",
|
||||
"MiB": "MiB",
|
||||
"GiB": "GiB",
|
||||
"TiB": "TiB",
|
||||
"PiB": "PiB",
|
||||
"EiB": "EiB",
|
||||
"ZiB": "ZiB",
|
||||
"YiB": "YiB",
|
||||
"Format": "Formát",
|
||||
"Plain Text": "Čistý text",
|
||||
"Source Code": "Zdrojový kód",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Stiahnuť prílohu",
|
||||
"Cloned: '%s'": "Naklonované: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "K tomuto príspevku bol pripojený klonovaný súbor '%s'.",
|
||||
"Attach a file": "Priložiť súbor",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "prípadne presuňte súbor myšou alebo vložte obrázok zo schránky",
|
||||
"File too large, to display a preview. Please download the attachment.": "Súbor je príliš veľký na zobrazenie ukážky. Stiahnite si prosím prílohu.",
|
||||
"Remove attachment": "Odstrániť prílohu",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Váš prehliadač nepodporuje nahrávanie šifrovaných súborov. Použite prosím novší prehliadač.",
|
||||
"Invalid attachment.": "Neplatná príloha.",
|
||||
"Options": "Možnosti",
|
||||
"Shorten URL": "Skrátiť URL",
|
||||
"Editor": "Editor",
|
||||
"Preview": "Náhľad",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH končila na \"%s\". Aktualizujte prosím PATH vo svojom index.php.",
|
||||
"Decrypt": "Dešifrovať",
|
||||
"Enter password": "Zadajte heslo",
|
||||
"Loading…": "Načítava sa…",
|
||||
"Decrypting paste…": "Dešifrovanie príspevku…",
|
||||
"Preparing new paste…": "Príprava nového príspevku…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "V prípade, že táto správa nezmizne, pozrite si <a href=\"%s\">tieto často kladené otázky, kde nájdete informácie na riešenie problémov</a>.",
|
||||
"+++ no paste text +++": "+++ žiadny vložený text +++",
|
||||
"Could not get paste data: %s": "Nepodarilo sa načítať údaje príspevku: %s",
|
||||
"QR code": "QR kód",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "Táto webová stránka používa nezabezpečené pripojenie HTTP! Používajte ju len na testovanie.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "Pre viac informácií si pozrite <a href=\"%s\">tento záznam FAQ</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Váš prehliadač môže na podporu rozhrania WebCrypto API vyžadovať pripojenie HTTPS. Skúste <a href=\"%s\">prepnúť na HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Váš prehliadač nepodporuje WebAssembly, ktorý sa používa na kompresiu zlib. Môžete vytvárať nekomprimované dokumenty, ale nemôžete čítať komprimované.",
|
||||
"waiting on user to provide a password": "čakám na zadanie hesla",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Údaje sa nepodarilo dešifrovať. Zadali ste nesprávne heslo? Skúste to znova pomocou tlačidla v hornej časti.",
|
||||
"Retry": "Opakovať",
|
||||
"Showing raw text…": "Zobrazuje sa surový text…",
|
||||
"Notice:": "Upozornenie:",
|
||||
"This link will expire after %s.": "Platnosť odkazu vyprší za %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Tento odkaz je prístupný iba raz, nepoužívajte v prehliadači tlačidlo Späť ani Obnoviť.",
|
||||
"Link:": "Odkaz:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Príjemca sa môže dozvedieť o vašom časovom pásme, previesť čas na UTC?",
|
||||
"Use Current Timezone": "Použiť aktuálne časové pásmo",
|
||||
"Convert To UTC": "Previesť na UTC",
|
||||
"Close": "Zavrieť",
|
||||
"Encrypted note on %s": "Zašifrovaná poznámka na %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Ak chcete zobraziť poznámku, navštívte tento odkaz. Poskytnutie adresy URL komukoľvek im umožní prístup aj k poznámke.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Skracovač adries URL môže odhaliť váš dešifrovací kľúč v adrese URL.",
|
||||
"Save paste": "Uložiť príspevok",
|
||||
"Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať príspevky.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Pokúšate sa skrátiť adresu URL, ktorá neukazuje na túto inštanciu.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
}
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on %s": "Encrypted note on %s",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
193
i18n/th.json
193
i18n/th.json
@@ -1,193 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s เป็น pastebin ออนไลน์แบบโอเพ่นซอร์สที่มีสไตล์แบบมินิมัลลิสท์ เซิร์ฟเวอร์ไม่สามารถรู้ได้ว่าข้อมูลโค้ดที่มาฝากนั้นเป็นข้อมูลอะไร โดยจะถูก %sเข้ารหัส/ถอดรหัส%s ด้วยกระบวนการ AES จำนวน 256 บิตผ่านเบราว์เซอร์",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "ข้อมูลเพิ่มเติม ดูได้ที่<a href=\"https://privatebin.info/\">หน้าโครงการ</a>",
|
||||
"Because ignorance is bliss": "ไม่รู้ไม่ชี้ดีที่สุด",
|
||||
"en": "th",
|
||||
"Paste does not exist, has expired or has been deleted.": "การฝากโค้ดไม่มีอยู่ อาจจะหมดอายุหรือถูกลบไปแล้ว",
|
||||
"%s requires php %s or above to work. Sorry.": "ขออภัย %s ต้องใช้ PHP %s ขึ้นไปจึงจะใช้งานได้",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s จำเป็นต้องตั้งค่าตัวแปร [%s] ในไฟล์กำหนดค่า",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"กรุณาเว้นระยะเวลาการส่งข้อมูลอย่างน้อย %d วินาที",
|
||||
"กรุณาเว้นระยะเวลาการส่งข้อมูลอย่างน้อย %d วินาที",
|
||||
"กรุณาเว้นระยะเวลาการส่งข้อมูลอย่างน้อย %d วินาที",
|
||||
"กรุณาเว้นระยะเวลาการส่งข้อมูลอย่างน้อย %d วินาที"
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "การฝากโค้ดแบบเข้ารหัส ขีดจำกัดสูงสุดคือ %s",
|
||||
"Invalid data.": "ข้อมูลไม่ถูกต้อง",
|
||||
"You are unlucky. Try again.": "วันนี้คุณดวงไม่เฮงเลย ลองใหม่อีกครั้งนะ",
|
||||
"Error saving comment. Sorry.": "ขออภัย เกิดข้อผิดพลาดในระหว่างบันทึกความคิดเห็น",
|
||||
"Error saving paste. Sorry.": "ขออภัย เกิดข้อผิดพลาดในระหว่างบันทึกการฝากโค้ด",
|
||||
"Invalid paste ID.": "ID การฝากโค้ดไม่ถูกต้อง",
|
||||
"Paste is not of burn-after-reading type.": "ข้อมูลการฝากโค้ดนี้ไม่ได้เป็นรูปแบบลบทันทีเมื่อเปิดอ่าน",
|
||||
"Wrong deletion token. Paste was not deleted.": "โทเค็นการลบไม่ถูกต้อง ข้อมูลการฝากโค้ดไม่ถูกลบ",
|
||||
"Paste was properly deleted.": "ข้อมูลการฝากโค้ดถูกลบออกเรียบร้อยแล้ว",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "จำเป็นต้องใช้ JavaScript เพื่อให้ %s สามารถทำงานได้ ขออภัยในความไม่สะดวก",
|
||||
"%s requires a modern browser to work.": "%s ต้องใช้เบราว์เซอร์สมัยใหม่ถึงจะสามารถใช้งานได้",
|
||||
"New": "ใหม่",
|
||||
"Send": "ส่ง",
|
||||
"Clone": "โคลน",
|
||||
"Raw text": "ข้อความล้วน",
|
||||
"Expires": "หมดอายุ",
|
||||
"Burn after reading": "ลบทันทีเมื่อเปิดอ่าน",
|
||||
"Open discussion": "แสดงความคิดเห็นได้",
|
||||
"Password (recommended)": "รหัสผ่าน (แนะนำให้ใส่)",
|
||||
"Discussion": "ความคิดเห็น",
|
||||
"Toggle navigation": "สลับเปิดปิดการนำทาง",
|
||||
"%d seconds": [
|
||||
"%d วินาที",
|
||||
"%d วินาที",
|
||||
"%d วินาที",
|
||||
"%d วินาที"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d นาที",
|
||||
"%d นาที",
|
||||
"%d นาที",
|
||||
"%d นาที"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d ชั่วโมง",
|
||||
"%d ชั่วโมง",
|
||||
"%d ชั่วโมง",
|
||||
"%d ชั่วโมง"
|
||||
],
|
||||
"%d days": [
|
||||
"%d วัน",
|
||||
"%d วัน",
|
||||
"%d วัน",
|
||||
"%d วัน"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d สัปดาห์",
|
||||
"%d สัปดาห์",
|
||||
"%d สัปดาห์",
|
||||
"%d สัปดาห์"
|
||||
],
|
||||
"%d months": [
|
||||
"%d เดือน",
|
||||
"%d เดือน",
|
||||
"%d เดือน",
|
||||
"%d เดือน"
|
||||
],
|
||||
"%d years": [
|
||||
"%d ปี",
|
||||
"%d ปี",
|
||||
"%d ปี",
|
||||
"%d ปี"
|
||||
],
|
||||
"Never": "ไม่หมดอายุ",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "โปรดทราบ: เว็บไซต์นี้เป็นการให้บริการแบบเบต้า ข้อมูลอาจถูกลบได้ตลอดเวลา หากคุณใช้บริการนี้ในทางที่ผิดอาจจะทำให้ข้อมูลของคุณสูญหายอย่างถาวรได้",
|
||||
"This document will expire in %d seconds.": [
|
||||
"เอกสารนี้จะหมดอายุใน %d วินาที",
|
||||
"เอกสารนี้จะหมดอายุใน %d วินาที",
|
||||
"เอกสารนี้จะหมดอายุใน %d วินาที",
|
||||
"เอกสารนี้จะหมดอายุใน %d วินาที"
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"เอกสารนี้จะหมดอายุใน %d นาที",
|
||||
"เอกสารนี้จะหมดอายุใน %d นาที",
|
||||
"เอกสารนี้จะหมดอายุใน %d นาที",
|
||||
"เอกสารนี้จะหมดอายุใน %d นาที"
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"เอกสารนี้จะหมดอายุใน %d ชั่วโมง",
|
||||
"เอกสารนี้จะหมดอายุใน %d ชั่วโมง",
|
||||
"เอกสารนี้จะหมดอายุใน %d ชั่วโมง",
|
||||
"เอกสารนี้จะหมดอายุใน %d ชั่วโมง"
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"เอกสารนี้จะหมดอายุใน %d วัน",
|
||||
"เอกสารนี้จะหมดอายุใน %d วัน",
|
||||
"เอกสารนี้จะหมดอายุใน %d วัน",
|
||||
"เอกสารนี้จะหมดอายุใน %d วัน"
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"เอกสารนี้จะหมดอายุใน %d เดือน",
|
||||
"เอกสารนี้จะหมดอายุใน %d เดือน",
|
||||
"เอกสารนี้จะหมดอายุใน %d เดือน",
|
||||
"เอกสารนี้จะหมดอายุใน %d เดือน"
|
||||
],
|
||||
"Please enter the password for this paste:": "กรุณากรอกรหัสผ่านเพื่อเปิดข้อมูลการฝากโค้ดนี้:",
|
||||
"Could not decrypt data (Wrong key?)": "ไม่สามารถถอดรหัสข้อมูลได้ (คีย์ไม่ถูกต้องหรือไม่)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "ไม่สามารถลบการฝากโค้ดนี้ได้ เนื่องจากว่าไม่ได้ถูกเก็บไว้ในโหมดลบทันทีเมื่อเปิดอ่าน",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "เก็บไว้ดูคนเดียวนะ อย่าปิดหน้าต่างนี้ ข้อความนี้จะไม่สามารถแสดงได้อีก",
|
||||
"Could not decrypt comment; Wrong key?": "ไม่สามารถถอดรหัสความคิดเห็นได้ คีย์ไม่ถูกต้องหรือไม่",
|
||||
"Reply": "ตอบกลับ",
|
||||
"Anonymous": "ไม่ระบุชื่อ",
|
||||
"Avatar generated from IP address": "อวาตารสร้างมาจากไอพี",
|
||||
"Add comment": "เพิ่มความคิดเห็น",
|
||||
"Optional nickname…": "ใส่ชื่อคนให้ความคิดเห็น…",
|
||||
"Post comment": "ส่งความคิดเห็น",
|
||||
"Sending comment…": "กำลังส่งความคิดเห็น…",
|
||||
"Comment posted.": "ส่งความคิดเห็นแล้ว",
|
||||
"Could not refresh display: %s": "ไม่สามารถรีเฟรชการแสดงผลได้: %s",
|
||||
"unknown status": "ไม่ทราบสถานะ",
|
||||
"server error or not responding": "เซิร์ฟเวอร์มีข้อผิดพลาดหรือไม่ตอบสนอง",
|
||||
"Could not post comment: %s": "ไม่สามารถส่งความคิดเห็นได้: %s",
|
||||
"Sending paste…": "กำลังส่งข้อมูล…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "การฝากโค้ดของคุณอยู่ที่ <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(กดปุ่ม [Ctrl]+[c] เพื่อคัดลอก)</span>",
|
||||
"Delete data": "ลบข้อมูล",
|
||||
"Could not create paste: %s": "ไม่สามารถสร้างข้อมูลการฝากโค้ดได้: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "ไม่สามารถถอดรหัสข้อมูลการฝากโค้ดได้: คีย์ถอดรหัสที่อยู่ใน URL หายไป (คุณได้ใช้ตัวเปลี่ยนเส้นทางหรือตัวย่อ URL ที่มีการตัดส่วนของ URL ออกหรือไม่)",
|
||||
"B": "B",
|
||||
"KiB": "KiB",
|
||||
"MiB": "MiB",
|
||||
"GiB": "GiB",
|
||||
"TiB": "TiB",
|
||||
"PiB": "PiB",
|
||||
"EiB": "EiB",
|
||||
"ZiB": "ZiB",
|
||||
"YiB": "YiB",
|
||||
"Format": "รูปแบบ",
|
||||
"Plain Text": "ข้อความล้วน",
|
||||
"Source Code": "ซอร์สโค้ด",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "ดาวน์โหลดไฟล์แนบ",
|
||||
"Cloned: '%s'": "โคลนแล้ว: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "การโคลนข้อมูลการฝากโค้ด มีไฟล์ '%s' แนบมาด้วย",
|
||||
"Attach a file": "แนบไฟล์",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "หรือสามารถลากและวางไฟล์หรือวางรูปภาพจากคลิปบอร์ดได้",
|
||||
"File too large, to display a preview. Please download the attachment.": "ไฟล์มีขนาดใหญ่เกินไปที่จะแสดงตัวอย่าง กรุณาดาวน์โหลดเป็นไฟล์แนบแทน",
|
||||
"Remove attachment": "ลบไฟล์แนบ",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "เบราว์เซอร์ของคุณไม่สนับสนุนการอัปโหลดไฟล์แบบเข้ารหัสได้ กรุณาใช้เบราว์เซอร์ที่ใหม่กว่า",
|
||||
"Invalid attachment.": "ไฟล์แนบไม่ถูกต้อง",
|
||||
"Options": "ตัวเลือก",
|
||||
"Shorten URL": "สร้างลิงก์ย่อ",
|
||||
"Editor": "ตัวแก้ไข",
|
||||
"Preview": "ดูตัวอย่าง",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s กำหนดให้ PATH ลงท้ายด้วย \"%s\" กรุณาอัปเดต PATH ในไฟล์ index.php ของคุณ",
|
||||
"Decrypt": "ถอดรหัส",
|
||||
"Enter password": "กรอกรหัสผ่าน",
|
||||
"Loading…": "กำลังโหลด…",
|
||||
"Decrypting paste…": "กำลังถอดรหัสข้อมูลการฝากโค้ด…",
|
||||
"Preparing new paste…": "กำลังเตรียมข้อมูลการฝากโค้ดใหม่…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "ในกรณีที่ข้อความนี้ยังปรากฎให้เห็นอยู่ กรุณาดู<a href=\"%s\">คำถามที่พบบ่อยนี้เพื่อใช้แก้ไขปัญหา</a>",
|
||||
"+++ no paste text +++": "+++ ไม่มีข้อความการฝากโค้ด +++",
|
||||
"Could not get paste data: %s": "ไม่สามารถดึงข้อมูลการฝากโค้ดได้: %s",
|
||||
"QR code": "คิวอาร์โค้ด",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "เว็บไซต์นี้ใช้การเชื่อมต่อแบบ HTTP ที่ไม่ปลอดภัย! กรุณาใช้เพื่อการทดสอบเท่านั้น",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "สำหรับข้อมูลเพิ่มเติม <a href=\"%s\">กรุณาดูรายการคำถามที่พบบ่อยนี้</a>",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "เบราว์เซอร์ของคุณอาจต้องใช้การเชื่อมต่อ HTTPS เพื่อสนับสนุน API แบบ WebCrypto ลอง<a href=\"%s\">เปลี่ยนเป็น HTTPS</a>",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "เบราว์เซอร์ของคุณไม่สนับสนุน WebAssembly ที่ทำหน้าที่ในการบีบอัดข้อมูลในรูปแบบ zlib คุณยังสามารถสร้างเอกสารที่ไม่บีบอัด แต่จะไม่สามารถอ่านเอกสารที่บีบอัดได้",
|
||||
"waiting on user to provide a password": "กำลังรอผู้ใช้กรอกรหัสผ่าน",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "ไม่สามารถถอดรหัสข้อมูลได้ คุณกรอกรหัสผ่านผิดหรือเปล่า กดปุ่มลองอีกครั้งด้านบน",
|
||||
"Retry": "ลองอีกครั้ง",
|
||||
"Showing raw text…": "กำลังแสดงข้อความล้วน…",
|
||||
"Notice:": "โปรดทราบ:",
|
||||
"This link will expire after %s.": "ลิงก์นี้จะหมดอายุหลังจาก %s",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "ลิงก์นี้สามารถเข้าถึงได้เพียงครั้งเดียวเท่านั้น ไม่ควรใช้ปุ่มย้อนกลับหรือรีเฟรชหน้าเว็บบนเบราว์เซอร์ของคุณ",
|
||||
"Link:": "ลิงก์:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "ผู้รับอีเมลอาจทราบโซนเวลาของคุณได้ คุณต้องการแปลงโซนเวลาเป็น UTC หรือไม่",
|
||||
"Use Current Timezone": "ใช้โซนเวลาปัจจุบัน",
|
||||
"Convert To UTC": "แปลงเป็น UTC",
|
||||
"Close": "ปิด",
|
||||
"Encrypted note on %s": "เขารหัสบันทึกย่อบน %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "ไปที่ลิงก์นี้เพื่อดูบันทึกย่อทั้งหมด ส่ง URL นี้ให้ใครก็ได้เพื่อให้สามารถเข้าถึงบันทึกย่อได้",
|
||||
"URL shortener may expose your decrypt key in URL.": "เครื่องมือสร้างลิงก์ย่ออาจเปิดเผยคีย์ถอดรหัสของคุณใน URL ได้",
|
||||
"Save paste": "ดาวน์โหลดข้อมูลการฝากโค้ด",
|
||||
"Your IP is not authorized to create pastes.": "IP ของคุณไม่ได้รับอนุญาตให้สร้างการฝากโค้ด",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "กำลังพยายามใช้เครื่องมือสร้างลิงก์ย่อ ที่ไม่ได้ชี้ไปที่อินสแตนซ์ของเรา",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "เกิดข้อผิดพลาดในการเรียก YOURLS อาจเป็นปัญหามาจากการกำหนดค่า เช่น \"apiurl\" หรือ \"signature\" ไม่ถูกต้องหรือขาดหายไป",
|
||||
"Error parsing YOURLS response.": "เกิดข้อผิดพลาดในการแยกวิเคราะห์การตอบสนองของ YOURLS"
|
||||
}
|
||||
268
i18n/tr.json
268
i18n/tr.json
@@ -1,135 +1,135 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s sunucunun burada paylaştığınız veriyi görmediği, minimal, açık kaynak bir pastebindir. Veriler tarayıcıda 256 bit AES kullanılarak şifrelenir/çözülür.",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.",
|
||||
"More information on the <a href=\"https://privatebin.info/\">project page</a>.": "Daha fazla bilgi için <a href=\"https://privatebin.info/\">proje sayfası</a>'na göz atabilirsiniz.",
|
||||
"Because ignorance is bliss": "Çünkü, cehalet mutluluktur",
|
||||
"en": "tr",
|
||||
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.",
|
||||
"%s requires php %s or above to work. Sorry.": "%s PHP %s veya daha üstünü gerektirir.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s konfigürasyon bölümünün [%s] bulunmasını gerektir.",
|
||||
"%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Lütfen paylaşımlar arasında %d saniye bekleyiniz.",
|
||||
"Lütfen paylaşımlar arasında %d saniye bekleyiniz.",
|
||||
"Lütfen paylaşımlar arasında %d saniye bekleyiniz.",
|
||||
"Lütfen paylaşımlar arasında %d saniye bekleyiniz."
|
||||
"Please wait %d second between each post. (singular)",
|
||||
"Please wait %d seconds between each post. (1st plural)",
|
||||
"Please wait %d seconds between each post. (2nd plural)",
|
||||
"Please wait %d seconds between each post. (3rd plural)"
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "Yazılar %s şifreli veriyle sınırlıdır.",
|
||||
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.",
|
||||
"Invalid data.": "Geçersiz veri.",
|
||||
"You are unlucky. Try again.": "Lütfen tekrar deneyiniz.",
|
||||
"Error saving comment. Sorry.": "Yorum kaydedilemedi.",
|
||||
"Error saving paste. Sorry.": "Yazı kaydedilemedi. Üzgünüz.",
|
||||
"Invalid paste ID.": "Geçersiz yazı ID'si.",
|
||||
"Paste is not of burn-after-reading type.": "Yazı okunduğunda silinmeyecek şekilde ayarlanmış.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Yanlış silme anahtarı. Yazı silinemedi.",
|
||||
"Paste was properly deleted.": "Yazı başarıyla silindi.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript %s 'in çalışması için gereklidir. Rahatsızlıktan dolayı özür dileriz.",
|
||||
"%s requires a modern browser to work.": "%s çalışmak için çağdaş bir tarayıcı gerektirir.",
|
||||
"Error saving comment. Sorry.": "Error saving comment. Sorry.",
|
||||
"Error saving paste. Sorry.": "Error saving paste. Sorry.",
|
||||
"Invalid paste ID.": "Invalid paste ID.",
|
||||
"Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.",
|
||||
"Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.",
|
||||
"Paste was properly deleted.": "Paste was properly deleted.",
|
||||
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.",
|
||||
"%s requires a modern browser to work.": "%s requires a modern browser to work.",
|
||||
"New": "Yeni",
|
||||
"Send": "Gönder",
|
||||
"Clone": "Kopyala",
|
||||
"Raw text": "Açık yazı",
|
||||
"Expires": "Süre Sonu",
|
||||
"Burn after reading": "Okuduktan sonra sil",
|
||||
"Open discussion": "Açık Tartışmalar",
|
||||
"Password (recommended)": "Şifre (önerilir)",
|
||||
"Discussion": "Tartışma",
|
||||
"Toggle navigation": "Gezinmeyi değiştir",
|
||||
"Clone": "Clone",
|
||||
"Raw text": "Raw text",
|
||||
"Expires": "Expires",
|
||||
"Burn after reading": "Burn after reading",
|
||||
"Open discussion": "Open discussion",
|
||||
"Password (recommended)": "Password (recommended)",
|
||||
"Discussion": "Discussion",
|
||||
"Toggle navigation": "Toggle navigation",
|
||||
"%d seconds": [
|
||||
"%d saniye",
|
||||
"%d saniye",
|
||||
"%d saniye",
|
||||
"%d saniye"
|
||||
"%d second (singular)",
|
||||
"%d seconds (1st plural)",
|
||||
"%d seconds (2nd plural)",
|
||||
"%d seconds (3rd plural)"
|
||||
],
|
||||
"%d minutes": [
|
||||
"%d dakika",
|
||||
"%d dakika",
|
||||
"%d dakika",
|
||||
"%d dakika"
|
||||
"%d minute (singular)",
|
||||
"%d minutes (1st plural)",
|
||||
"%d minutes (2nd plural)",
|
||||
"%d minutes (3rd plural)"
|
||||
],
|
||||
"%d hours": [
|
||||
"%d saat",
|
||||
"%d saat",
|
||||
"%d saat",
|
||||
"%d saat"
|
||||
"%d hour (singular)",
|
||||
"%d hours (1st plural)",
|
||||
"%d hours (2nd plural)",
|
||||
"%d hours (3rd plural)"
|
||||
],
|
||||
"%d days": [
|
||||
"%d gün",
|
||||
"%d gün",
|
||||
"%d gün",
|
||||
"%d gün"
|
||||
"%d day (singular)",
|
||||
"%d days (1st plural)",
|
||||
"%d days (2nd plural)",
|
||||
"%d days (3rd plural)"
|
||||
],
|
||||
"%d weeks": [
|
||||
"%d hafta",
|
||||
"%d haftalar",
|
||||
"%d hafta",
|
||||
"%d hafta"
|
||||
"%d hafta (tekil)",
|
||||
"%d haftalar (çoğul)",
|
||||
"%d weeks (2nd plural)",
|
||||
"%d weeks (3rd plural)"
|
||||
],
|
||||
"%d months": [
|
||||
"%d ay",
|
||||
"%d ay",
|
||||
"%d ay",
|
||||
"%d ay"
|
||||
"%d month (singular)",
|
||||
"%d months (1st plural)",
|
||||
"%d months (2nd plural)",
|
||||
"%d months (3rd plural)"
|
||||
],
|
||||
"%d years": [
|
||||
"%d yıl",
|
||||
"%d yıl",
|
||||
"%d yıl",
|
||||
"%d yıl"
|
||||
"%d year (singular)",
|
||||
"%d years (1st plural)",
|
||||
"%d years (2nd plural)",
|
||||
"%d years (3rd plural)"
|
||||
],
|
||||
"Never": "Asla",
|
||||
"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.": [
|
||||
"Bu belge %d saniyede silinecektir.",
|
||||
"Bu belge %d saniyede silinecektir.",
|
||||
"Bu belge %d saniyede silinecektir.",
|
||||
"Bu belge %d saniyede silinecektir."
|
||||
"This document will expire in %d second. (singular)",
|
||||
"This document will expire in %d seconds. (1st plural)",
|
||||
"This document will expire in %d seconds. (2nd plural)",
|
||||
"This document will expire in %d seconds. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d minutes.": [
|
||||
"Bu belge %d dakikada silinecektir.",
|
||||
"Bu belge %d dakikada silinecektir.",
|
||||
"Bu belge %d dakikada silinecektir.",
|
||||
"Bu belge %d dakikada silinecektir."
|
||||
"This document will expire in %d minute. (singular)",
|
||||
"This document will expire in %d minutes. (1st plural)",
|
||||
"This document will expire in %d minutes. (2nd plural)",
|
||||
"This document will expire in %d minutes. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d hours.": [
|
||||
"Bu belge %d saatte silinecektir.",
|
||||
"Bu belge %d saatte silinecektir.",
|
||||
"Bu belge %d saatte silinecektir.",
|
||||
"Bu belge %d saatte silinecektir."
|
||||
"This document will expire in %d hour. (singular)",
|
||||
"This document will expire in %d hours. (1st plural)",
|
||||
"This document will expire in %d hours. (2nd plural)",
|
||||
"This document will expire in %d hours. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d days.": [
|
||||
"Bu belge %d günde silinecektir.",
|
||||
"Bu belge %d günde silinecektir.",
|
||||
"Bu belge %d günde silinecektir.",
|
||||
"Bu belge %d günde silinecektir."
|
||||
"This document will expire in %d day. (singular)",
|
||||
"This document will expire in %d days. (1st plural)",
|
||||
"This document will expire in %d days. (2nd plural)",
|
||||
"This document will expire in %d days. (3rd plural)"
|
||||
],
|
||||
"This document will expire in %d months.": [
|
||||
"Bu belge %d ayda silinecektir.",
|
||||
"Bu belge %d ayda silinecektir.",
|
||||
"Bu belge %d ayda silinecektir.",
|
||||
"Bu belge %d ayda silinecektir."
|
||||
"This document will expire in %d month. (singular)",
|
||||
"This document will expire in %d months. (1st plural)",
|
||||
"This document will expire in %d months. (2nd plural)",
|
||||
"This document will expire in %d months. (3rd plural)"
|
||||
],
|
||||
"Please enter the password for this paste:": "Lütfen bu yazı için şifrenizi girin:",
|
||||
"Could not decrypt data (Wrong key?)": "Şifre çözülemedi (Yanlış anahtar mı kullandınız?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Yazı silinemedi, okunduktan sonra silinmek için ayarlanmadı.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "BU DOSYAYI SADECE SİZ GÖRÜNTÜLEYEBİLİRSİNİZ. Bu pencereyi kapatmayın, yazıyı tekrar görüntüleyemeyeceksiniz.",
|
||||
"Could not decrypt comment; Wrong key?": "Dosya şifresi çözülemedi, doğru anahtarı girdiğinizden emin misiniz?",
|
||||
"Reply": "Cevapla",
|
||||
"Anonymous": "Anonim",
|
||||
"Avatar generated from IP address": "IP adresinden oluşturulmuş avatar",
|
||||
"Add comment": "Yorum ekle",
|
||||
"Optional nickname…": "İsteğe bağlı takma isim…",
|
||||
"Post comment": "Yorumu gönder",
|
||||
"Sending comment…": "Yorum gönderiliyor…",
|
||||
"Comment posted.": "Yorum gönderildi.",
|
||||
"Could not refresh display: %s": "Görüntü yenilenemedi: %s",
|
||||
"unknown status": "bilinmeyen durum",
|
||||
"server error or not responding": "sunucu hatası veya yanıt vermiyor",
|
||||
"Could not post comment: %s": "Yorum paylaşılamadı: %s",
|
||||
"Sending paste…": "Yazı gönderiliyor…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Yazınız: <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">([Ctrl]+[c] tuşlarına basarak kopyalayın.)</span>",
|
||||
"Delete data": "Veriyi sil",
|
||||
"Could not create paste: %s": "Yazı oluşturulamadı: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Yazı şifresi çözülemedi, çözme anahtarı URL'de bulunamadı. (Buraya bir yönlendirici veya URL kısaltıcı kullanarak gelmiş olabilirsiniz.)",
|
||||
"Please enter the password for this paste:": "Please enter the password for this paste:",
|
||||
"Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.",
|
||||
"Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?",
|
||||
"Reply": "Reply",
|
||||
"Anonymous": "Anonymous",
|
||||
"Avatar generated from IP address": "Avatar generated from IP address",
|
||||
"Add comment": "Add comment",
|
||||
"Optional nickname…": "Optional nickname…",
|
||||
"Post comment": "Post comment",
|
||||
"Sending comment…": "Sending comment…",
|
||||
"Comment posted.": "Comment posted.",
|
||||
"Could not refresh display: %s": "Could not refresh display: %s",
|
||||
"unknown status": "unknown status",
|
||||
"server error or not responding": "server error or not responding",
|
||||
"Could not post comment: %s": "Could not post comment: %s",
|
||||
"Sending paste…": "Sending paste…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>",
|
||||
"Delete data": "Delete data",
|
||||
"Could not create paste: %s": "Could not create paste: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
|
||||
"B": "B",
|
||||
"KiB": "KiB",
|
||||
"MiB": "MiB",
|
||||
@@ -140,54 +140,50 @@
|
||||
"ZiB": "ZiB",
|
||||
"YiB": "YiB",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Düz Yazı",
|
||||
"Source Code": "Kaynak Kodu",
|
||||
"Plain Text": "Plain Text",
|
||||
"Source Code": "Source Code",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Eki indir",
|
||||
"Cloned: '%s'": "Klonlandı: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "Klonlanmış dosya '%s' bu yazıya eklendi.",
|
||||
"Attach a file": "Dosya ekle",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "alternatif olarak dosyasyı yapıştırabilir veya sürükleyip bırakabilirsin",
|
||||
"File too large, to display a preview. Please download the attachment.": "Dosya önizleme için çok büyük. Lütfen eki indirin.",
|
||||
"Remove attachment": "Eki sil",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Tarayıcınız şifreli dosyaları desteklemiyor.",
|
||||
"Invalid attachment.": "Geçersiz ek.",
|
||||
"Options": "Seçenekler",
|
||||
"Shorten URL": "URL kısaltma",
|
||||
"Editor": "Düzenleyici",
|
||||
"Preview": "Ön izleme",
|
||||
"Download attachment": "Download attachment",
|
||||
"Cloned: '%s'": "Cloned: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Attach a file",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
|
||||
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
|
||||
"Remove attachment": "Remove attachment",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.",
|
||||
"Invalid attachment.": "Invalid attachment.",
|
||||
"Options": "Options",
|
||||
"Shorten URL": "Shorten URL",
|
||||
"Editor": "Editor",
|
||||
"Preview": "Preview",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
|
||||
"Decrypt": "Şifreyi çöz",
|
||||
"Enter password": "Şifreyi girin",
|
||||
"Loading…": "Yükleniyor…",
|
||||
"Decrypting paste…": "Yazı şifresi çözülüyor…",
|
||||
"Preparing new paste…": "Yeni yazı hazırlanıyor…",
|
||||
"Decrypt": "Decrypt",
|
||||
"Enter password": "Enter password",
|
||||
"Loading…": "Loading…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.",
|
||||
"+++ no paste text +++": "+++ no paste text +++",
|
||||
"Could not get paste data: %s": "Yazı verisi alınamıyor: %s",
|
||||
"QR code": "QR kodu",
|
||||
"Could not get paste data: %s": "Could not get paste data: %s",
|
||||
"QR code": "QR code",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.": "For more information <a href=\"%s\">see this FAQ entry</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
|
||||
"waiting on user to provide a password": "waiting on user to provide a password",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Dosya şifresi çözülemedi, doğru şifreyi kullandığınıza emin misiniz? Üstteki buton ile tekrar deneyin.",
|
||||
"Retry": "Yeniden Dene",
|
||||
"Showing raw text…": "Açık yazı gösteriliyor…",
|
||||
"Notice:": "Bildirim:",
|
||||
"This link will expire after %s.": "Bu bağlantı şu kadar zaman sonra etkisiz kalacaktır: %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Bu bağlantı sadece bir kere erişilebilir, lütfen sayfayı yenilemeyiniz.",
|
||||
"Link:": "Bağlantı:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Alıcı zaman dilmini öğrenebilir, zaman dilimini UTC'ye çevirmek ister misin?",
|
||||
"Use Current Timezone": "Şuanki zaman dilimini kullan",
|
||||
"Convert To UTC": "UTC zaman dilimine çevir",
|
||||
"Close": "Kapat",
|
||||
"Encrypted note on %s": "%s üzerinde şifrelenmiş not",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Notu görmek için bu bağlantıyı ziyaret et. Bağlantıya sahip olan birisi notu görebilir.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL kısaltıcı şifreleme anahtarınızı URL içerisinde gösterebilir.",
|
||||
"Save paste": "Yazıyı kaydet",
|
||||
"Your IP is not authorized to create pastes.": "IP adresinizin yazı oluşturmaya yetkisi yoktur.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
|
||||
"Retry": "Retry",
|
||||
"Showing raw text…": "Showing raw text…",
|
||||
"Notice:": "Notice:",
|
||||
"This link will expire after %s.": "This link will expire after %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.",
|
||||
"Link:": "Link:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?",
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
44
i18n/uk.json
44
i18n/uk.json
@@ -8,10 +8,10 @@
|
||||
"%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] в конфігураційному файлі.",
|
||||
"Please wait %d seconds between each post.": [
|
||||
"Будь ласка, зачекайте %d секунду між створеннями.",
|
||||
"Будь ласка, зачекайте %d секунди між створеннями.",
|
||||
"Будь ласка, зачекайте %d секунд між створеннями.",
|
||||
"Будь ласка, зачекайте %d секунд між створеннями."
|
||||
"Please wait %d second between each post. (singular)",
|
||||
"Please wait %d seconds between each post. (1st plural)",
|
||||
"Please wait %d seconds between each post. (2nd plural)",
|
||||
"Please wait %d seconds between each post. (3rd plural)"
|
||||
],
|
||||
"Paste is limited to %s of encrypted data.": "Розмір допису обмежений %s зашифрованих даних.",
|
||||
"Invalid data.": "Неправильні дані.",
|
||||
@@ -170,24 +170,20 @@
|
||||
"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 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": "очікування користувача для вводу паролю",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Не вдалося розшифрувати дані. Може, ви ввели неправильний пароль? Спробуйте знову за допомогою верхньої кнопки.",
|
||||
"Retry": "Спробуйте ще раз",
|
||||
"Showing raw text…": "Відображається неформатований текст…",
|
||||
"Notice:": "Зверніть увагу:",
|
||||
"This link will expire after %s.": "Термін дії цього посилання сплине через %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "Дане посилання доступна тільки один раз, не натискайте кнопку назад та не обновляйте сторінку браузера.",
|
||||
"Link:": "Посилання:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Отримувач дізнається ваш часовий пояс, перетворити час в UTC?",
|
||||
"Use Current Timezone": "Використовувати поточний часовий пояс",
|
||||
"Convert To UTC": "Конвертувати в UTC",
|
||||
"Close": "Закрити",
|
||||
"Encrypted note on %s": "Зашифрована нотатка на %s",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Відвідайте посилання, щоб переглянути нотатку. Передача посилання будь-кому дозволить їм переглянути нотатку.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Сервіс скорочення посилань може викрити ваш ключ дешифрування з URL.",
|
||||
"Save paste": "Зберегти вставку",
|
||||
"Your IP is not authorized to create pastes.": "Вашому IP не дозволено створювати вставки.",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"waiting on user to provide a password": "waiting on user to provide a password",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
|
||||
"Retry": "Retry",
|
||||
"Showing raw text…": "Showing raw text…",
|
||||
"Notice:": "Notice:",
|
||||
"This link will expire after %s.": "This link will expire after %s.",
|
||||
"This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.",
|
||||
"Link:": "Link:",
|
||||
"Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?",
|
||||
"Use Current Timezone": "Use Current Timezone",
|
||||
"Convert To UTC": "Convert To UTC",
|
||||
"Close": "Close",
|
||||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
}
|
||||
|
||||
@@ -182,12 +182,8 @@
|
||||
"Use Current Timezone": "使用当前时区",
|
||||
"Convert To UTC": "转换为 UTC",
|
||||
"Close": "关闭",
|
||||
"Encrypted note on %s": "%s 上的加密笔记",
|
||||
"Encrypted note on PrivateBin": "PrivateBin 上的加密笔记",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "访问此链接来查看该笔记。将此 URL 发送给任何人即可允许其访问该笔记。",
|
||||
"URL shortener may expose your decrypt key in URL.": "短链接服务可能会暴露您在 URL 中的解密密钥。",
|
||||
"Save paste": "保存内容",
|
||||
"Your IP is not authorized to create pastes.": "您的 IP 无权创建粘贴。",
|
||||
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
|
||||
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
|
||||
"Error parsing YOURLS response.": "Error parsing YOURLS response."
|
||||
"Save paste": "保存内容"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
// change this, if your php files and data is outside of your webservers document root
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
'use strict';
|
||||
// base-x encoding / decoding
|
||||
// based on https://github.com/cryptocoinjs/base-x 3.0.7
|
||||
// modification: removed Buffer dependency and node.modules entry
|
||||
// Copyright (c) 2018 base-x contributors
|
||||
// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
(function(){
|
||||
this.baseX = function base (ALPHABET) {
|
||||
if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }
|
||||
var BASE_MAP = new Uint8Array(256)
|
||||
for (var j = 0; j < BASE_MAP.length; j++) {
|
||||
BASE_MAP[j] = 255
|
||||
}
|
||||
BASE_MAP.fill(255)
|
||||
for (var i = 0; i < ALPHABET.length; i++) {
|
||||
var x = ALPHABET.charAt(i)
|
||||
var xc = x.charCodeAt(0)
|
||||
@@ -22,13 +23,6 @@ this.baseX = function base (ALPHABET) {
|
||||
var FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up
|
||||
var iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up
|
||||
function encode (source) {
|
||||
if (source instanceof Uint8Array) {
|
||||
} else if (ArrayBuffer.isView(source)) {
|
||||
source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength)
|
||||
} else if (Array.isArray(source)) {
|
||||
source = Uint8Array.from(source)
|
||||
}
|
||||
if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') }
|
||||
if (source.length === 0) { return '' }
|
||||
// Skip & count leading zeroes.
|
||||
var zeroes = 0
|
||||
@@ -68,8 +62,10 @@ this.baseX = function base (ALPHABET) {
|
||||
}
|
||||
function decodeUnsafe (source) {
|
||||
if (typeof source !== 'string') { throw new TypeError('Expected String') }
|
||||
if (source.length === 0) { return new Uint8Array() }
|
||||
if (source.length === 0) { return '' }
|
||||
var psz = 0
|
||||
// Skip leading spaces.
|
||||
if (source[psz] === ' ') { return }
|
||||
// Skip and count leading '1's.
|
||||
var zeroes = 0
|
||||
var length = 0
|
||||
@@ -96,12 +92,14 @@ this.baseX = function base (ALPHABET) {
|
||||
length = i
|
||||
psz++
|
||||
}
|
||||
// Skip trailing spaces.
|
||||
if (source[psz] === ' ') { return }
|
||||
// Skip leading zeroes in b256.
|
||||
var it4 = size - length
|
||||
while (it4 !== size && b256[it4] === 0) {
|
||||
it4++
|
||||
}
|
||||
var vch = new Uint8Array(zeroes + (size - it4))
|
||||
var vch = []
|
||||
var j = zeroes
|
||||
while (it4 !== size) {
|
||||
vch[j++] = b256[it4++]
|
||||
7
js/bootstrap-3.3.7.js
vendored
Normal file
7
js/bootstrap-3.3.7.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
js/bootstrap-3.4.1.js
vendored
6
js/bootstrap-3.4.1.js
vendored
File diff suppressed because one or more lines are too long
13
js/common.js
13
js/common.js
@@ -10,17 +10,17 @@ global.fs = require('fs');
|
||||
global.WebCrypto = require('@peculiar/webcrypto').Crypto;
|
||||
|
||||
// application libraries to test
|
||||
global.$ = global.jQuery = require('./jquery-3.6.0');
|
||||
global.$ = global.jQuery = require('./jquery-3.4.1');
|
||||
global.RawDeflate = require('./rawinflate-0.3').RawDeflate;
|
||||
global.zlib = require('./zlib-1.2.13').zlib;
|
||||
global.zlib = require('./zlib-1.2.11').zlib;
|
||||
require('./prettify');
|
||||
global.prettyPrint = window.PR.prettyPrint;
|
||||
global.prettyPrintOne = window.PR.prettyPrintOne;
|
||||
global.showdown = require('./showdown-2.0.3');
|
||||
global.DOMPurify = require('./purify-2.3.6');
|
||||
global.baseX = require('./base-x-4.0.0').baseX;
|
||||
global.showdown = require('./showdown-1.9.1');
|
||||
global.DOMPurify = require('./purify-2.2.7');
|
||||
global.baseX = require('./base-x-3.0.7').baseX;
|
||||
global.Legacy = require('./legacy').Legacy;
|
||||
require('./bootstrap-3.4.1');
|
||||
require('./bootstrap-3.3.7');
|
||||
require('./privatebin');
|
||||
|
||||
// internal variables
|
||||
@@ -131,3 +131,4 @@ exports.jscMimeTypes = function() {
|
||||
exports.jscFormats = function() {
|
||||
return jsc.elements(formats);
|
||||
};
|
||||
|
||||
|
||||
2
js/jquery-3.4.1.js
vendored
Normal file
2
js/jquery-3.4.1.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/jquery-3.6.0.js
vendored
2
js/jquery-3.6.0.js
vendored
File diff suppressed because one or more lines are too long
1785
js/package-lock.json
generated
1785
js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "privatebin",
|
||||
"version": "1.4.0",
|
||||
"version": "1.3.0",
|
||||
"description": "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bit AES in Galois Counter mode (GCM).",
|
||||
"main": "privatebin.js",
|
||||
"directories": {
|
||||
|
||||
151
js/privatebin.js
151
js/privatebin.js
@@ -6,7 +6,7 @@
|
||||
* @see {@link https://github.com/PrivateBin/PrivateBin}
|
||||
* @copyright 2012 Sébastien SAUVAGE ({@link http://sebsauvage.net})
|
||||
* @license {@link https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License}
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
* @name PrivateBin
|
||||
* @namespace
|
||||
*/
|
||||
@@ -52,31 +52,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
*/
|
||||
let z;
|
||||
|
||||
/**
|
||||
* DOMpurify settings for HTML content
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
const purifyHtmlConfig = {
|
||||
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
|
||||
SAFE_FOR_JQUERY: true,
|
||||
USE_PROFILES: {
|
||||
html: true
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* DOMpurify settings for SVG content
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
const purifySvgConfig = {
|
||||
USE_PROFILES: {
|
||||
svg: true,
|
||||
svgFilters: true
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* CryptoData class
|
||||
*
|
||||
@@ -434,8 +409,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
element.html().replace(
|
||||
/(((https?|ftp):\/\/[\w?!=&.\/-;#@~%+*-]+(?![\w\s?!&.\/;#~%"=-]>))|((magnet):[\w?=&.\/-;#@~%+*-]+))/ig,
|
||||
'<a href="$1" rel="nofollow noopener noreferrer">$1</a>'
|
||||
),
|
||||
purifyHtmlConfig
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
@@ -627,7 +601,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
* @prop {string[]}
|
||||
* @readonly
|
||||
*/
|
||||
const supportedLanguages = ['bg', 'ca', 'co', 'cs', 'de', 'el', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sk', 'sl', 'th', 'tr', 'uk', 'zh'];
|
||||
const supportedLanguages = ['bg', 'ca', 'cs', 'de', 'es', 'et', 'fr', 'he', 'hu', 'id', 'it', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sl', 'uk', 'zh'];
|
||||
|
||||
/**
|
||||
* built in language
|
||||
@@ -793,7 +767,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
/**
|
||||
* per language functions to use to determine the plural form
|
||||
*
|
||||
* @see {@link https://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html}
|
||||
* @see {@link https://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html}
|
||||
* @name I18n.getPluralForm
|
||||
* @function
|
||||
* @param {int} n
|
||||
@@ -803,30 +777,25 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
switch (language)
|
||||
{
|
||||
case 'cs':
|
||||
case 'sk':
|
||||
return n === 1 ? 0 : (n >= 2 && n <= 4 ? 1 : 2);
|
||||
case 'co':
|
||||
return n === 1 ? 0 : (n >= 2 && n <=4 ? 1 : 2);
|
||||
case 'fr':
|
||||
case 'oc':
|
||||
case 'tr':
|
||||
case 'zh':
|
||||
return n > 1 ? 1 : 0;
|
||||
case 'he':
|
||||
return n === 1 ? 0 : (n === 2 ? 1 : ((n < 0 || n > 10) && (n % 10 === 0) ? 2 : 3));
|
||||
case 'id':
|
||||
case 'jbo':
|
||||
case 'th':
|
||||
return 0;
|
||||
case 'lt':
|
||||
return n % 10 === 1 && n % 100 !== 11 ? 0 : ((n % 10 >= 2 && n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
|
||||
case 'pl':
|
||||
return n === 1 ? 0 : (n % 10 >= 2 && n %10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
|
||||
return n === 1 ? 0 : (n % 10 >= 2 && n %10 <=4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
|
||||
case 'ru':
|
||||
case 'uk':
|
||||
return n % 10 === 1 && n % 100 !== 11 ? 0 : (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
|
||||
case 'sl':
|
||||
return n % 100 === 1 ? 1 : (n % 100 === 2 ? 2 : (n % 100 === 3 || n % 100 === 4 ? 3 : 0));
|
||||
// bg, ca, de, el, en, es, et, fi, hu, it, nl, no, pt
|
||||
// bg, ca, de, en, es, et, hu, it, nl, no, pt
|
||||
default:
|
||||
return n !== 1 ? 1 : 0;
|
||||
}
|
||||
@@ -2565,8 +2534,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
// let showdown convert the HTML and sanitize HTML *afterwards*!
|
||||
$plainText.html(
|
||||
DOMPurify.sanitize(
|
||||
converter.makeHtml(text),
|
||||
purifyHtmlConfig
|
||||
converter.makeHtml(text)
|
||||
)
|
||||
);
|
||||
// add table classes from bootstrap css
|
||||
@@ -2782,34 +2750,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
$dropzone;
|
||||
|
||||
/**
|
||||
* get blob URL from string data and mime type
|
||||
*
|
||||
* @name AttachmentViewer.getBlobUrl
|
||||
* @private
|
||||
* @function
|
||||
* @param {string} data - raw data of attachment
|
||||
* @param {string} data - mime type of attachment
|
||||
* @return {string} objectURL
|
||||
*/
|
||||
function getBlobUrl(data, mimeType)
|
||||
{
|
||||
// Transform into a Blob
|
||||
const buf = new Uint8Array(data.length);
|
||||
for (let i = 0; i < data.length; ++i) {
|
||||
buf[i] = data.charCodeAt(i);
|
||||
}
|
||||
const blob = new window.Blob(
|
||||
[buf],
|
||||
{
|
||||
type: mimeType
|
||||
}
|
||||
);
|
||||
|
||||
// Get blob URL
|
||||
return window.URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the attachment but does not yet show it
|
||||
*
|
||||
* @name AttachmentViewer.setAttachment
|
||||
@@ -2819,42 +2759,44 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
*/
|
||||
me.setAttachment = function(attachmentData, fileName)
|
||||
{
|
||||
// skip, if attachments got disabled
|
||||
if (!$attachmentLink || !$attachmentPreview) return;
|
||||
|
||||
// data URI format: data:[<mimeType>][;base64],<data>
|
||||
// data URI format: data:[<mediaType>][;base64],<data>
|
||||
|
||||
// position in data URI string of where data begins
|
||||
const base64Start = attachmentData.indexOf(',') + 1;
|
||||
// position in data URI string of where mimeType ends
|
||||
const mimeTypeEnd = attachmentData.indexOf(';');
|
||||
// position in data URI string of where mediaType ends
|
||||
const mediaTypeEnd = attachmentData.indexOf(';');
|
||||
|
||||
// extract mimeType
|
||||
const mimeType = attachmentData.substring(5, mimeTypeEnd);
|
||||
// extract mediaType
|
||||
const mediaType = attachmentData.substring(5, mediaTypeEnd);
|
||||
// extract data and convert to binary
|
||||
const rawData = attachmentData.substring(base64Start);
|
||||
const decodedData = rawData.length > 0 ? atob(rawData) : '';
|
||||
|
||||
let blobUrl = getBlobUrl(decodedData, mimeType);
|
||||
$attachmentLink.attr('href', blobUrl);
|
||||
// Transform into a Blob
|
||||
const buf = new Uint8Array(decodedData.length);
|
||||
for (let i = 0; i < decodedData.length; ++i) {
|
||||
buf[i] = decodedData.charCodeAt(i);
|
||||
}
|
||||
const blob = new window.Blob([ buf ], { type: mediaType });
|
||||
|
||||
// Get Blob URL
|
||||
const blobUrl = window.URL.createObjectURL(blob);
|
||||
|
||||
// IE does not support setting a data URI on an a element
|
||||
// Using msSaveBlob to download
|
||||
if (window.Blob && navigator.msSaveBlob) {
|
||||
$attachmentLink.off('click').on('click', function () {
|
||||
navigator.msSaveBlob(blob, fileName);
|
||||
});
|
||||
} else {
|
||||
$attachmentLink.attr('href', blobUrl);
|
||||
}
|
||||
|
||||
if (typeof fileName !== 'undefined') {
|
||||
$attachmentLink.attr('download', fileName);
|
||||
}
|
||||
|
||||
// sanitize SVG preview
|
||||
// prevents executing embedded scripts when CSP is not set and user
|
||||
// right-clicks/long-taps and opens the SVG in a new tab - prevented
|
||||
// in the preview by use of an img tag, which disables scripts, too
|
||||
if (mimeType.match(/^image\/.*svg/i)) {
|
||||
const sanitizedData = DOMPurify.sanitize(
|
||||
decodedData,
|
||||
purifySvgConfig
|
||||
);
|
||||
blobUrl = getBlobUrl(sanitizedData, mimeType);
|
||||
}
|
||||
|
||||
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mimeType);
|
||||
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mediaType);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2865,9 +2807,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
*/
|
||||
me.showAttachment = function()
|
||||
{
|
||||
// skip, if attachments got disabled
|
||||
if (!$attachment || !$attachmentPreview) return;
|
||||
|
||||
$attachment.removeClass('hidden');
|
||||
|
||||
if (attachmentHasPreview) {
|
||||
@@ -3075,13 +3014,13 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
me.handleBlobAttachmentPreview = function ($targetElement, blobUrl, mimeType) {
|
||||
if (blobUrl) {
|
||||
attachmentHasPreview = true;
|
||||
if (mimeType.match(/^image\//i)) {
|
||||
if (mimeType.match(/image\//i)) {
|
||||
$targetElement.html(
|
||||
$(document.createElement('img'))
|
||||
.attr('src', blobUrl)
|
||||
.attr('class', 'img-thumbnail')
|
||||
);
|
||||
} else if (mimeType.match(/^video\//i)) {
|
||||
} else if (mimeType.match(/video\//i)) {
|
||||
$targetElement.html(
|
||||
$(document.createElement('video'))
|
||||
.attr('controls', 'true')
|
||||
@@ -3092,7 +3031,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
.attr('type', mimeType)
|
||||
.attr('src', blobUrl))
|
||||
);
|
||||
} else if (mimeType.match(/^audio\//i)) {
|
||||
} else if (mimeType.match(/audio\//i)) {
|
||||
$targetElement.html(
|
||||
$(document.createElement('audio'))
|
||||
.attr('controls', 'true')
|
||||
@@ -3724,14 +3663,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
for (let i = 0; i < $head.length; ++i) {
|
||||
newDoc.write($head[i].outerHTML);
|
||||
}
|
||||
newDoc.write(
|
||||
'</head><body><pre>' +
|
||||
DOMPurify.sanitize(
|
||||
Helper.htmlEntities(paste),
|
||||
purifyHtmlConfig
|
||||
) +
|
||||
'</pre></body></html>'
|
||||
);
|
||||
newDoc.write('</head><body><pre>' + DOMPurify.sanitize(Helper.htmlEntities(paste)) + '</pre></body></html>');
|
||||
newDoc.close();
|
||||
}
|
||||
|
||||
@@ -5460,6 +5392,11 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
// first load translations
|
||||
I18n.loadTranslations();
|
||||
|
||||
DOMPurify.setConfig({
|
||||
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
|
||||
SAFE_FOR_JQUERY: true
|
||||
});
|
||||
|
||||
// Add a hook to make all links open a new window
|
||||
DOMPurify.addHook('afterSanitizeAttributes', function(node) {
|
||||
// set all elements owning target to target=_blank
|
||||
@@ -5467,8 +5404,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||
node.setAttribute('target', '_blank');
|
||||
}
|
||||
// set non-HTML/MathML links to xlink:show=new
|
||||
if (!node.hasAttribute('target')
|
||||
&& (node.hasAttribute('xlink:href')
|
||||
if (!node.hasAttribute('target')
|
||||
&& (node.hasAttribute('xlink:href')
|
||||
|| node.hasAttribute('href'))) {
|
||||
node.setAttribute('xlink:show', 'new');
|
||||
}
|
||||
|
||||
2
js/purify-2.2.7.js
Normal file
2
js/purify-2.2.7.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
js/showdown-1.9.1.js
Normal file
2
js/showdown-1.9.1.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -110,3 +110,4 @@ describe('DiscussionViewer', function () {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -52,12 +52,12 @@ describe('Editor', function () {
|
||||
!$.PrivateBin.Editor.isPreview() &&
|
||||
!$('#message').hasClass('hidden')
|
||||
);
|
||||
$('#messagepreview').trigger('click');
|
||||
$('#messagepreview').click();
|
||||
results.push(
|
||||
$.PrivateBin.Editor.isPreview() &&
|
||||
$('#message').hasClass('hidden')
|
||||
);
|
||||
$('#messageedit').trigger('click');
|
||||
$('#messageedit').click();
|
||||
results.push(
|
||||
!$.PrivateBin.Editor.isPreview() &&
|
||||
!$('#message').hasClass('hidden')
|
||||
@@ -68,3 +68,4 @@ describe('Editor', function () {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -280,8 +280,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'collapses the navigation when displayed on a small screen',
|
||||
function () {
|
||||
var clean = jsdom(),
|
||||
results = [];
|
||||
var results = [];
|
||||
$('body').html(
|
||||
'<nav><div class="navbar-header"><button type="button" ' +
|
||||
'class="navbar-toggle collapsed" data-toggle="collapse" ' +
|
||||
@@ -302,11 +301,7 @@ describe('TopNav', function () {
|
||||
$('.navbar-toggle').hasClass('collapsed') &&
|
||||
$('#navbar').attr('aria-expanded') != 'true'
|
||||
);
|
||||
/*
|
||||
with the upgrade for bootstrap-3.3.7.js to bootstrap-3.4.1.js
|
||||
the mobile interface detection changed to check if the
|
||||
ontouchstart event exists, which broke this section of the test
|
||||
$('.navbar-toggle').trigger('click');
|
||||
$('.navbar-toggle').click();
|
||||
results.push(
|
||||
!$('.navbar-toggle').hasClass('collapsed') &&
|
||||
$('#navbar').attr('aria-expanded') == 'true'
|
||||
@@ -316,8 +311,7 @@ describe('TopNav', function () {
|
||||
$('.navbar-toggle').hasClass('collapsed') &&
|
||||
$('#navbar').attr('aria-expanded') == 'false'
|
||||
);
|
||||
*/
|
||||
clean();
|
||||
cleanup();
|
||||
assert.ok(results.every(element => element));
|
||||
}
|
||||
);
|
||||
@@ -676,3 +670,4 @@ describe('TopNav', function () {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
|
||||
let buff;
|
||||
if (typeof fetch === 'undefined') {
|
||||
buff = fs.readFileSync('zlib-1.2.13.wasm');
|
||||
buff = fs.readFileSync('zlib-1.2.11.wasm');
|
||||
} else {
|
||||
const resp = await fetch('js/zlib-1.2.13.wasm');
|
||||
const resp = await fetch('js/zlib-1.2.11.wasm');
|
||||
buff = await resp.arrayBuffer();
|
||||
}
|
||||
const module = await WebAssembly.compile(buff);
|
||||
BIN
js/zlib-1.2.11.wasm
Normal file
BIN
js/zlib-1.2.11.wasm
Normal file
Binary file not shown.
Binary file not shown.
@@ -7,13 +7,14 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
||||
use Exception;
|
||||
use PDO;
|
||||
use PrivateBin\Persistence\DataStore;
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
@@ -44,7 +45,7 @@ class Configuration
|
||||
'fileupload' => false,
|
||||
'burnafterreadingselected' => false,
|
||||
'defaultformatter' => 'plaintext',
|
||||
'syntaxhighlightingtheme' => '',
|
||||
'syntaxhighlightingtheme' => null,
|
||||
'sizelimit' => 10485760,
|
||||
'template' => 'bootstrap',
|
||||
'info' => 'More information on the <a href=\'https://privatebin.info/\'>project page</a>.',
|
||||
@@ -53,8 +54,8 @@ class Configuration
|
||||
'languagedefault' => '',
|
||||
'urlshortener' => '',
|
||||
'qrcode' => true,
|
||||
'icon' => 'jdenticon',
|
||||
'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\'; style-src \'self\'; font-src \'self\'; frame-ancestors \'none\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads',
|
||||
'icon' => 'identicon',
|
||||
'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\' resource:; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads',
|
||||
'zerobincompatibility' => false,
|
||||
'httpwarning' => true,
|
||||
'compression' => 'zlib',
|
||||
@@ -78,14 +79,15 @@ class Configuration
|
||||
'markdown' => 'Markdown',
|
||||
),
|
||||
'traffic' => array(
|
||||
'limit' => 10,
|
||||
'header' => '',
|
||||
'exempted' => '',
|
||||
'creators' => '',
|
||||
'limit' => 10,
|
||||
'header' => null,
|
||||
'dir' => 'data',
|
||||
'exemptedIp' => null,
|
||||
),
|
||||
'purge' => array(
|
||||
'limit' => 300,
|
||||
'batchsize' => 10,
|
||||
'dir' => 'data',
|
||||
),
|
||||
'model' => array(
|
||||
'class' => 'Filesystem',
|
||||
@@ -93,10 +95,6 @@ class Configuration
|
||||
'model_options' => array(
|
||||
'dir' => 'data',
|
||||
),
|
||||
'yourls' => array(
|
||||
'signature' => '',
|
||||
'apiurl' => '',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -106,23 +104,28 @@ class Configuration
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$basePaths = array();
|
||||
$config = array();
|
||||
$configPath = getenv('CONFIG_PATH');
|
||||
if ($configPath !== false && !empty($configPath)) {
|
||||
$basePaths[] = $configPath;
|
||||
$basePath = (getenv('CONFIG_PATH') !== false ? getenv('CONFIG_PATH') : PATH . 'cfg') . DIRECTORY_SEPARATOR;
|
||||
$configIni = $basePath . 'conf.ini';
|
||||
$configFile = $basePath . 'conf.php';
|
||||
|
||||
// rename INI files to avoid configuration leakage
|
||||
if (is_readable($configIni)) {
|
||||
DataStore::prependRename($configIni, $configFile, ';');
|
||||
|
||||
// cleanup sample, too
|
||||
$configIniSample = $configIni . '.sample';
|
||||
if (is_readable($configIniSample)) {
|
||||
DataStore::prependRename($configIniSample, $basePath . 'conf.sample.php', ';');
|
||||
}
|
||||
}
|
||||
$basePaths[] = PATH . 'cfg';
|
||||
foreach ($basePaths as $basePath) {
|
||||
$configFile = $basePath . DIRECTORY_SEPARATOR . 'conf.php';
|
||||
if (is_readable($configFile)) {
|
||||
$config = parse_ini_file($configFile, true);
|
||||
foreach (array('main', 'model', 'model_options') as $section) {
|
||||
if (!array_key_exists($section, $config)) {
|
||||
throw new Exception(I18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 2);
|
||||
}
|
||||
|
||||
if (is_readable($configFile)) {
|
||||
$config = parse_ini_file($configFile, true);
|
||||
foreach (array('main', 'model', 'model_options') as $section) {
|
||||
if (!array_key_exists($section, $config)) {
|
||||
throw new Exception(I18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,25 +160,8 @@ class Configuration
|
||||
)
|
||||
) {
|
||||
$values = array(
|
||||
'bucket' => getenv('PRIVATEBIN_GCS_BUCKET') ? getenv('PRIVATEBIN_GCS_BUCKET') : null,
|
||||
'prefix' => 'pastes',
|
||||
'uniformacl' => false,
|
||||
);
|
||||
} elseif (
|
||||
$section == 'model_options' && in_array(
|
||||
$this->_configuration['model']['class'],
|
||||
array('S3Storage')
|
||||
)
|
||||
) {
|
||||
$values = array(
|
||||
'region' => null,
|
||||
'version' => null,
|
||||
'endpoint' => null,
|
||||
'accesskey' => null,
|
||||
'secretkey' => null,
|
||||
'use_path_style_endpoint' => null,
|
||||
'bucket' => null,
|
||||
'prefix' => '',
|
||||
'bucket' => getenv('PRIVATEBIN_GCS_BUCKET') ? getenv('PRIVATEBIN_GCS_BUCKET') : null,
|
||||
'prefix' => 'pastes',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -236,14 +222,6 @@ class Configuration
|
||||
if (!array_key_exists($this->_configuration['expire']['default'], $this->_configuration['expire_options'])) {
|
||||
$this->_configuration['expire']['default'] = key($this->_configuration['expire_options']);
|
||||
}
|
||||
|
||||
// ensure the basepath ends in a slash, if one is set
|
||||
if (
|
||||
strlen($this->_configuration['main']['basepath']) &&
|
||||
substr_compare($this->_configuration['main']['basepath'], '/', -1) !== 0
|
||||
) {
|
||||
$this->_configuration['main']['basepath'] .= '/';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@@ -28,7 +28,7 @@ class Controller
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const VERSION = '1.4.0';
|
||||
const VERSION = '1.3.5';
|
||||
|
||||
/**
|
||||
* minimal required PHP version
|
||||
@@ -136,9 +136,6 @@ class Controller
|
||||
case 'jsonld':
|
||||
$this->_jsonld($this->_request->getParam('jsonld'));
|
||||
return;
|
||||
case 'yourlsproxy':
|
||||
$this->_yourlsproxy($this->_request->getParam('link'));
|
||||
break;
|
||||
}
|
||||
|
||||
// output JSON or HTML
|
||||
@@ -165,6 +162,7 @@ class Controller
|
||||
$this->_model = new Model($this->_conf);
|
||||
$this->_request = new Request;
|
||||
$this->_urlBase = $this->_request->getRequestUri();
|
||||
ServerSalt::setPath($this->_conf->getKey('dir', 'traffic'));
|
||||
|
||||
// set default language
|
||||
$lang = $this->_conf->getKey('languagedefault');
|
||||
@@ -198,14 +196,20 @@ class Controller
|
||||
*/
|
||||
private function _create()
|
||||
{
|
||||
// Ensure last paste from visitors IP address was more than configured amount of seconds ago.
|
||||
ServerSalt::setStore($this->_model->getStore());
|
||||
TrafficLimiter::setConfiguration($this->_conf);
|
||||
TrafficLimiter::setStore($this->_model->getStore());
|
||||
try {
|
||||
TrafficLimiter::canPass();
|
||||
// Ensure last paste from visitors IP address was more than configured amount of seconds ago.
|
||||
TrafficLimiter::setConfiguration($this->_conf);
|
||||
if (!TrafficLimiter::canPass()) {
|
||||
$this->_return_message(
|
||||
1, I18n::_(
|
||||
'Please wait %d seconds between each post.',
|
||||
$this->_conf->getKey('limit', 'traffic')
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->_return_message(1, $e->getMessage());
|
||||
$this->_return_message(1, I18n::_($e->getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -344,11 +348,8 @@ class Controller
|
||||
header('Content-Security-Policy: ' . $this->_conf->getKey('cspheader'));
|
||||
header('Cross-Origin-Resource-Policy: same-origin');
|
||||
header('Cross-Origin-Embedder-Policy: require-corp');
|
||||
// disabled, because it prevents links from a paste to the same site to
|
||||
// be opened. Didn't work with `same-origin-allow-popups` either.
|
||||
// See issue https://github.com/PrivateBin/PrivateBin/issues/970 for details.
|
||||
// header('Cross-Origin-Opener-Policy: same-origin');
|
||||
header('Permissions-Policy: browsing-topics=()');
|
||||
header('Cross-Origin-Opener-Policy: same-origin');
|
||||
header('Permissions-Policy: interest-cohort=()');
|
||||
header('Referrer-Policy: no-referrer');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
header('X-Frame-Options: deny');
|
||||
@@ -370,26 +371,10 @@ class Controller
|
||||
setcookie('lang', $languageselection, 0, '', '', true);
|
||||
}
|
||||
|
||||
// strip policies that are unsupported in meta tag
|
||||
$metacspheader = str_replace(
|
||||
array(
|
||||
'frame-ancestors \'none\'; ',
|
||||
'; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads',
|
||||
),
|
||||
'',
|
||||
$this->_conf->getKey('cspheader')
|
||||
);
|
||||
|
||||
$page = new View;
|
||||
$page->assign('CSPHEADER', $metacspheader);
|
||||
$page->assign('ERROR', I18n::_($this->_error));
|
||||
$page->assign('NAME', $this->_conf->getKey('name'));
|
||||
if ($this->_request->getOperation() === 'yourlsproxy') {
|
||||
$page->assign('SHORTURL', $this->_status);
|
||||
$page->draw('yourlsproxy');
|
||||
return;
|
||||
}
|
||||
$page->assign('BASEPATH', I18n::_($this->_conf->getKey('basepath')));
|
||||
$page->assign('ERROR', I18n::_($this->_error));
|
||||
$page->assign('STATUS', I18n::_($this->_status));
|
||||
$page->assign('VERSION', self::VERSION);
|
||||
$page->assign('DISCUSSION', $this->_conf->getKey('discussion'));
|
||||
@@ -447,22 +432,6 @@ class Controller
|
||||
echo $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* proxies link to YOURLS, updates status or error with response
|
||||
*
|
||||
* @access private
|
||||
* @param string $link
|
||||
*/
|
||||
private function _yourlsproxy($link)
|
||||
{
|
||||
$yourls = new YourlsProxy($this->_conf, $link);
|
||||
if ($yourls->isError()) {
|
||||
$this->_error = $yourls->getError();
|
||||
} else {
|
||||
$this->_status = $yourls->getUrl();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* prepares JSON encoded status message
|
||||
*
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
@@ -15,17 +15,52 @@ namespace PrivateBin\Data;
|
||||
/**
|
||||
* AbstractData
|
||||
*
|
||||
* Abstract model for data access
|
||||
* Abstract model for PrivateBin data access, implemented as a singleton.
|
||||
*/
|
||||
abstract class AbstractData
|
||||
{
|
||||
/**
|
||||
* cache for the traffic limiter
|
||||
* singleton instance
|
||||
*
|
||||
* @access protected
|
||||
* @var array
|
||||
* @static
|
||||
* @var AbstractData
|
||||
*/
|
||||
protected $_last_cache = array();
|
||||
protected static $_instance = null;
|
||||
|
||||
/**
|
||||
* enforce singleton, disable constructor
|
||||
*
|
||||
* Instantiate using {@link getInstance()}, privatebin is a singleton object.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* enforce singleton, disable cloning
|
||||
*
|
||||
* Instantiate using {@link getInstance()}, privatebin is a singleton object.
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* get instance of singleton
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $options
|
||||
* @return AbstractData
|
||||
*/
|
||||
public static function getInstance(array $options)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a paste.
|
||||
@@ -95,46 +130,6 @@ abstract class AbstractData
|
||||
*/
|
||||
abstract public function existsComment($pasteid, $parentid, $commentid);
|
||||
|
||||
/**
|
||||
* Purge outdated entries.
|
||||
*
|
||||
* @access public
|
||||
* @param string $namespace
|
||||
* @param int $time
|
||||
* @return void
|
||||
*/
|
||||
public function purgeValues($namespace, $time)
|
||||
{
|
||||
if ($namespace === 'traffic_limiter') {
|
||||
foreach ($this->_last_cache as $key => $last_submission) {
|
||||
if ($last_submission <= $time) {
|
||||
unset($this->_last_cache[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a value.
|
||||
*
|
||||
* @access public
|
||||
* @param string $value
|
||||
* @param string $namespace
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function setValue($value, $namespace, $key = '');
|
||||
|
||||
/**
|
||||
* Load a value.
|
||||
*
|
||||
* @access public
|
||||
* @param string $namespace
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getValue($namespace, $key = '');
|
||||
|
||||
/**
|
||||
* Returns up to batch size number of paste ids that have expired
|
||||
*
|
||||
@@ -163,14 +158,6 @@ abstract class AbstractData
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all paste ids
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
abstract public function getAllPastes();
|
||||
|
||||
/**
|
||||
* Get next free slot for comment from postdate.
|
||||
*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,13 +7,12 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
|
||||
use Exception;
|
||||
use PrivateBin\Json;
|
||||
use PrivateBin\Persistence\DataStore;
|
||||
|
||||
/**
|
||||
* Filesystem
|
||||
@@ -23,43 +22,27 @@ use PrivateBin\Json;
|
||||
class Filesystem extends AbstractData
|
||||
{
|
||||
/**
|
||||
* first line in paste or comment files, to protect their contents from browsing exposed data directories
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const PROTECTION_LINE = '<?php http_response_code(403); /*';
|
||||
|
||||
/**
|
||||
* line in generated .htaccess files, to protect exposed directories from being browsable on apache web servers
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const HTACCESS_LINE = 'Require all denied';
|
||||
|
||||
/**
|
||||
* path in which to persist something
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_path = 'data';
|
||||
|
||||
/**
|
||||
* instantiates a new Filesystem data backend
|
||||
* get instance of singleton
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $options
|
||||
* @return
|
||||
* @return Filesystem
|
||||
*/
|
||||
public function __construct(array $options)
|
||||
public static function getInstance(array $options)
|
||||
{
|
||||
// if needed initialize the singleton
|
||||
if (!(self::$_instance instanceof self)) {
|
||||
self::$_instance = new self;
|
||||
}
|
||||
// if given update the data directory
|
||||
if (
|
||||
is_array($options) &&
|
||||
array_key_exists('dir', $options)
|
||||
) {
|
||||
$this->_path = $options['dir'];
|
||||
DataStore::setPath($options['dir']);
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +55,7 @@ class Filesystem extends AbstractData
|
||||
*/
|
||||
public function create($pasteid, array $paste)
|
||||
{
|
||||
$storagedir = $this->_dataid2path($pasteid);
|
||||
$storagedir = self::_dataid2path($pasteid);
|
||||
$file = $storagedir . $pasteid . '.php';
|
||||
if (is_file($file)) {
|
||||
return false;
|
||||
@@ -80,7 +63,7 @@ class Filesystem extends AbstractData
|
||||
if (!is_dir($storagedir)) {
|
||||
mkdir($storagedir, 0700, true);
|
||||
}
|
||||
return $this->_store($file, $paste);
|
||||
return DataStore::store($file, $paste);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,13 +75,12 @@ class Filesystem extends AbstractData
|
||||
*/
|
||||
public function read($pasteid)
|
||||
{
|
||||
if (
|
||||
!$this->exists($pasteid) ||
|
||||
!$paste = $this->_get($this->_dataid2path($pasteid) . $pasteid . '.php')
|
||||
) {
|
||||
if (!$this->exists($pasteid)) {
|
||||
return false;
|
||||
}
|
||||
return self::upgradePreV1Format($paste);
|
||||
return self::upgradePreV1Format(
|
||||
DataStore::get(self::_dataid2path($pasteid) . $pasteid . '.php')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +91,7 @@ class Filesystem extends AbstractData
|
||||
*/
|
||||
public function delete($pasteid)
|
||||
{
|
||||
$pastedir = $this->_dataid2path($pasteid);
|
||||
$pastedir = self::_dataid2path($pasteid);
|
||||
if (is_dir($pastedir)) {
|
||||
// Delete the paste itself.
|
||||
if (is_file($pastedir . $pasteid . '.php')) {
|
||||
@@ -117,7 +99,7 @@ class Filesystem extends AbstractData
|
||||
}
|
||||
|
||||
// Delete discussion if it exists.
|
||||
$discdir = $this->_dataid2discussionpath($pasteid);
|
||||
$discdir = self::_dataid2discussionpath($pasteid);
|
||||
if (is_dir($discdir)) {
|
||||
// Delete all files in discussion directory
|
||||
$dir = dir($discdir);
|
||||
@@ -141,20 +123,20 @@ class Filesystem extends AbstractData
|
||||
*/
|
||||
public function exists($pasteid)
|
||||
{
|
||||
$basePath = $this->_dataid2path($pasteid) . $pasteid;
|
||||
$basePath = self::_dataid2path($pasteid) . $pasteid;
|
||||
$pastePath = $basePath . '.php';
|
||||
// convert to PHP protected files if needed
|
||||
if (is_readable($basePath)) {
|
||||
$this->_prependRename($basePath, $pastePath);
|
||||
DataStore::prependRename($basePath, $pastePath);
|
||||
|
||||
// convert comments, too
|
||||
$discdir = $this->_dataid2discussionpath($pasteid);
|
||||
$discdir = self::_dataid2discussionpath($pasteid);
|
||||
if (is_dir($discdir)) {
|
||||
$dir = dir($discdir);
|
||||
while (false !== ($filename = $dir->read())) {
|
||||
if (substr($filename, -4) !== '.php' && strlen($filename) >= 16) {
|
||||
$commentFilename = $discdir . $filename . '.php';
|
||||
$this->_prependRename($discdir . $filename, $commentFilename);
|
||||
DataStore::prependRename($discdir . $filename, $commentFilename);
|
||||
}
|
||||
}
|
||||
$dir->close();
|
||||
@@ -175,7 +157,7 @@ class Filesystem extends AbstractData
|
||||
*/
|
||||
public function createComment($pasteid, $parentid, $commentid, array $comment)
|
||||
{
|
||||
$storagedir = $this->_dataid2discussionpath($pasteid);
|
||||
$storagedir = self::_dataid2discussionpath($pasteid);
|
||||
$file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid . '.php';
|
||||
if (is_file($file)) {
|
||||
return false;
|
||||
@@ -183,7 +165,7 @@ class Filesystem extends AbstractData
|
||||
if (!is_dir($storagedir)) {
|
||||
mkdir($storagedir, 0700, true);
|
||||
}
|
||||
return $this->_store($file, $comment);
|
||||
return DataStore::store($file, $comment);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +178,7 @@ class Filesystem extends AbstractData
|
||||
public function readComments($pasteid)
|
||||
{
|
||||
$comments = array();
|
||||
$discdir = $this->_dataid2discussionpath($pasteid);
|
||||
$discdir = self::_dataid2discussionpath($pasteid);
|
||||
if (is_dir($discdir)) {
|
||||
$dir = dir($discdir);
|
||||
while (false !== ($filename = $dir->read())) {
|
||||
@@ -205,7 +187,7 @@ class Filesystem extends AbstractData
|
||||
// - commentid is the comment identifier itself.
|
||||
// - parentid is the comment this comment replies to (It can be pasteid)
|
||||
if (is_file($discdir . $filename)) {
|
||||
$comment = $this->_get($discdir . $filename);
|
||||
$comment = DataStore::get($discdir . $filename);
|
||||
$items = explode('.', $filename);
|
||||
// Add some meta information not contained in file.
|
||||
$comment['id'] = $items[1];
|
||||
@@ -236,101 +218,11 @@ class Filesystem extends AbstractData
|
||||
public function existsComment($pasteid, $parentid, $commentid)
|
||||
{
|
||||
return is_file(
|
||||
$this->_dataid2discussionpath($pasteid) .
|
||||
self::_dataid2discussionpath($pasteid) .
|
||||
$pasteid . '.' . $commentid . '.' . $parentid . '.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a value.
|
||||
*
|
||||
* @access public
|
||||
* @param string $value
|
||||
* @param string $namespace
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function setValue($value, $namespace, $key = '')
|
||||
{
|
||||
switch ($namespace) {
|
||||
case 'purge_limiter':
|
||||
return $this->_storeString(
|
||||
$this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php',
|
||||
'<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . $value . ';'
|
||||
);
|
||||
case 'salt':
|
||||
return $this->_storeString(
|
||||
$this->_path . DIRECTORY_SEPARATOR . 'salt.php',
|
||||
'<?php # |' . $value . '|'
|
||||
);
|
||||
case 'traffic_limiter':
|
||||
$this->_last_cache[$key] = $value;
|
||||
return $this->_storeString(
|
||||
$this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php',
|
||||
'<?php' . PHP_EOL . '$GLOBALS[\'traffic_limiter\'] = ' . var_export($this->_last_cache, true) . ';'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a value.
|
||||
*
|
||||
* @access public
|
||||
* @param string $namespace
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
public function getValue($namespace, $key = '')
|
||||
{
|
||||
switch ($namespace) {
|
||||
case 'purge_limiter':
|
||||
$file = $this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php';
|
||||
if (is_readable($file)) {
|
||||
require $file;
|
||||
return $GLOBALS['purge_limiter'];
|
||||
}
|
||||
break;
|
||||
case 'salt':
|
||||
$file = $this->_path . DIRECTORY_SEPARATOR . 'salt.php';
|
||||
if (is_readable($file)) {
|
||||
$items = explode('|', file_get_contents($file));
|
||||
if (is_array($items) && count($items) == 3) {
|
||||
return $items[1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'traffic_limiter':
|
||||
$file = $this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php';
|
||||
if (is_readable($file)) {
|
||||
require $file;
|
||||
$this->_last_cache = $GLOBALS['traffic_limiter'];
|
||||
if (array_key_exists($key, $this->_last_cache)) {
|
||||
return $this->_last_cache[$key];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* get the data
|
||||
*
|
||||
* @access public
|
||||
* @param string $filename
|
||||
* @return array|false $data
|
||||
*/
|
||||
private function _get($filename)
|
||||
{
|
||||
return Json::decode(
|
||||
substr(
|
||||
file_get_contents($filename),
|
||||
strlen(self::PROTECTION_LINE . PHP_EOL)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns up to batch size number of paste ids that have expired
|
||||
*
|
||||
@@ -341,17 +233,18 @@ class Filesystem extends AbstractData
|
||||
protected function _getExpiredPastes($batchsize)
|
||||
{
|
||||
$pastes = array();
|
||||
$mainpath = DataStore::getPath();
|
||||
$firstLevel = array_filter(
|
||||
scandir($this->_path),
|
||||
'PrivateBin\Data\Filesystem::_isFirstLevelDir'
|
||||
scandir($mainpath),
|
||||
'self::_isFirstLevelDir'
|
||||
);
|
||||
if (count($firstLevel) > 0) {
|
||||
// try at most 10 times the $batchsize pastes before giving up
|
||||
for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) {
|
||||
$firstKey = array_rand($firstLevel);
|
||||
$secondLevel = array_filter(
|
||||
scandir($this->_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]),
|
||||
'PrivateBin\Data\Filesystem::_isSecondLevelDir'
|
||||
scandir($mainpath . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]),
|
||||
'self::_isSecondLevelDir'
|
||||
);
|
||||
|
||||
// skip this folder in the next checks if it is empty
|
||||
@@ -361,7 +254,7 @@ class Filesystem extends AbstractData
|
||||
}
|
||||
|
||||
$secondKey = array_rand($secondLevel);
|
||||
$path = $this->_path . DIRECTORY_SEPARATOR .
|
||||
$path = $mainpath . DIRECTORY_SEPARATOR .
|
||||
$firstLevel[$firstKey] . DIRECTORY_SEPARATOR .
|
||||
$secondLevel[$secondKey];
|
||||
if (!is_dir($path)) {
|
||||
@@ -404,46 +297,6 @@ class Filesystem extends AbstractData
|
||||
return $pastes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getAllPastes()
|
||||
{
|
||||
$pastes = array();
|
||||
$subdirs = scandir($this->_path);
|
||||
if ($subdirs === false) {
|
||||
dieerr('Unable to list directory ' . $this->_path);
|
||||
}
|
||||
$subdirs = preg_grep('/^[^.].$/', $subdirs);
|
||||
|
||||
foreach ($subdirs as $subdir) {
|
||||
$subpath = $this->_path . DIRECTORY_SEPARATOR . $subdir;
|
||||
|
||||
$subsubdirs = scandir($subpath);
|
||||
if ($subsubdirs === false) {
|
||||
dieerr('Unable to list directory ' . $subpath);
|
||||
}
|
||||
$subsubdirs = preg_grep('/^[^.].$/', $subsubdirs);
|
||||
foreach ($subsubdirs as $subsubdir) {
|
||||
$subsubpath = $subpath . DIRECTORY_SEPARATOR . $subsubdir;
|
||||
|
||||
$files = scandir($subsubpath);
|
||||
if ($files === false) {
|
||||
dieerr('Unable to list directory ' . $subsubpath);
|
||||
}
|
||||
$files = preg_grep('/\.php$/', $files);
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (substr($file, 0, 4) === $subdir . $subsubdir) {
|
||||
$pastes[] = substr($file, 0, strlen($file) - 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $pastes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert paste id to storage path.
|
||||
*
|
||||
@@ -455,14 +308,16 @@ class Filesystem extends AbstractData
|
||||
* eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/'
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $dataid
|
||||
* @return string
|
||||
*/
|
||||
private function _dataid2path($dataid)
|
||||
private static function _dataid2path($dataid)
|
||||
{
|
||||
return $this->_path . DIRECTORY_SEPARATOR .
|
||||
return DataStore::getPath(
|
||||
substr($dataid, 0, 2) . DIRECTORY_SEPARATOR .
|
||||
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR;
|
||||
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -471,12 +326,13 @@ class Filesystem extends AbstractData
|
||||
* eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/e3570978f9e4aa90.discussion/'
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $dataid
|
||||
* @return string
|
||||
*/
|
||||
private function _dataid2discussionpath($dataid)
|
||||
private static function _dataid2discussionpath($dataid)
|
||||
{
|
||||
return $this->_dataid2path($dataid) . $dataid .
|
||||
return self::_dataid2path($dataid) . $dataid .
|
||||
'.discussion' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
@@ -484,114 +340,26 @@ class Filesystem extends AbstractData
|
||||
* Check that the given element is a valid first level directory.
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $element
|
||||
* @return bool
|
||||
*/
|
||||
private function _isFirstLevelDir($element)
|
||||
private static function _isFirstLevelDir($element)
|
||||
{
|
||||
return $this->_isSecondLevelDir($element) &&
|
||||
is_dir($this->_path . DIRECTORY_SEPARATOR . $element);
|
||||
return self::_isSecondLevelDir($element) &&
|
||||
is_dir(DataStore::getPath($element));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given element is a valid second level directory.
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $element
|
||||
* @return bool
|
||||
*/
|
||||
private function _isSecondLevelDir($element)
|
||||
private static function _isSecondLevelDir($element)
|
||||
{
|
||||
return (bool) preg_match('/^[a-f0-9]{2}$/', $element);
|
||||
}
|
||||
|
||||
/**
|
||||
* store the data
|
||||
*
|
||||
* @access public
|
||||
* @param string $filename
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
private function _store($filename, array $data)
|
||||
{
|
||||
try {
|
||||
return $this->_storeString(
|
||||
$filename,
|
||||
self::PROTECTION_LINE . PHP_EOL . Json::encode($data)
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* store a string
|
||||
*
|
||||
* @access public
|
||||
* @param string $filename
|
||||
* @param string $data
|
||||
* @return bool
|
||||
*/
|
||||
private function _storeString($filename, $data)
|
||||
{
|
||||
// Create storage directory if it does not exist.
|
||||
if (!is_dir($this->_path)) {
|
||||
if (!@mkdir($this->_path, 0700)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$file = $this->_path . DIRECTORY_SEPARATOR . '.htaccess';
|
||||
if (!is_file($file)) {
|
||||
$writtenBytes = 0;
|
||||
if ($fileCreated = @touch($file)) {
|
||||
$writtenBytes = @file_put_contents(
|
||||
$file,
|
||||
self::HTACCESS_LINE . PHP_EOL,
|
||||
LOCK_EX
|
||||
);
|
||||
}
|
||||
if (
|
||||
$fileCreated === false ||
|
||||
$writtenBytes === false ||
|
||||
$writtenBytes < strlen(self::HTACCESS_LINE . PHP_EOL)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$fileCreated = true;
|
||||
$writtenBytes = 0;
|
||||
if (!is_file($filename)) {
|
||||
$fileCreated = @touch($filename);
|
||||
}
|
||||
if ($fileCreated) {
|
||||
$writtenBytes = @file_put_contents($filename, $data, LOCK_EX);
|
||||
}
|
||||
if ($fileCreated === false || $writtenBytes === false || $writtenBytes < strlen($data)) {
|
||||
return false;
|
||||
}
|
||||
@chmod($filename, 0640); // protect file from access by other users on the host
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* rename a file, prepending the protection line at the beginning
|
||||
*
|
||||
* @access public
|
||||
* @param string $srcFile
|
||||
* @param string $destFile
|
||||
* @return void
|
||||
*/
|
||||
private function _prependRename($srcFile, $destFile)
|
||||
{
|
||||
// don't overwrite already converted file
|
||||
if (!is_readable($destFile)) {
|
||||
$handle = fopen($srcFile, 'r', false, stream_context_create());
|
||||
file_put_contents($destFile, self::PROTECTION_LINE . PHP_EOL);
|
||||
file_put_contents($destFile, $handle, FILE_APPEND);
|
||||
fclose($handle);
|
||||
}
|
||||
unlink($srcFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,53 +4,25 @@ namespace PrivateBin\Data;
|
||||
|
||||
use Exception;
|
||||
use Google\Cloud\Core\Exception\NotFoundException;
|
||||
use Google\Cloud\Storage\Bucket;
|
||||
use Google\Cloud\Storage\StorageClient;
|
||||
use PrivateBin\Json;
|
||||
|
||||
class GoogleCloudStorage extends AbstractData
|
||||
{
|
||||
/**
|
||||
* GCS client
|
||||
*
|
||||
* @access private
|
||||
* @var StorageClient
|
||||
*/
|
||||
private $_client = null;
|
||||
|
||||
/**
|
||||
* GCS bucket
|
||||
*
|
||||
* @access private
|
||||
* @var Bucket
|
||||
*/
|
||||
private $_bucket = null;
|
||||
|
||||
/**
|
||||
* object prefix
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_prefix = 'pastes';
|
||||
|
||||
/**
|
||||
* bucket acl type
|
||||
*
|
||||
* @access private
|
||||
* @var bool
|
||||
*/
|
||||
private $_uniformacl = false;
|
||||
|
||||
/**
|
||||
* instantiantes a new Google Cloud Storage data backend.
|
||||
* returns a Google Cloud Storage data backend.
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $options
|
||||
* @return
|
||||
* @return GoogleCloudStorage
|
||||
*/
|
||||
public function __construct(array $options)
|
||||
public static function getInstance(array $options)
|
||||
{
|
||||
$client = null;
|
||||
$bucket = null;
|
||||
$prefix = 'pastes';
|
||||
|
||||
if (getenv('PRIVATEBIN_GCS_BUCKET')) {
|
||||
$bucket = getenv('PRIVATEBIN_GCS_BUCKET');
|
||||
}
|
||||
@@ -58,22 +30,40 @@ class GoogleCloudStorage extends AbstractData
|
||||
$bucket = $options['bucket'];
|
||||
}
|
||||
if (is_array($options) && array_key_exists('prefix', $options)) {
|
||||
$this->_prefix = $options['prefix'];
|
||||
$prefix = $options['prefix'];
|
||||
}
|
||||
if (is_array($options) && array_key_exists('uniformacl', $options)) {
|
||||
$this->_uniformacl = $options['uniformacl'];
|
||||
if (is_array($options) && array_key_exists('client', $options)) {
|
||||
$client = $options['client'];
|
||||
}
|
||||
|
||||
if (!(self::$_instance instanceof self)) {
|
||||
self::$_instance = new self($bucket, $prefix, $client);
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
protected $_client = null;
|
||||
protected $_bucket = null;
|
||||
protected $_prefix = 'pastes';
|
||||
|
||||
public function __construct($bucket, $prefix, $client = null)
|
||||
{
|
||||
parent::__construct();
|
||||
if ($client == null) {
|
||||
$this->_client = new StorageClient(array('suppressKeyFileNotice' => true));
|
||||
} else {
|
||||
// use given client for test purposes
|
||||
$this->_client = $client;
|
||||
}
|
||||
|
||||
$this->_client = class_exists('StorageClientStub', false) ?
|
||||
new \StorageClientStub(array()) :
|
||||
new StorageClient(array('suppressKeyFileNotice' => true));
|
||||
$this->_bucket = $this->_client->bucket($bucket);
|
||||
if ($prefix != null) {
|
||||
$this->_prefix = $prefix;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the google storage object key for $pasteid in $this->_bucket.
|
||||
*
|
||||
* @access private
|
||||
* @param $pasteid string to get the key for
|
||||
* @return string
|
||||
*/
|
||||
@@ -95,7 +85,7 @@ class GoogleCloudStorage extends AbstractData
|
||||
* @param $payload array to store
|
||||
* @return bool true if successful, otherwise false.
|
||||
*/
|
||||
private function _upload($key, $payload)
|
||||
private function upload($key, $payload)
|
||||
{
|
||||
$metadata = array_key_exists('meta', $payload) ? $payload['meta'] : array();
|
||||
unset($metadata['attachment'], $metadata['attachmentname'], $metadata['salt']);
|
||||
@@ -103,18 +93,15 @@ class GoogleCloudStorage extends AbstractData
|
||||
$metadata[$k] = strval($v);
|
||||
}
|
||||
try {
|
||||
$data = array(
|
||||
$this->_bucket->upload(Json::encode($payload), array(
|
||||
'name' => $key,
|
||||
'chunkSize' => 262144,
|
||||
'predefinedAcl' => 'private',
|
||||
'metadata' => array(
|
||||
'content-type' => 'application/json',
|
||||
'metadata' => $metadata,
|
||||
),
|
||||
);
|
||||
if (!$this->_uniformacl) {
|
||||
$data['predefinedAcl'] = 'private';
|
||||
}
|
||||
$this->_bucket->upload(Json::encode($payload), $data);
|
||||
));
|
||||
} catch (Exception $e) {
|
||||
error_log('failed to upload ' . $key . ' to ' . $this->_bucket->name() . ', ' .
|
||||
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||
@@ -132,7 +119,7 @@ class GoogleCloudStorage extends AbstractData
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->_upload($this->_getKey($pasteid), $paste);
|
||||
return $this->upload($this->_getKey($pasteid), $paste);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,7 +184,7 @@ class GoogleCloudStorage extends AbstractData
|
||||
return false;
|
||||
}
|
||||
$key = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid;
|
||||
return $this->_upload($key, $comment);
|
||||
return $this->upload($key, $comment);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,91 +217,6 @@ class GoogleCloudStorage extends AbstractData
|
||||
return $o->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function purgeValues($namespace, $time)
|
||||
{
|
||||
$path = 'config/' . $namespace;
|
||||
try {
|
||||
foreach ($this->_bucket->objects(array('prefix' => $path)) as $object) {
|
||||
$name = $object->name();
|
||||
if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') {
|
||||
continue;
|
||||
}
|
||||
$info = $object->info();
|
||||
if (key_exists('metadata', $info) && key_exists('value', $info['metadata'])) {
|
||||
$value = $info['metadata']['value'];
|
||||
if (is_numeric($value) && intval($value) < $time) {
|
||||
try {
|
||||
$object->delete();
|
||||
} catch (NotFoundException $e) {
|
||||
// deleted by another instance.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NotFoundException $e) {
|
||||
// no objects in the bucket yet
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For GoogleCloudStorage, the value will also be stored in the metadata for the
|
||||
* namespaces traffic_limiter and purge_limiter.
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setValue($value, $namespace, $key = '')
|
||||
{
|
||||
if ($key === '') {
|
||||
$key = 'config/' . $namespace;
|
||||
} else {
|
||||
$key = 'config/' . $namespace . '/' . $key;
|
||||
}
|
||||
|
||||
$metadata = array('namespace' => $namespace);
|
||||
if ($namespace != 'salt') {
|
||||
$metadata['value'] = strval($value);
|
||||
}
|
||||
try {
|
||||
$data = array(
|
||||
'name' => $key,
|
||||
'chunkSize' => 262144,
|
||||
'metadata' => array(
|
||||
'content-type' => 'application/json',
|
||||
'metadata' => $metadata,
|
||||
),
|
||||
);
|
||||
if (!$this->_uniformacl) {
|
||||
$data['predefinedAcl'] = 'private';
|
||||
}
|
||||
$this->_bucket->upload($value, $data);
|
||||
} catch (Exception $e) {
|
||||
error_log('failed to set key ' . $key . ' to ' . $this->_bucket->name() . ', ' .
|
||||
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getValue($namespace, $key = '')
|
||||
{
|
||||
if ($key === '') {
|
||||
$key = 'config/' . $namespace;
|
||||
} else {
|
||||
$key = 'config/' . $namespace . '/' . $key;
|
||||
}
|
||||
try {
|
||||
$o = $this->_bucket->object($key);
|
||||
return $o->downloadAsString();
|
||||
} catch (NotFoundException $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -325,7 +227,7 @@ class GoogleCloudStorage extends AbstractData
|
||||
$now = time();
|
||||
$prefix = $this->_prefix;
|
||||
if ($prefix != '') {
|
||||
$prefix .= '/';
|
||||
$prefix = $prefix . '/';
|
||||
}
|
||||
try {
|
||||
foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $object) {
|
||||
@@ -346,28 +248,4 @@ class GoogleCloudStorage extends AbstractData
|
||||
}
|
||||
return $expired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getAllPastes()
|
||||
{
|
||||
$pastes = array();
|
||||
$prefix = $this->_prefix;
|
||||
if ($prefix != '') {
|
||||
$prefix .= '/';
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $object) {
|
||||
$candidate = substr($object->name(), strlen($prefix));
|
||||
if (strpos($candidate, '/') === false) {
|
||||
$pastes[] = $candidate;
|
||||
}
|
||||
}
|
||||
} catch (NotFoundException $e) {
|
||||
// no objects in the bucket yet
|
||||
}
|
||||
return $pastes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,473 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* S3.php
|
||||
*
|
||||
* an S3 compatible data backend for PrivateBin with CEPH/RadosGW in mind
|
||||
* see https://docs.ceph.com/en/latest/radosgw/s3/php/
|
||||
* based on lib/Data/GoogleCloudStorage.php from PrivateBin version 1.4.0
|
||||
*
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2022 Felix J. Ogris (https://ogris.de/)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.1
|
||||
*
|
||||
* Installation:
|
||||
* 1. Make sure you have composer.lock and composer.json in the document root of your PasteBin
|
||||
* 2. If not, grab a copy from https://github.com/PrivateBin/PrivateBin
|
||||
* 3. As non-root user, install the AWS SDK for PHP:
|
||||
* composer require aws/aws-sdk-php
|
||||
* (On FreeBSD, install devel/php-composer2 prior, e.g.: make -C /usr/ports/devel/php-composer2 install clean)
|
||||
* 4. In cfg/conf.php, comment out all [model] and [model_options] settings
|
||||
* 5. Still in cfg/conf.php, add a new [model] section:
|
||||
* [model]
|
||||
* class = S3Storage
|
||||
* 6. Add a new [model_options] as well, e.g. for a Rados gateway as part of your CEPH cluster:
|
||||
* [model_options]
|
||||
* region = ""
|
||||
* version = "2006-03-01"
|
||||
* endpoint = "https://s3.my-ceph.invalid"
|
||||
* use_path_style_endpoint = true
|
||||
* bucket = "my-bucket"
|
||||
* prefix = "privatebin" (place all PrivateBin data beneath this prefix)
|
||||
* accesskey = "my-rados-user"
|
||||
* secretkey = "my-rados-pass"
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
|
||||
use Aws\S3\Exception\S3Exception;
|
||||
use Aws\S3\S3Client;
|
||||
use PrivateBin\Json;
|
||||
|
||||
class S3Storage extends AbstractData
|
||||
{
|
||||
/**
|
||||
* S3 client
|
||||
*
|
||||
* @access private
|
||||
* @var S3Client
|
||||
*/
|
||||
private $_client = null;
|
||||
|
||||
/**
|
||||
* S3 client options
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $_options = array();
|
||||
|
||||
/**
|
||||
* S3 bucket
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_bucket = null;
|
||||
|
||||
/**
|
||||
* S3 prefix for all PrivateBin data in this bucket
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_prefix = '';
|
||||
|
||||
/**
|
||||
* instantiates a new S3 data backend.
|
||||
*
|
||||
* @access public
|
||||
* @param array $options
|
||||
* @return
|
||||
*/
|
||||
public function __construct(array $options)
|
||||
{
|
||||
$this->_options['credentials'] = array();
|
||||
|
||||
if (is_array($options) && array_key_exists('region', $options)) {
|
||||
$this->_options['region'] = $options['region'];
|
||||
}
|
||||
if (is_array($options) && array_key_exists('version', $options)) {
|
||||
$this->_options['version'] = $options['version'];
|
||||
}
|
||||
if (is_array($options) && array_key_exists('endpoint', $options)) {
|
||||
$this->_options['endpoint'] = $options['endpoint'];
|
||||
}
|
||||
if (is_array($options) && array_key_exists('accesskey', $options)) {
|
||||
$this->_options['credentials']['key'] = $options['accesskey'];
|
||||
}
|
||||
if (is_array($options) && array_key_exists('secretkey', $options)) {
|
||||
$this->_options['credentials']['secret'] = $options['secretkey'];
|
||||
}
|
||||
if (is_array($options) && array_key_exists('use_path_style_endpoint', $options)) {
|
||||
$this->_options['use_path_style_endpoint'] = filter_var($options['use_path_style_endpoint'], FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
if (is_array($options) && array_key_exists('bucket', $options)) {
|
||||
$this->_bucket = $options['bucket'];
|
||||
}
|
||||
if (is_array($options) && array_key_exists('prefix', $options)) {
|
||||
$this->_prefix = $options['prefix'];
|
||||
}
|
||||
|
||||
$this->_client = new S3Client($this->_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all objects in the given prefix.
|
||||
*
|
||||
* @access private
|
||||
* @param $prefix string with prefix
|
||||
* @return array all objects in the given prefix
|
||||
*/
|
||||
private function _listAllObjects($prefix)
|
||||
{
|
||||
$allObjects = array();
|
||||
$options = array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Prefix' => $prefix,
|
||||
);
|
||||
|
||||
do {
|
||||
$objectsListResponse = $this->_client->listObjects($options);
|
||||
$objects = $objectsListResponse['Contents'] ?? array();
|
||||
foreach ($objects as $object) {
|
||||
$allObjects[] = $object;
|
||||
$options['Marker'] = $object['Key'];
|
||||
}
|
||||
} while ($objectsListResponse['IsTruncated']);
|
||||
|
||||
return $allObjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the S3 storage object key for $pasteid in $this->_bucket.
|
||||
*
|
||||
* @access private
|
||||
* @param $pasteid string to get the key for
|
||||
* @return string
|
||||
*/
|
||||
private function _getKey($pasteid)
|
||||
{
|
||||
if ($this->_prefix != '') {
|
||||
return $this->_prefix . '/' . $pasteid;
|
||||
}
|
||||
return $pasteid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads the payload in the $this->_bucket under the specified key.
|
||||
* The entire payload is stored as a JSON document. The metadata is replicated
|
||||
* as the S3 object's metadata except for the fields attachment, attachmentname
|
||||
* and salt.
|
||||
*
|
||||
* @param $key string to store the payload under
|
||||
* @param $payload array to store
|
||||
* @return bool true if successful, otherwise false.
|
||||
*/
|
||||
private function _upload($key, $payload)
|
||||
{
|
||||
$metadata = array_key_exists('meta', $payload) ? $payload['meta'] : array();
|
||||
unset($metadata['attachment'], $metadata['attachmentname'], $metadata['salt']);
|
||||
foreach ($metadata as $k => $v) {
|
||||
$metadata[$k] = strval($v);
|
||||
}
|
||||
try {
|
||||
$this->_client->putObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $key,
|
||||
'Body' => Json::encode($payload),
|
||||
'ContentType' => 'application/json',
|
||||
'Metadata' => $metadata,
|
||||
));
|
||||
} catch (S3Exception $e) {
|
||||
error_log('failed to upload ' . $key . ' to ' . $this->_bucket . ', ' .
|
||||
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function create($pasteid, array $paste)
|
||||
{
|
||||
if ($this->exists($pasteid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->_upload($this->_getKey($pasteid), $paste);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function read($pasteid)
|
||||
{
|
||||
try {
|
||||
$object = $this->_client->getObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $this->_getKey($pasteid),
|
||||
));
|
||||
$data = $object['Body']->getContents();
|
||||
return Json::decode($data);
|
||||
} catch (S3Exception $e) {
|
||||
error_log('failed to read ' . $pasteid . ' from ' . $this->_bucket . ', ' .
|
||||
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function delete($pasteid)
|
||||
{
|
||||
$name = $this->_getKey($pasteid);
|
||||
|
||||
try {
|
||||
$comments = $this->_listAllObjects($name . '/discussion/');
|
||||
foreach ($comments as $comment) {
|
||||
try {
|
||||
$this->_client->deleteObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $comment['Key'],
|
||||
));
|
||||
} catch (S3Exception $e) {
|
||||
// ignore if already deleted.
|
||||
}
|
||||
}
|
||||
} catch (S3Exception $e) {
|
||||
// there are no discussions associated with the paste
|
||||
}
|
||||
|
||||
try {
|
||||
$this->_client->deleteObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $name,
|
||||
));
|
||||
} catch (S3Exception $e) {
|
||||
// ignore if already deleted
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function exists($pasteid)
|
||||
{
|
||||
return $this->_client->doesObjectExistV2($this->_bucket, $this->_getKey($pasteid));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function createComment($pasteid, $parentid, $commentid, array $comment)
|
||||
{
|
||||
if ($this->existsComment($pasteid, $parentid, $commentid)) {
|
||||
return false;
|
||||
}
|
||||
$key = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid;
|
||||
return $this->_upload($key, $comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function readComments($pasteid)
|
||||
{
|
||||
$comments = array();
|
||||
$prefix = $this->_getKey($pasteid) . '/discussion/';
|
||||
try {
|
||||
$entries = $this->_listAllObjects($prefix);
|
||||
foreach ($entries as $entry) {
|
||||
$object = $this->_client->getObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $entry['Key'],
|
||||
));
|
||||
$body = JSON::decode($object['Body']->getContents());
|
||||
$items = explode('/', $entry['Key']);
|
||||
$body['id'] = $items[3];
|
||||
$body['parentid'] = $items[2];
|
||||
$slot = $this->getOpenSlot($comments, (int) $object['Metadata']['created']);
|
||||
$comments[$slot] = $body;
|
||||
}
|
||||
} catch (S3Exception $e) {
|
||||
// no comments found
|
||||
}
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function existsComment($pasteid, $parentid, $commentid)
|
||||
{
|
||||
$name = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid;
|
||||
return $this->_client->doesObjectExistV2($this->_bucket, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function purgeValues($namespace, $time)
|
||||
{
|
||||
$path = $this->_prefix;
|
||||
if ($path != '') {
|
||||
$path .= '/';
|
||||
}
|
||||
$path .= 'config/' . $namespace;
|
||||
|
||||
try {
|
||||
foreach ($this->_listAllObjects($path) as $object) {
|
||||
$name = $object['Key'];
|
||||
if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') {
|
||||
continue;
|
||||
}
|
||||
$head = $this->_client->headObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $name,
|
||||
));
|
||||
if ($head->get('Metadata') != null && array_key_exists('value', $head->get('Metadata'))) {
|
||||
$value = $head->get('Metadata')['value'];
|
||||
if (is_numeric($value) && intval($value) < $time) {
|
||||
try {
|
||||
$this->_client->deleteObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $name,
|
||||
));
|
||||
} catch (S3Exception $e) {
|
||||
// deleted by another instance.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (S3Exception $e) {
|
||||
// no objects in the bucket yet
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For S3, the value will also be stored in the metadata for the
|
||||
* namespaces traffic_limiter and purge_limiter.
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setValue($value, $namespace, $key = '')
|
||||
{
|
||||
$prefix = $this->_prefix;
|
||||
if ($prefix != '') {
|
||||
$prefix .= '/';
|
||||
}
|
||||
|
||||
if ($key === '') {
|
||||
$key = $prefix . 'config/' . $namespace;
|
||||
} else {
|
||||
$key = $prefix . 'config/' . $namespace . '/' . $key;
|
||||
}
|
||||
|
||||
$metadata = array('namespace' => $namespace);
|
||||
if ($namespace != 'salt') {
|
||||
$metadata['value'] = strval($value);
|
||||
}
|
||||
try {
|
||||
$this->_client->putObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $key,
|
||||
'Body' => $value,
|
||||
'ContentType' => 'application/json',
|
||||
'Metadata' => $metadata,
|
||||
));
|
||||
} catch (S3Exception $e) {
|
||||
error_log('failed to set key ' . $key . ' to ' . $this->_bucket . ', ' .
|
||||
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getValue($namespace, $key = '')
|
||||
{
|
||||
$prefix = $this->_prefix;
|
||||
if ($prefix != '') {
|
||||
$prefix .= '/';
|
||||
}
|
||||
|
||||
if ($key === '') {
|
||||
$key = $prefix . 'config/' . $namespace;
|
||||
} else {
|
||||
$key = $prefix . 'config/' . $namespace . '/' . $key;
|
||||
}
|
||||
|
||||
try {
|
||||
$object = $this->_client->getObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $key,
|
||||
));
|
||||
return $object['Body']->getContents();
|
||||
} catch (S3Exception $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function _getExpiredPastes($batchsize)
|
||||
{
|
||||
$expired = array();
|
||||
$now = time();
|
||||
$prefix = $this->_prefix;
|
||||
if ($prefix != '') {
|
||||
$prefix .= '/';
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($this->_listAllObjects($prefix) as $object) {
|
||||
$head = $this->_client->headObject(array(
|
||||
'Bucket' => $this->_bucket,
|
||||
'Key' => $object['Key'],
|
||||
));
|
||||
if ($head->get('Metadata') != null && array_key_exists('expire_date', $head->get('Metadata'))) {
|
||||
$expire_at = intval($head->get('Metadata')['expire_date']);
|
||||
if ($expire_at != 0 && $expire_at < $now) {
|
||||
array_push($expired, $object['Key']);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($expired) > $batchsize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (S3Exception $e) {
|
||||
// no objects in the bucket yet
|
||||
}
|
||||
return $expired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getAllPastes()
|
||||
{
|
||||
$pastes = array();
|
||||
$prefix = $this->_prefix;
|
||||
if ($prefix != '') {
|
||||
$prefix .= '/';
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($this->_listAllObjects($prefix) as $object) {
|
||||
$candidate = substr($object['Key'], strlen($prefix));
|
||||
if (strpos($candidate, '/') === false) {
|
||||
$pastes[] = $candidate;
|
||||
}
|
||||
}
|
||||
} catch (S3Exception $e) {
|
||||
// no objects in the bucket yet
|
||||
}
|
||||
return $pastes;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@@ -52,11 +52,6 @@ class FormatV2
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure adata is an array.
|
||||
if (!is_array($message['adata'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cipherParams = $isComment ? $message['adata'] : $message['adata'][0];
|
||||
|
||||
// Make sure some fields are base64 data:
|
||||
|
||||
25
lib/I18n.php
25
lib/I18n.php
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@@ -84,7 +84,7 @@ class I18n
|
||||
*/
|
||||
public static function _($messageId)
|
||||
{
|
||||
return forward_static_call_array('PrivateBin\I18n::translate', func_get_args());
|
||||
return forward_static_call_array('self::translate', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +195,7 @@ class I18n
|
||||
if (count(self::$_availableLanguages) == 0) {
|
||||
$i18n = dir(self::_getPath());
|
||||
while (false !== ($file = $i18n->read())) {
|
||||
if (preg_match('/^([a-z]{2,3}).json$/', $file, $match) === 1) {
|
||||
if (preg_match('/^([a-z]{2}).json$/', $file, $match) === 1) {
|
||||
self::$_availableLanguages[] = $match[1];
|
||||
}
|
||||
}
|
||||
@@ -305,7 +305,7 @@ class I18n
|
||||
/**
|
||||
* determines the plural form to use based on current language and given number
|
||||
*
|
||||
* From: https://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html
|
||||
* From: https://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
@@ -316,32 +316,27 @@ class I18n
|
||||
{
|
||||
switch (self::$_language) {
|
||||
case 'cs':
|
||||
case 'sk':
|
||||
return $n === 1 ? 0 : ($n >= 2 && $n <= 4 ? 1 : 2);
|
||||
case 'co':
|
||||
return $n == 1 ? 0 : ($n >= 2 && $n <= 4 ? 1 : 2);
|
||||
case 'fr':
|
||||
case 'oc':
|
||||
case 'tr':
|
||||
case 'zh':
|
||||
return $n > 1 ? 1 : 0;
|
||||
case 'he':
|
||||
return $n === 1 ? 0 : ($n === 2 ? 1 : (($n < 0 || $n > 10) && ($n % 10 === 0) ? 2 : 3));
|
||||
case 'id':
|
||||
case 'jbo':
|
||||
case 'th':
|
||||
return 0;
|
||||
case 'lt':
|
||||
return $n % 10 === 1 && $n % 100 !== 11 ? 0 : (($n % 10 >= 2 && $n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
|
||||
case 'pl':
|
||||
return $n === 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
|
||||
return $n == 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
|
||||
case 'ru':
|
||||
case 'uk':
|
||||
return $n % 10 === 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
|
||||
return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
|
||||
case 'sl':
|
||||
return $n % 100 === 1 ? 1 : ($n % 100 === 2 ? 2 : ($n % 100 === 3 || $n % 100 === 4 ? 3 : 0));
|
||||
// bg, ca, de, el, en, es, et, fi, hu, it, nl, no, pt
|
||||
return $n % 100 == 1 ? 1 : ($n % 100 == 2 ? 2 : ($n % 100 == 3 || $n % 100 == 4 ? 3 : 0));
|
||||
// bg, ca, de, en, es, et, hu, it, nl, no, pt
|
||||
default:
|
||||
return $n !== 1 ? 1 : 0;
|
||||
return $n != 1 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@@ -44,13 +44,13 @@ class Json
|
||||
* @static
|
||||
* @param string $input
|
||||
* @throws Exception
|
||||
* @return mixed
|
||||
* @return array
|
||||
*/
|
||||
public static function decode($input)
|
||||
{
|
||||
$output = json_decode($input, true);
|
||||
$array = json_decode($input, true);
|
||||
self::_detectError();
|
||||
return $output;
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@@ -54,7 +54,7 @@ class Model
|
||||
*/
|
||||
public function getPaste($pasteId = null)
|
||||
{
|
||||
$paste = new Paste($this->_conf, $this->getStore());
|
||||
$paste = new Paste($this->_conf, $this->_getStore());
|
||||
if ($pasteId !== null) {
|
||||
$paste->setId($pasteId);
|
||||
}
|
||||
@@ -67,9 +67,8 @@ class Model
|
||||
public function purge()
|
||||
{
|
||||
PurgeLimiter::setConfiguration($this->_conf);
|
||||
PurgeLimiter::setStore($this->getStore());
|
||||
if (PurgeLimiter::canPurge()) {
|
||||
$this->getStore()->purge($this->_conf->getKey('batchsize', 'purge'));
|
||||
$this->_getStore()->purge($this->_conf->getKey('batchsize', 'purge'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,11 +77,13 @@ class Model
|
||||
*
|
||||
* @return Data\AbstractData
|
||||
*/
|
||||
public function getStore()
|
||||
private function _getStore()
|
||||
{
|
||||
if ($this->_store === null) {
|
||||
$class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model');
|
||||
$this->_store = new $class($this->_conf->getSection('model_options'));
|
||||
$this->_store = forward_static_call(
|
||||
'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model') . '::getInstance',
|
||||
$this->_conf->getSection('model_options')
|
||||
);
|
||||
}
|
||||
return $this->_store;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Model;
|
||||
|
||||
@@ -7,14 +7,13 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Model;
|
||||
|
||||
use Exception;
|
||||
use Identicon\Identicon;
|
||||
use Jdenticon\Identicon as Jdenticon;
|
||||
use PrivateBin\Persistence\TrafficLimiter;
|
||||
use PrivateBin\Vizhash16x16;
|
||||
|
||||
@@ -165,17 +164,7 @@ class Comment extends AbstractModel
|
||||
if ($icon != 'none') {
|
||||
$pngdata = '';
|
||||
$hmac = TrafficLimiter::getHash();
|
||||
if ($icon == 'jdenticon') {
|
||||
$jdenticon = new Jdenticon(array(
|
||||
'hash' => $hmac,
|
||||
'size' => 16,
|
||||
'style' => array(
|
||||
'backgroundColor' => '#fff0', // fully transparent, for dark mode
|
||||
'padding' => 0,
|
||||
),
|
||||
));
|
||||
$pngdata = $jdenticon->getImageDataUri('png');
|
||||
} elseif ($icon == 'identicon') {
|
||||
if ($icon == 'identicon') {
|
||||
$identicon = new Identicon();
|
||||
$pngdata = $identicon->getImageDataUri($hmac, 16);
|
||||
} elseif ($icon == 'vizhash') {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Model;
|
||||
@@ -93,7 +93,7 @@ class Paste extends AbstractModel
|
||||
}
|
||||
|
||||
$this->_data['meta']['created'] = time();
|
||||
$this->_data['meta']['salt'] = ServerSalt::generate();
|
||||
$this->_data['meta']['salt'] = serversalt::generate();
|
||||
|
||||
// store paste
|
||||
if (
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
|
||||
use PrivateBin\Data\AbstractData;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* AbstractPersistence
|
||||
@@ -22,23 +22,104 @@ use PrivateBin\Data\AbstractData;
|
||||
abstract class AbstractPersistence
|
||||
{
|
||||
/**
|
||||
* data storage to use to persist something
|
||||
* path in which to persist something
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var AbstractData
|
||||
* @var string
|
||||
*/
|
||||
protected static $_store;
|
||||
private static $_path = 'data';
|
||||
|
||||
/**
|
||||
* set the path
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param AbstractData $store
|
||||
* @param string $path
|
||||
*/
|
||||
public static function setStore(AbstractData $store)
|
||||
public static function setPath($path)
|
||||
{
|
||||
self::$_store = $store;
|
||||
self::$_path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the path
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
public static function getPath($filename = null)
|
||||
{
|
||||
if (strlen($filename)) {
|
||||
return self::$_path . DIRECTORY_SEPARATOR . $filename;
|
||||
} else {
|
||||
return self::$_path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the file exists
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @param string $filename
|
||||
* @return bool
|
||||
*/
|
||||
protected static function _exists($filename)
|
||||
{
|
||||
self::_initialize();
|
||||
return is_file(self::$_path . DIRECTORY_SEPARATOR . $filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* prepares path for storage
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @throws Exception
|
||||
*/
|
||||
protected static function _initialize()
|
||||
{
|
||||
// Create storage directory if it does not exist.
|
||||
if (!is_dir(self::$_path)) {
|
||||
if (!@mkdir(self::$_path, 0700)) {
|
||||
throw new Exception('unable to create directory ' . self::$_path, 10);
|
||||
}
|
||||
}
|
||||
$file = self::$_path . DIRECTORY_SEPARATOR . '.htaccess';
|
||||
if (!is_file($file)) {
|
||||
$writtenBytes = @file_put_contents(
|
||||
$file,
|
||||
'Require all denied' . PHP_EOL,
|
||||
LOCK_EX
|
||||
);
|
||||
if ($writtenBytes === false || $writtenBytes < 19) {
|
||||
throw new Exception('unable to write to file ' . $file, 11);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* store the data
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @param string $filename
|
||||
* @param string $data
|
||||
* @throws Exception
|
||||
* @return string
|
||||
*/
|
||||
protected static function _store($filename, $data)
|
||||
{
|
||||
self::_initialize();
|
||||
$file = self::$_path . DIRECTORY_SEPARATOR . $filename;
|
||||
$writtenBytes = @file_put_contents($file, $data, LOCK_EX);
|
||||
if ($writtenBytes === false || $writtenBytes < strlen($data)) {
|
||||
throw new Exception('unable to write to file ' . $file, 13);
|
||||
}
|
||||
@chmod($file, 0640); // protect file access
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
97
lib/Persistence/DataStore.php
Normal file
97
lib/Persistence/DataStore.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* PrivateBin
|
||||
*
|
||||
* a zero-knowledge paste bin
|
||||
*
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
|
||||
use Exception;
|
||||
use PrivateBin\Json;
|
||||
|
||||
/**
|
||||
* DataStore
|
||||
*
|
||||
* Handles data storage for Data\Filesystem.
|
||||
*/
|
||||
class DataStore extends AbstractPersistence
|
||||
{
|
||||
/**
|
||||
* first line in file, to protect its contents
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const PROTECTION_LINE = '<?php http_response_code(403); /*';
|
||||
|
||||
/**
|
||||
* store the data
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $filename
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public static function store($filename, $data)
|
||||
{
|
||||
$path = self::getPath();
|
||||
if (strpos($filename, $path) === 0) {
|
||||
$filename = substr($filename, strlen($path));
|
||||
}
|
||||
try {
|
||||
self::_store(
|
||||
$filename,
|
||||
self::PROTECTION_LINE . PHP_EOL . Json::encode($data)
|
||||
);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the data
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $filename
|
||||
* @return array|false $data
|
||||
*/
|
||||
public static function get($filename)
|
||||
{
|
||||
return Json::decode(
|
||||
substr(
|
||||
file_get_contents($filename),
|
||||
strlen(self::PROTECTION_LINE . PHP_EOL)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* rename a file, prepending the protection line at the beginning
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $srcFile
|
||||
* @param string $destFile
|
||||
* @param string $prefix (optional)
|
||||
* @return void
|
||||
*/
|
||||
public static function prependRename($srcFile, $destFile, $prefix = '')
|
||||
{
|
||||
// don't overwrite already converted file
|
||||
if (!is_readable($destFile)) {
|
||||
$handle = fopen($srcFile, 'r', false, stream_context_create());
|
||||
file_put_contents($destFile, $prefix . self::PROTECTION_LINE . PHP_EOL);
|
||||
file_put_contents($destFile, $handle, FILE_APPEND);
|
||||
fclose($handle);
|
||||
}
|
||||
unlink($srcFile);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
@@ -52,6 +52,7 @@ class PurgeLimiter extends AbstractPersistence
|
||||
public static function setConfiguration(Configuration $conf)
|
||||
{
|
||||
self::setLimit($conf->getKey('limit', 'purge'));
|
||||
self::setPath($conf->getKey('dir', 'purge'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,6 +60,7 @@ class PurgeLimiter extends AbstractPersistence
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @throws \Exception
|
||||
* @return bool
|
||||
*/
|
||||
public static function canPurge()
|
||||
@@ -69,14 +71,17 @@ class PurgeLimiter extends AbstractPersistence
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$pl = (int) self::$_store->getValue('purge_limiter');
|
||||
if ($pl + self::$_limit >= $now) {
|
||||
return false;
|
||||
$file = 'purge_limiter.php';
|
||||
if (self::_exists($file)) {
|
||||
require self::getPath($file);
|
||||
$pl = $GLOBALS['purge_limiter'];
|
||||
if ($pl + self::$_limit >= $now) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$hasStored = self::$_store->setValue((string) $now, 'purge_limiter');
|
||||
if (!$hasStored) {
|
||||
error_log('failed to store the purge limiter, skipping purge cycle to avoid getting stuck in a purge loop');
|
||||
}
|
||||
return $hasStored;
|
||||
|
||||
$content = '<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . $now . ';';
|
||||
self::_store($file, $content);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
|
||||
use PrivateBin\Data\AbstractData;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* ServerSalt
|
||||
@@ -26,6 +26,15 @@ use PrivateBin\Data\AbstractData;
|
||||
*/
|
||||
class ServerSalt extends AbstractPersistence
|
||||
{
|
||||
/**
|
||||
* file where salt is saved to
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string
|
||||
*/
|
||||
private static $_file = 'salt.php';
|
||||
|
||||
/**
|
||||
* generated salt
|
||||
*
|
||||
@@ -44,7 +53,8 @@ class ServerSalt extends AbstractPersistence
|
||||
*/
|
||||
public static function generate()
|
||||
{
|
||||
return bin2hex(random_bytes(256));
|
||||
$randomSalt = bin2hex(random_bytes(256));
|
||||
return $randomSalt;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,6 +62,7 @@ class ServerSalt extends AbstractPersistence
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @throws Exception
|
||||
* @return string
|
||||
*/
|
||||
public static function get()
|
||||
@@ -60,14 +71,20 @@ class ServerSalt extends AbstractPersistence
|
||||
return self::$_salt;
|
||||
}
|
||||
|
||||
$salt = self::$_store->getValue('salt');
|
||||
if ($salt) {
|
||||
self::$_salt = $salt;
|
||||
if (self::_exists(self::$_file)) {
|
||||
if (is_readable(self::getPath(self::$_file))) {
|
||||
$items = explode('|', file_get_contents(self::getPath(self::$_file)));
|
||||
}
|
||||
if (!isset($items) || !is_array($items) || count($items) != 3) {
|
||||
throw new Exception('unable to read file ' . self::getPath(self::$_file), 20);
|
||||
}
|
||||
self::$_salt = $items[1];
|
||||
} else {
|
||||
self::$_salt = self::generate();
|
||||
if (!self::$_store->setValue(self::$_salt, 'salt')) {
|
||||
error_log('failed to store the server salt, delete tokens, traffic limiter and user icons won\'t work');
|
||||
}
|
||||
self::_store(
|
||||
self::$_file,
|
||||
'<?php # |' . self::$_salt . '|'
|
||||
);
|
||||
}
|
||||
return self::$_salt;
|
||||
}
|
||||
@@ -77,11 +94,11 @@ class ServerSalt extends AbstractPersistence
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param AbstractData $store
|
||||
* @param string $path
|
||||
*/
|
||||
public static function setStore(AbstractData $store)
|
||||
public static function setPath($path)
|
||||
{
|
||||
self::$_salt = '';
|
||||
parent::setStore($store);
|
||||
parent::setPath($path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,14 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
|
||||
use Exception;
|
||||
use IPLib\Factory;
|
||||
use IPLib\ParseStringFlag;
|
||||
use PrivateBin\Configuration;
|
||||
use PrivateBin\I18n;
|
||||
|
||||
/**
|
||||
* TrafficLimiter
|
||||
@@ -27,22 +25,22 @@ use PrivateBin\I18n;
|
||||
class TrafficLimiter extends AbstractPersistence
|
||||
{
|
||||
/**
|
||||
* listed IPs are the only ones allowed to create, defaults to null
|
||||
* time limit in seconds, defaults to 10s
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string|null
|
||||
* @var int
|
||||
*/
|
||||
private static $_creators = null;
|
||||
private static $_limit = 10;
|
||||
|
||||
/**
|
||||
* listed IPs are exempted from limits, defaults to null
|
||||
* listed ips are exempted from limits, defaults to null
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string|null
|
||||
*/
|
||||
private static $_exempted = null;
|
||||
private static $_exemptedIp = null;
|
||||
|
||||
/**
|
||||
* key to fetch IP address
|
||||
@@ -54,13 +52,28 @@ class TrafficLimiter extends AbstractPersistence
|
||||
private static $_ipKey = 'REMOTE_ADDR';
|
||||
|
||||
/**
|
||||
* time limit in seconds, defaults to 10s
|
||||
* set the time limit in seconds
|
||||
*
|
||||
* @access private
|
||||
* @access public
|
||||
* @static
|
||||
* @var int
|
||||
* @param int $limit
|
||||
*/
|
||||
private static $_limit = 10;
|
||||
public static function setLimit($limit)
|
||||
{
|
||||
self::$_limit = $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* set a list of ip(ranges) as string
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $exemptedIps
|
||||
*/
|
||||
public static function setExemptedIp($exemptedIp)
|
||||
{
|
||||
self::$_exemptedIp = $exemptedIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* set configuration options of the traffic limiter
|
||||
@@ -71,11 +84,11 @@ class TrafficLimiter extends AbstractPersistence
|
||||
*/
|
||||
public static function setConfiguration(Configuration $conf)
|
||||
{
|
||||
self::setCreators($conf->getKey('creators', 'traffic'));
|
||||
self::setExempted($conf->getKey('exempted', 'traffic'));
|
||||
self::setLimit($conf->getKey('limit', 'traffic'));
|
||||
self::setPath($conf->getKey('dir', 'traffic'));
|
||||
self::setExemptedIp($conf->getKey('exemptedIp', 'traffic'));
|
||||
|
||||
if (($option = $conf->getKey('header', 'traffic')) !== '') {
|
||||
if (($option = $conf->getKey('header', 'traffic')) !== null) {
|
||||
$httpHeader = 'HTTP_' . $option;
|
||||
if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) {
|
||||
self::$_ipKey = $httpHeader;
|
||||
@@ -83,42 +96,6 @@ class TrafficLimiter extends AbstractPersistence
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set a list of creator IP(-ranges) as string
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $creators
|
||||
*/
|
||||
public static function setCreators($creators)
|
||||
{
|
||||
self::$_creators = $creators;
|
||||
}
|
||||
|
||||
/**
|
||||
* set a list of exempted IP(-ranges) as string
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $exempted
|
||||
*/
|
||||
public static function setExempted($exempted)
|
||||
{
|
||||
self::$_exempted = $exempted;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the time limit in seconds
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param int $limit
|
||||
*/
|
||||
public static function setLimit($limit)
|
||||
{
|
||||
self::$_limit = $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a HMAC of the current visitors IP address
|
||||
*
|
||||
@@ -133,7 +110,7 @@ class TrafficLimiter extends AbstractPersistence
|
||||
}
|
||||
|
||||
/**
|
||||
* validate $_ipKey against configured ipranges. If matched we will ignore the ip
|
||||
* Validate $_ipKey against configured ipranges. If matched we will ignore the ip
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
@@ -145,11 +122,8 @@ class TrafficLimiter extends AbstractPersistence
|
||||
if (is_string($ipRange)) {
|
||||
$ipRange = trim($ipRange);
|
||||
}
|
||||
$address = Factory::parseAddressString($_SERVER[self::$_ipKey]);
|
||||
$range = Factory::parseRangeString(
|
||||
$ipRange,
|
||||
ParseStringFlag::IPV4_MAYBE_NON_DECIMAL | ParseStringFlag::IPV4SUBNET_MAYBE_COMPACT | ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED
|
||||
);
|
||||
$address = Factory::addressFromString($_SERVER[self::$_ipKey]);
|
||||
$range = Factory::rangeFromString($ipRange);
|
||||
|
||||
// address could not be parsed, we might not be in IP space and try a string comparison instead
|
||||
if (is_null($address)) {
|
||||
@@ -160,39 +134,35 @@ class TrafficLimiter extends AbstractPersistence
|
||||
return false;
|
||||
}
|
||||
|
||||
return $address->matches($range);
|
||||
// Ip-lib throws an exception when something goes wrong, if so we want to catch it and set contained to false
|
||||
try {
|
||||
return $address->matches($range);
|
||||
} catch (Exception $e) {
|
||||
// If something is wrong with matching the ip, we assume it doesn't match
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* make sure the IP address is allowed to perfom a request
|
||||
* traffic limiter
|
||||
*
|
||||
* Make sure the IP address makes at most 1 request every 10 seconds.
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @throws Exception
|
||||
* @return true
|
||||
* @return bool
|
||||
*/
|
||||
public static function canPass()
|
||||
{
|
||||
// if creators are defined, the traffic limiter will only allow creation
|
||||
// for these, with no limits, and skip any other rules
|
||||
if (!empty(self::$_creators)) {
|
||||
$creatorIps = explode(',', self::$_creators);
|
||||
foreach ($creatorIps as $ipRange) {
|
||||
if (self::matchIp($ipRange) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
throw new Exception(I18n::_('Your IP is not authorized to create pastes.'));
|
||||
}
|
||||
|
||||
// disable limits if set to less then 1
|
||||
if (self::$_limit < 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if $_ipKey is exempted from ratelimiting
|
||||
if (!empty(self::$_exempted)) {
|
||||
$exIp_array = explode(',', self::$_exempted);
|
||||
// Check if $_ipKey is exempted from ratelimiting
|
||||
if (!is_null(self::$_exemptedIp)) {
|
||||
$exIp_array = explode(',', self::$_exemptedIp);
|
||||
foreach ($exIp_array as $ipRange) {
|
||||
if (self::matchIp($ipRange) === true) {
|
||||
return true;
|
||||
@@ -200,26 +170,35 @@ class TrafficLimiter extends AbstractPersistence
|
||||
}
|
||||
}
|
||||
|
||||
// used as array key, which are limited in length, hence using algo with shorter range
|
||||
$file = 'traffic_limiter.php';
|
||||
if (self::_exists($file)) {
|
||||
require self::getPath($file);
|
||||
$tl = $GLOBALS['traffic_limiter'];
|
||||
} else {
|
||||
$tl = array();
|
||||
}
|
||||
|
||||
// purge file of expired hashes to keep it small
|
||||
$now = time();
|
||||
foreach ($tl as $key => $time) {
|
||||
if ($time + self::$_limit < $now) {
|
||||
unset($tl[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// this hash is used as an array key, hence a shorter algo is used
|
||||
$hash = self::getHash('sha256');
|
||||
$now = time();
|
||||
$tl = (int) self::$_store->getValue('traffic_limiter', $hash);
|
||||
self::$_store->purgeValues('traffic_limiter', $now - self::$_limit);
|
||||
if ($tl > 0 && ($tl + self::$_limit >= $now)) {
|
||||
if (array_key_exists($hash, $tl) && ($tl[$hash] + self::$_limit >= $now)) {
|
||||
$result = false;
|
||||
} else {
|
||||
$tl = time();
|
||||
$result = true;
|
||||
$tl[$hash] = time();
|
||||
$result = true;
|
||||
}
|
||||
if (!self::$_store->setValue((string) $tl, 'traffic_limiter', $hash)) {
|
||||
error_log('failed to store the traffic limiter, it probably contains outdated information');
|
||||
}
|
||||
if ($result) {
|
||||
return true;
|
||||
}
|
||||
throw new Exception(I18n::_(
|
||||
'Please wait %d seconds between each post.',
|
||||
self::$_limit
|
||||
));
|
||||
self::_store(
|
||||
$file,
|
||||
'<?php' . PHP_EOL .
|
||||
'$GLOBALS[\'traffic_limiter\'] = ' . var_export($tl, true) . ';'
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@@ -108,9 +108,7 @@ class Request
|
||||
case 'DELETE':
|
||||
case 'PUT':
|
||||
case 'POST':
|
||||
// it might be a creation or a deletion, the latter is detected below
|
||||
$this->_operation = 'create';
|
||||
$this->_params = Json::decode(
|
||||
$this->_params = Json::decode(
|
||||
file_get_contents(self::$_inputStream)
|
||||
);
|
||||
break;
|
||||
@@ -120,7 +118,6 @@ class Request
|
||||
if (
|
||||
!array_key_exists('pasteid', $this->_params) &&
|
||||
!array_key_exists('jsonld', $this->_params) &&
|
||||
!array_key_exists('link', $this->_params) &&
|
||||
array_key_exists('QUERY_STRING', $_SERVER) &&
|
||||
!empty($_SERVER['QUERY_STRING'])
|
||||
) {
|
||||
@@ -128,18 +125,19 @@ class Request
|
||||
}
|
||||
|
||||
// prepare operation, depending on current parameters
|
||||
if (array_key_exists('pasteid', $this->_params) && !empty($this->_params['pasteid'])) {
|
||||
if (
|
||||
array_key_exists('ct', $this->_params) &&
|
||||
!empty($this->_params['ct'])
|
||||
) {
|
||||
$this->_operation = 'create';
|
||||
} elseif (array_key_exists('pasteid', $this->_params) && !empty($this->_params['pasteid'])) {
|
||||
if (array_key_exists('deletetoken', $this->_params) && !empty($this->_params['deletetoken'])) {
|
||||
$this->_operation = 'delete';
|
||||
} elseif ($this->_operation != 'create') {
|
||||
} else {
|
||||
$this->_operation = 'read';
|
||||
}
|
||||
} elseif (array_key_exists('jsonld', $this->_params) && !empty($this->_params['jsonld'])) {
|
||||
$this->_operation = 'jsonld';
|
||||
} elseif (array_key_exists('link', $this->_params) && !empty($this->_params['link'])) {
|
||||
if (strpos($this->getRequestUri(), '/shortenviayourls') !== false) {
|
||||
$this->_operation = 'yourlsproxy';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +172,7 @@ class Request
|
||||
$data['meta'] = $meta;
|
||||
}
|
||||
foreach ($required_keys as $key) {
|
||||
$data[$key] = $this->getParam($key, $key == 'v' ? 1 : '');
|
||||
$data[$key] = $this->getParam($key);
|
||||
}
|
||||
// forcing a cast to int or float
|
||||
$data['v'] = $data['v'] + 0;
|
||||
@@ -290,7 +288,7 @@ class Request
|
||||
}
|
||||
krsort($mediaTypes);
|
||||
foreach ($mediaTypes as $acceptedQuality => $acceptedValues) {
|
||||
if ($acceptedQuality === '0.0') {
|
||||
if ($acceptedQuality === 0.0) {
|
||||
continue;
|
||||
}
|
||||
foreach ($acceptedValues as $acceptedValue) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.4.0
|
||||
* @version 1.3.5
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user