Merge branch 'master-1.3.2' into chapril-1.3.2
This commit is contained in:
commit
7fa2bb226e
47
CHANGELOG.md
47
CHANGELOG.md
@ -1,6 +1,51 @@
|
||||
# PrivateBin version history
|
||||
|
||||
* **1.3 (not yet released)**
|
||||
* **1.4 (not yet released)**
|
||||
* **1.3.2 (2020-01-11)**
|
||||
* ADDED: Translation for Ukrainian (#533)
|
||||
* ADDED: Option to send a mail with the link, when creating a paste (#398)
|
||||
* ADDED: Add support for CONFIG_PATH environment variable (#552)
|
||||
* CHANGED: Upgrading libraries to: base-x 3.0.7, DOMpurify 2.0.7 & Showdown 1.9.1
|
||||
* 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, 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)
|
||||
* CHANGED: Improved mobile UI - obscured send button and hard to click shortener button (#477)
|
||||
* CHANGED: Enhanced URL shortener integration (#479)
|
||||
* CHANGED: Improved file upload drag & drop UI (#317)
|
||||
* CHANGED: Increased default size limit from 2 to 10 MiB, switch data from BLOB to MEDIUMBLOB in MySQL (#458)
|
||||
* 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: 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)
|
||||
* FIXED: Showdown.js error when posting svg qrcode (#485)
|
||||
* FIXED: Failed to handle the case where user cancelled attachment selection properly (#487)
|
||||
* FIXED: Displaying the appropriate errors in older browsers (#508)
|
||||
* **1.3 (2019-07-09)**
|
||||
* ADDED: Translation for Czech (#424)
|
||||
* ADDED: Threat modeled the application (#177)
|
||||
* ADDED: Made compression configurable (#38)
|
||||
* CHANGED: Minimum required PHP version is 5.5, due to a change in the identicon library
|
||||
* CHANGED: Minimum required browser versions are Firefox 54, Chrome 57, Opera 44, Safari 11, Edge 16, due to use of WebCrypto API, async/await, ES6 & WebAssembly features - all Internet Explorer versions are incompatible
|
||||
* CHANGED: JSON and encryption formats were changed to replace SJCL library by browser integrated WebCrypto API (#28, #74)
|
||||
* CHANGED: Replaced rawdeflate.js with zlib.wasm to resolve decompression failures and gain compatibility with standard deflate implementations (#193, #260, #328, #434, #440)
|
||||
* CHANGED: Increase PBKDF2 iterations to 100k (#350)
|
||||
* CHANGED: Replaced last use of MD5 with Fowler–Noll–Vo checksum which produces the exact length we need for the paste ID (#49)
|
||||
* CHANGED: Simplified some PHP code & renamed PrivateBin class into Controller, to make MVC pattern use more obvious (#342)
|
||||
* CHANGED: Upgrading libraries to: identicon 1.2.0, random_compat 2.0.18, jQuery 3.4.1, Showdown 1.9.0, DOMpurify 1.0.11 & kjua 0.6.0
|
||||
* FIXED: Prevent Chrome from sending content of paste to Google for translation (#378)
|
||||
* FIXED: To support attachments larger then 2 MiB in newer Chrome versions, we switched to blob instead of data URIs (#432)
|
||||
* FIXED: Since Outlook strips trailing equal signs in links, the key in URL hash is now base58 encoded, instead of base64 (#377)
|
||||
* FIXED: Facebooks started injecting parameters into shared URLs for tracking that lead to inaccessible pastes (#396)
|
||||
* FIXED: Properly escaped HTML in raw text mode (#358)
|
||||
* FIXED: Made download links better readable in the dark bootstrap theme (#364)
|
||||
* FIXED: Allow Letsencrypt bot to access on apache servers (#413)
|
||||
* **1.2.1 (2018-08-11)**
|
||||
* ADDED: Add support for mega.nz links in pastes and comments (#331)
|
||||
* CHANGED: Added some missing Russian translations (#348)
|
||||
|
11
CREDITS.md
11
CREDITS.md
@ -4,6 +4,7 @@
|
||||
|
||||
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
|
||||
|
||||
@ -12,7 +13,7 @@ Sébastien Sauvage - original idea and main developer
|
||||
* Alexey Gladkov - syntax highlighting
|
||||
* Greg Knaddison - robots.txt
|
||||
* MrKooky - HTML5 markup, CSS cleanup
|
||||
* Simon Rupf - MVC refactoring, configuration, i18n and unit tests
|
||||
* Simon Rupf - WebCrypto, unit tests, current docker containers, MVC, configuration, i18n
|
||||
* Hexalyse - Password protection
|
||||
* Viktor Stanchev - File upload support
|
||||
* azlux - Tab character input support
|
||||
@ -21,8 +22,11 @@ Sébastien Sauvage - original idea and main developer
|
||||
* Sobak - PSR-4 and PSR-2 refactoring
|
||||
* Nathaniel Olsen - jQuery upgrade
|
||||
* Alexander Demenshin - modal password dialog
|
||||
* PunKeel - Dockerfile
|
||||
* PunKeel - first docker container
|
||||
* thororm - Display of video, audio & PDF, drag & drop, preview of attachments
|
||||
* Harald Leithner - base58 encoding of key
|
||||
* Haocen - lots of bugfixes and UI improvements
|
||||
* Lucas Savva - configurable config file location, NixOS packaging
|
||||
|
||||
## Translations
|
||||
* Hexalyse - French
|
||||
@ -39,3 +43,6 @@ Sébastien Sauvage - original idea and main developer
|
||||
* Tulio Leao - Portuguese
|
||||
* Michael van Schaik - Dutch
|
||||
* Péter Tabajdi - Hungarian
|
||||
* info-path - Czech
|
||||
* BigWax - Bulgarian
|
||||
* AndriiZ - Ukrainian
|
32
INSTALL.md
32
INSTALL.md
@ -11,7 +11,7 @@ options](#configuration) to adjust as you see fit.
|
||||
|
||||
### Minimal requirements
|
||||
|
||||
- PHP version 5.4 or above
|
||||
- PHP version 5.5 or above
|
||||
- _one_ of the following sources of cryptographically safe randomness is required:
|
||||
- PHP 7 or higher
|
||||
- [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)
|
||||
@ -50,6 +50,27 @@ process (see also
|
||||
> 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 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.
|
||||
|
||||
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:
|
||||
> SetEnv CONFIG_PATH /var/lib/privatebin/conf.php
|
||||
>
|
||||
> In a php-fpm pool config:
|
||||
> env[CONFIG_PATH] = /var/lib/privatebin/conf.php
|
||||
>
|
||||
> In the index.php, near the top:
|
||||
> putenv('CONFIG_PATH=/var/lib/privatebin/conf.php');
|
||||
|
||||
### Transport security
|
||||
|
||||
When setting up PrivateBin, also set up HTTPS, if you haven't already. Without HTTPS
|
||||
@ -66,8 +87,9 @@ See [this FAQ item](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#what-are-t
|
||||
|
||||
In the file `cfg/conf.php` you can configure PrivateBin. A `cfg/conf.sample.php`
|
||||
is provided containing all options and default values. You can copy it to
|
||||
`cfg/conf.php` and adapt it as needed. The config file is divided into multiple
|
||||
sections, which are enclosed in square brackets.
|
||||
`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
|
||||
@ -139,7 +161,7 @@ For reference or if you want to create the table schema for yourself to avoid ha
|
||||
```sql
|
||||
CREATE TABLE prefix_paste (
|
||||
dataid CHAR(16) NOT NULL,
|
||||
data BLOB,
|
||||
data MEDIUMBLOB,
|
||||
postdate INT,
|
||||
expiredate INT,
|
||||
opendiscussion INT,
|
||||
@ -165,7 +187,7 @@ CREATE INDEX parent ON prefix_comment(pasteid);
|
||||
CREATE TABLE prefix_config (
|
||||
id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id)
|
||||
);
|
||||
INSERT INTO prefix_config VALUES('VERSION', '1.2.1');
|
||||
INSERT INTO prefix_config VALUES('VERSION', '1.3.2');
|
||||
```
|
||||
|
||||
In **PostgreSQL**, the data, attachment, nickname and vizhash columns needs to be TEXT and not BLOB or MEDIUMBLOB.
|
||||
|
174
LICENSE.md
174
LICENSE.md
@ -2,15 +2,15 @@
|
||||
|
||||
PrivateBin consists of PHP and JS code which was originally written by Sébastien
|
||||
Sauvage in 2012 and falls unter the Zlib/libpng license. Also included are
|
||||
libraries that fall under the GPLv2 (SJCL, rawinflate, rawdeflate), BSD
|
||||
2-clause (SJCL), BSD 3-clause (base64.js version 2.1.9, Showdown), MIT
|
||||
(base64.js version 1.7, Bootstrap, Identicon, random_compat), Apache
|
||||
(prettify.js) and CC-BY (favicon, icon, logo) licenses. All of these license
|
||||
terms can be found here below:
|
||||
libraries that fall under the GPLv2 (rawinflate), BSD 3-clause (Showdown), MIT
|
||||
(base64.js version 1.7, Bootstrap, Identicon, random_compat, composer, kjua,
|
||||
base-x), Apache (prettify.js) and CC-BY (favicon, icon, logo) licenses. All of
|
||||
these license terms can be found here below:
|
||||
|
||||
## Zlib/libpng license for PrivateBin
|
||||
## Zlib/libpng license for PrivateBin and zlib
|
||||
|
||||
Copyright © 2012 Sébastien Sauvage
|
||||
Copyright © 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. In
|
||||
no event will the authors be held liable for any damages arising from the use
|
||||
@ -30,17 +30,7 @@ the following restrictions:
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
### MIT license for kjua
|
||||
|
||||
Copyright (c) 2016 Lars Jung (https://larsjung.de)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## GNU General Public License, version 2.0, for SJCL, rawdeflate and rawinflate
|
||||
## GNU General Public License, version 2.0, for rawinflate
|
||||
|
||||
_Version 2, June 1991_
|
||||
_Copyright © 1989, 1991 Free Software Foundation, Inc.,_
|
||||
@ -317,31 +307,6 @@ POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
## BSD 2-Clause License for SJCL
|
||||
|
||||
_Copyright © 2009-2015, Emily Stark, Mike Hamburg and Dan Boneh at Stanford University._
|
||||
_All rights reserved._
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## BSD 3-Clause License for Showdown
|
||||
|
||||
Showdown Copyright © 2007, John Fraser
|
||||
@ -377,61 +342,16 @@ any theory of liability, whether in contract, strict liability, or tort
|
||||
(including negligence or otherwise) arising in any way out of the use of this
|
||||
software, even if advised of the possibility of such damage.
|
||||
|
||||
## BSD 3-Clause License for base64.js version 2.1.9
|
||||
|
||||
Copyright © 2014, Dan Kogai
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of base64.js nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## MIT License for base64.js version 1.7
|
||||
## MIT License for base64.js version 1.7, Bootstrap, Identicon, random_compat, Composer, kjua and base-x
|
||||
|
||||
Copyright © 2012 Dan Kogai
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## MIT License for Bootstrap
|
||||
|
||||
Copyright © 2011-2016 Twitter, Inc.
|
||||
Copyright © 2013 Benjamin Laugueux <benjamin@yzalis.com>
|
||||
Copyright © 2015 Paragon Initiative Enterprises
|
||||
Copyright © 2016 Nils Adermann, Jordi Boggiano
|
||||
Copyright © 2016 Lars Jung (https://larsjung.de)
|
||||
Copyright © 2018 base-x contributors
|
||||
Copyright © 2014-2018 The Bitcoin Core developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -451,72 +371,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## MIT License for Identicon
|
||||
|
||||
Copyright © 2013 Benjamin Laugueux <benjamin@yzalis.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## MIT License for random_compat
|
||||
|
||||
Copyright © 2015 Paragon Initiative Enterprises
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## MIT license for Composer
|
||||
|
||||
Copyright (c) 2016 Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## Apache License for prettify.js
|
||||
|
||||
_Version 2.0, January 2004_
|
||||
|
11
README.md
11
README.md
@ -1,13 +1,6 @@
|
||||
# [<img alt="PrivateBin" src="https://cdn.rawgit.com/PrivateBin/assets/master/images/minified/logo.svg" width="500" />](https://privatebin.info/)
|
||||
[![Build Status](https://travis-ci.org/PrivateBin/PrivateBin.svg?branch=master)](https://travis-ci.org/PrivateBin/PrivateBin) [![Build Status](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/build.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/build-status/master)
|
||||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/094500f62abf4c9aa0c8a8a4520e4789)](https://www.codacy.com/app/PrivateBin/PrivateBin)
|
||||
[![Code Climate](https://codeclimate.com/github/PrivateBin/PrivateBin/badges/gpa.svg)](https://codeclimate.com/github/PrivateBin/PrivateBin)
|
||||
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/?branch=master)
|
||||
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/57c9e74e-c6f9-4de6-a876-df66ec2ea1ff/mini.png)](https://insight.sensiolabs.com/projects/57c9e74e-c6f9-4de6-a876-df66ec2ea1ff)
|
||||
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/094500f62abf4c9aa0c8a8a4520e4789)](https://www.codacy.com/app/PrivateBin/PrivateBin)
|
||||
[![Test Coverage](https://codeclimate.com/github/PrivateBin/PrivateBin/badges/coverage.svg)](https://codeclimate.com/github/PrivateBin/PrivateBin/coverage) [![Code Coverage](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/?branch=master)
|
||||
# [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/)
|
||||
|
||||
*Current version: 1.2.1*
|
||||
*Current version: 1.3.2*
|
||||
|
||||
**PrivateBin** is a minimalist, open source online [pastebin](https://en.wikipedia.org/wiki/Pastebin)
|
||||
where the server has zero knowledge of pasted data.
|
||||
|
18
SECURITY.md
Normal file
18
SECURITY.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.3.2 | :heavy_check_mark: |
|
||||
| < 1.3.2 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
You can send us email at security@privatebin.org. You should be able to get
|
||||
a response within a week (usually during the next weekend). The respondee will
|
||||
reply from their personal address and can offer you their GPG public key to
|
||||
support end-to-end encrypted communication on sensitive topics or attachments.
|
||||
|
||||
You can also contact us via the regular issue tracker if the risk of early
|
||||
publication is low or you would request input from other PrivateBin users.
|
@ -1,2 +1 @@
|
||||
Allow from none
|
||||
Deny from all
|
||||
Require all denied
|
||||
|
@ -29,8 +29,8 @@ defaultformatter = "plaintext"
|
||||
; (optional) set a syntax highlighting theme, as found in css/prettify/
|
||||
; syntaxhighlightingtheme = "sons-of-obsidian"
|
||||
|
||||
; size limit per paste or comment in bytes, defaults to 2 Mebibytes
|
||||
sizelimit = 2097152
|
||||
; size limit per paste or comment in bytes, defaults to 10 Mebibytes
|
||||
sizelimit = 10485760
|
||||
|
||||
; template to include, default is "bootstrap" (tpl/bootstrap.php)
|
||||
template = "bootstrap"
|
||||
@ -60,22 +60,43 @@ languageselection = false
|
||||
; 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
|
||||
; 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
|
||||
; allowed to be accessed in its context. You need to change this if you added
|
||||
; custom scripts from third-party domains to your templates, e.g. tracking
|
||||
; scripts or run your site behind certain DDoS-protection services.
|
||||
; Check the documentation at https://content-security-policy.com/
|
||||
; Note: If you use a bootstrap theme, you can remove the allow-popups from the sandbox restrictions.
|
||||
; By default this disallows to load images from third-party servers, e.g. when they are embedded in pastes. If you wish to allow that, you can adjust the policy here. See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-it-load-embedded-images for details.
|
||||
; cspheader = "default-src 'none'; manifest-src 'self'; connect-src *; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; media-src data:; object-src data:; Referrer-Policy: 'no-referrer'; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals"
|
||||
; Notes:
|
||||
; - If you use a bootstrap theme, you can remove the allow-popups from the
|
||||
; sandbox restrictions.
|
||||
; - By default this disallows to load images from third-party servers, e.g. when
|
||||
; they are embedded in pastes. If you wish to allow that, you can adjust the
|
||||
; policy here. See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-it-load-embedded-images
|
||||
; for details.
|
||||
; - The 'unsafe-eval' is used in two cases; to check if the browser supports
|
||||
; 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'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval'; 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"
|
||||
|
||||
; 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
|
||||
; sha256 in HMAC for the deletion token
|
||||
zerobincompatibility = false
|
||||
; zerobincompatibility = false
|
||||
|
||||
; Enable or disable the warning message when the site is served over an insecure
|
||||
; connection (insecure HTTP instead of HTTPS), defaults to true.
|
||||
; Secure transport methods like Tor and I2P domains are automatically whitelisted.
|
||||
; It is **strongly discouraged** to disable this.
|
||||
; See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection for more information.
|
||||
; httpwarning = true
|
||||
|
||||
; Pick compression algorithm or disable it. Only applies to pastes/comments
|
||||
; created after changing the setting.
|
||||
; Can be set to one these values: "none" / "zlib" (default).
|
||||
; compression = "zlib"
|
||||
|
||||
[expire]
|
||||
; expire value that is selected per default
|
||||
|
14
css/bootstrap/bootstrap-3.3.5.css
vendored
14
css/bootstrap/bootstrap-3.3.5.css
vendored
File diff suppressed because one or more lines are too long
5
css/bootstrap/bootstrap-3.4.1.css
vendored
Normal file
5
css/bootstrap/bootstrap-3.4.1.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -315,8 +315,8 @@ th {
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Glyphicons Halflings';
|
||||
src: url(fonts/../fonts/glyphicons-halflings-regular.eot?1445975532);
|
||||
src: url(fonts/../fonts/glyphicons-halflings-regular.eot?&1445975532#iefix) format("embedded-opentype"), url(fonts/../fonts/glyphicons-halflings-regular.woff2?1445975532) format("woff2"), url(fonts/../fonts/glyphicons-halflings-regular.woff?1445975532) format("woff"), url(fonts/../fonts/glyphicons-halflings-regular.ttf?1445975532) format("truetype"), url(fonts/../fonts/glyphicons-halflings-regular.svg?1445975532#glyphicons_halflingsregular) format("svg");
|
||||
src: url(fonts/glyphicons-halflings-regular.eot?1445975532);
|
||||
src: url(fonts/glyphicons-halflings-regular.eot?&1445975532#iefix) format("embedded-opentype"), url(fonts/glyphicons-halflings-regular.woff2?1445975532) format("woff2"), url(fonts/glyphicons-halflings-regular.woff?1445975532) format("woff"), url(fonts/glyphicons-halflings-regular.ttf?1445975532) format("truetype"), url(fonts/glyphicons-halflings-regular.svg?1445975532#glyphicons_halflingsregular) format("svg");
|
||||
}
|
||||
.glyphicon {
|
||||
position: relative;
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
body {
|
||||
@ -80,12 +80,30 @@ body.loading {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.dragAndDropFile{
|
||||
color:#777;
|
||||
font-size:1em;
|
||||
display:inline;
|
||||
#dropzone {
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1000;
|
||||
opacity: 0.6;
|
||||
background-color: #99ccff;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 25vh;
|
||||
outline: 2px dashed #228bff;
|
||||
outline-offset: -50px;
|
||||
}
|
||||
|
||||
.dragAndDropFile{
|
||||
color: #777;
|
||||
font-size: 1em;
|
||||
display: inline;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#deletelink {
|
||||
float: right;
|
||||
@ -113,8 +131,9 @@ body.loading {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#message {
|
||||
#message, .replymessage {
|
||||
font-family: monospace;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
#nickname {
|
||||
@ -125,6 +144,10 @@ body.loading {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#filewrap {
|
||||
transition: background-color 0.75s ease-out;
|
||||
}
|
||||
|
||||
.comment {
|
||||
border-left: 1px solid #ccc;
|
||||
padding: 5px 0 5px 10px;
|
||||
@ -132,7 +155,7 @@ body.loading {
|
||||
transition: background-color 0.75s ease-out;
|
||||
}
|
||||
|
||||
.comment.highlight {
|
||||
.highlight {
|
||||
background-color: #ffdd86;
|
||||
transition: background-color 0.2s ease-in;
|
||||
}
|
||||
@ -144,3 +167,41 @@ footer h4 {
|
||||
li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 {
|
||||
list-style-type: decimal !important;
|
||||
}
|
||||
|
||||
.dark-theme .alert-info .alert-link {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* address 2K or 4K monitors when using bootstrap 3 */
|
||||
@media (min-width: 1280px) {
|
||||
.container {
|
||||
width: 100%;
|
||||
padding-left: 4ch;
|
||||
padding-right: 4ch;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
margin: auto !important;
|
||||
}
|
||||
|
||||
/* makeup for the original margin on modal-dialog */
|
||||
@media (min-width: 768px) {
|
||||
.modal-content {
|
||||
margin: 30px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal .modal-content button {
|
||||
margin: 0.5em 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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
/* 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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
|
||||
@ -102,6 +102,7 @@ h3.title {
|
||||
padding: 5px;
|
||||
white-space: pre-wrap;
|
||||
font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
#attachmentPreview img {
|
||||
@ -115,10 +116,29 @@ h3.title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#dropzone {
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1000;
|
||||
opacity: 0.6;
|
||||
background-color: #99ccff;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 25vh;
|
||||
outline: 2px dashed #228bff;
|
||||
outline-offset: -50px;
|
||||
}
|
||||
|
||||
.dragAndDropFile{
|
||||
color:#777;
|
||||
font-size:1em;
|
||||
display:inline;
|
||||
color: #777;
|
||||
font-size: 1em;
|
||||
display: inline;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#status {
|
||||
@ -290,9 +310,9 @@ input {
|
||||
|
||||
#ienotice a { color: #000; }
|
||||
|
||||
#oldienotice { display: none; }
|
||||
#oldnotice, #httpnotice { display: none; }
|
||||
|
||||
.errorMessage {
|
||||
#errormessage, .errorMessage {
|
||||
background-color: #f77 !important;
|
||||
color:#ff0;
|
||||
}
|
||||
@ -405,6 +425,15 @@ h4.title {
|
||||
|
||||
.commentdate { color: #bfcede; }
|
||||
|
||||
#filewrap {
|
||||
transition: background-color 0.75s ease-out;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: #ffdd86;
|
||||
transition: background-color 0.2s ease-in;
|
||||
}
|
||||
|
||||
img.vizhash {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
172
i18n/bg.json
Normal file
172
i18n/bg.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s е изчистен и изцяло достъпен като отворен код, онлайн \"paste\" услуга, където сървъра не знае подадената информация. Тя се шифрова/дешифрова <i>във браузъра</i> използвайки 256 битов AES алгоритъм. Повече информация може да намерите на <a href=\"https://privatebin.info/\">страницата на проекта (Английски)</a>",
|
||||
"Because ignorance is bliss":
|
||||
"Невежеството е блаженство",
|
||||
"en": "bg",
|
||||
"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 секунди между всяка публикация.",
|
||||
"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.<br />Sorry for the inconvenience.":
|
||||
"Услугата %s се нуждае от JavaScript, за да работи.<br />Съжаляваме за неудобството.",
|
||||
"%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 minutes": ["%d минути", "%d минута"],
|
||||
"%d hours": ["%d часа", "%d час"],
|
||||
"%d days": ["%d дни", "%d ден"],
|
||||
"%d weeks": ["%d седмици", "%d седмица"],
|
||||
"%d months": ["%d месеци", "%d месец"],
|
||||
"%d years": ["%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 секунди."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Този документ изтича след една минута.", "Този документ изтича след %d минути."],
|
||||
"This document will expire in %d hours.":
|
||||
["Този документ изтича след един час.", "Този документ изтича след %d часа."],
|
||||
"This document will expire in %d days.":
|
||||
["Този документ изтича след един ден.", "Този документ изтича след %d дни."],
|
||||
"This document will expire in %d months.":
|
||||
["Този документ изтича след една година.", "Този документ изтича след %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":
|
||||
"Аватар (на базата на 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?)":
|
||||
"Дешифроването на информацията беше неуспешно: Ключа за декриптиране липсва във връзката (Да не сте използвали услуга за пренасочване или скъсяване на връзката, което би изрязало части от нея?)",
|
||||
"Format": "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.":
|
||||
"PATH трябва да е във края на \"%s\" за да може %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\">този FAQ (Английски)</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.":
|
||||
"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…"
|
||||
}
|
172
i18n/cs.json
Normal file
172
i18n/cs.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s je minimalistický open source 'pastebin' server, který neanalyzuje vložená data. Data jsou šifrována <i>v prohlížeči</i> pomocí 256 bitů AES. Více informací na <a href=\"https://privatebin.info/\">stránce projetu</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Protože nevědomost je sladká",
|
||||
"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 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.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Příspěvek je limitován na %s šífrovaných dat",
|
||||
"Invalid data.":
|
||||
"Chybná data.",
|
||||
"You are unlucky. Try again.":
|
||||
"Lituji, zkuste to znovu.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Chyba při ukládání komentáře.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Chyba při ukládání příspěvku.",
|
||||
"Invalid paste ID.":
|
||||
"Chybně vložené ID.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"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.<br />Sorry for the inconvenience.":
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%%s requires a modern browser to work.",
|
||||
"New":
|
||||
"Nový",
|
||||
"Send":
|
||||
"Odeslat",
|
||||
"Clone":
|
||||
"Klonovat",
|
||||
"Raw text":
|
||||
"Pouze Text",
|
||||
"Expires":
|
||||
"Expirace",
|
||||
"Burn after reading":
|
||||
"Po přečtení smazat",
|
||||
"Open discussion":
|
||||
"Povolit komentáře",
|
||||
"Password (recommended)":
|
||||
"Heslo (doporučeno)",
|
||||
"Discussion":
|
||||
"Komentáře",
|
||||
"Toggle navigation":
|
||||
"Toggle navigation",
|
||||
"%d seconds": ["%d sekuda", "%d sekundy", "%d sekund"],
|
||||
"%d minutes": ["%d minuta", "%d minuty", "%d minut"],
|
||||
"%d hours": ["%d hodin", "%d hodiny", "%d hodin"],
|
||||
"%d days": ["%d den", "%d dny", "%d dní"],
|
||||
"%d weeks": ["%d týden", "%d týdeny", "%d týdnů"],
|
||||
"%d months": ["%d měsíc", "%d měsíce", "%d měsíců"],
|
||||
"%d years": ["%d rok", "%d roky", "%d roků"],
|
||||
"Never":
|
||||
"Nikdy",
|
||||
"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.", "Tento dokument expiruje za %d sekund."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Tento dokument expiruje za %d minutu.", "Tento dokument expiruje za %d minuty.", "Tento dokument expiruje za %d minut."],
|
||||
"This document will expire in %d hours.":
|
||||
["Tento dokument expiruje za %d hodinu.", "Tento dokument expiruje za %d hodiny.", "Tento dokument expiruje za %d hodin."],
|
||||
"This document will expire in %d days.":
|
||||
["Tento dokument expiruje za %d den.", "Tento dokument expiruje za %d dny.", "Tento dokument expiruje za %d dny."],
|
||||
"This document will expire in %d months.":
|
||||
["Tento dokument expiruje za %d měsíc.", "Tento dokument expiruje za %d měsíce.", "Tento dokument expiruje za %d měsíců."],
|
||||
"Please enter the password for this paste:":
|
||||
"Zadejte prosím heslo:",
|
||||
"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 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":
|
||||
"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",
|
||||
"Sending paste…":
|
||||
"Odesílání příspěvku…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Váš link je <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Stiskněte [Ctrl]+[c] pro zkopírování)</span>",
|
||||
"Delete data":
|
||||
"Odstranit data",
|
||||
"Could not create paste: %s":
|
||||
"Nelze vytvořit příspěvek: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Nepodařilo se dešifrovat příspěvek: V adrese chybí dešifrovací klíč (Možnou příčinou může být URL shortener?)",
|
||||
"Format": "Formát",
|
||||
"Plain Text": "Prostý Text",
|
||||
"Source Code": "Zdrojový kód",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Stáhnout přílohu",
|
||||
"Cloned: '%s'": "Klonováno: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "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": "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": "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 requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
|
||||
"Decrypt":
|
||||
"Decrypt",
|
||||
"Enter password":
|
||||
"Zadejte heslo",
|
||||
"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":
|
||||
"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…"
|
||||
}
|
43
i18n/de.json
43
i18n/de.json
@ -35,8 +35,6 @@
|
||||
"JavaScript ist eine Voraussetzung, um %s zu nutzen.<br />Bitte entschuldige die Unannehmlichkeiten.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s setzt einen modernen Browser voraus, um funktionieren zu können.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Du benutzt immer noch den Internet Explorer? Tu Dir einen Gefallen und wechsle zu einem moderneren Browser:",
|
||||
"New":
|
||||
"Neu",
|
||||
"Send":
|
||||
@ -48,13 +46,13 @@
|
||||
"Expires":
|
||||
"Ablaufzeit",
|
||||
"Burn after reading":
|
||||
"Einmal-Text",
|
||||
"Nach dem Lesen löschen",
|
||||
"Open discussion":
|
||||
"Diskussion eröffnen",
|
||||
"Kommentare aktivieren",
|
||||
"Password (recommended)":
|
||||
"Passwort (empfohlen)",
|
||||
"Discussion":
|
||||
"Diskussion",
|
||||
"Kommentare",
|
||||
"Toggle navigation":
|
||||
"Navigation umschalten",
|
||||
"%d seconds": ["%d Sekunde", "%d Sekunden"],
|
||||
@ -105,23 +103,21 @@
|
||||
"Comment posted.":
|
||||
"Kommentar gesendet.",
|
||||
"Could not refresh display: %s":
|
||||
"Konnte Ansicht nicht aktualisieren: %s",
|
||||
"Ansicht konnte nicht aktualisiert werden: %s",
|
||||
"unknown status":
|
||||
"Unbekannter Grund",
|
||||
"server error or not responding":
|
||||
"Fehler auf dem Server oder keine Antwort vom Server",
|
||||
"Could not post comment: %s":
|
||||
"Konnte Kommentar nicht senden: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Bitte bewege Deine Maus um die Entropie zu erhöhen…",
|
||||
"Sending paste…":
|
||||
"Sende Paste…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Dein Paste ist unter <a id=\"pasteurl\" href=\"%s\">%s</a> zu finden <span id=\"copyhint\">(Drücke [Strg]+[c] um den Link zu kopieren)</span>",
|
||||
"Dein Text ist unter <a id=\"pasteurl\" href=\"%s\">%s</a> zu finden <span id=\"copyhint\">(Drücke [Strg]+[c] um den Link zu kopieren)</span>",
|
||||
"Delete data":
|
||||
"Lösche Daten",
|
||||
"Could not create paste: %s":
|
||||
"Konnte Paste nicht erstellen: %s",
|
||||
"Text konnte nicht erstellt werden: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Konnte Paste nicht entschlüsseln: Der Schlüssel fehlt in der Adresse (Hast du eine Umleitung oder einen URL-Verkürzer benutzt, der Teile der Adresse entfernt?)",
|
||||
"Format": "Format",
|
||||
@ -149,11 +145,28 @@
|
||||
"Enter password":
|
||||
"Passwort eingeben",
|
||||
"Loading…": "Lädt…",
|
||||
"Decrypting paste…": "Entschlüssle Paste…",
|
||||
"Preparing new paste…": "Bereite neues Paste vor…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Wenn diese Nachricht nicht mehr verschwindet, schau bitte in <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">die FAQ</a> (englisch), um zu sehen, wie der Fehler behoben werden kann.",
|
||||
"Decrypting paste…": "Entschlüssle Text…",
|
||||
"Preparing new paste…": "Bereite neuen Text vor…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"Wenn diese Nachricht nicht mehr verschwindet, schau bitte in <a href=\"%s\">die FAQ</a> (englisch), um zu sehen, wie der Fehler behoben werden kann.",
|
||||
"+++ no paste text +++": "+++ kein Paste-Text +++",
|
||||
"Could not get paste data: %s":
|
||||
"Konnte Paste nicht laden: %s"
|
||||
"Text konnte nicht geladen werden: %s",
|
||||
"QR code": "QR code",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.":
|
||||
"Diese Webseite verwendet eine unsichere HTTP Verbindung! Bitte benutze sie nur zum Testen.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.":
|
||||
"<a href=\"%s\">Besuche diesen FAQ Eintrag</a> für weitere Informationen dazu.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
|
||||
"Dein Browser benötigt möglicherweise eine HTTPS Verbindung um das WebCrypto API nutzen zu können. Versuche <a href=\"%s\">auf HTTPS zu wechseln</a>.",
|
||||
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
|
||||
"Dein Browser unterstützt WebAssembly nicht, welches für zlib Komprimierung benötigt wird. Du kannst unkomprimierte Dokumente erzeugen, aber keine komprimierten lesen.",
|
||||
"waiting on user to provide a password":
|
||||
"warte auf Passworteingabe durch Benutzer",
|
||||
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
|
||||
"Konnte Daten nicht entschlüsseln. Hast Du das falsche Passwort eingegeben? Wiederhole den Vorgang mit dem oben stehenden Knopf.",
|
||||
"Retry":
|
||||
"Wiederholen",
|
||||
"Showing raw text…":
|
||||
"Zeige reinen Text an…"
|
||||
}
|
57
i18n/es.json
57
i18n/es.json
@ -1,12 +1,12 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s es un servicio de tipo \"Pastebin\" minimalista de código abierto, donde el servidor no tiene ningún conocimiento de los datos guardados. Los datos son cifrados/descifrados <i>en el navegador</i> usando 256 bits AES. Más información en la <a href=\"https://privatebin.info/\">página del proyecto</a>.",
|
||||
"%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 <i>en el navegador</i> usando 256 bits AES. Más información en la <a href=\"https://privatebin.info/\">página del proyecto</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Porque la ignorancia es dicha",
|
||||
"en": "es",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"El texto no existe, ha caducado o ha sido eliminado.",
|
||||
"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.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
@ -14,7 +14,7 @@
|
||||
"Please wait %d seconds between each post.":
|
||||
"Por favor espere %d segundos entre cada publicación.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"El texto está limitado a %s de datos cifrados.",
|
||||
"El \"paste\" está limitado a %s de datos cifrados.",
|
||||
"Invalid data.":
|
||||
"Datos inválidos.",
|
||||
"You are unlucky. Try again.":
|
||||
@ -22,21 +22,19 @@
|
||||
"Error saving comment. Sorry.":
|
||||
"Error al guardar el comentario. Lo siento.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Error al guardar el texto. Lo siento",
|
||||
"Error al guardar el \"paste\". Lo siento",
|
||||
"Invalid paste ID.":
|
||||
"ID del texto inválido.",
|
||||
"ID del \"paste\" inválido.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"El texto no es del tipo \"destruir despues de leer\".",
|
||||
"El \"paste\" no es del tipo \"destruir despues de leer\".",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Token de eliminación erróneo. El texto no fue eliminado.",
|
||||
"Token de eliminación erróneo. El \"paste\" no fue eliminado.",
|
||||
"Paste was properly deleted.":
|
||||
"El texto se ha eliminado correctamente.",
|
||||
"El \"paste\" se ha eliminado correctamente.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"JavaScript es necesario para que %s funcione.<br />Sentimos los inconvenientes ocasionados.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s requiere un navegador moderno para funcionar.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"¿Sigues usando Internet Explorer? Hazte un favor, cambia a un navegador moderno:",
|
||||
"New":
|
||||
"Nuevo",
|
||||
"Send":
|
||||
@ -67,7 +65,7 @@
|
||||
"Never":
|
||||
"Nunca",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Nota: Este es un servicio de prueba. Los datos pueden ser eliminados en cualquier momento. Gatitos morirán si se abusa de este servicio.",
|
||||
"Nota: Este es un servicio de prueba. Los datos pueden ser eliminados en cualquier momento. Morirán gatitos si abusas de este servicio.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Este documento caducará en un segundo.", "Este documento caducará en %d segundos."],
|
||||
"This document will expire in %d minutes.":
|
||||
@ -79,13 +77,13 @@
|
||||
"This document will expire in %d months.":
|
||||
["Este documento caducará en un mes.", "Este documento caducará en %d meses."],
|
||||
"Please enter the password for this paste:":
|
||||
"Por favor ingrese la contraseña para este documento:",
|
||||
"Por favor ingrese la contraseña para este \"paste\":",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"No fue posible descifrar los datos (¿Clave errónea?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"No fue posible eliminar el documento, no fue guardado en modo \"destruir despues de leer\".",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"SÓLO PARA TUS OJOS. No cierre esta ventana, este mensaje no se puede volver a mostrar.",
|
||||
"SÓLO PARA TUS OJOS. No cierres esta ventana, este mensaje no se puede volver a mostrar.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"No se pudo descifrar el comentario; ¿Llave incorrecta?",
|
||||
"Reply":
|
||||
@ -112,10 +110,8 @@
|
||||
"Error del servidor o el servidor no responde",
|
||||
"Could not post comment: %s":
|
||||
"No fue posible publicar comentario: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Por favor, mueva el ratón para mayor entropía…",
|
||||
"Sending paste…":
|
||||
"Enviando texto…",
|
||||
"Enviando \"paste\"…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Su texto está en <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Presione [Ctrl]+[c] para copiar)</span>",
|
||||
"Delete data":
|
||||
@ -149,11 +145,28 @@
|
||||
"Enter password":
|
||||
"Ingrese contraseña",
|
||||
"Loading…": "Cargando…",
|
||||
"Decrypting paste…": "Descifrando texto…",
|
||||
"Preparing new paste…": "Preparando texto nuevo…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"En caso de que este mensaje nunca desaparezca por favor revise <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">este FAQ para obtener información para solucionar problemas</a>.",
|
||||
"+++ no paste text +++": "+++ sin texto +++",
|
||||
"Decrypting paste…": "Descifrando \"paste\"…",
|
||||
"Preparing new paste…": "Preparando \"paste\" nuevo…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"En caso de que este mensaje nunca desaparezca por favor revise <a href=\"%s\">este FAQ para obtener información para solucionar problemas</a>.",
|
||||
"+++ no paste text +++": "+++ \"paste\" sin texto +++",
|
||||
"Could not get paste data: %s":
|
||||
"Could not get paste data: %s"
|
||||
"No se pudieron obtener los datos: %s",
|
||||
"QR code": "Código QR",
|
||||
"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…"
|
||||
}
|
33
i18n/fr.json
33
i18n/fr.json
@ -35,8 +35,6 @@
|
||||
"JavaScript est requis pour faire fonctionner %s. <br />Désolé pour cet inconvénient.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s nécessite un navigateur moderne pour fonctionner.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Encore sur Internet Explorer ? Faites-vous une faveur, passez à un navigateur moderne :",
|
||||
"New":
|
||||
"Nouveau",
|
||||
"Send":
|
||||
@ -87,7 +85,7 @@
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"POUR VOS YEUX UNIQUEMENT. Ne fermez pas cette fenêtre, ce paste ne pourra plus être affiché.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Impossible de déchiffrer le commentaire ; mauvaise clé ?",
|
||||
"Impossible de déchiffrer le commentaire; mauvaise clé ?",
|
||||
"Reply":
|
||||
"Répondre",
|
||||
"Anonymous":
|
||||
@ -112,8 +110,6 @@
|
||||
"Le serveur ne répond pas ou a rencontré une erreur",
|
||||
"Could not post comment: %s":
|
||||
"Impossible de poster le commentaire : %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Merci de bouger votre souris pour plus d'entropie…",
|
||||
"Sending paste…":
|
||||
"Envoi du paste…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -141,8 +137,8 @@
|
||||
"Cloned: '%s'": "Cloner '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "Le fichier cloné '%s' a été attaché à ce paste.",
|
||||
"Attach a file": "Attacher un fichier ",
|
||||
"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.",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "alternativement, glisser & déposer un fichier ou coller une image à partir du presse-papiers",
|
||||
"File too large, to display a preview. Please download the attachment.": "Fichier trop volumineux, pour afficher un aperçu. Veuillez télécharger la pièce jointe.",
|
||||
"Remove attachment": "Enlever l'attachement",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.",
|
||||
@ -160,9 +156,26 @@
|
||||
"Loading…": "Chargement…",
|
||||
"Decrypting paste…": "Déchiffrement du paste…",
|
||||
"Preparing new paste…": "Préparation du paste…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Si ce message ne disparaîssait pas, jetez un oeil à <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">cette FAQ pour des idées de résolution</a> (en Anglais).",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"Si ce message ne disparaîssait pas, jetez un oeil à <a href=\"%s\">cette FAQ pour des idées de résolution</a> (en Anglais).",
|
||||
"+++ no paste text +++": "+++ pas de paste-text +++",
|
||||
"Could not get paste data: %s":
|
||||
"Could not get paste data: %s"
|
||||
"Impossible d'obtenir les données du paste: %s",
|
||||
"QR code": "QR code",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.":
|
||||
"Ce site web utilise une connexion HTTP non sécurisée ! Veuillez l’utiliser uniquement pour des tests.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.":
|
||||
"Pour plus d'informations <a href=\"%s\">consultez cette rubrique de la FAQ</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
|
||||
"Votre navigateur peut nécessiter une connexion HTTPS pour prendre en charge l’API WebCrypto. Essayez <a href=\"%s\">de passer en 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…"
|
||||
}
|
27
i18n/hu.json
27
i18n/hu.json
@ -35,8 +35,6 @@
|
||||
"JavaScript szükséges a %s működéséhez. Elnézést a fennakadásért.",
|
||||
"%s requires a modern browser to work.":
|
||||
"A %s működéséhez a jelenleginél újabb böngészőre van szükség.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Még mindig Internet Explorert használsz? Ideje váltani:",
|
||||
"New":
|
||||
"Új",
|
||||
"Send":
|
||||
@ -112,8 +110,6 @@
|
||||
"A szerveren hiba lépett fel vagy nem válaszol.",
|
||||
"Could not post comment: %s":
|
||||
"Nem tudtuk beküldeni a hozzászólást: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Nincs elég véletlenszerűség a rendszerben. Mozgasd az egered, hogy növeld az entrópiát.",
|
||||
"Sending paste…":
|
||||
"Bejegyzés elküldése...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -151,9 +147,26 @@
|
||||
"Loading…": "Folyamatban...",
|
||||
"Decrypting paste…": "Bejegyzés dekódolása...",
|
||||
"Preparing new paste…": "Új bejegyzés előkészítése...",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Abban az esetben, ha ez az üzenet mindig látható lenne, látogass el a <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">Gyakran Ismételt Kérdések szekcióba a megoldásához</a>.",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"Abban az esetben, ha ez az üzenet mindig látható lenne, látogass el a <a href=\"%s\">Gyakran Ismételt Kérdések szekcióba a megoldásához</a>.",
|
||||
"+++ no paste text +++": "+++ nincs beillesztett szöveg +++",
|
||||
"Could not get paste data: %s":
|
||||
"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…"
|
||||
}
|
27
i18n/it.json
27
i18n/it.json
@ -35,8 +35,6 @@
|
||||
"%s funziona solo con JavaScript attivo.<br />Ci dispiace per l'inconveniente.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s richiede un browser moderno e aggiornato per funzionare.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Usi ancora Internet Explorer? Ti consigliamo di passare ad un browser più sicuro:",
|
||||
"New":
|
||||
"Nuovo",
|
||||
"Send":
|
||||
@ -112,8 +110,6 @@
|
||||
"errore o mancata risposta dal server",
|
||||
"Could not post comment: %s":
|
||||
"Impossibile inviare il commento: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Muovi il mouse in modo casuale, per generare maggior entropia…",
|
||||
"Sending paste…":
|
||||
"Messaggio in fase di invio…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -151,9 +147,26 @@
|
||||
"Loading…": "Carico…",
|
||||
"Decrypting paste…": "Decifro il messaggio…",
|
||||
"Preparing new paste…": "Preparo il nuovo messaggio…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Nel caso questo messaggio non scompaia, controlla questa <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">FAQ</a> per trovare informazioni su come risolvere il problema (in Inglese).",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"Nel caso questo messaggio non scompaia, controlla questa <a href=\"%s\">FAQ</a> per trovare informazioni su come risolvere il problema (in Inglese).",
|
||||
"+++ no paste text +++": "+++ nessun testo nel messaggio +++",
|
||||
"Could not get paste data: %s":
|
||||
"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…"
|
||||
}
|
27
i18n/nl.json
27
i18n/nl.json
@ -35,8 +35,6 @@
|
||||
"JavaScript vereist om %s te laten werken.<br />Sorry voor het ongemak.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s vereist een moderne browser om te kunnen werken ",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Gebruik je nog steeds Internet explorer? Doe jezelf een plezier en maak gebruik van een moderne browser:",
|
||||
"New":
|
||||
"Nieuw",
|
||||
"Send":
|
||||
@ -112,8 +110,6 @@
|
||||
"Serverfout of server reageert niet",
|
||||
"Could not post comment: %s":
|
||||
"Kon het commentaar niet plaatsen: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Aub uw muis bewegen voor meer entropie…",
|
||||
"Sending paste…":
|
||||
"Geplakte tekst verzenden…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -151,9 +147,26 @@
|
||||
"Loading…": "Laden…",
|
||||
"Decrypting paste…": "Geplakte tekst decoderen…",
|
||||
"Preparing new paste…": "Nieuwe geplakte tekst voorbereiden…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"In het geval dat dit bericht nooit verdwijnt, kijkt u dan eens naar <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\"> veelgestelde vragen voor informatie over het oplossen van problemen </a>.",
|
||||
"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":
|
||||
"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…"
|
||||
}
|
27
i18n/no.json
27
i18n/no.json
@ -35,8 +35,6 @@
|
||||
"Javascript kreves for at %s skal fungere<br />Beklager.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s krever en moderne nettleser for å fungere.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Fortsatt bruker av Internet Explorer? Gjør deg selv en tjeneste og bytt til en moderne nettleser:",
|
||||
"New":
|
||||
"Ny",
|
||||
"Send":
|
||||
@ -112,8 +110,6 @@
|
||||
"tjener feilet eller svarer ikke",
|
||||
"Could not post comment: %s":
|
||||
"Kunne ikke sende kommentar: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Flytt musen for mer entropi…",
|
||||
"Sending paste…":
|
||||
"Sender innlegg…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -151,9 +147,26 @@
|
||||
"Loading…": "Laster…",
|
||||
"Decrypting paste…": "Dekrypterer innlegg…",
|
||||
"Preparing new paste…": "Klargjør nytt innlegg…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Hvis denne meldingen ikke forsvinner kan du ta en titt på siden med <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">ofte stilte spørsmål</a> for informasjon om feilsøking.",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"Hvis denne meldingen ikke forsvinner kan du ta en titt på siden med <a href=\"%s\">ofte stilte spørsmål</a> for informasjon om feilsøking.",
|
||||
"+++ no paste text +++": "+++ ingen innleggstekst +++",
|
||||
"Could not get paste data: %s":
|
||||
"Could not get paste data: %s"
|
||||
"Kunne ikke hente utklippsdata: %s",
|
||||
"QR code": "QR kode",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.":
|
||||
"Denne websiden bruker usikker HTTP tilkobling! Bruk den kun for testing.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.":
|
||||
"For mer informasjon <a href=\"%s\">se ofte stilte spørsmål</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
|
||||
"Din nettleser har behov for HTTPS tilkobling for å støtte WebCrypto biblioteket. Prøv å <a href=\"%s\">bytt til 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…"
|
||||
}
|
31
i18n/oc.json
31
i18n/oc.json
@ -30,13 +30,11 @@
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Geton de supression incorrècte. Lo tèxte es pas estat suprimit.",
|
||||
"Paste was properly deleted.":
|
||||
"Lo tèxte es estat correctament suprimit.",
|
||||
"Lo tèxte es estat corrèctament suprimit.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"JavaScript es requesit per far foncionar %s. <br />O planhèm per l’inconvenient.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s necessita un navigator modèrn per foncionar.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Encora sus Internet Explorer ? Fasètz-vos una favor, passatz a un navigator modèrn :",
|
||||
"New":
|
||||
"Nòu",
|
||||
"Send":
|
||||
@ -109,11 +107,9 @@
|
||||
"unknown status":
|
||||
"Estatut desconegut",
|
||||
"server error or not responding":
|
||||
"Lo servidor respond pas o a rencontrat una error",
|
||||
"Lo servidor respond pas o a rescontrat una error",
|
||||
"Could not post comment: %s":
|
||||
"Impossible de mandar lo comentari : %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Mercés de bolegar vòstra mirga per mai entropia…",
|
||||
"Sending paste…":
|
||||
"Mandadís del tèxte…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -160,9 +156,26 @@
|
||||
"Loading…": "Cargament…",
|
||||
"Decrypting paste…": "Deschirament del tèxte…",
|
||||
"Preparing new paste…": "Preparacion…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Se per cas aqueste messatge quita pas de s’afichar mercés de gaitar <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">aquesta FAQ per las solucions</a> (en anglés).",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"Se per cas aqueste messatge quite pas de s’afichar mercés de gaitar <a href=\"%s\">aquesta FAQ per las solucions</a> (en anglés).",
|
||||
"+++ no paste text +++": "+++ cap de tèxte pegat +++",
|
||||
"Could not get paste data: %s":
|
||||
"Could not get paste data: %s"
|
||||
"Recuperacion impossibla de las donadas copiadas : %s",
|
||||
"QR code": "Còdi QR",
|
||||
"This website is using an insecure HTTP connection! Please use it only for testing.":
|
||||
"Aqueste site utiliza una connexion HTTP pas segura ! Mercés de l’utilizar pas que per d’ensages.",
|
||||
"For more information <a href=\"%s\">see this FAQ entry</a>.":
|
||||
"Per mai d’informacions <a href=\"%s\">vejatz aqueste article de FAQ</a>.",
|
||||
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
|
||||
"Se pòt que vòstre navigator faga besonh d’una connexion HTTPS per èsser compatible amb l’API WebCrypto. Ensajatz de <a href=\"%s\">passar al 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…"
|
||||
}
|
49
i18n/pl.json
49
i18n/pl.json
@ -8,7 +8,7 @@
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Wklejka nie istnieje, wygasła albo została usunięta.",
|
||||
"%s requires php %s or above to work. Sorry.":
|
||||
"%s wymaga PHP w wersji %s lub nowszej, sorry.",
|
||||
"%s wymaga PHP w wersji %s lub nowszej. Przykro mi.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s wymaga obecności sekcji [%s] w pliku konfiguracyjnym.",
|
||||
"Please wait %d seconds between each post.":
|
||||
@ -35,8 +35,6 @@
|
||||
"Do działania %sa jest wymagany JavaScript. Przepraszamy za tę niedogodność.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s wymaga do działania nowoczesnej przeglądarki.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Cały czas używasz Internet Explorera? Zrób sobie przysługę, przesiądź się na nowoczesną przeglądarkę:",
|
||||
"New":
|
||||
"Nowa",
|
||||
"Send":
|
||||
@ -109,11 +107,9 @@
|
||||
"unknown status":
|
||||
"nieznany status",
|
||||
"server error or not responding":
|
||||
"bląd serwera lub brak odpowiedzi",
|
||||
"błąd serwera lub brak odpowiedzi",
|
||||
"Could not post comment: %s":
|
||||
"Nie udało się wysłać komentarza: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Proszę poruszać myszą aby uzyskać większą entropię…",
|
||||
"Sending paste…":
|
||||
"Wysyłanie wklejki…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -130,10 +126,10 @@
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Pobierz załącznik",
|
||||
"Cloned: '%s'": "Sklonowano: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"The cloned file '%s' was attached to this paste.": "Sklonowany plik '%s' był dołączony do tej wklejki.",
|
||||
"Attach a file": "Załącz plik",
|
||||
"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.",
|
||||
"alternatively drag & drop a file or paste an image from the clipboard": "Alternatywnie przeciągnij i upuść plik albo wklej obraz ze schowka",
|
||||
"File too large, to display a preview. Please download the attachment.": "Plik zbyt duży aby wyświetlić podgląd. Proszę pobrać załącznik.",
|
||||
"Remove attachment": "Usuń załącznik",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Twoja przeglądarka nie wspiera wysyłania zaszyfrowanych plików. Użyj nowszej przeglądarki.",
|
||||
@ -141,19 +137,36 @@
|
||||
"Options": "Opcje",
|
||||
"Shorten URL": "Skróć adres URL",
|
||||
"Editor": "Edytować",
|
||||
"Preview": "Zapowiedź",
|
||||
"Preview": "Podgląd",
|
||||
"%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",
|
||||
"Odszyfruj",
|
||||
"Enter password":
|
||||
"Wpisz hasło",
|
||||
"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=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a> (in English).",
|
||||
"+++ no paste text +++": "+++ no paste text +++",
|
||||
"Loading…": "Wczytywanie…",
|
||||
"Decrypting paste…": "Odszyfrowywanie wklejki…",
|
||||
"Preparing new paste…": "Przygotowywanie nowej wklejki…",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"W przypadku gdy ten komunikat nigdy nie znika, proszę spójrz na <a href=\"%s\">to FAQ aby rozwiązać problem</a> (po angielsku).",
|
||||
"+++ no paste text +++": "+++ brak wklejonego tekstu +++",
|
||||
"Could not get paste data: %s":
|
||||
"Could not get paste data: %s"
|
||||
"Nie można było pobrać danych wklejki: %s",
|
||||
"QR code": "Kod QR",
|
||||
"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…"
|
||||
}
|
27
i18n/pt.json
27
i18n/pt.json
@ -35,8 +35,6 @@
|
||||
"JavaScript é necessário para que %s funcione.<br />Pedimos desculpas pela inconveniência.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s requer um navegador moderno para funcionar.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Ainda usando Internet Explorer? Faça-se um favor, mude para um navegador moderno:",
|
||||
"New":
|
||||
"Novo",
|
||||
"Send":
|
||||
@ -112,8 +110,6 @@
|
||||
"Servidor em erro ou não responsivo",
|
||||
"Could not post comment: %s":
|
||||
"Não foi possível publicar o comentário: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Por favor, mova o mouse para maior entropia…",
|
||||
"Sending paste…":
|
||||
"Enviando cópia…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -151,9 +147,26 @@
|
||||
"Loading…": "Carregando…",
|
||||
"Decrypting paste…": "Decifrando cópia…",
|
||||
"Preparing new paste…": "Preparando nova cópia…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Caso essa mensagem nunca desapareça, por favor veja <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">este FAQ para saber como resolver os problemas</a>.",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"Caso essa mensagem nunca desapareça, por favor veja <a href=\"%s\">este FAQ para saber como resolver os problemas</a>.",
|
||||
"+++ no paste text +++": "+++ sem texto de cópia +++",
|
||||
"Could not get paste data: %s":
|
||||
"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…"
|
||||
}
|
43
i18n/ru.json
43
i18n/ru.json
@ -12,7 +12,7 @@
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s необходимо наличие секции [%s] в конфигурационном файле.",
|
||||
"Please wait %d seconds between each post.":
|
||||
["Пожалуйста ожидайте %d секунду между каждыми записями.", "Пожалуйста ожидайте %d секунды между каждыми записями.", "Пожалуйста ожидайте %d секунд между каждыми записями."],
|
||||
["Пожалуйста, ожидайте %d секунду между каждыми записями.", "Пожалуйста, ожидайте %d секунды между каждыми записями.", "Пожалуйста, ожидайте %d секунд между каждыми записями."],
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Размер записи ограничен %s зашифрованных данных.",
|
||||
"Invalid data.":
|
||||
@ -28,15 +28,13 @@
|
||||
"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.<br />Sorry for the inconvenience.":
|
||||
"Для работы %s требуется включенный JavaScript.<br />Приносим извинения за неудобства.",
|
||||
"%s requires a modern browser to work.":
|
||||
"Для работы %s требуется более современный браузер.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"До сих пор используете Internet Explorer? Пожалейте себя, перейдите на более современный браузер:",
|
||||
"New":
|
||||
"Новая запись",
|
||||
"Send":
|
||||
@ -79,11 +77,11 @@
|
||||
"This document will expire in %d months.":
|
||||
["Документ будет удален через %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?":
|
||||
@ -112,18 +110,16 @@
|
||||
"ошибка сервера или нет ответа",
|
||||
"Could not post comment: %s":
|
||||
"Не удалось опубликовать комментарий: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Пожалуйста двигайте мышкой для большей энтропии…",
|
||||
"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>",
|
||||
"Ссылка на запись <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?)":
|
||||
"Невозможно расшифровать запись: Ключ расшифровки отсутствует в ссылке (Может быть вы используете сокращатель ссылок, который удаляет часть ссылки?)",
|
||||
"Невозможно расшифровать запись: Ключ расшифровки отсутствует в ссылке (Может быть, вы используете сокращатель ссылок, который удаляет часть ссылки?)",
|
||||
"B": "байт",
|
||||
"KiB": "Кбайт",
|
||||
"MiB": "Мбайт",
|
||||
@ -143,7 +139,7 @@
|
||||
"Дубликат файла '%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.": "Файл слишком большой для отображения предпросмотра. Пожалуйста скачайте прикрепленный файл.",
|
||||
"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.":
|
||||
"Ваш браузер не поддерживает отправку зашифрованных файлов. Используйте более новый браузер.",
|
||||
@ -153,7 +149,7 @@
|
||||
"Editor": "Редактор",
|
||||
"Preview": "Предпросмотр",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"Переменная PATH необходима %s в конце \"%s\". Пожалуйста обновите переменную PATH в вашем index.php.",
|
||||
"Переменная PATH необходима %s в конце \"%s\". Пожалуйста, обновите переменную PATH в вашем index.php.",
|
||||
"Decrypt":
|
||||
"Расшифровать",
|
||||
"Enter password":
|
||||
@ -161,9 +157,26 @@
|
||||
"Loading…": "Загрузка…",
|
||||
"Decrypting paste…": "Расшифровка записи…",
|
||||
"Preparing new paste…": "Подготовка новой записи…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Если данное сообщение не исчезает длительное время, посмотрите <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">этот FAQ с информацией о возможном решении проблемы (на английском)</a>.",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"Если данное сообщение не исчезает длительное время, посмотрите <a href=\"%s\">этот FAQ с информацией о возможном решении проблемы (на английском)</a>.",
|
||||
"+++ no paste text +++": "+++ в записи нет текста +++",
|
||||
"Could not get paste data: %s":
|
||||
"Не удалось получить данные записи: %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\">прочтите информацию в 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.":
|
||||
"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…"
|
||||
}
|
||||
|
27
i18n/sl.json
27
i18n/sl.json
@ -35,8 +35,6 @@
|
||||
"Da %s deluje, moraš vklopiti JavaScript.<br />Oprosti za povročene nevšečnosti.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s za svoje delovanje potrebuje moderen brskalnik.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Še vedno uporabljaš Internet Explorer? Naredi si uslugo, preklopi na moderen brskalnik:",
|
||||
"New":
|
||||
"Nov prilepek",
|
||||
"Send":
|
||||
@ -112,8 +110,6 @@
|
||||
"napaka na strežniku, ali pa se strežnik ne odziva",
|
||||
"Could not post comment: %s":
|
||||
"Komentarja ni bilo mogoče objaviti : %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Prosim premakni svojo miško za več entropije…",
|
||||
"Sending paste…":
|
||||
"Pošiljam prilepek…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
@ -160,9 +156,26 @@
|
||||
"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=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a> (in English).",
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
|
||||
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a> (in English).",
|
||||
"+++ no paste text +++": "+++ no paste text +++",
|
||||
"Could not get paste data: %s":
|
||||
"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…"
|
||||
}
|
||||
|
182
i18n/uk.json
Normal file
182
i18n/uk.json
Normal file
@ -0,0 +1,182 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s це мінімалістичний Open Source проєкт для створення нотаток, де сервер не знає нічого про дані, що зберігаються. Дані шифруються/розшифровуються <i>у переглядачі</i> з використанням 256-бітного шифрувания AES. Подробиці можна дізнатися на <a href=\"https://privatebin.info/\">сайті проєкту</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Бо незнання - благо",
|
||||
"en": "uk",
|
||||
"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 секунд між дописами."],
|
||||
"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.<br />Sorry for the inconvenience.":
|
||||
"Для роботи %s потрібен увімкнутий JavaScript.<br />Вибачте.",
|
||||
"%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 minutes": ["%d хвилину", "%d хвилини", "%d хвилин"],
|
||||
"%d hours": ["%d годину", "%d години", "%d годин"],
|
||||
"%d days": ["%d день", "%d дні", "%d днів"],
|
||||
"%d weeks": ["%d тиждень", "%d тижні", "%d тижнів"],
|
||||
"%d months": ["%d місяць", "%d місяці", "%d місяців"],
|
||||
"%d years": ["%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 секунд."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Документ буде вилучений через %d хвилину.", "Документ буде вилучений через %d хвилини.", "Документ буде вилучений через %d хвилин."],
|
||||
"This document will expire in %d hours.":
|
||||
["Документ буде вилучений через %d годину.", "Документ буде вилучений через %d години.", "Документ буде вилучений через %d годин."],
|
||||
"This document will expire in %d days.":
|
||||
["Документ буде вилучений через %d день.", "Документ буде вилучений через %d дні.", "Документ буде вилучений через %d днів."],
|
||||
"This document will expire in %d months.":
|
||||
["Документ буде вилучений через %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":
|
||||
"Аватар зґенерований з 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?)":
|
||||
"Неможливо розшифрувати запис: Ключ дешифрування відсутній в посиланні (Можливо, ви використовуєте скорочувач посилань, що видаляє частину посилання?)",
|
||||
"B": "байт",
|
||||
"KiB": "Кбайт",
|
||||
"MiB": "Мбайт",
|
||||
"GiB": "Гбайт",
|
||||
"TiB": "Тбайт",
|
||||
"PiB": "Пбайт",
|
||||
"EiB": "Ебайт",
|
||||
"ZiB": "Збайт",
|
||||
"YiB": "Йбайт",
|
||||
"Format": "Формат",
|
||||
"Plain Text": "Звичайний текст",
|
||||
"Source Code": "Джерельний код",
|
||||
"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.":
|
||||
"Змінна PATH необхідна %s в конці \"%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\">цей FAQ з інформацією про можливе вирішення проблеми</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\">дивіться інформацію в 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":
|
||||
"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…"
|
||||
}
|
81
i18n/zh.json
81
i18n/zh.json
@ -1,16 +1,16 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s是一个极简,开源,对粘贴内容毫不知情的在线粘贴板,数据<i>在浏览器内</i>进行AES-256加密。更多信息请查看<a href=\"https://privatebin.info/\">项目主页</a>。",
|
||||
"%s是一个极简、开源、对粘贴内容毫不知情的在线粘贴板,数据<i>在浏览器内</i>进行AES-256加密。更多信息请查看<a href=\"https://privatebin.info/\">项目主页</a>。",
|
||||
"Because ignorance is bliss":
|
||||
"因为无知是福",
|
||||
"en": "zh",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"粘贴不存在,已过期或者已被删除。",
|
||||
"粘贴内容不存在,已过期或已被删除。",
|
||||
"%s requires php %s or above to work. Sorry.":
|
||||
"%s需要工作于PHP %s及以上版本,抱歉。",
|
||||
"%s需要PHP %s及以上版本来工作,抱歉。",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s需要设置配置文件中 [%s] 的部分。",
|
||||
"%s需要设置配置文件中 [%s] 部分。",
|
||||
"Please wait %d seconds between each post.":
|
||||
"每 %d 秒只能粘贴一次。",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
@ -20,29 +20,27 @@
|
||||
"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.":
|
||||
"错误的删除token,粘贴没有被删除。",
|
||||
"错误的删除token,粘贴内容没有被删除。",
|
||||
"Paste was properly deleted.":
|
||||
"粘贴已被正确删除。",
|
||||
"粘贴内容已被正确删除。",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"%s需要JavaScript来进行加解密。<br />带来的不便敬请谅解。",
|
||||
"%s需要JavaScript来进行加解密。<br />给你带来的不便敬请谅解。",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s需要工作于现代化的浏览器。",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"还在使用Internet Explorer?帮自己个忙,换上一个现代化的浏览器:",
|
||||
"%s需要在现代浏览器上工作。",
|
||||
"New":
|
||||
"新建",
|
||||
"Send":
|
||||
"送出",
|
||||
"Clone":
|
||||
"克隆",
|
||||
"复制",
|
||||
"Raw text":
|
||||
"纯文本",
|
||||
"Expires":
|
||||
@ -52,7 +50,7 @@
|
||||
"Open discussion":
|
||||
"开放讨论",
|
||||
"Password (recommended)":
|
||||
"密码 (推荐)",
|
||||
"密码(推荐)",
|
||||
"Discussion":
|
||||
"讨论",
|
||||
"Toggle navigation":
|
||||
@ -79,13 +77,13 @@
|
||||
"This document will expire in %d months.":
|
||||
["这份文档将在一个月后过期。", "这份文档将在 %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":
|
||||
@ -105,35 +103,33 @@
|
||||
"Comment posted.":
|
||||
"评论已发送。",
|
||||
"Could not refresh display: %s":
|
||||
"无法刷新显示: %s",
|
||||
"无法刷新显示:%s",
|
||||
"unknown status":
|
||||
"未知状态",
|
||||
"server error or not responding":
|
||||
"服务器错误或无回应",
|
||||
"Could not post comment: %s":
|
||||
"无法发送评论: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"请移动鼠标增加随机性…",
|
||||
"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>",
|
||||
"您粘贴内容的链接是<a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(按下 [Ctrl]+[c] 以复制)</span>",
|
||||
"Delete data":
|
||||
"删除数据",
|
||||
"Could not create paste: %s":
|
||||
"无法创建粘贴: %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中缺失解密密钥(是否使用了重定向或者短链接导致密钥丢失?)",
|
||||
"Format": "格式",
|
||||
"Plain Text": "纯文本",
|
||||
"Source Code": "源代码",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "下载附件",
|
||||
"Cloned: '%s'": "克隆: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "克隆文件 '%s' 已附加到此粘贴。",
|
||||
"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": "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.",
|
||||
"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.":
|
||||
"您的浏览器不支持上传加密的文件,请使用更新的浏览器。",
|
||||
@ -150,10 +146,27 @@
|
||||
"输入密码",
|
||||
"Loading…": "载入中…",
|
||||
"Decrypting paste…": "正在解密",
|
||||
"Preparing new paste…": "正在准备新的粘贴",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"如果这个消息一直不消失,请参考 <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">这里的 FAQ 进行故障排除</a> (英文版)。",
|
||||
"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\">这里的 FAQ (英文版)</a>进行故障排除。",
|
||||
"+++ no paste text +++": "+++ 没有粘贴内容 +++",
|
||||
"Could not get paste data: %s":
|
||||
"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连接才能支持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.":
|
||||
"您的浏览器不支持用于zlib压缩的WebAssembly。 您可以创建未压缩的文档,但不能读取压缩的文档。",
|
||||
"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…":
|
||||
"显示原始文字…"
|
||||
}
|
||||
|
BIN
img/icon_email.png
Normal file
BIN
img/icon_email.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 253 B |
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
// change this, if your php files and data is outside of your webservers document root
|
||||
|
120
js/base-x-3.0.7.js
Normal file
120
js/base-x-3.0.7.js
Normal file
@ -0,0 +1,120 @@
|
||||
'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)
|
||||
BASE_MAP.fill(255)
|
||||
for (var i = 0; i < ALPHABET.length; i++) {
|
||||
var x = ALPHABET.charAt(i)
|
||||
var xc = x.charCodeAt(0)
|
||||
if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') }
|
||||
BASE_MAP[xc] = i
|
||||
}
|
||||
var BASE = ALPHABET.length
|
||||
var LEADER = ALPHABET.charAt(0)
|
||||
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.length === 0) { return '' }
|
||||
// Skip & count leading zeroes.
|
||||
var zeroes = 0
|
||||
var length = 0
|
||||
var pbegin = 0
|
||||
var pend = source.length
|
||||
while (pbegin !== pend && source[pbegin] === 0) {
|
||||
pbegin++
|
||||
zeroes++
|
||||
}
|
||||
// Allocate enough space in big-endian base58 representation.
|
||||
var size = ((pend - pbegin) * iFACTOR + 1) >>> 0
|
||||
var b58 = new Uint8Array(size)
|
||||
// Process the bytes.
|
||||
while (pbegin !== pend) {
|
||||
var carry = source[pbegin]
|
||||
// Apply "b58 = b58 * 256 + ch".
|
||||
var i = 0
|
||||
for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {
|
||||
carry += (256 * b58[it1]) >>> 0
|
||||
b58[it1] = (carry % BASE) >>> 0
|
||||
carry = (carry / BASE) >>> 0
|
||||
}
|
||||
if (carry !== 0) { throw new Error('Non-zero carry') }
|
||||
length = i
|
||||
pbegin++
|
||||
}
|
||||
// Skip leading zeroes in base58 result.
|
||||
var it2 = size - length
|
||||
while (it2 !== size && b58[it2] === 0) {
|
||||
it2++
|
||||
}
|
||||
// Translate the result into a string.
|
||||
var str = LEADER.repeat(zeroes)
|
||||
for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]) }
|
||||
return str
|
||||
}
|
||||
function decodeUnsafe (source) {
|
||||
if (typeof source !== 'string') { throw new TypeError('Expected String') }
|
||||
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
|
||||
while (source[psz] === LEADER) {
|
||||
zeroes++
|
||||
psz++
|
||||
}
|
||||
// Allocate enough space in big-endian base256 representation.
|
||||
var size = (((source.length - psz) * FACTOR) + 1) >>> 0 // log(58) / log(256), rounded up.
|
||||
var b256 = new Uint8Array(size)
|
||||
// Process the characters.
|
||||
while (source[psz]) {
|
||||
// Decode character
|
||||
var carry = BASE_MAP[source.charCodeAt(psz)]
|
||||
// Invalid character
|
||||
if (carry === 255) { return }
|
||||
var i = 0
|
||||
for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {
|
||||
carry += (BASE * b256[it3]) >>> 0
|
||||
b256[it3] = (carry % 256) >>> 0
|
||||
carry = (carry / 256) >>> 0
|
||||
}
|
||||
if (carry !== 0) { throw new Error('Non-zero carry') }
|
||||
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 = []
|
||||
var j = zeroes
|
||||
while (it4 !== size) {
|
||||
vch[j++] = b256[it4++]
|
||||
}
|
||||
return vch
|
||||
}
|
||||
function decode (string) {
|
||||
var buffer = decodeUnsafe(string)
|
||||
if (buffer) { return buffer }
|
||||
throw new Error('Non-base' + BASE + ' character')
|
||||
}
|
||||
return {
|
||||
encode: encode,
|
||||
decodeUnsafe: decodeUnsafe,
|
||||
decode: decode
|
||||
}
|
||||
}
|
||||
}).call(this);
|
@ -1 +0,0 @@
|
||||
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory(global):typeof define==="function"&&define.amd?define(factory):factory(global)})(typeof self!=="undefined"?self:typeof window!=="undefined"?window:typeof global!=="undefined"?global:this,function(global){"use strict";var _Base64=global.Base64;var version="2.4.5";var buffer;if(typeof module!=="undefined"&&module.exports){try{buffer=require("buffer").Buffer}catch(err){}}var b64chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var b64tab=function(bin){var t={};for(var i=0,l=bin.length;i<l;i++)t[bin.charAt(i)]=i;return t}(b64chars);var fromCharCode=String.fromCharCode;var cb_utob=function(c){if(c.length<2){var cc=c.charCodeAt(0);return cc<128?c:cc<2048?fromCharCode(192|cc>>>6)+fromCharCode(128|cc&63):fromCharCode(224|cc>>>12&15)+fromCharCode(128|cc>>>6&63)+fromCharCode(128|cc&63)}else{var cc=65536+(c.charCodeAt(0)-55296)*1024+(c.charCodeAt(1)-56320);return fromCharCode(240|cc>>>18&7)+fromCharCode(128|cc>>>12&63)+fromCharCode(128|cc>>>6&63)+fromCharCode(128|cc&63)}};var re_utob=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;var utob=function(u){return u.replace(re_utob,cb_utob)};var cb_encode=function(ccc){var padlen=[0,2,1][ccc.length%3],ord=ccc.charCodeAt(0)<<16|(ccc.length>1?ccc.charCodeAt(1):0)<<8|(ccc.length>2?ccc.charCodeAt(2):0),chars=[b64chars.charAt(ord>>>18),b64chars.charAt(ord>>>12&63),padlen>=2?"=":b64chars.charAt(ord>>>6&63),padlen>=1?"=":b64chars.charAt(ord&63)];return chars.join("")};var btoa=global.btoa?function(b){return global.btoa(b)}:function(b){return b.replace(/[\s\S]{1,3}/g,cb_encode)};var _encode=buffer?buffer.from&&Uint8Array&&buffer.from!==Uint8Array.from?function(u){return(u.constructor===buffer.constructor?u:buffer.from(u)).toString("base64")}:function(u){return(u.constructor===buffer.constructor?u:new buffer(u)).toString("base64")}:function(u){return btoa(utob(u))};var encode=function(u,urisafe){return!urisafe?_encode(String(u)):_encode(String(u)).replace(/[+\/]/g,function(m0){return m0=="+"?"-":"_"}).replace(/=/g,"")};var encodeURI=function(u){return encode(u,true)};var re_btou=new RegExp(["[À-ß][-¿]","[à-ï][-¿]{2}","[ð-÷][-¿]{3}"].join("|"),"g");var cb_btou=function(cccc){switch(cccc.length){case 4:var cp=(7&cccc.charCodeAt(0))<<18|(63&cccc.charCodeAt(1))<<12|(63&cccc.charCodeAt(2))<<6|63&cccc.charCodeAt(3),offset=cp-65536;return fromCharCode((offset>>>10)+55296)+fromCharCode((offset&1023)+56320);case 3:return fromCharCode((15&cccc.charCodeAt(0))<<12|(63&cccc.charCodeAt(1))<<6|63&cccc.charCodeAt(2));default:return fromCharCode((31&cccc.charCodeAt(0))<<6|63&cccc.charCodeAt(1))}};var btou=function(b){return b.replace(re_btou,cb_btou)};var cb_decode=function(cccc){var len=cccc.length,padlen=len%4,n=(len>0?b64tab[cccc.charAt(0)]<<18:0)|(len>1?b64tab[cccc.charAt(1)]<<12:0)|(len>2?b64tab[cccc.charAt(2)]<<6:0)|(len>3?b64tab[cccc.charAt(3)]:0),chars=[fromCharCode(n>>>16),fromCharCode(n>>>8&255),fromCharCode(n&255)];chars.length-=[0,0,2,1][padlen];return chars.join("")};var atob=global.atob?function(a){return global.atob(a)}:function(a){return a.replace(/[\s\S]{1,4}/g,cb_decode)};var _decode=buffer?buffer.from&&Uint8Array&&buffer.from!==Uint8Array.from?function(a){return(a.constructor===buffer.constructor?a:buffer.from(a,"base64")).toString()}:function(a){return(a.constructor===buffer.constructor?a:new buffer(a,"base64")).toString()}:function(a){return btou(atob(a))};var decode=function(a){return _decode(String(a).replace(/[-_]/g,function(m0){return m0=="-"?"+":"/"}).replace(/[^A-Za-z0-9\+\/]/g,""))};var noConflict=function(){var Base64=global.Base64;global.Base64=_Base64;return Base64};global.Base64={VERSION:version,atob:atob,btoa:btoa,fromBase64:decode,toBase64:encode,utob:utob,encode:encode,encodeURI:encodeURI,btou:btou,decode:decode,noConflict:noConflict};if(typeof Object.defineProperty==="function"){var noEnum=function(v){return{value:v,enumerable:false,writable:true,configurable:true}};global.Base64.extendString=function(){Object.defineProperty(String.prototype,"fromBase64",noEnum(function(){return decode(this)}));Object.defineProperty(String.prototype,"toBase64",noEnum(function(urisafe){return encode(this,urisafe)}));Object.defineProperty(String.prototype,"toBase64URI",noEnum(function(){return encode(this,true)}))}}if(global["Meteor"]){Base64=global.Base64}if(typeof module!=="undefined"&&module.exports){module.exports.Base64=global.Base64}else if(typeof define==="function"&&define.amd){define([],function(){return global.Base64})}return{Base64:global.Base64}});
|
@ -1,16 +1,35 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"status": "so:Integer",
|
||||
"id": "so:name",
|
||||
"parentid": "so:name",
|
||||
"url: {
|
||||
"@id": "so:url",
|
||||
"@type": "@id"
|
||||
"pb": "?jsonld=types#",
|
||||
"cm": "?jsonld=commentmeta#",
|
||||
"status": {
|
||||
"@type": "so:Integer"
|
||||
},
|
||||
"id": {
|
||||
"@type": "so:name"
|
||||
},
|
||||
"pasteid": {
|
||||
"@type": "so:name"
|
||||
},
|
||||
"parentid": {
|
||||
"@type": "so:name"
|
||||
},
|
||||
"url": {
|
||||
"@type": "so:url"
|
||||
},
|
||||
"v": {
|
||||
"@type": "so:Integer",
|
||||
"@value": 2
|
||||
},
|
||||
"ct": {
|
||||
"@type": "pb:CipherText"
|
||||
},
|
||||
"adata": {
|
||||
"@type": "pb:CipherParameters"
|
||||
},
|
||||
"data": "so:Text",
|
||||
"meta": {
|
||||
"@id": "?jsonld=commentmeta"
|
||||
"@type": "cm:MetaData"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,14 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"postdate": "so:Integer",
|
||||
"nickname": "so:Text",
|
||||
"vizhash": "so:Text"
|
||||
"pb": "?jsonld=types#"
|
||||
},
|
||||
"MetaData": {
|
||||
"created": {
|
||||
"@type": "CreationTime"
|
||||
},
|
||||
"icon": {
|
||||
"@type": "so:url"
|
||||
}
|
||||
}
|
||||
}
|
160
js/common.js
160
js/common.js
@ -1,160 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// testing prerequisites
|
||||
global.assert = require('assert');
|
||||
global.jsc = require('jsverify');
|
||||
global.jsdom = require('jsdom-global');
|
||||
global.cleanup = global.jsdom();
|
||||
global.fs = require('fs');
|
||||
|
||||
// application libraries to test
|
||||
global.$ = global.jQuery = require('./jquery-3.3.1');
|
||||
global.sjcl = require('./sjcl-1.0.7');
|
||||
global.Base64 = require('./base64-2.4.5').Base64;
|
||||
global.RawDeflate = require('./rawdeflate-0.5').RawDeflate;
|
||||
global.RawDeflate.inflate = require('./rawinflate-0.3').RawDeflate.inflate;
|
||||
require('./prettify');
|
||||
global.prettyPrint = window.PR.prettyPrint;
|
||||
global.prettyPrintOne = window.PR.prettyPrintOne;
|
||||
global.showdown = require('./showdown-1.8.6');
|
||||
global.DOMPurify = require('./purify-1.0.7');
|
||||
require('./bootstrap-3.3.7');
|
||||
require('./privatebin');
|
||||
|
||||
// internal variables
|
||||
var a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m',
|
||||
'n','o','p','q','r','s','t','u','v','w','x','y','z'],
|
||||
alnumString = a2zString.concat(['0','1','2','3','4','5','6','7','8','9']),
|
||||
queryString = alnumString.concat(['+','%','&','.','*','-','_']),
|
||||
hashString = queryString.concat(['!']),
|
||||
base64String = alnumString.concat(['+','/','=']).concat(
|
||||
a2zString.map(function(c) {
|
||||
return c.toUpperCase();
|
||||
})
|
||||
),
|
||||
schemas = ['ftp','gopher','http','https','ws','wss'],
|
||||
supportedLanguages = ['de', 'es', 'fr', 'it', 'no', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh'],
|
||||
mimeTypes = ['image/png', 'application/octet-stream'],
|
||||
formats = ['plaintext', 'markdown', 'syntaxhighlighting'],
|
||||
/**
|
||||
* character to HTML entity lookup table
|
||||
*
|
||||
* @see {@link https://github.com/janl/mustache.js/blob/master/mustache.js#L60}
|
||||
*/
|
||||
entityMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'/': '/',
|
||||
'`': '`',
|
||||
'=': '='
|
||||
},
|
||||
logFile = fs.createWriteStream('test.log'),
|
||||
mimeFile = fs.createReadStream('/etc/mime.types'),
|
||||
mimeLine = '';
|
||||
|
||||
// redirect console messages to log file
|
||||
console.info = console.warn = console.error = function () {
|
||||
logFile.write(Array.prototype.slice.call(arguments).join('') + '\n');
|
||||
};
|
||||
|
||||
// populate mime types from environment
|
||||
mimeFile.on('data', function(data) {
|
||||
mimeLine += data;
|
||||
var index = mimeLine.indexOf('\n');
|
||||
while (index > -1) {
|
||||
var line = mimeLine.substring(0, index);
|
||||
mimeLine = mimeLine.substring(index + 1);
|
||||
parseMime(line);
|
||||
index = mimeLine.indexOf('\n');
|
||||
}
|
||||
});
|
||||
|
||||
mimeFile.on('end', function() {
|
||||
if (mimeLine.length > 0) {
|
||||
parseMime(mimeLine);
|
||||
}
|
||||
});
|
||||
|
||||
function parseMime(line) {
|
||||
// ignore comments
|
||||
var index = line.indexOf('#');
|
||||
if (index > -1) {
|
||||
line = line.substring(0, index);
|
||||
}
|
||||
|
||||
// ignore bits after tabs
|
||||
index = line.indexOf('\t');
|
||||
if (index > -1) {
|
||||
line = line.substring(0, index);
|
||||
}
|
||||
if (line.length > 0) {
|
||||
mimeTypes.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
// common testing helper functions
|
||||
|
||||
/**
|
||||
* convert all applicable characters to HTML entities
|
||||
*
|
||||
* @see {@link https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content}
|
||||
* @name htmlEntities
|
||||
* @function
|
||||
* @param {string} str
|
||||
* @return {string} escaped HTML
|
||||
*/
|
||||
exports.htmlEntities = function(str) {
|
||||
return String(str).replace(
|
||||
/[&<>"'`=\/]/g, function(s) {
|
||||
return entityMap[s];
|
||||
});
|
||||
};
|
||||
|
||||
// provides random lowercase characters from a to z
|
||||
exports.jscA2zString = function() {
|
||||
return jsc.elements(a2zString);
|
||||
};
|
||||
|
||||
// provides random lowercase alpha numeric characters (a to z and 0 to 9)
|
||||
exports.jscAlnumString = function() {
|
||||
return jsc.elements(alnumString);
|
||||
};
|
||||
|
||||
// provides random characters allowed in GET queries
|
||||
exports.jscQueryString = function() {
|
||||
return jsc.elements(queryString);
|
||||
};
|
||||
|
||||
// provides random characters allowed in hash queries
|
||||
exports.jscHashString = function() {
|
||||
return jsc.elements(hashString);
|
||||
};
|
||||
|
||||
// provides random characters allowed in base64 encoded strings
|
||||
exports.jscBase64String = function() {
|
||||
return jsc.elements(base64String);
|
||||
};
|
||||
|
||||
// provides a random URL schema supported by the whatwg-url library
|
||||
exports.jscSchemas = function() {
|
||||
return jsc.elements(schemas);
|
||||
};
|
||||
|
||||
// provides a random supported language string
|
||||
exports.jscSupportedLanguages = function() {
|
||||
return jsc.elements(supportedLanguages);
|
||||
};
|
||||
|
||||
// provides a random mime type
|
||||
exports.jscMimeTypes = function() {
|
||||
return jsc.elements(mimeTypes);
|
||||
};
|
||||
|
||||
// provides a random PrivateBin paste formatter
|
||||
exports.jscFormats = function() {
|
||||
return jsc.elements(formats);
|
||||
};
|
||||
|
2
js/jquery-3.3.1.js
vendored
2
js/jquery-3.3.1.js
vendored
File diff suppressed because one or more lines are too long
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
File diff suppressed because one or more lines are too long
2
js/kjua-0.6.0.js
Normal file
2
js/kjua-0.6.0.js
Normal file
File diff suppressed because one or more lines are too long
311
js/legacy.js
Normal file
311
js/legacy.js
Normal file
@ -0,0 +1,311 @@
|
||||
/**
|
||||
* PrivateBin
|
||||
*
|
||||
* a zero-knowledge paste bin
|
||||
*
|
||||
* @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.3.1
|
||||
* @name Legacy
|
||||
* @namespace
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT NOTICE FOR DEVELOPERS:
|
||||
* The logic in this file is intended to run in legacy browsers. Avoid any use of:
|
||||
* - jQuery (doesn't work in older browsers)
|
||||
* - ES5 or newer in general
|
||||
* - const/let, use the traditional var declarations instead
|
||||
* - async/await or Promises, use traditional callbacks
|
||||
* - shorthand function notation "() => output", use the full "function() {return output;}" style
|
||||
* - IE doesn't support:
|
||||
* - URL(), use the traditional window.location object
|
||||
* - endsWith(), use indexof()
|
||||
* - yes, this logic needs to support IE 6, to at least display the error message
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
(function() {
|
||||
/**
|
||||
* compatibility check
|
||||
*
|
||||
* @name Check
|
||||
* @class
|
||||
*/
|
||||
var Check = (function () {
|
||||
var me = {};
|
||||
|
||||
/**
|
||||
* Status of the initial check, true means it passed
|
||||
*
|
||||
* @private
|
||||
* @prop {bool}
|
||||
*/
|
||||
var status = false;
|
||||
|
||||
/**
|
||||
* Initialization check did run
|
||||
*
|
||||
* @private
|
||||
* @prop {bool}
|
||||
*/
|
||||
var init = false;
|
||||
|
||||
/**
|
||||
* blacklist of UserAgents (parts) known to belong to a bot
|
||||
*
|
||||
* @private
|
||||
* @enum {Array}
|
||||
* @readonly
|
||||
*/
|
||||
var badBotUA = [
|
||||
'Bot',
|
||||
'bot'
|
||||
];
|
||||
|
||||
/**
|
||||
* whitelist of top level domains to consider a secure context,
|
||||
* regardless of protocol
|
||||
*
|
||||
* @private
|
||||
* @enum {Array}
|
||||
* @readonly
|
||||
*/
|
||||
var tld = [
|
||||
'.onion',
|
||||
'.i2p'
|
||||
];
|
||||
|
||||
/**
|
||||
* whitelist of hostnames to consider a secure context,
|
||||
* regardless of protocol
|
||||
*
|
||||
* @private
|
||||
* @enum {Array}
|
||||
* @readonly
|
||||
*/
|
||||
// whitelists of TLDs & local hostnames
|
||||
var hostname = [
|
||||
'localhost',
|
||||
'127.0.0.1',
|
||||
'[::1]'
|
||||
];
|
||||
|
||||
/**
|
||||
* check if the context is secure
|
||||
*
|
||||
* @private
|
||||
* @name Check.isSecureContext
|
||||
* @function
|
||||
* @return {bool}
|
||||
*/
|
||||
function isSecureContext()
|
||||
{
|
||||
// use .isSecureContext if available
|
||||
if (window.isSecureContext === true || window.isSecureContext === false) {
|
||||
return window.isSecureContext;
|
||||
}
|
||||
|
||||
// HTTP is obviously insecure
|
||||
if (window.location.protocol !== 'http:') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// filter out actually secure connections over HTTP
|
||||
for (var i = 0; i < tld.length; i++) {
|
||||
if (
|
||||
window.location.hostname.indexOf(
|
||||
tld[i],
|
||||
window.location.hostname.length - tld[i].length
|
||||
) !== -1
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// whitelist localhost for development
|
||||
for (var j = 0; j < hostname.length; j++) {
|
||||
if (window.location.hostname === hostname[j]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// totally INSECURE http protocol!
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether this is a bot we dislike
|
||||
*
|
||||
* @private
|
||||
* @name Check.isBadBot
|
||||
* @function
|
||||
* @return {bool}
|
||||
*/
|
||||
function isBadBot() {
|
||||
// check whether a bot user agent part can be found in the current
|
||||
// user agent
|
||||
for (var i = 0; i < badBotUA.length; i++) {
|
||||
if (navigator.userAgent.indexOf(badBotUA[i]) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether this is an unsupported browser, via feature detection
|
||||
*
|
||||
* @private
|
||||
* @name Check.isOldBrowser
|
||||
* @function
|
||||
* @return {bool}
|
||||
*/
|
||||
function isOldBrowser() {
|
||||
// webcrypto support
|
||||
if (!(
|
||||
'crypto' in window &&
|
||||
'getRandomValues' in window.crypto &&
|
||||
'subtle' in window.crypto &&
|
||||
'encrypt' in window.crypto.subtle &&
|
||||
'decrypt' in window.crypto.subtle &&
|
||||
'Uint8Array' in window &&
|
||||
'Uint32Array' in window
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// async & ES6 support
|
||||
try {
|
||||
eval('async () => {}');
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
return true;
|
||||
} else {
|
||||
throw e; // throws CSP error
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* shows an error message
|
||||
*
|
||||
* @private
|
||||
* @name Check.showError
|
||||
* @param {string} message
|
||||
* @function
|
||||
*/
|
||||
function showError(message)
|
||||
{
|
||||
var element = document.getElementById('errormessage');
|
||||
if (message.indexOf('<a') === -1) {
|
||||
element.appendChild(
|
||||
document.createTextNode(message)
|
||||
);
|
||||
} else {
|
||||
element.innerHTML = message;
|
||||
}
|
||||
removeHiddenFromId('errormessage');
|
||||
}
|
||||
|
||||
/**
|
||||
* removes "hidden" CSS class from element with given ID
|
||||
*
|
||||
* @private
|
||||
* @name Check.removeHiddenFromId
|
||||
* @param {string} id
|
||||
* @function
|
||||
*/
|
||||
function removeHiddenFromId(id)
|
||||
{
|
||||
var element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.className = element.className.replace(/\bhidden\b/g, '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns if the check has concluded
|
||||
*
|
||||
* @name Check.getInit
|
||||
* @function
|
||||
* @return {bool}
|
||||
*/
|
||||
me.getInit = function()
|
||||
{
|
||||
return init;
|
||||
};
|
||||
|
||||
/**
|
||||
* returns the current status of the check
|
||||
*
|
||||
* @name Check.getStatus
|
||||
* @function
|
||||
* @return {bool}
|
||||
*/
|
||||
me.getStatus = function()
|
||||
{
|
||||
return status;
|
||||
};
|
||||
|
||||
/**
|
||||
* init on application start, returns an all-clear signal
|
||||
*
|
||||
* @name Check.init
|
||||
* @function
|
||||
*/
|
||||
me.init = function()
|
||||
{
|
||||
// prevent bots from viewing a paste and potentially deleting data
|
||||
// when burn-after-reading is set
|
||||
if (isBadBot()) {
|
||||
showError('I love you too, bot…');
|
||||
init = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isOldBrowser()) {
|
||||
// some browsers (Chrome based ones) would have webcrypto support if using HTTPS
|
||||
if (!isSecureContext()) {
|
||||
removeHiddenFromId('insecurecontextnotice');
|
||||
}
|
||||
removeHiddenFromId('oldnotice');
|
||||
init = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSecureContext()) {
|
||||
removeHiddenFromId('httpnotice');
|
||||
}
|
||||
init = true;
|
||||
|
||||
// only if everything passed, we set the status to true
|
||||
status = true;
|
||||
};
|
||||
|
||||
return me;
|
||||
})();
|
||||
|
||||
// main application start, called when DOM is fully loaded
|
||||
if (document.readyState === 'complete' || (!document.attachEvent && document.readyState === 'interactive')) {
|
||||
Check.init();
|
||||
} else {
|
||||
if (document.addEventListener) {
|
||||
// first choice is DOMContentLoaded event
|
||||
document.addEventListener('DOMContentLoaded', Check.init, false);
|
||||
// backup is window load event
|
||||
window.addEventListener('load', Check.init, false);
|
||||
} else {
|
||||
// must be IE
|
||||
document.attachEvent('onreadystatechange', Check.init);
|
||||
window.attachEvent('onload', Check.init);
|
||||
}
|
||||
}
|
||||
|
||||
this.Legacy = {
|
||||
Check: Check
|
||||
};
|
||||
}).call(this);
|
43
js/package.json
Normal file
43
js/package.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "privatebin",
|
||||
"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": {
|
||||
"test": "test"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"jsdom": "^9.12.0",
|
||||
"jsdom-global": "^2.1.1",
|
||||
"jsdom-url": "^2.2.1",
|
||||
"jsverify": "^0.8.3",
|
||||
"node-webcrypto-ossl": "^1.0.37"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/PrivateBin/PrivateBin.git"
|
||||
},
|
||||
"keywords": [
|
||||
"private",
|
||||
"secure",
|
||||
"end-to-end-encrypted",
|
||||
"e2e",
|
||||
"paste",
|
||||
"pastebin",
|
||||
"zero",
|
||||
"zero-knowledge",
|
||||
"encryption",
|
||||
"encrypted",
|
||||
"AES"
|
||||
],
|
||||
"author": "",
|
||||
"license": "zlib-acknowledgement",
|
||||
"bugs": {
|
||||
"url": "https://github.com/PrivateBin/PrivateBin/issues"
|
||||
},
|
||||
"homepage": "https://privatebin.info/"
|
||||
}
|
@ -1,24 +1,42 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"status": {"@id": "so:Integer"},
|
||||
"id": {"@id": "so:name"},
|
||||
"deletetoken": {"@id": "so:Text"},
|
||||
"url": {
|
||||
"@type": "@id",
|
||||
"@id": "so:url"
|
||||
"pb": "?jsonld=types#",
|
||||
"pm": "?jsonld=pastemeta#",
|
||||
"status": {
|
||||
"@type": "so:Integer"
|
||||
},
|
||||
"id": {
|
||||
"@type": "so:name"
|
||||
},
|
||||
"deletetoken": {
|
||||
"@type": "so:Text"
|
||||
},
|
||||
"url": {
|
||||
"@type": "so:url"
|
||||
},
|
||||
"v": {
|
||||
"@type": "so:Integer",
|
||||
"@value": 2
|
||||
},
|
||||
"ct": {
|
||||
"@type": "pb:CipherText"
|
||||
},
|
||||
"adata": {
|
||||
"@type": "pm:AuthenticatedData"
|
||||
},
|
||||
"data": {"@id": "so:Text"},
|
||||
"attachment": {"@id": "so:Text"},
|
||||
"attachmentname": {"@id": "so:Text"},
|
||||
"meta": {
|
||||
"@id": "?jsonld=pastemeta"
|
||||
"@type": "pm:MetaData"
|
||||
},
|
||||
"comments": {
|
||||
"@id": "?jsonld=comment",
|
||||
"@type": "?jsonld=comment",
|
||||
"@container": "@list"
|
||||
},
|
||||
"comment_count": {"@id": "so:Integer"},
|
||||
"comment_offset": {"@id": "so:Integer"}
|
||||
"comment_count": {
|
||||
"@type": "so:Integer"
|
||||
},
|
||||
"comment_offset": {
|
||||
"@type": "so:Integer"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,31 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"formatter": {"@id": "so:Text"},
|
||||
"postdate": {"@id": "so:Integer"},
|
||||
"opendiscussion": {"@id": "so:True"},
|
||||
"burnafterreading": {"@id": "so:True"},
|
||||
"expire_date": {"@id": "so:Integer"},
|
||||
"remaining_time": {"@id": "so:Integer"}
|
||||
"pb": "?jsonld=types#"
|
||||
},
|
||||
"AuthenticatedData": {
|
||||
"@container": "@list",
|
||||
"@value": [
|
||||
{
|
||||
"@type": "pb:CipherParameters"
|
||||
},
|
||||
{
|
||||
"@type": "pb:Formatter"
|
||||
},
|
||||
{
|
||||
"@type": "pb:OpenDiscussion"
|
||||
},
|
||||
{
|
||||
"@type": "pb:BurnAfterReading"
|
||||
}
|
||||
]
|
||||
},
|
||||
"MetaData": {
|
||||
"expire": {
|
||||
"@type": "pb:Expiration"
|
||||
},
|
||||
"time_to_live": {
|
||||
"@type": "pb:RemainingSeconds"
|
||||
}
|
||||
}
|
||||
}
|
2511
js/privatebin.js
2511
js/privatebin.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
1
js/purify-2.0.7.js
Normal file
1
js/purify-2.0.7.js
Normal file
File diff suppressed because one or more lines are too long
1675
js/rawdeflate-0.5.js
1675
js/rawdeflate-0.5.js
File diff suppressed because it is too large
Load Diff
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
@ -1,60 +0,0 @@
|
||||
"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
|
||||
sjcl.cipher.aes=function(a){this.s[0][0][0]||this.O();var b,c,d,e,f=this.s[0][4],g=this.s[1];b=a.length;var h=1;if(4!==b&&6!==b&&8!==b)throw new sjcl.exception.invalid("invalid aes key size");this.b=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(0===a%b||8===b&&4===a%b)c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255],0===a%b&&(c=c<<8^c>>>24^h<<24,h=h<<1^283*(h>>7));d[a]=d[a-b]^c}for(b=0;a;b++,a--)c=d[b&3?a:a-4],e[b]=4>=a||4>b?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^g[3][f[c&
|
||||
255]]};
|
||||
sjcl.cipher.aes.prototype={encrypt:function(a){return t(this,a,0)},decrypt:function(a){return t(this,a,1)},s:[[[],[],[],[],[]],[[],[],[],[],[]]],O:function(){var a=this.s[0],b=this.s[1],c=a[4],d=b[4],e,f,g,h=[],k=[],l,n,m,p;for(e=0;0x100>e;e++)k[(h[e]=e<<1^283*(e>>7))^e]=e;for(f=g=0;!c[f];f^=l||1,g=k[g]||1)for(m=g^g<<1^g<<2^g<<3^g<<4,m=m>>8^m&255^99,c[f]=m,d[m]=f,n=h[e=h[l=h[f]]],p=0x1010101*n^0x10001*e^0x101*l^0x1010100*f,n=0x101*h[m]^0x1010100*m,e=0;4>e;e++)a[e][f]=n=n<<24^n>>>8,b[e][m]=p=p<<24^p>>>8;for(e=
|
||||
0;5>e;e++)a[e]=a[e].slice(0),b[e]=b[e].slice(0)}};
|
||||
function t(a,b,c){if(4!==b.length)throw new sjcl.exception.invalid("invalid aes block size");var d=a.b[c],e=b[0]^d[0],f=b[c?3:1]^d[1],g=b[2]^d[2];b=b[c?1:3]^d[3];var h,k,l,n=d.length/4-2,m,p=4,r=[0,0,0,0];h=a.s[c];a=h[0];var q=h[1],v=h[2],w=h[3],x=h[4];for(m=0;m<n;m++)h=a[e>>>24]^q[f>>16&255]^v[g>>8&255]^w[b&255]^d[p],k=a[f>>>24]^q[g>>16&255]^v[b>>8&255]^w[e&255]^d[p+1],l=a[g>>>24]^q[b>>16&255]^v[e>>8&255]^w[f&255]^d[p+2],b=a[b>>>24]^q[e>>16&255]^v[f>>8&255]^w[g&255]^d[p+3],p+=4,e=h,f=k,g=l;for(m=
|
||||
0;4>m;m++)r[c?3&-m:m]=x[e>>>24]<<24^x[f>>16&255]<<16^x[g>>8&255]<<8^x[b&255]^d[p++],h=e,e=f,f=g,g=b,b=h;return r}
|
||||
sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.$(a.slice(b/32),32-(b&31)).slice(1);return void 0===c?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<<c)-1},concat:function(a,b){if(0===a.length||0===b.length)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return 32===d?a.concat(b):sjcl.bitArray.$(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;return 0===
|
||||
b?0:32*(b-1)+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(32*a.length<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b=b&31;0<c&&b&&(a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1));return a},partial:function(a,b,c){return 32===a?b:(c?b|0:b<<32-a)+0x10000000000*a},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return!1;var c=0,d;for(d=0;d<a.length;d++)c|=a[d]^b[d];return 0===
|
||||
c},$:function(a,b,c,d){var e;e=0;for(void 0===d&&(d=[]);32<=b;b-=32)d.push(c),c=0;if(0===b)return d.concat(a);for(e=0;e<a.length;e++)d.push(c|a[e]>>>b),c=a[e]<<32-b;e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,32<b+a?c:d.pop(),1));return d},i:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]},byteswapM:function(a){var b,c;for(b=0;b<a.length;++b)c=a[b],a[b]=c>>>24|c>>>8&0xff00|(c&0xff00)<<8|c<<24;return a}};
|
||||
sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d<c/8;d++)0===(d&3)&&(e=a[d/4]),b+=String.fromCharCode(e>>>8>>>8>>>8),e<<=8;return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++)d=d<<8|a.charCodeAt(c),3===(c&3)&&(b.push(d),d=0);c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}};
|
||||
sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a=a+"00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,4*d)}};
|
||||
sjcl.codec.base32={B:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",X:"0123456789ABCDEFGHIJKLMNOPQRSTUV",BITS:32,BASE:5,REMAINING:27,fromBits:function(a,b,c){var d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,f="",g=0,h=sjcl.codec.base32.B,k=0,l=sjcl.bitArray.bitLength(a);c&&(h=sjcl.codec.base32.X);for(c=0;f.length*d<l;)f+=h.charAt((k^a[c]>>>g)>>>e),g<d?(k=a[c]<<d-g,g+=e,c++):(k<<=d,g-=d);for(;f.length&7&&!b;)f+="=";return f},toBits:function(a,b){a=a.replace(/\s|=/g,"").toUpperCase();var c=sjcl.codec.base32.BITS,
|
||||
d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,f=[],g,h=0,k=sjcl.codec.base32.B,l=0,n,m="base32";b&&(k=sjcl.codec.base32.X,m="base32hex");for(g=0;g<a.length;g++){n=k.indexOf(a.charAt(g));if(0>n){if(!b)try{return sjcl.codec.base32hex.toBits(a)}catch(p){}throw new sjcl.exception.invalid("this isn't "+m+"!");}h>e?(h-=e,f.push(l^n>>>h),l=n<<c-h):(h+=d,l^=n<<c-h)}h&56&&f.push(sjcl.bitArray.partial(h&56,l,1));return f}};
|
||||
sjcl.codec.base32hex={fromBits:function(a,b){return sjcl.codec.base32.fromBits(a,b,1)},toBits:function(a){return sjcl.codec.base32.toBits(a,1)}};
|
||||
sjcl.codec.base64={B:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b,c){var d="",e=0,f=sjcl.codec.base64.B,g=0,h=sjcl.bitArray.bitLength(a);c&&(f=f.substr(0,62)+"-_");for(c=0;6*d.length<h;)d+=f.charAt((g^a[c]>>>e)>>>26),6>e?(g=a[c]<<6-e,e+=26,c++):(g<<=6,e-=6);for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d,e=0,f=sjcl.codec.base64.B,g=0,h;b&&(f=f.substr(0,62)+"-_");for(d=0;d<a.length;d++){h=f.indexOf(a.charAt(d));
|
||||
if(0>h)throw new sjcl.exception.invalid("this isn't base64!");26<e?(e-=26,c.push(g^h>>>e),g=h<<32-e):(e+=6,g^=h<<32-e)}e&56&&c.push(sjcl.bitArray.partial(e&56,g,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.b[0]||this.O();a?(this.F=a.F.slice(0),this.A=a.A.slice(0),this.l=a.l):this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
|
||||
sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.F=this.Y.slice(0);this.A=[];this.l=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.A=sjcl.bitArray.concat(this.A,a);b=this.l;a=this.l=b+sjcl.bitArray.bitLength(a);if(0x1fffffffffffff<a)throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");if("undefined"!==typeof Uint32Array){var d=new Uint32Array(c),e=0;for(b=512+b-(512+b&0x1ff);b<=a;b+=512)u(this,d.subarray(16*e,
|
||||
16*(e+1))),e+=1;c.splice(0,16*e)}else for(b=512+b-(512+b&0x1ff);b<=a;b+=512)u(this,c.splice(0,16));return this},finalize:function(){var a,b=this.A,c=this.F,b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.l/0x100000000));for(b.push(this.l|0);b.length;)u(this,b.splice(0,16));this.reset();return c},Y:[],b:[],O:function(){function a(a){return 0x100000000*(a-Math.floor(a))|0}for(var b=0,c=2,d,e;64>b;c++){e=!0;for(d=2;d*d<=c;d++)if(0===c%d){e=
|
||||
!1;break}e&&(8>b&&(this.Y[b]=a(Math.pow(c,.5))),this.b[b]=a(Math.pow(c,1/3)),b++)}}};
|
||||
function u(a,b){var c,d,e,f=a.F,g=a.b,h=f[0],k=f[1],l=f[2],n=f[3],m=f[4],p=f[5],r=f[6],q=f[7];for(c=0;64>c;c++)16>c?d=b[c]:(d=b[c+1&15],e=b[c+14&15],d=b[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+b[c&15]+b[c+9&15]|0),d=d+q+(m>>>6^m>>>11^m>>>25^m<<26^m<<21^m<<7)+(r^m&(p^r))+g[c],q=r,r=p,p=m,m=n+d|0,n=l,l=k,k=h,h=d+(k&l^n&(k^l))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;f[0]=f[0]+h|0;f[1]=f[1]+k|0;f[2]=f[2]+l|0;f[3]=f[3]+n|0;f[4]=f[4]+m|0;f[5]=f[5]+p|0;f[6]=f[6]+r|0;f[7]=
|
||||
f[7]+q|0}
|
||||
sjcl.mode.ccm={name:"ccm",G:[],listenProgress:function(a){sjcl.mode.ccm.G.push(a)},unListenProgress:function(a){a=sjcl.mode.ccm.G.indexOf(a);-1<a&&sjcl.mode.ccm.G.splice(a,1)},fa:function(a){var b=sjcl.mode.ccm.G.slice(),c;for(c=0;c<b.length;c+=1)b[c](a)},encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,k=h.bitLength(c)/8,l=h.bitLength(g)/8;e=e||64;d=d||[];if(7>k)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;4>f&&l>>>8*f;f++);f<15-k&&(f=15-k);c=h.clamp(c,
|
||||
8*(15-f));b=sjcl.mode.ccm.V(a,b,c,d,e,f);g=sjcl.mode.ccm.C(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),k=f.clamp(b,h-e),l=f.bitSlice(b,h-e),h=(h-e)/8;if(7>g)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;4>b&&h>>>8*b;b++);b<15-g&&(b=15-g);c=f.clamp(c,8*(15-b));k=sjcl.mode.ccm.C(a,k,c,l,e,b);a=sjcl.mode.ccm.V(a,k.data,c,d,e,b);if(!f.equal(k.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");
|
||||
return k.data},na:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,k=h.i;d=[h.partial(8,(b.length?64:0)|d-2<<2|f-1)];d=h.concat(d,c);d[3]|=e;d=a.encrypt(d);if(b.length)for(c=h.bitLength(b)/8,65279>=c?g=[h.partial(16,c)]:0xffffffff>=c&&(g=h.concat([h.partial(16,65534)],[c])),g=h.concat(g,b),b=0;b<g.length;b+=4)d=a.encrypt(k(d,g.slice(b,b+4).concat([0,0,0])));return d},V:function(a,b,c,d,e,f){var g=sjcl.bitArray,h=g.i;e/=8;if(e%2||4>e||16<e)throw new sjcl.exception.invalid("ccm: invalid tag length");
|
||||
if(0xffffffff<d.length||0xffffffff<b.length)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");c=sjcl.mode.ccm.na(a,d,c,e,g.bitLength(b)/8,f);for(d=0;d<b.length;d+=4)c=a.encrypt(h(c,b.slice(d,d+4).concat([0,0,0])));return g.clamp(c,8*e)},C:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.i;var k=b.length,l=h.bitLength(b),n=k/50,m=n;c=h.concat([h.partial(8,f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!k)return{tag:d,data:[]};for(g=0;g<k;g+=4)g>n&&(sjcl.mode.ccm.fa(g/
|
||||
k),n+=m),c[3]++,e=a.encrypt(c),b[g]^=e[0],b[g+1]^=e[1],b[g+2]^=e[2],b[g+3]^=e[3];return{tag:d,data:h.clamp(b,l)}}};
|
||||
sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.S,k=sjcl.bitArray,l=k.i,n=[0,0,0,0];c=h(a.encrypt(c));var m,p=[];d=d||[];e=e||64;for(g=0;g+4<b.length;g+=4)m=b.slice(g,g+4),n=l(n,m),p=p.concat(l(c,a.encrypt(l(c,m)))),c=h(c);m=b.slice(g);b=k.bitLength(m);g=a.encrypt(l(c,[0,0,0,b]));m=k.clamp(l(m.concat([0,0,0]),g),b);n=l(n,l(m.concat([0,0,0]),g));n=a.encrypt(l(n,l(c,h(c))));
|
||||
d.length&&(n=l(n,f?d:sjcl.mode.ocb2.pmac(a,d)));return p.concat(k.concat(m,k.clamp(n,e)))},decrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.S,h=sjcl.bitArray,k=h.i,l=[0,0,0,0],n=g(a.encrypt(c)),m,p,r=sjcl.bitArray.bitLength(b)-e,q=[];d=d||[];for(c=0;c+4<r/32;c+=4)m=k(n,a.decrypt(k(n,b.slice(c,c+4)))),l=k(l,m),q=q.concat(m),n=g(n);p=r-32*c;m=a.encrypt(k(n,[0,0,0,p]));m=k(m,h.clamp(b.slice(c),p).concat([0,
|
||||
0,0]));l=k(l,m);l=a.encrypt(k(l,k(n,g(n))));d.length&&(l=k(l,f?d:sjcl.mode.ocb2.pmac(a,d)));if(!h.equal(h.clamp(l,e),h.bitSlice(b,r)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return q.concat(h.clamp(m,p))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.S,e=sjcl.bitArray,f=e.i,g=[0,0,0,0],h=a.encrypt([0,0,0,0]),h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4)h=d(h),g=f(g,a.encrypt(f(h,b.slice(c,c+4))));c=b.slice(c);128>e.bitLength(c)&&(h=f(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));g=f(g,c);
|
||||
return a.encrypt(f(d(f(h,d(h))),g))},S:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^135*(a[0]>>>31)]}};
|
||||
sjcl.mode.gcm={name:"gcm",encrypt:function(a,b,c,d,e){var f=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.C(!0,a,f,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var f=b.slice(0),g=sjcl.bitArray,h=g.bitLength(f);e=e||128;d=d||[];e<=h?(b=g.bitSlice(f,h-e),f=g.bitSlice(f,0,h-e)):(b=f,f=[]);a=sjcl.mode.gcm.C(!1,a,f,d,c,e);if(!g.equal(a.tag,b))throw new sjcl.exception.corrupt("gcm: tag doesn't match");return a.data},ka:function(a,b){var c,d,e,f,g,h=sjcl.bitArray.i;e=[0,0,
|
||||
0,0];f=b.slice(0);for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,f));g=0!==(f[3]&1);for(d=3;0<d;d--)f[d]=f[d]>>>1|(f[d-1]&1)<<31;f[0]>>>=1;g&&(f[0]^=-0x1f000000)}return e},j:function(a,b,c){var d,e=c.length;b=b.slice(0);for(d=0;d<e;d+=4)b[0]^=0xffffffff&c[d],b[1]^=0xffffffff&c[d+1],b[2]^=0xffffffff&c[d+2],b[3]^=0xffffffff&c[d+3],b=sjcl.mode.gcm.ka(b,a);return b},C:function(a,b,c,d,e,f){var g,h,k,l,n,m,p,r,q=sjcl.bitArray;m=c.length;p=q.bitLength(c);r=q.bitLength(d);h=q.bitLength(e);
|
||||
g=b.encrypt([0,0,0,0]);96===h?(e=e.slice(0),e=q.concat(e,[1])):(e=sjcl.mode.gcm.j(g,[0,0,0,0],e),e=sjcl.mode.gcm.j(g,e,[0,0,Math.floor(h/0x100000000),h&0xffffffff]));h=sjcl.mode.gcm.j(g,[0,0,0,0],d);n=e.slice(0);d=h.slice(0);a||(d=sjcl.mode.gcm.j(g,h,c));for(l=0;l<m;l+=4)n[3]++,k=b.encrypt(n),c[l]^=k[0],c[l+1]^=k[1],c[l+2]^=k[2],c[l+3]^=k[3];c=q.clamp(c,p);a&&(d=sjcl.mode.gcm.j(g,h,c));a=[Math.floor(r/0x100000000),r&0xffffffff,Math.floor(p/0x100000000),p&0xffffffff];d=sjcl.mode.gcm.j(g,d,a);k=b.encrypt(e);
|
||||
d[0]^=k[0];d[1]^=k[1];d[2]^=k[2];d[3]^=k[3];return{tag:q.bitSlice(d,0,f),data:c}}};sjcl.misc.hmac=function(a,b){this.W=b=b||sjcl.hash.sha256;var c=[[],[]],d,e=b.prototype.blockSize/32;this.w=[new b,new b];a.length>e&&(a=b.hash(a));for(d=0;d<e;d++)c[0][d]=a[d]^909522486,c[1][d]=a[d]^1549556828;this.w[0].update(c[0]);this.w[1].update(c[1]);this.R=new b(this.w[0])};
|
||||
sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a){if(this.aa)throw new sjcl.exception.invalid("encrypt on already updated hmac called!");this.update(a);return this.digest(a)};sjcl.misc.hmac.prototype.reset=function(){this.R=new this.W(this.w[0]);this.aa=!1};sjcl.misc.hmac.prototype.update=function(a){this.aa=!0;this.R.update(a)};sjcl.misc.hmac.prototype.digest=function(){var a=this.R.finalize(),a=(new this.W(this.w[1])).update(a).finalize();this.reset();return a};
|
||||
sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E4;if(0>d||0>c)throw new sjcl.exception.invalid("invalid params to pbkdf2");"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,k,l=[],n=sjcl.bitArray;for(k=1;32*l.length<(d||1);k++){e=f=a.encrypt(n.concat(b,[k]));for(g=1;g<c;g++)for(f=a.encrypt(f),h=0;h<f.length;h++)e[h]^=f[h];l=l.concat(e)}d&&(l=n.clamp(l,d));return l};
|
||||
sjcl.prng=function(a){this.c=[new sjcl.hash.sha256];this.m=[0];this.P=0;this.H={};this.N=0;this.U={};this.Z=this.f=this.o=this.ha=0;this.b=[0,0,0,0,0,0,0,0];this.h=[0,0,0,0];this.L=void 0;this.M=a;this.D=!1;this.K={progress:{},seeded:{}};this.u=this.ga=0;this.I=1;this.J=2;this.ca=0x10000;this.T=[0,48,64,96,128,192,0x100,384,512,768,1024];this.da=3E4;this.ba=80};
|
||||
sjcl.prng.prototype={randomWords:function(a,b){var c=[],d;d=this.isReady(b);var e;if(d===this.u)throw new sjcl.exception.notReady("generator isn't seeded");if(d&this.J){d=!(d&this.I);e=[];var f=0,g;this.Z=e[0]=(new Date).valueOf()+this.da;for(g=0;16>g;g++)e.push(0x100000000*Math.random()|0);for(g=0;g<this.c.length&&(e=e.concat(this.c[g].finalize()),f+=this.m[g],this.m[g]=0,d||!(this.P&1<<g));g++);this.P>=1<<this.c.length&&(this.c.push(new sjcl.hash.sha256),this.m.push(0));this.f-=f;f>this.o&&(this.o=
|
||||
f);this.P++;this.b=sjcl.hash.sha256.hash(this.b.concat(e));this.L=new sjcl.cipher.aes(this.b);for(d=0;4>d&&(this.h[d]=this.h[d]+1|0,!this.h[d]);d++);}for(d=0;d<a;d+=4)0===(d+1)%this.ca&&y(this),e=z(this),c.push(e[0],e[1],e[2],e[3]);y(this);return c.slice(0,a)},setDefaultParanoia:function(a,b){if(0===a&&"Setting paranoia=0 will ruin your security; use it only for testing"!==b)throw new sjcl.exception.invalid("Setting paranoia=0 will ruin your security; use it only for testing");this.M=a},addEntropy:function(a,
|
||||
b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.H[c],h=this.isReady(),k=0;d=this.U[c];void 0===d&&(d=this.U[c]=this.ha++);void 0===g&&(g=this.H[c]=0);this.H[c]=(this.H[c]+1)%this.c.length;switch(typeof a){case "number":void 0===b&&(b=1);this.c[g].update([d,this.N++,1,b,f,1,a|0]);break;case "object":c=Object.prototype.toString.call(a);if("[object Uint32Array]"===c){e=[];for(c=0;c<a.length;c++)e.push(a[c]);a=e}else for("[object Array]"!==c&&(k=1),c=0;c<a.length&&!k;c++)"number"!==typeof a[c]&&
|
||||
(k=1);if(!k){if(void 0===b)for(c=b=0;c<a.length;c++)for(e=a[c];0<e;)b++,e=e>>>1;this.c[g].update([d,this.N++,2,b,f,a.length].concat(a))}break;case "string":void 0===b&&(b=a.length);this.c[g].update([d,this.N++,3,b,f,a.length]);this.c[g].update(a);break;default:k=1}if(k)throw new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string");this.m[g]+=b;this.f+=b;h===this.u&&(this.isReady()!==this.u&&A("seeded",Math.max(this.o,this.f)),A("progress",this.getProgress()))},
|
||||
isReady:function(a){a=this.T[void 0!==a?a:this.M];return this.o&&this.o>=a?this.m[0]>this.ba&&(new Date).valueOf()>this.Z?this.J|this.I:this.I:this.f>=a?this.J|this.u:this.u},getProgress:function(a){a=this.T[a?a:this.M];return this.o>=a?1:this.f>a?1:this.f/a},startCollectors:function(){if(!this.D){this.a={loadTimeCollector:B(this,this.ma),mouseCollector:B(this,this.oa),keyboardCollector:B(this,this.la),accelerometerCollector:B(this,this.ea),touchCollector:B(this,this.qa)};if(window.addEventListener)window.addEventListener("load",
|
||||
this.a.loadTimeCollector,!1),window.addEventListener("mousemove",this.a.mouseCollector,!1),window.addEventListener("keypress",this.a.keyboardCollector,!1),window.addEventListener("devicemotion",this.a.accelerometerCollector,!1),window.addEventListener("touchmove",this.a.touchCollector,!1);else if(document.attachEvent)document.attachEvent("onload",this.a.loadTimeCollector),document.attachEvent("onmousemove",this.a.mouseCollector),document.attachEvent("keypress",this.a.keyboardCollector);else throw new sjcl.exception.bug("can't attach event");
|
||||
this.D=!0}},stopCollectors:function(){this.D&&(window.removeEventListener?(window.removeEventListener("load",this.a.loadTimeCollector,!1),window.removeEventListener("mousemove",this.a.mouseCollector,!1),window.removeEventListener("keypress",this.a.keyboardCollector,!1),window.removeEventListener("devicemotion",this.a.accelerometerCollector,!1),window.removeEventListener("touchmove",this.a.touchCollector,!1)):document.detachEvent&&(document.detachEvent("onload",this.a.loadTimeCollector),document.detachEvent("onmousemove",
|
||||
this.a.mouseCollector),document.detachEvent("keypress",this.a.keyboardCollector)),this.D=!1)},addEventListener:function(a,b){this.K[a][this.ga++]=b},removeEventListener:function(a,b){var c,d,e=this.K[a],f=[];for(d in e)e.hasOwnProperty(d)&&e[d]===b&&f.push(d);for(c=0;c<f.length;c++)d=f[c],delete e[d]},la:function(){C(this,1)},oa:function(a){var b,c;try{b=a.x||a.clientX||a.offsetX||0,c=a.y||a.clientY||a.offsetY||0}catch(d){c=b=0}0!=b&&0!=c&&this.addEntropy([b,c],2,"mouse");C(this,0)},qa:function(a){a=
|
||||
a.touches[0]||a.changedTouches[0];this.addEntropy([a.pageX||a.clientX,a.pageY||a.clientY],1,"touch");C(this,0)},ma:function(){C(this,2)},ea:function(a){a=a.accelerationIncludingGravity.x||a.accelerationIncludingGravity.y||a.accelerationIncludingGravity.z;if(window.orientation){var b=window.orientation;"number"===typeof b&&this.addEntropy(b,1,"accelerometer")}a&&this.addEntropy(a,2,"accelerometer");C(this,0)}};
|
||||
function A(a,b){var c,d=sjcl.random.K[a],e=[];for(c in d)d.hasOwnProperty(c)&&e.push(d[c]);for(c=0;c<e.length;c++)e[c](b)}function C(a,b){"undefined"!==typeof window&&window.performance&&"function"===typeof window.performance.now?a.addEntropy(window.performance.now(),b,"loadtime"):a.addEntropy((new Date).valueOf(),b,"loadtime")}function y(a){a.b=z(a).concat(z(a));a.L=new sjcl.cipher.aes(a.b)}function z(a){for(var b=0;4>b&&(a.h[b]=a.h[b]+1|0,!a.h[b]);b++);return a.L.encrypt(a.h)}
|
||||
function B(a,b){return function(){b.apply(a,arguments)}}sjcl.random=new sjcl.prng(6);
|
||||
a:try{var D,E,F,G;if(G="undefined"!==typeof module&&module.exports){var H;try{H=require("crypto")}catch(a){H=null}G=E=H}if(G&&E.randomBytes)D=E.randomBytes(128),D=new Uint32Array((new Uint8Array(D)).buffer),sjcl.random.addEntropy(D,1024,"crypto['randomBytes']");else if("undefined"!==typeof window&&"undefined"!==typeof Uint32Array){F=new Uint32Array(32);if(window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(F);else if(window.msCrypto&&window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(F);
|
||||
else break a;sjcl.random.addEntropy(F,1024,"crypto['getRandomValues']")}}catch(a){"undefined"!==typeof window&&window.console&&(console.log("There was an error collecting entropy from the browser:"),console.log(a))}
|
||||
sjcl.json={defaults:{v:1,iter:1E4,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},ja:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.g({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.g(f,c);c=f.adata;"string"===typeof f.salt&&(f.salt=sjcl.codec.base64.toBits(f.salt));"string"===typeof f.iv&&(f.iv=sjcl.codec.base64.toBits(f.iv));if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||"string"===typeof a&&100>=f.iter||64!==f.ts&&96!==f.ts&&128!==f.ts||128!==f.ks&&192!==f.ks&&0x100!==f.ks||2>f.iv.length||
|
||||
4<f.iv.length)throw new sjcl.exception.invalid("json encrypt: invalid parameters");"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,f),a=g.key.slice(0,f.ks/32),f.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.publicKey&&(g=a.kem(),f.kemtag=g.tag,a=g.key.slice(0,f.ks/32));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));"string"===typeof c&&(f.adata=c=sjcl.codec.utf8String.toBits(c));g=new sjcl.cipher[f.cipher](a);e.g(d,f);d.key=a;f.ct="ccm"===f.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&
|
||||
b instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.encrypt(g,b,f.iv,c,f.ts):sjcl.mode[f.mode].encrypt(g,b,f.iv,c,f.ts);return f},encrypt:function(a,b,c,d){var e=sjcl.json,f=e.ja.apply(e,arguments);return e.encode(f)},ia:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.g(e.g(e.g({},e.defaults),b),c,!0);var f,g;f=b.adata;"string"===typeof b.salt&&(b.salt=sjcl.codec.base64.toBits(b.salt));"string"===typeof b.iv&&(b.iv=sjcl.codec.base64.toBits(b.iv));if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||"string"===
|
||||
typeof a&&100>=b.iter||64!==b.ts&&96!==b.ts&&128!==b.ts||128!==b.ks&&192!==b.ks&&0x100!==b.ks||!b.iv||2>b.iv.length||4<b.iv.length)throw new sjcl.exception.invalid("json decrypt: invalid parameters");"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,b),a=g.key.slice(0,b.ks/32),b.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.secretKey&&(a=a.unkem(sjcl.codec.base64.toBits(b.kemtag)).slice(0,b.ks/32));"string"===typeof f&&(f=sjcl.codec.utf8String.toBits(f));g=new sjcl.cipher[b.cipher](a);f="ccm"===
|
||||
b.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&b.ct instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.decrypt(g,b.ct,b.iv,b.tag,f,b.ts):sjcl.mode[b.mode].decrypt(g,b.ct,b.iv,f,b.ts);e.g(d,b);d.key=a;return 1===c.raw?f:sjcl.codec.utf8String.fromBits(f)},decrypt:function(a,b,c,d){var e=sjcl.json;return e.ia(a,e.decode(b),c,d)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+'"'+
|
||||
b+'":';d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],0)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type");}}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c<a.length;c++){if(!(d=a[c].match(/^\s*(?:(["']?)([a-z][a-z0-9]*)\1)\s*:\s*(?:(-?\d+)|"([a-z0-9+\/%*_.@=\-]*)"|(true|false))$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");
|
||||
null!=d[3]?b[d[2]]=parseInt(d[3],10):null!=d[4]?b[d[2]]=d[2].match(/^(ct|adata|salt|iv)$/)?sjcl.codec.base64.toBits(d[4]):unescape(d[4]):null!=d[5]&&(b[d[2]]="true"===d[5])}return b},g:function(a,b,c){void 0===a&&(a={});if(void 0===b)return a;for(var d in b)if(b.hasOwnProperty(d)){if(c&&void 0!==a[d]&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},sa:function(a,b){var c={},d;for(d in a)a.hasOwnProperty(d)&&a[d]!==b[d]&&(c[d]=a[d]);return c},ra:function(a,
|
||||
b){var c={},d;for(d=0;d<b.length;d++)void 0!==a[b[d]]&&(c[b[d]]=a[b[d]]);return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.pa={};sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.pa,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=void 0===b.salt?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};
|
||||
"undefined"!==typeof module&&module.exports&&(module.exports=sjcl);"function"===typeof define&&define([],function(){return sjcl});
|
124
js/types.jsonld
Normal file
124
js/types.jsonld
Normal file
@ -0,0 +1,124 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"dp": "http://dbpedia.org/resource/",
|
||||
"pb": "?jsonld=types#"
|
||||
},
|
||||
"Base64": {
|
||||
"@type": "so:Text"
|
||||
},
|
||||
"CipherText": {
|
||||
"@type": "pb:Base64"
|
||||
},
|
||||
"PasteCipherMessage": {
|
||||
"paste": {
|
||||
"@type": "so:Text"
|
||||
},
|
||||
"attachment": {
|
||||
"@type": "so:MediaObject"
|
||||
},
|
||||
"attachment_name": {
|
||||
"@type": "so:Text"
|
||||
}
|
||||
},
|
||||
"CommentCipherMessage": {
|
||||
"comment": {
|
||||
"@type": "so:Text"
|
||||
},
|
||||
"nickname": {
|
||||
"@type": "so:Text"
|
||||
}
|
||||
},
|
||||
"InitializationVector": {
|
||||
"@type": "pb:Base64"
|
||||
},
|
||||
"Salt": {
|
||||
"@type": "pb:Base64"
|
||||
},
|
||||
"Iterations": {
|
||||
"@type": "so:Integer",
|
||||
"@minimum": 1
|
||||
},
|
||||
"KeySize": {
|
||||
"@type": "so:Integer",
|
||||
"@value": 256,
|
||||
"@minimum": 128,
|
||||
"@maximum": 256,
|
||||
"@enum": [128, 196, 256]
|
||||
},
|
||||
"TagSize": {
|
||||
"@type": "so:Integer",
|
||||
"@value": 128,
|
||||
"@minimum": 32,
|
||||
"@maximum": 128,
|
||||
"@enum": [32, 64, 96, 104, 112, 120, 128]
|
||||
},
|
||||
"Algorithm": {
|
||||
"@type": "so:Text",
|
||||
"@value": "aes"
|
||||
},
|
||||
"Mode": {
|
||||
"@type": "so:Text",
|
||||
"@value": "gcm",
|
||||
"@enum": ["ctr", "cbc", "gcm"]
|
||||
},
|
||||
"Compression": {
|
||||
"@type": "so:Text",
|
||||
"@value": "zlib",
|
||||
"@enum": ["zlib", "none"]
|
||||
},
|
||||
"Formatter": {
|
||||
"@type": "so:Text",
|
||||
"@value": "plaintext",
|
||||
"@enum": ["plaintext", "syntaxhighlighting", "markdown"]
|
||||
},
|
||||
"Expiration": {
|
||||
"@type": "so:Text",
|
||||
"@value": "1week",
|
||||
"@enum": ["5min", "10min", "1hour", "1day", "1week", "1month", "1year", "never"]
|
||||
},
|
||||
"OpenDiscussion": {
|
||||
"@type": "so:Boolean",
|
||||
"@enum": [false, true]
|
||||
},
|
||||
"BurnAfterReading": {
|
||||
"@type": "so:Boolean",
|
||||
"@enum": [false, true]
|
||||
},
|
||||
"CreationTime": {
|
||||
"@type": "dp:Unix_time"
|
||||
},
|
||||
"RemainingSeconds": {
|
||||
"@type": "dp:Second",
|
||||
"@minimum": 1
|
||||
},
|
||||
"CipherParameters": {
|
||||
"@container": "@list",
|
||||
"@value": [
|
||||
{
|
||||
"@type": "pb:InitializationVector"
|
||||
},
|
||||
{
|
||||
"@type": "pb:Salt"
|
||||
},
|
||||
{
|
||||
"@type": "pb:Iterations"
|
||||
},
|
||||
{
|
||||
"@type": "pb:KeySize"
|
||||
},
|
||||
{
|
||||
"@type": "pb:TagSize"
|
||||
},
|
||||
{
|
||||
"@type": "pb:Algorithm"
|
||||
},
|
||||
{
|
||||
"@type": "pb:Mode"
|
||||
},
|
||||
{
|
||||
"@type": "pb:Compression"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
146
js/zlib-1.2.11.js
Normal file
146
js/zlib-1.2.11.js
Normal file
@ -0,0 +1,146 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
let ret;
|
||||
|
||||
async function initialize() {
|
||||
if (ret) return ret;
|
||||
|
||||
const COMPRESSION_LEVEL = 7;
|
||||
const NO_ZLIB_HEADER = -1;
|
||||
const CHUNK_SIZE = 32 * 1024;
|
||||
const map = {};
|
||||
const memory = new WebAssembly.Memory({
|
||||
initial: 1,
|
||||
maximum: 1024, // 64MB
|
||||
});
|
||||
const env = {
|
||||
memory,
|
||||
writeToJs(ptr, size) {
|
||||
const o = map[ptr];
|
||||
o.onData(new Uint8Array(memory.buffer, dstPtr, size));
|
||||
},
|
||||
_abort: errno => { console.error(`Error: ${errno}`) },
|
||||
_grow: () => { },
|
||||
};
|
||||
|
||||
let buff;
|
||||
if (typeof fetch === 'undefined') {
|
||||
buff = fs.readFileSync('zlib-1.2.11.wasm');
|
||||
} else {
|
||||
const resp = await fetch('js/zlib-1.2.11.wasm');
|
||||
buff = await resp.arrayBuffer();
|
||||
}
|
||||
const module = await WebAssembly.compile(buff);
|
||||
const ins = await WebAssembly.instantiate(module, { env });
|
||||
|
||||
const srcPtr = ins.exports._malloc(CHUNK_SIZE);
|
||||
const dstPtr = ins.exports._malloc(CHUNK_SIZE);
|
||||
|
||||
class RawDef {
|
||||
constructor() {
|
||||
this.zstreamPtr = ins.exports._createDeflateContext(COMPRESSION_LEVEL, NO_ZLIB_HEADER);
|
||||
map[this.zstreamPtr] = this;
|
||||
this.offset = 0;
|
||||
this.buff = new Uint8Array(CHUNK_SIZE);
|
||||
}
|
||||
|
||||
deflate(chunk, flush) {
|
||||
const src = new Uint8Array(memory.buffer, srcPtr, chunk.length);
|
||||
src.set(chunk);
|
||||
ins.exports._deflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE, flush);
|
||||
}
|
||||
|
||||
onData(chunk) {
|
||||
if (this.buff.length < this.offset + chunk.length) {
|
||||
const buff = this.buff;
|
||||
this.buff = new Uint8Array(this.buff.length * 2);
|
||||
this.buff.set(buff);
|
||||
}
|
||||
this.buff.set(chunk, this.offset);
|
||||
this.offset += chunk.length;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
ins.exports._freeDeflateContext(this.zstreamPtr);
|
||||
delete map[this.zstreamPtr];
|
||||
this.buff = null;
|
||||
}
|
||||
|
||||
getBuffer() {
|
||||
const res = new Uint8Array(this.offset);
|
||||
for (let i = 0; i < this.offset; ++i) {
|
||||
res[i] = this.buff[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
class RawInf {
|
||||
constructor() {
|
||||
this.zstreamPtr = ins.exports._createInflateContext(NO_ZLIB_HEADER);
|
||||
map[this.zstreamPtr] = this;
|
||||
this.offset = 0;
|
||||
this.buff = new Uint8Array(CHUNK_SIZE);
|
||||
}
|
||||
|
||||
inflate(chunk) {
|
||||
const src = new Uint8Array(memory.buffer, srcPtr, chunk.length);
|
||||
src.set(chunk);
|
||||
ins.exports._inflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE);
|
||||
}
|
||||
|
||||
onData(chunk) {
|
||||
if (this.buff.length < this.offset + chunk.length) {
|
||||
const buff = this.buff;
|
||||
this.buff = new Uint8Array(this.buff.length * 2);
|
||||
this.buff.set(buff);
|
||||
}
|
||||
this.buff.set(chunk, this.offset);
|
||||
this.offset += chunk.length;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
ins.exports._freeInflateContext(this.zstreamPtr);
|
||||
delete map[this.zstreamPtr];
|
||||
this.buff = null;
|
||||
}
|
||||
|
||||
getBuffer() {
|
||||
const res = new Uint8Array(this.offset);
|
||||
for (let i = 0; i < this.offset; ++i) {
|
||||
res[i] = this.buff[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
ret = {
|
||||
inflate(rawDeflateBuffer) {
|
||||
const rawInf = new RawInf();
|
||||
for (let offset = 0; offset < rawDeflateBuffer.length; offset += CHUNK_SIZE) {
|
||||
const end = Math.min(offset + CHUNK_SIZE, rawDeflateBuffer.length);
|
||||
const chunk = rawDeflateBuffer.subarray(offset, end);
|
||||
rawInf.inflate(chunk);
|
||||
}
|
||||
const ret = rawInf.getBuffer();
|
||||
rawInf.destroy();
|
||||
return ret;
|
||||
},
|
||||
deflate(rawInflateBuffer) {
|
||||
const rawDef = new RawDef();
|
||||
for (let offset = 0; offset < rawInflateBuffer.length; offset += CHUNK_SIZE) {
|
||||
const end = Math.min(offset + CHUNK_SIZE, rawInflateBuffer.length);
|
||||
const chunk = rawInflateBuffer.subarray(offset, end);
|
||||
rawDef.deflate(chunk, rawInflateBuffer.length <= offset + CHUNK_SIZE);
|
||||
}
|
||||
const ret = rawDef.getBuffer();
|
||||
rawDef.destroy();
|
||||
return ret;
|
||||
},
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
this.zlib = initialize();
|
||||
}).call(this);
|
BIN
js/zlib-1.2.11.wasm
Normal file
BIN
js/zlib-1.2.11.wasm
Normal file
Binary file not shown.
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@ -45,7 +45,7 @@ class Configuration
|
||||
'burnafterreadingselected' => false,
|
||||
'defaultformatter' => 'plaintext',
|
||||
'syntaxhighlightingtheme' => null,
|
||||
'sizelimit' => 2097152,
|
||||
'sizelimit' => 10485760,
|
||||
'template' => 'bootstrap',
|
||||
'notice' => '',
|
||||
'languageselection' => false,
|
||||
@ -53,8 +53,10 @@ class Configuration
|
||||
'urlshortener' => '',
|
||||
'qrcode' => true,
|
||||
'icon' => 'identicon',
|
||||
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; media-src data:; object-src data:; Referrer-Policy: \'no-referrer\'; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals',
|
||||
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\'; 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',
|
||||
'zerobincompatibility' => false,
|
||||
'httpwarning' => true,
|
||||
'compression' => 'zlib',
|
||||
),
|
||||
'expire' => array(
|
||||
'default' => '1week',
|
||||
@ -100,8 +102,9 @@ class Configuration
|
||||
public function __construct()
|
||||
{
|
||||
$config = array();
|
||||
$configFile = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php';
|
||||
$configIni = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini';
|
||||
$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)) {
|
||||
@ -110,7 +113,7 @@ class Configuration
|
||||
// cleanup sample, too
|
||||
$configIniSample = $configIni . '.sample';
|
||||
if (is_readable($configIniSample)) {
|
||||
DataStore::prependRename($configIniSample, PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.sample.php', ';');
|
||||
DataStore::prependRename($configIniSample, $basePath . 'conf.sample.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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@ -28,14 +28,14 @@ class Controller
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const VERSION = '1.2.1';
|
||||
const VERSION = '1.3.2';
|
||||
|
||||
/**
|
||||
* minimal required PHP version
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const MIN_PHP_VERSION = '5.4.0';
|
||||
const MIN_PHP_VERSION = '5.5.0';
|
||||
|
||||
/**
|
||||
* show the same error message if the paste expired or does not exist
|
||||
@ -154,6 +154,7 @@ class Controller
|
||||
* initialize PrivateBin
|
||||
*
|
||||
* @access private
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _init()
|
||||
{
|
||||
@ -177,16 +178,16 @@ class Controller
|
||||
* Store new paste or comment
|
||||
*
|
||||
* POST contains one or both:
|
||||
* data = json encoded SJCL encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* attachment = json encoded SJCL encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* data = json encoded FormatV2 encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* attachment = json encoded FormatV2 encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
*
|
||||
* All optional data will go to meta information:
|
||||
* expire (optional) = expiration delay (never,5min,10min,1hour,1day,1week,1month,1year,burn) (default:never)
|
||||
* formatter (optional) = format to display the paste as (plaintext,syntaxhighlighting,markdown) (default:syntaxhighlighting)
|
||||
* burnafterreading (optional) = if this paste may only viewed once ? (0/1) (default:0)
|
||||
* opendiscusssion (optional) = is the discussion allowed on this paste ? (0/1) (default:0)
|
||||
* attachmentname = json encoded SJCL encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* nickname (optional) = in discussion, encoded SJCL encrypted text nickname of author of comment (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* attachmentname = json encoded FormatV2 encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* nickname (optional) = in discussion, encoded FormatV2 encrypted text nickname of author of comment (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* parentid (optional) = in discussion, which comment this comment replies to.
|
||||
* pasteid (optional) = in discussion, which paste this comment belongs to.
|
||||
*
|
||||
@ -198,59 +199,52 @@ class Controller
|
||||
// Ensure last paste from visitors IP address was more than configured amount of seconds ago.
|
||||
TrafficLimiter::setConfiguration($this->_conf);
|
||||
if (!TrafficLimiter::canPass()) {
|
||||
return $this->_return_message(
|
||||
1, I18n::_(
|
||||
'Please wait %d seconds between each post.',
|
||||
$this->_conf->getKey('limit', 'traffic')
|
||||
)
|
||||
);
|
||||
$this->_return_message(
|
||||
1, I18n::_(
|
||||
'Please wait %d seconds between each post.',
|
||||
$this->_conf->getKey('limit', 'traffic')
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this->_request->getParam('data');
|
||||
$attachment = $this->_request->getParam('attachment');
|
||||
$attachmentname = $this->_request->getParam('attachmentname');
|
||||
|
||||
// Ensure content is not too big.
|
||||
$data = $this->_request->getData();
|
||||
$isComment = array_key_exists('pasteid', $data) &&
|
||||
!empty($data['pasteid']) &&
|
||||
array_key_exists('parentid', $data) &&
|
||||
!empty($data['parentid']);
|
||||
if (!FormatV2::isValid($data, $isComment)) {
|
||||
$this->_return_message(1, I18n::_('Invalid data.'));
|
||||
return;
|
||||
}
|
||||
$sizelimit = $this->_conf->getKey('sizelimit');
|
||||
if (
|
||||
strlen($data) + strlen($attachment) + strlen($attachmentname) > $sizelimit
|
||||
) {
|
||||
return $this->_return_message(
|
||||
1,
|
||||
I18n::_(
|
||||
'Paste is limited to %s of encrypted data.',
|
||||
Filter::formatHumanReadableSize($sizelimit)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure attachment did not get lost due to webserver limits or Suhosin
|
||||
if (strlen($attachmentname) > 0 && strlen($attachment) == 0) {
|
||||
return $this->_return_message(1, 'Attachment missing in data received by server. Please check your webserver or suhosin configuration for maximum POST parameter limitations.');
|
||||
// Ensure content is not too big.
|
||||
if (strlen($data['ct']) > $sizelimit) {
|
||||
$this->_return_message(
|
||||
1,
|
||||
I18n::_(
|
||||
'Paste is limited to %s of encrypted data.',
|
||||
Filter::formatHumanReadableSize($sizelimit)
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// The user posts a comment.
|
||||
$pasteid = $this->_request->getParam('pasteid');
|
||||
$parentid = $this->_request->getParam('parentid');
|
||||
if (!empty($pasteid) && !empty($parentid)) {
|
||||
$paste = $this->_model->getPaste($pasteid);
|
||||
if ($isComment) {
|
||||
$paste = $this->_model->getPaste($data['pasteid']);
|
||||
if ($paste->exists()) {
|
||||
try {
|
||||
$comment = $paste->getComment($parentid);
|
||||
|
||||
$nickname = $this->_request->getParam('nickname');
|
||||
if (!empty($nickname)) {
|
||||
$comment->setNickname($nickname);
|
||||
}
|
||||
|
||||
$comment = $paste->getComment($data['parentid']);
|
||||
$comment->setData($data);
|
||||
$comment->store();
|
||||
} catch (Exception $e) {
|
||||
return $this->_return_message(1, $e->getMessage());
|
||||
$this->_return_message(1, $e->getMessage());
|
||||
return;
|
||||
}
|
||||
$this->_return_message(0, $comment->getId());
|
||||
} else {
|
||||
$this->_return_message(1, 'Invalid data.');
|
||||
$this->_return_message(1, I18n::_('Invalid data.'));
|
||||
}
|
||||
}
|
||||
// The user posts a standard paste.
|
||||
@ -259,34 +253,6 @@ class Controller
|
||||
$paste = $this->_model->getPaste();
|
||||
try {
|
||||
$paste->setData($data);
|
||||
|
||||
if (!empty($attachment)) {
|
||||
$paste->setAttachment($attachment);
|
||||
if (!empty($attachmentname)) {
|
||||
$paste->setAttachmentName($attachmentname);
|
||||
}
|
||||
}
|
||||
|
||||
$expire = $this->_request->getParam('expire');
|
||||
if (!empty($expire)) {
|
||||
$paste->setExpiration($expire);
|
||||
}
|
||||
|
||||
$burnafterreading = $this->_request->getParam('burnafterreading');
|
||||
if (!empty($burnafterreading)) {
|
||||
$paste->setBurnafterreading($burnafterreading);
|
||||
}
|
||||
|
||||
$opendiscussion = $this->_request->getParam('opendiscussion');
|
||||
if (!empty($opendiscussion)) {
|
||||
$paste->setOpendiscussion($opendiscussion);
|
||||
}
|
||||
|
||||
$formatter = $this->_request->getParam('formatter');
|
||||
if (!empty($formatter)) {
|
||||
$paste->setFormatter($formatter);
|
||||
}
|
||||
|
||||
$paste->store();
|
||||
} catch (Exception $e) {
|
||||
return $this->_return_message(1, $e->getMessage());
|
||||
@ -307,22 +273,17 @@ class Controller
|
||||
try {
|
||||
$paste = $this->_model->getPaste($dataid);
|
||||
if ($paste->exists()) {
|
||||
// accessing this property ensures that the paste would be
|
||||
// accessing this method ensures that the paste would be
|
||||
// deleted if it has already expired
|
||||
$burnafterreading = $paste->isBurnafterreading();
|
||||
$paste->get();
|
||||
if (
|
||||
($burnafterreading && $deletetoken == 'burnafterreading') || // either we burn-after it has been read //@TODO: not needed anymore now?
|
||||
Filter::slowEquals($deletetoken, $paste->getDeleteToken()) // or we manually delete it with this secret token
|
||||
Filter::slowEquals($deletetoken, $paste->getDeleteToken())
|
||||
) {
|
||||
// Paste exists and deletion token (if required) is valid: Delete the paste.
|
||||
// Paste exists and deletion token is valid: Delete the paste.
|
||||
$paste->delete();
|
||||
$this->_status = 'Paste was properly deleted.';
|
||||
} else {
|
||||
if (!$burnafterreading && $deletetoken == 'burnafterreading') {
|
||||
$this->_error = 'Paste is not of burn-after-reading type.';
|
||||
} else {
|
||||
$this->_error = 'Wrong deletion token. Paste was not deleted.';
|
||||
}
|
||||
$this->_error = 'Wrong deletion token. Paste was not deleted.';
|
||||
}
|
||||
} else {
|
||||
$this->_error = self::GENERIC_ERROR;
|
||||
@ -355,8 +316,8 @@ class Controller
|
||||
$paste = $this->_model->getPaste($dataid);
|
||||
if ($paste->exists()) {
|
||||
$data = $paste->get();
|
||||
if (property_exists($data->meta, 'salt')) {
|
||||
unset($data->meta->salt);
|
||||
if (array_key_exists('salt', $data['meta'])) {
|
||||
unset($data['meta']['salt']);
|
||||
}
|
||||
$this->_return_message(0, $dataid, (array) $data);
|
||||
} else {
|
||||
@ -382,6 +343,7 @@ class Controller
|
||||
header('Last-Modified: ' . $time);
|
||||
header('Vary: Accept');
|
||||
header('Content-Security-Policy: ' . $this->_conf->getKey('cspheader'));
|
||||
header('Referrer-Policy: no-referrer');
|
||||
header('X-Xss-Protection: 1; mode=block');
|
||||
header('X-Frame-Options: DENY');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
@ -425,6 +387,9 @@ class Controller
|
||||
$page->assign('EXPIREDEFAULT', $this->_conf->getKey('default', 'expire'));
|
||||
$page->assign('URLSHORTENER', $this->_conf->getKey('urlshortener'));
|
||||
$page->assign('QRCODE', $this->_conf->getKey('qrcode'));
|
||||
$page->assign('HTTPWARNING', $this->_conf->getKey('httpwarning'));
|
||||
$page->assign('HTTPSLINK', 'https://' . $this->_request->getHost() . $this->_request->getRequestUri());
|
||||
$page->assign('COMPRESSION', $this->_conf->getKey('compression'));
|
||||
$page->draw($this->_conf->getKey('template'));
|
||||
}
|
||||
|
||||
@ -476,6 +441,6 @@ class Controller
|
||||
$result['url'] = $this->_urlBase . '?' . $message;
|
||||
}
|
||||
$result += $other;
|
||||
$this->_json = json_encode($result);
|
||||
$this->_json = Json::encode($result);
|
||||
}
|
||||
}
|
||||
|
@ -7,13 +7,11 @@
|
||||
* @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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* AbstractData
|
||||
*
|
||||
@ -60,7 +58,7 @@ abstract class AbstractData
|
||||
* @param array $options
|
||||
* @return AbstractData
|
||||
*/
|
||||
public static function getInstance($options)
|
||||
public static function getInstance(array $options)
|
||||
{
|
||||
}
|
||||
|
||||
@ -72,14 +70,14 @@ abstract class AbstractData
|
||||
* @param array $paste
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function create($pasteid, $paste);
|
||||
abstract public function create($pasteid, array $paste);
|
||||
|
||||
/**
|
||||
* Read a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return stdClass|false
|
||||
* @return array|false
|
||||
*/
|
||||
abstract public function read($pasteid);
|
||||
|
||||
@ -110,7 +108,7 @@ abstract class AbstractData
|
||||
* @param array $comment
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function createComment($pasteid, $parentid, $commentid, $comment);
|
||||
abstract public function createComment($pasteid, $parentid, $commentid, array $comment);
|
||||
|
||||
/**
|
||||
* Read all comments of paste.
|
||||
@ -163,12 +161,12 @@ abstract class AbstractData
|
||||
/**
|
||||
* Get next free slot for comment from postdate.
|
||||
*
|
||||
* @access public
|
||||
* @access protected
|
||||
* @param array $comments
|
||||
* @param int|string $postdate
|
||||
* @return int|string
|
||||
*/
|
||||
protected function getOpenSlot(&$comments, $postdate)
|
||||
protected function getOpenSlot(array &$comments, $postdate)
|
||||
{
|
||||
if (array_key_exists($postdate, $comments)) {
|
||||
$parts = explode('.', $postdate, 2);
|
||||
@ -180,4 +178,25 @@ abstract class AbstractData
|
||||
}
|
||||
return $postdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade pre-version 1 pastes with attachment to version 1 format.
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @param array $paste
|
||||
* @return array
|
||||
*/
|
||||
protected static function upgradePreV1Format(array $paste)
|
||||
{
|
||||
if (array_key_exists('attachment', $paste['meta'])) {
|
||||
$paste['attachment'] = $paste['meta']['attachment'];
|
||||
unset($paste['meta']['attachment']);
|
||||
if (array_key_exists('attachmentname', $paste['meta'])) {
|
||||
$paste['attachmentname'] = $paste['meta']['attachmentname'];
|
||||
unset($paste['meta']['attachmentname']);
|
||||
}
|
||||
}
|
||||
return $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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
@ -16,7 +16,7 @@ use Exception;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use PrivateBin\Controller;
|
||||
use stdClass;
|
||||
use PrivateBin\Json;
|
||||
|
||||
/**
|
||||
* Database
|
||||
@ -68,80 +68,78 @@ class Database extends AbstractData
|
||||
* @throws Exception
|
||||
* @return Database
|
||||
*/
|
||||
public static function getInstance($options = null)
|
||||
public static function getInstance(array $options)
|
||||
{
|
||||
// if needed initialize the singleton
|
||||
if (!(self::$_instance instanceof self)) {
|
||||
self::$_instance = new self;
|
||||
}
|
||||
|
||||
if (is_array($options)) {
|
||||
// set table prefix if given
|
||||
if (array_key_exists('tbl', $options)) {
|
||||
self::$_prefix = $options['tbl'];
|
||||
// set table prefix if given
|
||||
if (array_key_exists('tbl', $options)) {
|
||||
self::$_prefix = $options['tbl'];
|
||||
}
|
||||
|
||||
// initialize the db connection with new options
|
||||
if (
|
||||
array_key_exists('dsn', $options) &&
|
||||
array_key_exists('usr', $options) &&
|
||||
array_key_exists('pwd', $options) &&
|
||||
array_key_exists('opt', $options)
|
||||
) {
|
||||
// set default options
|
||||
$options['opt'][PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
|
||||
$options['opt'][PDO::ATTR_EMULATE_PREPARES] = false;
|
||||
$options['opt'][PDO::ATTR_PERSISTENT] = true;
|
||||
$db_tables_exist = true;
|
||||
|
||||
// setup type and dabase connection
|
||||
self::$_type = strtolower(
|
||||
substr($options['dsn'], 0, strpos($options['dsn'], ':'))
|
||||
);
|
||||
$tableQuery = self::_getTableQuery(self::$_type);
|
||||
self::$_db = new PDO(
|
||||
$options['dsn'],
|
||||
$options['usr'],
|
||||
$options['pwd'],
|
||||
$options['opt']
|
||||
);
|
||||
|
||||
// check if the database contains the required tables
|
||||
$tables = self::$_db->query($tableQuery)->fetchAll(PDO::FETCH_COLUMN, 0);
|
||||
|
||||
// create paste table if necessary
|
||||
if (!in_array(self::_sanitizeIdentifier('paste'), $tables)) {
|
||||
self::_createPasteTable();
|
||||
$db_tables_exist = false;
|
||||
}
|
||||
|
||||
// initialize the db connection with new options
|
||||
if (
|
||||
array_key_exists('dsn', $options) &&
|
||||
array_key_exists('usr', $options) &&
|
||||
array_key_exists('pwd', $options) &&
|
||||
array_key_exists('opt', $options)
|
||||
) {
|
||||
// set default options
|
||||
$options['opt'][PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
|
||||
$options['opt'][PDO::ATTR_EMULATE_PREPARES] = false;
|
||||
$options['opt'][PDO::ATTR_PERSISTENT] = true;
|
||||
$db_tables_exist = true;
|
||||
// create comment table if necessary
|
||||
if (!in_array(self::_sanitizeIdentifier('comment'), $tables)) {
|
||||
self::_createCommentTable();
|
||||
$db_tables_exist = false;
|
||||
}
|
||||
|
||||
// setup type and dabase connection
|
||||
self::$_type = strtolower(
|
||||
substr($options['dsn'], 0, strpos($options['dsn'], ':'))
|
||||
);
|
||||
$tableQuery = self::_getTableQuery(self::$_type);
|
||||
self::$_db = new PDO(
|
||||
$options['dsn'],
|
||||
$options['usr'],
|
||||
$options['pwd'],
|
||||
$options['opt']
|
||||
);
|
||||
|
||||
// check if the database contains the required tables
|
||||
$tables = self::$_db->query($tableQuery)->fetchAll(PDO::FETCH_COLUMN, 0);
|
||||
|
||||
// create paste table if necessary
|
||||
if (!in_array(self::_sanitizeIdentifier('paste'), $tables)) {
|
||||
self::_createPasteTable();
|
||||
$db_tables_exist = false;
|
||||
}
|
||||
|
||||
// create comment table if necessary
|
||||
if (!in_array(self::_sanitizeIdentifier('comment'), $tables)) {
|
||||
self::_createCommentTable();
|
||||
$db_tables_exist = false;
|
||||
}
|
||||
|
||||
// create config table if necessary
|
||||
$db_version = Controller::VERSION;
|
||||
if (!in_array(self::_sanitizeIdentifier('config'), $tables)) {
|
||||
self::_createConfigTable();
|
||||
// if we only needed to create the config table, the DB is older then 0.22
|
||||
if ($db_tables_exist) {
|
||||
$db_version = '0.21';
|
||||
}
|
||||
} else {
|
||||
$db_version = self::_getConfig('VERSION');
|
||||
}
|
||||
|
||||
// update database structure if necessary
|
||||
if (version_compare($db_version, Controller::VERSION, '<')) {
|
||||
self::_upgradeDatabase($db_version);
|
||||
// create config table if necessary
|
||||
$db_version = Controller::VERSION;
|
||||
if (!in_array(self::_sanitizeIdentifier('config'), $tables)) {
|
||||
self::_createConfigTable();
|
||||
// if we only needed to create the config table, the DB is older then 0.22
|
||||
if ($db_tables_exist) {
|
||||
$db_version = '0.21';
|
||||
}
|
||||
} else {
|
||||
throw new Exception(
|
||||
'Missing configuration for key dsn, usr, pwd or opt in the section model_options, please check your configuration file', 6
|
||||
);
|
||||
$db_version = self::_getConfig('VERSION');
|
||||
}
|
||||
|
||||
// update database structure if necessary
|
||||
if (version_compare($db_version, Controller::VERSION, '<')) {
|
||||
self::_upgradeDatabase($db_version);
|
||||
}
|
||||
} else {
|
||||
throw new Exception(
|
||||
'Missing configuration for key dsn, usr, pwd or opt in the section model_options, please check your configuration file', 6
|
||||
);
|
||||
}
|
||||
|
||||
return self::$_instance;
|
||||
@ -155,7 +153,7 @@ class Database extends AbstractData
|
||||
* @param array $paste
|
||||
* @return bool
|
||||
*/
|
||||
public function create($pasteid, $paste)
|
||||
public function create($pasteid, array $paste)
|
||||
{
|
||||
if (
|
||||
array_key_exists($pasteid, self::$_cache)
|
||||
@ -167,42 +165,50 @@ class Database extends AbstractData
|
||||
}
|
||||
}
|
||||
|
||||
$opendiscussion = $burnafterreading = false;
|
||||
$attachment = $attachmentname = '';
|
||||
$meta = $paste['meta'];
|
||||
unset($meta['postdate']);
|
||||
$expire_date = 0;
|
||||
if (array_key_exists('expire_date', $paste['meta'])) {
|
||||
$expire_date = (int) $paste['meta']['expire_date'];
|
||||
$expire_date = 0;
|
||||
$opendiscussion = $burnafterreading = false;
|
||||
$attachment = $attachmentname = null;
|
||||
$meta = $paste['meta'];
|
||||
$isVersion1 = array_key_exists('data', $paste);
|
||||
list($createdKey) = self::_getVersionedKeys($isVersion1 ? 1 : 2);
|
||||
$created = (int) $meta[$createdKey];
|
||||
unset($meta[$createdKey], $paste['meta']);
|
||||
if (array_key_exists('expire_date', $meta)) {
|
||||
$expire_date = (int) $meta['expire_date'];
|
||||
unset($meta['expire_date']);
|
||||
}
|
||||
if (array_key_exists('opendiscussion', $paste['meta'])) {
|
||||
$opendiscussion = (bool) $paste['meta']['opendiscussion'];
|
||||
if (array_key_exists('opendiscussion', $meta)) {
|
||||
$opendiscussion = $meta['opendiscussion'];
|
||||
unset($meta['opendiscussion']);
|
||||
}
|
||||
if (array_key_exists('burnafterreading', $paste['meta'])) {
|
||||
$burnafterreading = (bool) $paste['meta']['burnafterreading'];
|
||||
if (array_key_exists('burnafterreading', $meta)) {
|
||||
$burnafterreading = $meta['burnafterreading'];
|
||||
unset($meta['burnafterreading']);
|
||||
}
|
||||
if (array_key_exists('attachment', $paste['meta'])) {
|
||||
$attachment = $paste['meta']['attachment'];
|
||||
unset($meta['attachment']);
|
||||
}
|
||||
if (array_key_exists('attachmentname', $paste['meta'])) {
|
||||
$attachmentname = $paste['meta']['attachmentname'];
|
||||
unset($meta['attachmentname']);
|
||||
if ($isVersion1) {
|
||||
if (array_key_exists('attachment', $meta)) {
|
||||
$attachment = $meta['attachment'];
|
||||
unset($meta['attachment']);
|
||||
}
|
||||
if (array_key_exists('attachmentname', $meta)) {
|
||||
$attachmentname = $meta['attachmentname'];
|
||||
unset($meta['attachmentname']);
|
||||
}
|
||||
} else {
|
||||
$opendiscussion = $paste['adata'][2];
|
||||
$burnafterreading = $paste['adata'][3];
|
||||
}
|
||||
return self::_exec(
|
||||
'INSERT INTO ' . self::_sanitizeIdentifier('paste') .
|
||||
' VALUES(?,?,?,?,?,?,?,?,?)',
|
||||
array(
|
||||
$pasteid,
|
||||
$paste['data'],
|
||||
$paste['meta']['postdate'],
|
||||
$isVersion1 ? $paste['data'] : Json::encode($paste),
|
||||
$created,
|
||||
$expire_date,
|
||||
(int) $opendiscussion,
|
||||
(int) $burnafterreading,
|
||||
json_encode($meta),
|
||||
Json::encode($meta),
|
||||
$attachment,
|
||||
$attachmentname,
|
||||
)
|
||||
@ -214,65 +220,63 @@ class Database extends AbstractData
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return stdClass|false
|
||||
* @return array|false
|
||||
*/
|
||||
public function read($pasteid)
|
||||
{
|
||||
if (
|
||||
!array_key_exists($pasteid, self::$_cache)
|
||||
) {
|
||||
self::$_cache[$pasteid] = false;
|
||||
$paste = self::_select(
|
||||
'SELECT * FROM ' . self::_sanitizeIdentifier('paste') .
|
||||
' WHERE dataid = ?', array($pasteid), true
|
||||
);
|
||||
if (array_key_exists($pasteid, self::$_cache)) {
|
||||
return self::$_cache[$pasteid];
|
||||
}
|
||||
|
||||
if (false !== $paste) {
|
||||
// create object
|
||||
self::$_cache[$pasteid] = new stdClass;
|
||||
self::$_cache[$pasteid]->data = $paste['data'];
|
||||
self::$_cache[$pasteid] = false;
|
||||
$paste = self::_select(
|
||||
'SELECT * FROM ' . self::_sanitizeIdentifier('paste') .
|
||||
' WHERE dataid = ?', array($pasteid), true
|
||||
);
|
||||
|
||||
$meta = json_decode($paste['meta']);
|
||||
if (!is_object($meta)) {
|
||||
$meta = new stdClass;
|
||||
}
|
||||
if ($paste === false) {
|
||||
return false;
|
||||
}
|
||||
// create array
|
||||
$data = Json::decode($paste['data']);
|
||||
$isVersion2 = array_key_exists('v', $data) && $data['v'] >= 2;
|
||||
if ($isVersion2) {
|
||||
self::$_cache[$pasteid] = $data;
|
||||
list($createdKey) = self::_getVersionedKeys(2);
|
||||
} else {
|
||||
self::$_cache[$pasteid] = array('data' => $paste['data']);
|
||||
list($createdKey) = self::_getVersionedKeys(1);
|
||||
}
|
||||
|
||||
// support older attachments
|
||||
if (property_exists($meta, 'attachment')) {
|
||||
self::$_cache[$pasteid]->attachment = $meta->attachment;
|
||||
unset($meta->attachment);
|
||||
if (property_exists($meta, 'attachmentname')) {
|
||||
self::$_cache[$pasteid]->attachmentname = $meta->attachmentname;
|
||||
unset($meta->attachmentname);
|
||||
}
|
||||
}
|
||||
// support current attachments
|
||||
elseif (array_key_exists('attachment', $paste) && strlen($paste['attachment'])) {
|
||||
self::$_cache[$pasteid]->attachment = $paste['attachment'];
|
||||
if (array_key_exists('attachmentname', $paste) && strlen($paste['attachmentname'])) {
|
||||
self::$_cache[$pasteid]->attachmentname = $paste['attachmentname'];
|
||||
}
|
||||
}
|
||||
self::$_cache[$pasteid]->meta = $meta;
|
||||
self::$_cache[$pasteid]->meta->postdate = (int) $paste['postdate'];
|
||||
$expire_date = (int) $paste['expiredate'];
|
||||
if (
|
||||
$expire_date > 0
|
||||
) {
|
||||
self::$_cache[$pasteid]->meta->expire_date = $expire_date;
|
||||
}
|
||||
if (
|
||||
$paste['opendiscussion']
|
||||
) {
|
||||
self::$_cache[$pasteid]->meta->opendiscussion = true;
|
||||
}
|
||||
if (
|
||||
$paste['burnafterreading']
|
||||
) {
|
||||
self::$_cache[$pasteid]->meta->burnafterreading = true;
|
||||
}
|
||||
try {
|
||||
$paste['meta'] = Json::decode($paste['meta']);
|
||||
} catch (Exception $e) {
|
||||
$paste['meta'] = array();
|
||||
}
|
||||
$paste = self::upgradePreV1Format($paste);
|
||||
self::$_cache[$pasteid]['meta'] = $paste['meta'];
|
||||
self::$_cache[$pasteid]['meta'][$createdKey] = (int) $paste['postdate'];
|
||||
$expire_date = (int) $paste['expiredate'];
|
||||
if ($expire_date > 0) {
|
||||
self::$_cache[$pasteid]['meta']['expire_date'] = $expire_date;
|
||||
}
|
||||
if ($isVersion2) {
|
||||
return self::$_cache[$pasteid];
|
||||
}
|
||||
|
||||
// support v1 attachments
|
||||
if (array_key_exists('attachment', $paste) && strlen($paste['attachment'])) {
|
||||
self::$_cache[$pasteid]['attachment'] = $paste['attachment'];
|
||||
if (array_key_exists('attachmentname', $paste) && strlen($paste['attachmentname'])) {
|
||||
self::$_cache[$pasteid]['attachmentname'] = $paste['attachmentname'];
|
||||
}
|
||||
}
|
||||
if ($paste['opendiscussion']) {
|
||||
self::$_cache[$pasteid]['meta']['opendiscussion'] = true;
|
||||
}
|
||||
if ($paste['burnafterreading']) {
|
||||
self::$_cache[$pasteid]['meta']['burnafterreading'] = true;
|
||||
}
|
||||
|
||||
return self::$_cache[$pasteid];
|
||||
}
|
||||
@ -327,11 +331,21 @@ class Database extends AbstractData
|
||||
* @param array $comment
|
||||
* @return bool
|
||||
*/
|
||||
public function createComment($pasteid, $parentid, $commentid, $comment)
|
||||
public function createComment($pasteid, $parentid, $commentid, array $comment)
|
||||
{
|
||||
foreach (array('nickname', 'vizhash') as $key) {
|
||||
if (!array_key_exists($key, $comment['meta'])) {
|
||||
$comment['meta'][$key] = null;
|
||||
if (array_key_exists('data', $comment)) {
|
||||
$version = 1;
|
||||
$data = $comment['data'];
|
||||
} else {
|
||||
$version = 2;
|
||||
$data = Json::encode($comment);
|
||||
}
|
||||
list($createdKey, $iconKey) = self::_getVersionedKeys($version);
|
||||
$meta = $comment['meta'];
|
||||
unset($comment['meta']);
|
||||
foreach (array('nickname', $iconKey) as $key) {
|
||||
if (!array_key_exists($key, $meta)) {
|
||||
$meta[$key] = null;
|
||||
}
|
||||
}
|
||||
return self::_exec(
|
||||
@ -341,10 +355,10 @@ class Database extends AbstractData
|
||||
$commentid,
|
||||
$pasteid,
|
||||
$parentid,
|
||||
$comment['data'],
|
||||
$comment['meta']['nickname'],
|
||||
$comment['meta']['vizhash'],
|
||||
$comment['meta']['postdate'],
|
||||
$data,
|
||||
$meta['nickname'],
|
||||
$meta[$iconKey],
|
||||
$meta[$createdKey],
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -367,16 +381,22 @@ class Database extends AbstractData
|
||||
$comments = array();
|
||||
if (count($rows)) {
|
||||
foreach ($rows as $row) {
|
||||
$i = $this->getOpenSlot($comments, (int) $row['postdate']);
|
||||
$comments[$i] = new stdClass;
|
||||
$comments[$i]->id = $row['dataid'];
|
||||
$comments[$i]->parentid = $row['parentid'];
|
||||
$comments[$i]->data = $row['data'];
|
||||
$comments[$i]->meta = new stdClass;
|
||||
$comments[$i]->meta->postdate = (int) $row['postdate'];
|
||||
foreach (array('nickname', 'vizhash') as $key) {
|
||||
if (array_key_exists($key, $row) && !empty($row[$key])) {
|
||||
$comments[$i]->meta->$key = $row[$key];
|
||||
$i = $this->getOpenSlot($comments, (int) $row['postdate']);
|
||||
$data = Json::decode($row['data']);
|
||||
if (array_key_exists('v', $data) && $data['v'] >= 2) {
|
||||
$version = 2;
|
||||
$comments[$i] = $data;
|
||||
} else {
|
||||
$version = 1;
|
||||
$comments[$i] = array('data' => $row['data']);
|
||||
}
|
||||
list($createdKey, $iconKey) = self::_getVersionedKeys($version);
|
||||
$comments[$i]['id'] = $row['dataid'];
|
||||
$comments[$i]['parentid'] = $row['parentid'];
|
||||
$comments[$i]['meta'] = array($createdKey => (int) $row['postdate']);
|
||||
foreach (array('nickname' => 'nickname', 'vizhash' => $iconKey) as $rowKey => $commentKey) {
|
||||
if (array_key_exists($rowKey, $row) && !empty($row[$rowKey])) {
|
||||
$comments[$i]['meta'][$commentKey] = $row[$rowKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -415,7 +435,8 @@ class Database extends AbstractData
|
||||
$pastes = array();
|
||||
$rows = self::_select(
|
||||
'SELECT dataid FROM ' . self::_sanitizeIdentifier('paste') .
|
||||
' WHERE expiredate < ? AND expiredate != ? LIMIT ?', array(time(), 0, $batchsize)
|
||||
' WHERE expiredate < ? AND expiredate != ? LIMIT ?',
|
||||
array(time(), 0, $batchsize)
|
||||
);
|
||||
if (count($rows)) {
|
||||
foreach ($rows as $row) {
|
||||
@ -452,7 +473,7 @@ class Database extends AbstractData
|
||||
* @param array $params
|
||||
* @param bool $firstOnly if only the first row should be returned
|
||||
* @throws PDOException
|
||||
* @return array
|
||||
* @return array|false
|
||||
*/
|
||||
private static function _select($sql, array $params, $firstOnly = false)
|
||||
{
|
||||
@ -465,6 +486,22 @@ class Database extends AbstractData
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* get version dependent key names
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param int $version
|
||||
* @return array
|
||||
*/
|
||||
private static function _getVersionedKeys($version)
|
||||
{
|
||||
if ($version === 1) {
|
||||
return array('postdate', 'vizhash');
|
||||
}
|
||||
return array('created', 'icon');
|
||||
}
|
||||
|
||||
/**
|
||||
* get table list query, depending on the database type
|
||||
*
|
||||
@ -543,7 +580,7 @@ class Database extends AbstractData
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $key
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
private static function _getPrimaryKeyClauses($key = 'dataid')
|
||||
@ -557,6 +594,34 @@ class Database extends AbstractData
|
||||
return array($main_key, $after_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the data type, depending on the database driver
|
||||
*
|
||||
* PostgreSQL uses a different API for BLOBs then SQL, hence we use TEXT
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
private static function _getDataType()
|
||||
{
|
||||
return self::$_type === 'pgsql' ? 'TEXT' : 'BLOB';
|
||||
}
|
||||
|
||||
/**
|
||||
* get the attachment type, depending on the database driver
|
||||
*
|
||||
* PostgreSQL uses a different API for BLOBs then SQL, hence we use TEXT
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
private static function _getAttachmentType()
|
||||
{
|
||||
return self::$_type === 'pgsql' ? 'TEXT' : 'MEDIUMBLOB';
|
||||
}
|
||||
|
||||
/**
|
||||
* create the paste table
|
||||
*
|
||||
@ -566,17 +631,18 @@ class Database extends AbstractData
|
||||
private static function _createPasteTable()
|
||||
{
|
||||
list($main_key, $after_key) = self::_getPrimaryKeyClauses();
|
||||
$dataType = self::$_type === 'pgsql' ? 'TEXT' : 'BLOB';
|
||||
$dataType = self::_getDataType();
|
||||
$attachmentType = self::_getAttachmentType();
|
||||
self::$_db->exec(
|
||||
'CREATE TABLE ' . self::_sanitizeIdentifier('paste') . ' ( ' .
|
||||
"dataid CHAR(16) NOT NULL$main_key, " .
|
||||
"data $dataType, " .
|
||||
"data $attachmentType, " .
|
||||
'postdate INT, ' .
|
||||
'expiredate INT, ' .
|
||||
'opendiscussion INT, ' .
|
||||
'burnafterreading INT, ' .
|
||||
'meta TEXT, ' .
|
||||
'attachment ' . (self::$_type === 'pgsql' ? 'TEXT' : 'MEDIUMBLOB') . ', ' .
|
||||
"attachment $attachmentType, " .
|
||||
"attachmentname $dataType$after_key );"
|
||||
);
|
||||
}
|
||||
@ -590,7 +656,7 @@ class Database extends AbstractData
|
||||
private static function _createCommentTable()
|
||||
{
|
||||
list($main_key, $after_key) = self::_getPrimaryKeyClauses();
|
||||
$dataType = self::$_type === 'pgsql' ? 'text' : 'BLOB';
|
||||
$dataType = self::_getDataType();
|
||||
self::$_db->exec(
|
||||
'CREATE TABLE ' . self::_sanitizeIdentifier('comment') . ' ( ' .
|
||||
"dataid CHAR(16) NOT NULL$main_key, " .
|
||||
@ -649,7 +715,8 @@ class Database extends AbstractData
|
||||
*/
|
||||
private static function _upgradeDatabase($oldversion)
|
||||
{
|
||||
$dataType = self::$_type === 'pgsql' ? 'TEXT' : 'BLOB';
|
||||
$dataType = self::_getDataType();
|
||||
$attachmentType = self::_getAttachmentType();
|
||||
switch ($oldversion) {
|
||||
case '0.21':
|
||||
// create the meta column if necessary (pre 0.21 change)
|
||||
@ -661,8 +728,7 @@ class Database extends AbstractData
|
||||
// SQLite only allows one ALTER statement at a time...
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') .
|
||||
' ADD COLUMN attachment ' .
|
||||
(self::$_type === 'pgsql' ? 'TEXT' : 'MEDIUMBLOB') . ';'
|
||||
" ADD COLUMN attachment $attachmentType;"
|
||||
);
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') . " ADD COLUMN attachmentname $dataType;"
|
||||
@ -672,7 +738,7 @@ class Database extends AbstractData
|
||||
if (self::$_type !== 'sqlite') {
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') .
|
||||
' ADD PRIMARY KEY (dataid), MODIFY COLUMN data $dataType;'
|
||||
" ADD PRIMARY KEY (dataid), MODIFY COLUMN data $dataType;"
|
||||
);
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_sanitizeIdentifier('comment') .
|
||||
@ -694,6 +760,17 @@ class Database extends AbstractData
|
||||
self::_sanitizeIdentifier('comment') . '(pasteid);'
|
||||
);
|
||||
// no break, continue with updates for 0.22 and later
|
||||
case '1.3':
|
||||
// SQLite doesn't support MODIFY, but it allows TEXT of similar
|
||||
// size as BLOB and PostgreSQL uses TEXT, so there is no need
|
||||
// to change it there
|
||||
if (self::$_type !== 'sqlite' && self::$_type !== 'pgsql') {
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') .
|
||||
" MODIFY COLUMN data $attachmentType;"
|
||||
);
|
||||
}
|
||||
// no break, continue with updates for all newer versions
|
||||
default:
|
||||
self::_exec(
|
||||
'UPDATE ' . self::_sanitizeIdentifier('config') .
|
||||
|
@ -7,12 +7,11 @@
|
||||
* @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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
|
||||
use PrivateBin\Model\Paste;
|
||||
use PrivateBin\Persistence\DataStore;
|
||||
|
||||
/**
|
||||
@ -30,7 +29,7 @@ class Filesystem extends AbstractData
|
||||
* @param array $options
|
||||
* @return Filesystem
|
||||
*/
|
||||
public static function getInstance($options = null)
|
||||
public static function getInstance(array $options)
|
||||
{
|
||||
// if needed initialize the singleton
|
||||
if (!(self::$_instance instanceof self)) {
|
||||
@ -54,7 +53,7 @@ class Filesystem extends AbstractData
|
||||
* @param array $paste
|
||||
* @return bool
|
||||
*/
|
||||
public function create($pasteid, $paste)
|
||||
public function create($pasteid, array $paste)
|
||||
{
|
||||
$storagedir = self::_dataid2path($pasteid);
|
||||
$file = $storagedir . $pasteid . '.php';
|
||||
@ -73,24 +72,18 @@ class Filesystem extends AbstractData
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return stdClass|false
|
||||
* @return array|false
|
||||
*/
|
||||
public function read($pasteid)
|
||||
{
|
||||
if (!$this->exists($pasteid)) {
|
||||
return false;
|
||||
}
|
||||
$paste = DataStore::get(self::_dataid2path($pasteid) . $pasteid . '.php');
|
||||
if (property_exists($paste->meta, 'attachment')) {
|
||||
$paste->attachment = $paste->meta->attachment;
|
||||
unset($paste->meta->attachment);
|
||||
if (property_exists($paste->meta, 'attachmentname')) {
|
||||
$paste->attachmentname = $paste->meta->attachmentname;
|
||||
unset($paste->meta->attachmentname);
|
||||
}
|
||||
}
|
||||
|
||||
self::logToChapril("READ",$pasteid);
|
||||
return $paste;
|
||||
return self::upgradePreV1Format(
|
||||
DataStore::get(self::_dataid2path($pasteid) . $pasteid . '.php')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,7 +159,7 @@ class Filesystem extends AbstractData
|
||||
* @param array $comment
|
||||
* @return bool
|
||||
*/
|
||||
public function createComment($pasteid, $parentid, $commentid, $comment)
|
||||
public function createComment($pasteid, $parentid, $commentid, array $comment)
|
||||
{
|
||||
$storagedir = self::_dataid2discussionpath($pasteid);
|
||||
$file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid . '.php';
|
||||
@ -202,11 +195,11 @@ class Filesystem extends AbstractData
|
||||
$comment = DataStore::get($discdir . $filename);
|
||||
$items = explode('.', $filename);
|
||||
// Add some meta information not contained in file.
|
||||
$comment->id = $items[1];
|
||||
$comment->parentid = $items[2];
|
||||
$comment['id'] = $items[1];
|
||||
$comment['parentid'] = $items[2];
|
||||
|
||||
// Store in array
|
||||
$key = $this->getOpenSlot($comments, (int) $comment->meta->postdate);
|
||||
$key = $this->getOpenSlot($comments, (int) $comment['meta']['created']);
|
||||
$comments[$key] = $comment;
|
||||
}
|
||||
}
|
||||
@ -295,8 +288,8 @@ class Filesystem extends AbstractData
|
||||
if ($this->exists($pasteid)) {
|
||||
$data = $this->read($pasteid);
|
||||
if (
|
||||
property_exists($data->meta, 'expire_date') &&
|
||||
$data->meta->expire_date < time()
|
||||
array_key_exists('expire_date', $data['meta']) &&
|
||||
$data['meta']['expire_date'] < time()
|
||||
) {
|
||||
$pastes[] = $pasteid;
|
||||
if (count($pastes) >= $batchsize) {
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
127
lib/FormatV2.php
Normal file
127
lib/FormatV2.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?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.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
||||
/**
|
||||
* FormatV2
|
||||
*
|
||||
* Provides validation function for version 2 format of pastes & comments.
|
||||
*/
|
||||
class FormatV2
|
||||
{
|
||||
/**
|
||||
* version 2 format validator
|
||||
*
|
||||
* Checks if the given array is a proper version 2 formatted, encrypted message.
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $message
|
||||
* @param bool $isComment
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValid($message, $isComment = false)
|
||||
{
|
||||
$required_keys = array('adata', 'v', 'ct');
|
||||
if ($isComment) {
|
||||
$required_keys[] = 'pasteid';
|
||||
$required_keys[] = 'parentid';
|
||||
} else {
|
||||
$required_keys[] = 'meta';
|
||||
}
|
||||
|
||||
// Make sure no additionnal keys were added.
|
||||
if (count(array_keys($message)) != count($required_keys)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure required fields are present.
|
||||
foreach ($required_keys as $k) {
|
||||
if (!array_key_exists($k, $message)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$cipherParams = $isComment ? $message['adata'] : $message['adata'][0];
|
||||
|
||||
// Make sure some fields are base64 data:
|
||||
// - initialization vector
|
||||
if (!base64_decode($cipherParams[0], true)) {
|
||||
return false;
|
||||
}
|
||||
// - salt
|
||||
if (!base64_decode($cipherParams[1], true)) {
|
||||
return false;
|
||||
}
|
||||
// - cipher text
|
||||
if (!($ct = base64_decode($message['ct'], true))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure some fields have a reasonable size:
|
||||
// - initialization vector
|
||||
if (strlen($cipherParams[0]) > 24) {
|
||||
return false;
|
||||
}
|
||||
// - salt
|
||||
if (strlen($cipherParams[1]) > 14) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure some fields contain no unsupported values:
|
||||
// - version
|
||||
if (!(is_int($message['v']) || is_float($message['v'])) || (float) $message['v'] < 2) {
|
||||
return false;
|
||||
}
|
||||
// - iterations, refuse less then 10000 iterations (minimum NIST recommendation)
|
||||
if (!is_int($cipherParams[2]) || $cipherParams[2] <= 10000) {
|
||||
return false;
|
||||
}
|
||||
// - key size
|
||||
if (!in_array($cipherParams[3], array(128, 192, 256), true)) {
|
||||
return false;
|
||||
}
|
||||
// - tag size
|
||||
if (!in_array($cipherParams[4], array(64, 96, 128), true)) {
|
||||
return false;
|
||||
}
|
||||
// - algorithm, must be AES
|
||||
if ($cipherParams[5] !== 'aes') {
|
||||
return false;
|
||||
}
|
||||
// - mode
|
||||
if (!in_array($cipherParams[6], array('ctr', 'cbc', 'gcm'), true)) {
|
||||
return false;
|
||||
}
|
||||
// - compression
|
||||
if (!in_array($cipherParams[7], array('zlib', 'none'), true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reject data if entropy is too low
|
||||
if (strlen($ct) > strlen(gzdeflate($ct))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// require only the key 'expire' in the metadata of pastes
|
||||
if (!$isComment && (
|
||||
count($message['meta']) === 0 ||
|
||||
!array_key_exists('expire', $message['meta']) ||
|
||||
count($message['meta']) > 1
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
14
lib/I18n.php
14
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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@ -156,9 +156,8 @@ class I18n
|
||||
|
||||
// load translations
|
||||
self::$_language = $match;
|
||||
self::$_translations = ($match == 'en') ? array() : json_decode(
|
||||
file_get_contents(self::_getPath($match . '.json')),
|
||||
true
|
||||
self::$_translations = ($match == 'en') ? array() : Json::decode(
|
||||
file_get_contents(self::_getPath($match . '.json'))
|
||||
);
|
||||
}
|
||||
|
||||
@ -244,7 +243,7 @@ class I18n
|
||||
{
|
||||
$file = self::_getPath('languages.json');
|
||||
if (count(self::$_languageLabels) == 0 && is_readable($file)) {
|
||||
self::$_languageLabels = json_decode(file_get_contents($file), true);
|
||||
self::$_languageLabels = Json::decode(file_get_contents($file));
|
||||
}
|
||||
if (count($languages) == 0) {
|
||||
return self::$_languageLabels;
|
||||
@ -295,6 +294,8 @@ class I18n
|
||||
protected static function _getPluralForm($n)
|
||||
{
|
||||
switch (self::$_language) {
|
||||
case 'cs':
|
||||
return $n == 1 ? 0 : ($n >= 2 && $n <= 4 ? 1 : 2);
|
||||
case 'fr':
|
||||
case 'oc':
|
||||
case 'zh':
|
||||
@ -302,10 +303,11 @@ class I18n
|
||||
case 'pl':
|
||||
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));
|
||||
// de, en, es, hu, it, nl, no, pt
|
||||
// bg, de, en, es, hu, it, nl, no, pt
|
||||
default:
|
||||
return $n != 1 ? 1 : 0;
|
||||
}
|
||||
|
36
lib/Json.php
36
lib/Json.php
@ -7,7 +7,7 @@
|
||||
* @link https://github.com/PrivateBin/PrivateBin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 1.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@ -33,9 +33,39 @@ class Json
|
||||
public static function encode($input)
|
||||
{
|
||||
$jsonString = json_encode($input);
|
||||
$errorCode = json_last_error();
|
||||
self::_detectError();
|
||||
return $jsonString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with the contents as described in the given JSON input
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $input
|
||||
* @throws Exception
|
||||
* @return array
|
||||
*/
|
||||
public static function decode($input)
|
||||
{
|
||||
$array = json_decode($input, true);
|
||||
self::_detectError();
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects JSON errors and raises an exception if one is found
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
private static function _detectError()
|
||||
{
|
||||
$errorCode = json_last_error();
|
||||
if ($errorCode === JSON_ERROR_NONE) {
|
||||
return $jsonString;
|
||||
return;
|
||||
}
|
||||
|
||||
$message = 'A JSON error occurred';
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@ -32,7 +32,7 @@ class Model
|
||||
/**
|
||||
* Data storage.
|
||||
*
|
||||
* @var AbstractData
|
||||
* @var Data\AbstractData
|
||||
*/
|
||||
private $_store = null;
|
||||
|
||||
@ -75,7 +75,7 @@ class Model
|
||||
/**
|
||||
* Gets, and creates if neccessary, a store object
|
||||
*
|
||||
* @return AbstractData
|
||||
* @return Data\AbstractData
|
||||
*/
|
||||
private function _getStore()
|
||||
{
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Model;
|
||||
@ -15,8 +15,6 @@ namespace PrivateBin\Model;
|
||||
use Exception;
|
||||
use PrivateBin\Configuration;
|
||||
use PrivateBin\Data\AbstractData;
|
||||
use PrivateBin\Sjcl;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* AbstractModel
|
||||
@ -37,9 +35,9 @@ abstract class AbstractModel
|
||||
* Instance data.
|
||||
*
|
||||
* @access protected
|
||||
* @var stdClass
|
||||
* @var array
|
||||
*/
|
||||
protected $_data;
|
||||
protected $_data = array('meta' => array());
|
||||
|
||||
/**
|
||||
* Configuration.
|
||||
@ -68,8 +66,6 @@ abstract class AbstractModel
|
||||
{
|
||||
$this->_conf = $configuration;
|
||||
$this->_store = $storage;
|
||||
$this->_data = new stdClass;
|
||||
$this->_data->meta = new stdClass;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,28 +98,29 @@ abstract class AbstractModel
|
||||
* Set data and recalculate ID.
|
||||
*
|
||||
* @access public
|
||||
* @param string $data
|
||||
* @param array $data
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setData($data)
|
||||
public function setData(array $data)
|
||||
{
|
||||
if (!Sjcl::isValid($data)) {
|
||||
throw new Exception('Invalid data.', 61);
|
||||
}
|
||||
$this->_data->data = $data;
|
||||
$data = $this->_sanitize($data);
|
||||
$this->_validate($data);
|
||||
$this->_data = $data;
|
||||
|
||||
// We just want a small hash to avoid collisions:
|
||||
// Half-MD5 (64 bits) will do the trick
|
||||
$this->setId(substr(hash('md5', $data), 0, 16));
|
||||
// calculate a 64 bit checksum to avoid collisions
|
||||
$this->setId(hash(version_compare(PHP_VERSION, '5.6', '<') ? 'fnv164' : 'fnv1a64', $data['ct']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instance data.
|
||||
*
|
||||
* @access public
|
||||
* @return stdClass
|
||||
* @return array
|
||||
*/
|
||||
abstract public function get();
|
||||
public function get()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the instance's data.
|
||||
@ -161,4 +158,24 @@ abstract class AbstractModel
|
||||
{
|
||||
return (bool) preg_match('#\A[a-f\d]{16}\z#', (string) $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes data to conform with current configuration.
|
||||
*
|
||||
* @access protected
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function _sanitize(array $data);
|
||||
|
||||
/**
|
||||
* Validate data.
|
||||
*
|
||||
* @access protected
|
||||
* @param array $data
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function _validate(array $data)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Model;
|
||||
@ -15,7 +15,6 @@ namespace PrivateBin\Model;
|
||||
use Exception;
|
||||
use Identicon\Identicon;
|
||||
use PrivateBin\Persistence\TrafficLimiter;
|
||||
use PrivateBin\Sjcl;
|
||||
use PrivateBin\Vizhash16x16;
|
||||
|
||||
/**
|
||||
@ -33,29 +32,6 @@ class Comment extends AbstractModel
|
||||
*/
|
||||
private $_paste;
|
||||
|
||||
/**
|
||||
* Get comment data.
|
||||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return stdClass
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
// @todo add support to read specific comment
|
||||
$comments = $this->_store->readComments($this->getPaste()->getId());
|
||||
foreach ($comments as $comment) {
|
||||
if (
|
||||
$comment->parentid == $this->getParentId() &&
|
||||
$comment->id == $this->getId()
|
||||
) {
|
||||
$this->_data = $comment;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the comment's data.
|
||||
*
|
||||
@ -80,7 +56,7 @@ class Comment extends AbstractModel
|
||||
throw new Exception('You are unlucky. Try again.', 69);
|
||||
}
|
||||
|
||||
$this->_data->meta->postdate = time();
|
||||
$this->_data['meta']['created'] = time();
|
||||
|
||||
// store comment
|
||||
if (
|
||||
@ -88,7 +64,7 @@ class Comment extends AbstractModel
|
||||
$pasteid,
|
||||
$this->getParentId(),
|
||||
$this->getId(),
|
||||
json_decode(json_encode($this->_data), true)
|
||||
$this->_data
|
||||
) === false
|
||||
) {
|
||||
throw new Exception('Error saving comment. Sorry.', 70);
|
||||
@ -130,8 +106,8 @@ class Comment extends AbstractModel
|
||||
*/
|
||||
public function setPaste(Paste $paste)
|
||||
{
|
||||
$this->_paste = $paste;
|
||||
$this->_data->meta->pasteid = $paste->getId();
|
||||
$this->_paste = $paste;
|
||||
$this->_data['pasteid'] = $paste->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,7 +133,7 @@ class Comment extends AbstractModel
|
||||
if (!self::isValidId($id)) {
|
||||
throw new Exception('Invalid paste ID.', 65);
|
||||
}
|
||||
$this->_data->meta->parentid = $id;
|
||||
$this->_data['parentid'] = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,29 +144,22 @@ class Comment extends AbstractModel
|
||||
*/
|
||||
public function getParentId()
|
||||
{
|
||||
if (!property_exists($this->_data->meta, 'parentid')) {
|
||||
$this->_data->meta->parentid = '';
|
||||
if (!array_key_exists('parentid', $this->_data)) {
|
||||
$this->_data['parentid'] = $this->getPaste()->getId();
|
||||
}
|
||||
return $this->_data->meta->parentid;
|
||||
return $this->_data['parentid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set nickname.
|
||||
* Sanitizes data to conform with current configuration.
|
||||
*
|
||||
* @access public
|
||||
* @param string $nickname
|
||||
* @throws Exception
|
||||
* @access protected
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function setNickname($nickname)
|
||||
protected function _sanitize(array $data)
|
||||
{
|
||||
if (!Sjcl::isValid($nickname)) {
|
||||
throw new Exception('Invalid data.', 66);
|
||||
}
|
||||
$this->_data->meta->nickname = $nickname;
|
||||
|
||||
// If a nickname is provided, we generate an icon based on a SHA512 HMAC
|
||||
// of the users IP. (We assume that if the user did not enter a nickname,
|
||||
// the user wants to be anonymous and we will not generate an icon.)
|
||||
// we generate an icon based on a SHA512 HMAC of the users IP, if configured
|
||||
$icon = $this->_conf->getKey('icon');
|
||||
if ($icon != 'none') {
|
||||
$pngdata = '';
|
||||
@ -205,9 +174,12 @@ class Comment extends AbstractModel
|
||||
);
|
||||
}
|
||||
if ($pngdata != '') {
|
||||
$this->_data->meta->vizhash = $pngdata;
|
||||
if (!array_key_exists('meta', $data)) {
|
||||
$data['meta'] = array();
|
||||
}
|
||||
$data['meta']['icon'] = $pngdata;
|
||||
}
|
||||
}
|
||||
// Once the icon is generated, we do not keep the IP address hash.
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Model;
|
||||
@ -15,7 +15,6 @@ namespace PrivateBin\Model;
|
||||
use Exception;
|
||||
use PrivateBin\Controller;
|
||||
use PrivateBin\Persistence\ServerSalt;
|
||||
use PrivateBin\Sjcl;
|
||||
|
||||
/**
|
||||
* Paste
|
||||
@ -29,7 +28,7 @@ class Paste extends AbstractModel
|
||||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return stdClass
|
||||
* @return array
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
@ -39,44 +38,43 @@ class Paste extends AbstractModel
|
||||
}
|
||||
|
||||
// check if paste has expired and delete it if neccessary.
|
||||
if (property_exists($data->meta, 'expire_date')) {
|
||||
if ($data->meta->expire_date < time()) {
|
||||
if (array_key_exists('expire_date', $data['meta'])) {
|
||||
if ($data['meta']['expire_date'] < time()) {
|
||||
$this->delete();
|
||||
throw new Exception(Controller::GENERIC_ERROR, 63);
|
||||
}
|
||||
// We kindly provide the remaining time before expiration (in seconds)
|
||||
$data->meta->remaining_time = $data->meta->expire_date - time();
|
||||
$data['meta']['time_to_live'] = $data['meta']['expire_date'] - time();
|
||||
unset($data['meta']['expire_date']);
|
||||
}
|
||||
|
||||
// check if non-expired burn after reading paste needs to be deleted
|
||||
if (property_exists($data->meta, 'burnafterreading') && $data->meta->burnafterreading) {
|
||||
if (
|
||||
(array_key_exists('adata', $data) && $data['adata'][3] === 1) ||
|
||||
(array_key_exists('burnafterreading', $data['meta']) && $data['meta']['burnafterreading'])
|
||||
) {
|
||||
$this->delete();
|
||||
}
|
||||
|
||||
// set formatter for for the view.
|
||||
if (!property_exists($data->meta, 'formatter')) {
|
||||
// set formatter for the view in version 1 pastes.
|
||||
if (array_key_exists('data', $data) && !array_key_exists('formatter', $data['meta'])) {
|
||||
// support < 0.21 syntax highlighting
|
||||
if (property_exists($data->meta, 'syntaxcoloring') && $data->meta->syntaxcoloring === true) {
|
||||
$data->meta->formatter = 'syntaxhighlighting';
|
||||
if (array_key_exists('syntaxcoloring', $data['meta']) && $data['meta']['syntaxcoloring'] === true) {
|
||||
$data['meta']['formatter'] = 'syntaxhighlighting';
|
||||
} else {
|
||||
$data->meta->formatter = $this->_conf->getKey('defaultformatter');
|
||||
$data['meta']['formatter'] = $this->_conf->getKey('defaultformatter');
|
||||
}
|
||||
}
|
||||
|
||||
// support old paste format with server wide salt
|
||||
if (!property_exists($data->meta, 'salt')) {
|
||||
$data->meta->salt = ServerSalt::get();
|
||||
}
|
||||
$data->comments = array_values($this->getComments());
|
||||
$data->comment_count = count($data->comments);
|
||||
$data->comment_offset = 0;
|
||||
$data->{'@context'} = 'js/paste.jsonld';
|
||||
$this->_data = $data;
|
||||
|
||||
// If the paste was meant to be read only once, delete it.
|
||||
if ($this->isBurnafterreading()) {
|
||||
$this->delete();
|
||||
if (!array_key_exists('salt', $data['meta'])) {
|
||||
$data['meta']['salt'] = ServerSalt::get();
|
||||
}
|
||||
$data['comments'] = array_values($this->getComments());
|
||||
$data['comment_count'] = count($data['comments']);
|
||||
$data['comment_offset'] = 0;
|
||||
$data['@context'] = '?jsonld=paste';
|
||||
$this->_data = $data;
|
||||
|
||||
return $this->_data;
|
||||
}
|
||||
@ -94,14 +92,14 @@ class Paste extends AbstractModel
|
||||
throw new Exception('You are unlucky. Try again.', 75);
|
||||
}
|
||||
|
||||
$this->_data->meta->postdate = time();
|
||||
$this->_data->meta->salt = serversalt::generate();
|
||||
$this->_data['meta']['created'] = time();
|
||||
$this->_data['meta']['salt'] = serversalt::generate();
|
||||
|
||||
// store paste
|
||||
if (
|
||||
$this->_store->create(
|
||||
$this->getId(),
|
||||
json_decode(json_encode($this->_data), true)
|
||||
$this->_data
|
||||
) === false
|
||||
) {
|
||||
throw new Exception('Error saving paste. Sorry.', 76);
|
||||
@ -139,7 +137,7 @@ class Paste extends AbstractModel
|
||||
* @throws Exception
|
||||
* @return Comment
|
||||
*/
|
||||
public function getComment($parentId, $commentId = null)
|
||||
public function getComment($parentId, $commentId = '')
|
||||
{
|
||||
if (!$this->exists()) {
|
||||
throw new Exception('Invalid data.', 62);
|
||||
@ -147,7 +145,7 @@ class Paste extends AbstractModel
|
||||
$comment = new Comment($this->_conf, $this->_store);
|
||||
$comment->setPaste($this);
|
||||
$comment->setParentId($parentId);
|
||||
if ($commentId !== null) {
|
||||
if ($commentId !== '') {
|
||||
$comment->setId($commentId);
|
||||
}
|
||||
return $comment;
|
||||
@ -176,140 +174,16 @@ class Paste extends AbstractModel
|
||||
*/
|
||||
public function getDeleteToken()
|
||||
{
|
||||
if (!property_exists($this->_data->meta, 'salt')) {
|
||||
if (!array_key_exists('salt', $this->_data['meta'])) {
|
||||
$this->get();
|
||||
}
|
||||
return hash_hmac(
|
||||
$this->_conf->getKey('zerobincompatibility') ? 'sha1' : 'sha256',
|
||||
$this->getId(),
|
||||
$this->_data->meta->salt
|
||||
$this->_data['meta']['salt']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set paste's attachment.
|
||||
*
|
||||
* @access public
|
||||
* @param string $attachment
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setAttachment($attachment)
|
||||
{
|
||||
if (!$this->_conf->getKey('fileupload') || !Sjcl::isValid($attachment)) {
|
||||
throw new Exception('Invalid attachment.', 71);
|
||||
}
|
||||
$this->_data->meta->attachment = $attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set paste's attachment name.
|
||||
*
|
||||
* @access public
|
||||
* @param string $attachmentname
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setAttachmentName($attachmentname)
|
||||
{
|
||||
if (!$this->_conf->getKey('fileupload') || !Sjcl::isValid($attachmentname)) {
|
||||
throw new Exception('Invalid attachment.', 72);
|
||||
}
|
||||
$this->_data->meta->attachmentname = $attachmentname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set paste expiration.
|
||||
*
|
||||
* @access public
|
||||
* @param string $expiration
|
||||
*/
|
||||
public function setExpiration($expiration)
|
||||
{
|
||||
$expire_options = $this->_conf->getSection('expire_options');
|
||||
if (array_key_exists($expiration, $expire_options)) {
|
||||
$expire = $expire_options[$expiration];
|
||||
} else {
|
||||
// using getKey() to ensure a default value is present
|
||||
$expire = $this->_conf->getKey($this->_conf->getKey('default', 'expire'), 'expire_options');
|
||||
}
|
||||
if ($expire > 0) {
|
||||
$this->_data->meta->expire_date = time() + $expire;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set paste's burn-after-reading type.
|
||||
*
|
||||
* @access public
|
||||
* @param string $burnafterreading
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setBurnafterreading($burnafterreading = '1')
|
||||
{
|
||||
if ($burnafterreading === '0') {
|
||||
$this->_data->meta->burnafterreading = false;
|
||||
} else {
|
||||
if ($burnafterreading !== '1') {
|
||||
throw new Exception('Invalid data.', 73);
|
||||
}
|
||||
$this->_data->meta->burnafterreading = true;
|
||||
$this->_data->meta->opendiscussion = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set paste's discussion state.
|
||||
*
|
||||
* @access public
|
||||
* @param string $opendiscussion
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setOpendiscussion($opendiscussion = '1')
|
||||
{
|
||||
if (
|
||||
!$this->_conf->getKey('discussion') ||
|
||||
$this->isBurnafterreading() ||
|
||||
$opendiscussion === '0'
|
||||
) {
|
||||
$this->_data->meta->opendiscussion = false;
|
||||
} else {
|
||||
if ($opendiscussion !== '1') {
|
||||
throw new Exception('Invalid data.', 74);
|
||||
}
|
||||
$this->_data->meta->opendiscussion = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set paste's format.
|
||||
*
|
||||
* @access public
|
||||
* @param string $format
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setFormatter($format)
|
||||
{
|
||||
if (!array_key_exists($format, $this->_conf->getSection('formatter_options'))) {
|
||||
$format = $this->_conf->getKey('defaultformatter');
|
||||
}
|
||||
$this->_data->meta->formatter = $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if paste is of burn-after-reading type.
|
||||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return bool
|
||||
*/
|
||||
public function isBurnafterreading()
|
||||
{
|
||||
if (!property_exists($this->_data, 'data')) {
|
||||
$this->get();
|
||||
}
|
||||
return property_exists($this->_data->meta, 'burnafterreading') &&
|
||||
$this->_data->meta->burnafterreading === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if paste has discussions enabled.
|
||||
*
|
||||
@ -319,10 +193,66 @@ class Paste extends AbstractModel
|
||||
*/
|
||||
public function isOpendiscussion()
|
||||
{
|
||||
if (!property_exists($this->_data, 'data')) {
|
||||
if (!array_key_exists('adata', $this->_data) && !array_key_exists('data', $this->_data)) {
|
||||
$this->get();
|
||||
}
|
||||
return property_exists($this->_data->meta, 'opendiscussion') &&
|
||||
$this->_data->meta->opendiscussion === true;
|
||||
return
|
||||
(array_key_exists('adata', $this->_data) && $this->_data['adata'][2] === 1) ||
|
||||
(array_key_exists('opendiscussion', $this->_data['meta']) && $this->_data['meta']['opendiscussion']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes data to conform with current configuration.
|
||||
*
|
||||
* @access protected
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
protected function _sanitize(array $data)
|
||||
{
|
||||
$expiration = $data['meta']['expire'];
|
||||
unset($data['meta']['expire']);
|
||||
$expire_options = $this->_conf->getSection('expire_options');
|
||||
if (array_key_exists($expiration, $expire_options)) {
|
||||
$expire = $expire_options[$expiration];
|
||||
} else {
|
||||
// using getKey() to ensure a default value is present
|
||||
$expire = $this->_conf->getKey($this->_conf->getKey('default', 'expire'), 'expire_options');
|
||||
}
|
||||
if ($expire > 0) {
|
||||
$data['meta']['expire_date'] = time() + $expire;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate data.
|
||||
*
|
||||
* @access protected
|
||||
* @param array $data
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function _validate(array $data)
|
||||
{
|
||||
// reject invalid or disabled formatters
|
||||
if (!array_key_exists($data['adata'][1], $this->_conf->getSection('formatter_options'))) {
|
||||
throw new Exception('Invalid data.', 75);
|
||||
}
|
||||
|
||||
// discussion requested, but disabled in config or burn after reading requested as well, or invalid integer
|
||||
if (
|
||||
($data['adata'][2] === 1 && ( // open discussion flag
|
||||
!$this->_conf->getKey('discussion') ||
|
||||
$data['adata'][3] === 1 // burn after reading flag
|
||||
)) ||
|
||||
($data['adata'][2] !== 0 && $data['adata'][2] !== 1)
|
||||
) {
|
||||
throw new Exception('Invalid data.', 74);
|
||||
}
|
||||
|
||||
// reject invalid burn after reading
|
||||
if ($data['adata'][3] !== 0 && $data['adata'][3] !== 1) {
|
||||
throw new Exception('Invalid data.', 73);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
|
@ -45,7 +45,10 @@ class DataStore extends AbstractPersistence
|
||||
$filename = substr($filename, strlen($path));
|
||||
}
|
||||
try {
|
||||
self::_store($filename, self::PROTECTION_LINE . PHP_EOL . Json::encode($data));
|
||||
self::_store(
|
||||
$filename,
|
||||
self::PROTECTION_LINE . PHP_EOL . Json::encode($data)
|
||||
);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
@ -58,11 +61,16 @@ class DataStore extends AbstractPersistence
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $filename
|
||||
* @return stdClass|false $data
|
||||
* @return array|false $data
|
||||
*/
|
||||
public static function get($filename)
|
||||
{
|
||||
return json_decode(substr(file_get_contents($filename), strlen(self::PROTECTION_LINE . PHP_EOL)));
|
||||
return Json::decode(
|
||||
substr(
|
||||
file_get_contents($filename),
|
||||
strlen(self::PROTECTION_LINE . PHP_EOL)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
@ -60,7 +60,7 @@ class PurgeLimiter extends AbstractPersistence
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @throws Exception
|
||||
* @throws \Exception
|
||||
* @return bool
|
||||
*/
|
||||
public static function canPurge()
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Persistence;
|
||||
@ -90,7 +90,7 @@ class TrafficLimiter extends AbstractPersistence
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @throws Exception
|
||||
* @throws \Exception
|
||||
* @return bool
|
||||
*/
|
||||
public static function canPass()
|
||||
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
@ -72,6 +72,27 @@ class Request
|
||||
*/
|
||||
private $_isJsonApi = false;
|
||||
|
||||
/**
|
||||
* Return the paste ID of the current paste.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function getPasteId()
|
||||
{
|
||||
// RegEx to check for valid paste ID (16 base64 chars)
|
||||
$pasteIdRegEx = '/^[a-f0-9]{16}$/';
|
||||
|
||||
foreach ($_GET as $key => $value) {
|
||||
// only return if value is empty and key matches RegEx
|
||||
if (($value === '') and preg_match($pasteIdRegEx, $key, $match)) {
|
||||
return $match[0];
|
||||
}
|
||||
}
|
||||
|
||||
return 'invalid id';
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -86,10 +107,10 @@ class Request
|
||||
switch (array_key_exists('REQUEST_METHOD', $_SERVER) ? $_SERVER['REQUEST_METHOD'] : 'GET') {
|
||||
case 'DELETE':
|
||||
case 'PUT':
|
||||
parse_str(file_get_contents(self::$_inputStream), $this->_params);
|
||||
break;
|
||||
case 'POST':
|
||||
$this->_params = $_POST;
|
||||
$this->_params = Json::decode(
|
||||
file_get_contents(self::$_inputStream)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$this->_params = $_GET;
|
||||
@ -100,13 +121,13 @@ class Request
|
||||
array_key_exists('QUERY_STRING', $_SERVER) &&
|
||||
!empty($_SERVER['QUERY_STRING'])
|
||||
) {
|
||||
$this->_params['pasteid'] = $_SERVER['QUERY_STRING'];
|
||||
$this->_params['pasteid'] = $this->getPasteId();
|
||||
}
|
||||
|
||||
// prepare operation, depending on current parameters
|
||||
if (
|
||||
(array_key_exists('data', $this->_params) && !empty($this->_params['data'])) ||
|
||||
(array_key_exists('attachment', $this->_params) && !empty($this->_params['attachment']))
|
||||
array_key_exists('ct', $this->_params) &&
|
||||
!empty($this->_params['ct'])
|
||||
) {
|
||||
$this->_operation = 'create';
|
||||
} elseif (array_key_exists('pasteid', $this->_params) && !empty($this->_params['pasteid'])) {
|
||||
@ -131,6 +152,33 @@ class Request
|
||||
return $this->_operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data of paste or comment
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
$data = array(
|
||||
'adata' => $this->getParam('adata'),
|
||||
);
|
||||
$required_keys = array('v', 'ct');
|
||||
$meta = $this->getParam('meta');
|
||||
if (empty($meta)) {
|
||||
$required_keys[] = 'pasteid';
|
||||
$required_keys[] = 'parentid';
|
||||
} else {
|
||||
$data['meta'] = $meta;
|
||||
}
|
||||
foreach ($required_keys as $key) {
|
||||
$data[$key] = $this->getParam($key);
|
||||
}
|
||||
// forcing a cast to int or float
|
||||
$data['v'] = $data['v'] + 0;
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a request parameter
|
||||
*
|
||||
@ -145,6 +193,19 @@ class Request
|
||||
$this->_params[$param] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get host as requested by the client
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getHost()
|
||||
{
|
||||
return array_key_exists('HTTP_HOST', $_SERVER) ?
|
||||
htmlspecialchars($_SERVER['HTTP_HOST']) :
|
||||
'localhost';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request URI
|
||||
*
|
||||
@ -154,7 +215,9 @@ class Request
|
||||
public function getRequestUri()
|
||||
{
|
||||
return array_key_exists('REQUEST_URI', $_SERVER) ?
|
||||
htmlspecialchars($_SERVER['REQUEST_URI']) : '/';
|
||||
htmlspecialchars(
|
||||
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
|
||||
) : '/';
|
||||
}
|
||||
|
||||
/**
|
||||
|
103
lib/Sjcl.php
103
lib/Sjcl.php
@ -1,103 +0,0 @@
|
||||
<?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.2.1
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
||||
/**
|
||||
* Sjcl
|
||||
*
|
||||
* Provides SJCL validation function.
|
||||
*/
|
||||
class Sjcl
|
||||
{
|
||||
/**
|
||||
* SJCL validator
|
||||
*
|
||||
* Checks if a json string is a proper SJCL encrypted message.
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $encoded JSON
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValid($encoded)
|
||||
{
|
||||
$accepted_keys = array('iv', 'v', 'iter', 'ks', 'ts', 'mode', 'adata', 'cipher', 'salt', 'ct');
|
||||
|
||||
// Make sure content is valid json
|
||||
$decoded = json_decode($encoded);
|
||||
if (is_null($decoded)) {
|
||||
return false;
|
||||
}
|
||||
$decoded = (array) $decoded;
|
||||
|
||||
// Make sure no additionnal keys were added.
|
||||
if (
|
||||
count(array_keys($decoded)) != count($accepted_keys)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure required fields are present and contain base64 data.
|
||||
foreach ($accepted_keys as $k) {
|
||||
if (!array_key_exists($k, $decoded)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure some fields are base64 data.
|
||||
if (!base64_decode($decoded['iv'], true)) {
|
||||
return false;
|
||||
}
|
||||
if (!base64_decode($decoded['salt'], true)) {
|
||||
return false;
|
||||
}
|
||||
if (!($ct = base64_decode($decoded['ct'], true))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure some fields have a reasonable size.
|
||||
if (strlen($decoded['iv']) > 24) {
|
||||
return false;
|
||||
}
|
||||
if (strlen($decoded['salt']) > 14) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure some fields contain no unsupported values.
|
||||
if (!(is_int($decoded['v']) || is_float($decoded['v'])) || (float) $decoded['v'] < 1) {
|
||||
return false;
|
||||
}
|
||||
if (!is_int($decoded['iter']) || $decoded['iter'] <= 100) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array($decoded['ks'], array(128, 192, 256), true)) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array($decoded['ts'], array(64, 96, 128), true)) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array($decoded['mode'], array('ccm', 'ocb2', 'gcm'), true)) {
|
||||
return false;
|
||||
}
|
||||
if ($decoded['cipher'] !== 'aes') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reject data if entropy is too low
|
||||
if (strlen($ct) > strlen(gzdeflate($ct))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -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.2.1
|
||||
* @version 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
@ -8,7 +8,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.0.5 beta PrivateBin 1.2.1
|
||||
* @version 0.0.5 beta PrivateBin 1.3.2
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
@ -5,5 +5,4 @@
|
||||
# directory.
|
||||
|
||||
User-agent: *
|
||||
Allow: /index.php
|
||||
Disallow: /
|
||||
|
@ -10,16 +10,16 @@ $isPage = substr($template, -5) === '-page';
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="robots" content="noindex" />
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<meta name="google" content="notranslate">
|
||||
<title><?php echo I18n::_($NAME); ?></title>
|
||||
<?php
|
||||
if (!$isDark):
|
||||
?>
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.3.5.css" />
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.4.1.css" />
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.4.1.css" />
|
||||
<?php
|
||||
if ($isDark):
|
||||
?>
|
||||
@ -41,25 +41,21 @@ if ($SYNTAXHIGHLIGHTING):
|
||||
endif;
|
||||
?>
|
||||
<noscript><link type="text/css" rel="stylesheet" href="css/noscript.css" /></noscript>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.3.1.js" integrity="sha512-+NqPlbbtM1QqiK8ZAo4Yrj2c4lNQoGv8P79DPtKzj++l5jnN39rHA/xsqn8zE9l0uSoxaCdrOgFs6yjyfbBxSg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/sjcl-1.0.7.js" integrity="sha512-J2eNenPwyfXkMVNMFz9Q54kKfYi5AA3mQWpNgtjSJzsKHtpbhUt/7bvcjGwwmzE8ZUVWMI/ndagIX1lG+SfxGA==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.4.1.js" integrity="sha512-bnIvzh6FU75ZKxp0GXLH9bewza/OIw6dLVh9ICg0gogclmYGguQJWl8U30WpbsGTqbIiAwxTsbe76DErLq5EDQ==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
if ($QRCODE):
|
||||
?>
|
||||
<script async type="text/javascript" data-cfasync="false" src="js/kjua-0.1.2.js" integrity="sha512-hmvfOhcr4J8bjQ2GuNVzfSbuulv72wgQCJpgnXc2+cCHKqvYo8pK2nc0Q4Esem2973zo1radyIMTEkt+xJlhBA==" crossorigin="anonymous"></script>
|
||||
<script async type="text/javascript" data-cfasync="false" src="js/kjua-0.6.0.js" integrity="sha512-GEEIHvphDt1NmaxzX8X1ZkBiGKXCv+Ofzwi8SMEH5wQVWqdGIvBO/fnxxKZ90RU1bVp6srS68nHIpZo6iVcG9g==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
endif;
|
||||
if ($ZEROBINCOMPATIBILITY):
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
else:
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/base64-2.4.5.js" integrity="sha512-YINE6agO8ZrYuzlrZZwQJTu0uqURJDxD4gjsfZ6mV4fP2gW5j8giNJ734iyJVTBrnF2XMiUBM/DSi7ON1V5RMQ==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/rawdeflate-0.5.js" integrity="sha512-tTdZ7qMr7tt5VQy4iCHu6/aGB12eRwbUy+AEI5rXntfsjcRfBeeqJloMsBU9FrGk1bIYLiuND/FhU42LO1bi0g==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.2.11.js" integrity="sha512-Yey/0yoaVmSbqMEyyff3DIu8kCPwpHvHf7tY1AuZ1lrX9NPCMg87PwzngMi+VNbe4ilCApmePeuKT869RTcyCQ==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/base-x-3.0.7.js" integrity="sha512-/Bi1AJIP0TtxEB+Jh6Hk809H1G7vn4iJV80qagslf0+Hm0UjUi1s3qNrn1kZULjzUYuaf6ck0ndLGJ7MxWLmgQ==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/bootstrap-3.3.7.js" integrity="sha512-iztkobsvnjKfAtTNdHkGVjAYTrrtlC7mGp/54c40wowO7LhURYl3gVzzcEqGl/qKXQltJ2HwMrdLcNUdo+N/RQ==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
@ -70,15 +66,13 @@ if ($SYNTAXHIGHLIGHTING):
|
||||
endif;
|
||||
if ($MARKDOWN):
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.8.6.js" integrity="sha512-YFg2sBCGT00I6X5KzgCLP4VqRlmPMRhkVvJS9oJKk5LxiUzzcjzV5m4fNf6mQMctLrhgS5LFKiFF3vzIuXbjAw==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.1.js" integrity="sha512-nRri7kqh3iRLdHbhtjfe8w9eAQPmt+ubH5U88UZyKbz6O9Q0q4haaXF0krOUclKmRJou/kKZYulgBHvHXPqOvg==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.7.js" integrity="sha512-VnKJHLosO8z2ojNvWk9BEKYqnhZyWK9rM90FgZUUEp/PRnUqR5OLLKE0a3BkVmn7YgB7LXRrjHgFHQYKd6DAIA==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-5xT6WHyurvC0LFESbkycBMAjhsi0KL/Xhx2oU+d0bqiJPkWK6ZAZgZ7I02oQiXaLtFSLf7UqpBo5XEePlfhH7Q==" crossorigin="anonymous"></script>
|
||||
<!--[if lt IE 10]>
|
||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-wizOnILU1zHsTf7zI5sUykY0+hYrw0b43LaJv16fudk4K7t+nx2u3jRuGdjwhMZVSLQKb0dgiJ/IpXTaOCZslQ==" crossorigin="anonymous"></script>
|
||||
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
|
||||
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
|
||||
@ -88,10 +82,17 @@ endif;
|
||||
<meta name="msapplication-config" content="browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffe57e" />
|
||||
</head>
|
||||
<body role="document"<?php
|
||||
if ($isCpct):
|
||||
?> class="navbar-spacing"<?php
|
||||
endif;
|
||||
<body role="document" data-compression="<?php echo rawurlencode($COMPRESSION); ?>"<?php
|
||||
$class = array();
|
||||
if ($isCpct) {
|
||||
$class[] = 'navbar-spacing';
|
||||
}
|
||||
if ($isDark) {
|
||||
$class[] = 'dark-theme';
|
||||
}
|
||||
if (count($class)) {
|
||||
echo ' class="', implode(' ', $class), '"';
|
||||
}
|
||||
?>>
|
||||
<div id="passwordmodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
@ -117,13 +118,41 @@ if ($QRCODE):
|
||||
<div class="modal-body">
|
||||
<div class="mx-auto" id="qrcode-display"></div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal"><?php echo I18n::_('Close') ?></button>
|
||||
<div class="row">
|
||||
<div class="btn-group col-xs-12">
|
||||
<span class="col-xs-12">
|
||||
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal"><?php echo I18n::_('Close') ?></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<div id="emailconfirmmodal" tabindex="-1" class="modal fade" aria-labelledby="emailconfirmmodalTitle" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div id="emailconfirm-display"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="btn-group col-xs-12" data-toggle="buttons">
|
||||
<span class="col-xs-12 col-md-4">
|
||||
<button id="emailconfirm-timezone-current" type="button" class="btn btn-danger btn-block" data-dismiss="modal"><?php echo I18n::_('Use Current Timezone') ?></button>
|
||||
</span>
|
||||
<span class="col-xs-12 col-md-4">
|
||||
<button id="emailconfirm-timezone-utc" type="button" class="btn btn-default btn-block" data-dismiss="modal"><?php echo I18n::_('Convert To UTC') ?></button>
|
||||
</span>
|
||||
<span class="col-xs-12 col-md-4">
|
||||
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal"><?php echo I18n::_('Close') ?></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="navbar navbar-<?php echo $isDark ? 'inverse' : 'default'; ?> navbar-<?php echo $isCpct ? 'fixed' : 'static'; ?>-top"><?php
|
||||
if ($isCpct):
|
||||
?><div class="container"><?php
|
||||
@ -170,6 +199,9 @@ endif;
|
||||
<button id="rawtextbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
|
||||
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
|
||||
</button>
|
||||
<button id="emaillink" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
|
||||
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span> <?php echo I18n::_('Email'), PHP_EOL; ?>
|
||||
</button>
|
||||
<?php
|
||||
if ($QRCODE):
|
||||
?>
|
||||
@ -212,8 +244,8 @@ endforeach;
|
||||
<?php
|
||||
if ($isCpct):
|
||||
?>
|
||||
<li id="formatter" class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Options'); ?> <span class="caret"></span></a>
|
||||
<li class="dropdown">
|
||||
<a id="formatter" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Options'); ?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li id="burnafterreadingoption" class="checkbox hidden">
|
||||
<label>
|
||||
@ -394,20 +426,6 @@ if (strlen($LANGUAGESELECTION)):
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<li>
|
||||
<?php
|
||||
if ($isPage):
|
||||
?>
|
||||
<button id="newbutton" type="button" class="reloadlink hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
|
||||
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL;
|
||||
else:
|
||||
?>
|
||||
<button id="sendbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> navbar-btn">
|
||||
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL;
|
||||
endif;
|
||||
?>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<?php
|
||||
@ -440,41 +458,60 @@ if ($FILEUPLOAD):
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<div id="status" role="alert" class="statusmessage alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>">
|
||||
<div id="status" role="alert" class="alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
|
||||
<?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
|
||||
</div>
|
||||
<div id="errormessage" role="alert" class="statusmessage<?php echo empty($ERROR) ? ' hidden' : '' ?> alert alert-danger">
|
||||
<div id="errormessage" role="alert" class="<?php echo empty($ERROR) ? 'hidden' : '' ?> alert alert-danger">
|
||||
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
|
||||
<?php echo htmlspecialchars($ERROR), PHP_EOL; ?>
|
||||
</div>
|
||||
<noscript>
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
|
||||
<div id="noscript" role="alert" class="alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)), PHP_EOL; ?>
|
||||
</div>
|
||||
</noscript>
|
||||
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger">
|
||||
<div id="oldnotice" role="alert" class="hidden alert alert-danger">
|
||||
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?>
|
||||
</div>
|
||||
<div id="ienotice" role="alert" class="hidden alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
|
||||
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
|
||||
<a href="https://www.mozilla.org/firefox/">Firefox</a>,
|
||||
<a href="https://www.opera.com/">Opera</a>,
|
||||
<a href="https://www.google.com/chrome">Chrome</a>…
|
||||
</div>
|
||||
<div id="pastesuccess" role="alert" class="hidden alert alert-success">
|
||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
|
||||
<div id="deletelink"></div>
|
||||
<div id="pastelink"></div>
|
||||
<?php
|
||||
if ($HTTPWARNING):
|
||||
?>
|
||||
<div id="httpnotice" role="alert" class="hidden alert alert-danger">
|
||||
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'), PHP_EOL; ?><br />
|
||||
<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection'); ?></span>
|
||||
</div>
|
||||
<div id="insecurecontextnotice" role="alert" class="hidden alert alert-danger">
|
||||
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.', $HTTPSLINK); ?>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<div id="pastesuccess" class="hidden">
|
||||
<div role="alert" class="alert alert-success">
|
||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
|
||||
<div id="deletelink"></div>
|
||||
<div id="pastelink"></div>
|
||||
</div>
|
||||
<?php
|
||||
if (strlen($URLSHORTENER)):
|
||||
?>
|
||||
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?>">
|
||||
<p>
|
||||
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> btn-block">
|
||||
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
|
||||
</button>
|
||||
</p>
|
||||
<div role="alert" class="alert alert-danger">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('URL shortener may expose your decrypt key in URL.'), PHP_EOL; ?>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
@ -482,6 +519,20 @@ endif;
|
||||
<ul id="editorTabs" class="nav nav-tabs hidden">
|
||||
<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
|
||||
<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
|
||||
<li role="presentation" class="pull-right">
|
||||
<?php
|
||||
if ($isPage):
|
||||
?>
|
||||
<button id="newbutton" type="button" class="reloadlink hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?>">
|
||||
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL;
|
||||
else:
|
||||
?>
|
||||
<button id="sendbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?>">
|
||||
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL;
|
||||
endif;
|
||||
?>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="container">
|
||||
@ -502,10 +553,10 @@ endif;
|
||||
</div>
|
||||
</section>
|
||||
<section class="container">
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide">
|
||||
<div id="noscript" role="alert" class="alert alert-info noscript-hide">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('Loading…'); ?><br />
|
||||
<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away">this FAQ for information to troubleshoot</a>.'); ?></span>
|
||||
<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away'); ?></span>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="container">
|
||||
@ -530,6 +581,13 @@ if ($DISCUSSION):
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<?php
|
||||
if ($FILEUPLOAD):
|
||||
?>
|
||||
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</body>
|
||||
</html>
|
50
tpl/page.php
50
tpl/page.php
@ -5,7 +5,7 @@ use PrivateBin\I18n;
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="robots" content="noindex" />
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<meta name="google" content="notranslate">
|
||||
<title><?php echo I18n::_($NAME); ?></title>
|
||||
<link type="text/css" rel="stylesheet" href="css/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
|
||||
<?php
|
||||
@ -20,25 +20,21 @@ if ($SYNTAXHIGHLIGHTING):
|
||||
endif;
|
||||
endif;
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.3.1.js" integrity="sha512-+NqPlbbtM1QqiK8ZAo4Yrj2c4lNQoGv8P79DPtKzj++l5jnN39rHA/xsqn8zE9l0uSoxaCdrOgFs6yjyfbBxSg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/sjcl-1.0.7.js" integrity="sha512-J2eNenPwyfXkMVNMFz9Q54kKfYi5AA3mQWpNgtjSJzsKHtpbhUt/7bvcjGwwmzE8ZUVWMI/ndagIX1lG+SfxGA==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.4.1.js" integrity="sha512-bnIvzh6FU75ZKxp0GXLH9bewza/OIw6dLVh9ICg0gogclmYGguQJWl8U30WpbsGTqbIiAwxTsbe76DErLq5EDQ==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
if ($QRCODE):
|
||||
?>
|
||||
<script async type="text/javascript" data-cfasync="false" src="js/kjua-0.1.2.js" integrity="sha512-hmvfOhcr4J8bjQ2GuNVzfSbuulv72wgQCJpgnXc2+cCHKqvYo8pK2nc0Q4Esem2973zo1radyIMTEkt+xJlhBA==" crossorigin="anonymous"></script>
|
||||
<script async type="text/javascript" data-cfasync="false" src="js/kjua-0.6.0.js" integrity="sha512-GEEIHvphDt1NmaxzX8X1ZkBiGKXCv+Ofzwi8SMEH5wQVWqdGIvBO/fnxxKZ90RU1bVp6srS68nHIpZo6iVcG9g==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
endif;
|
||||
if ($ZEROBINCOMPATIBILITY):
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
else:
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/base64-2.4.5.js" integrity="sha512-YINE6agO8ZrYuzlrZZwQJTu0uqURJDxD4gjsfZ6mV4fP2gW5j8giNJ734iyJVTBrnF2XMiUBM/DSi7ON1V5RMQ==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/rawdeflate-0.5.js" integrity="sha512-tTdZ7qMr7tt5VQy4iCHu6/aGB12eRwbUy+AEI5rXntfsjcRfBeeqJloMsBU9FrGk1bIYLiuND/FhU42LO1bi0g==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.2.11.js" integrity="sha512-Yey/0yoaVmSbqMEyyff3DIu8kCPwpHvHf7tY1AuZ1lrX9NPCMg87PwzngMi+VNbe4ilCApmePeuKT869RTcyCQ==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/base-x-3.0.7.js" integrity="sha512-/Bi1AJIP0TtxEB+Jh6Hk809H1G7vn4iJV80qagslf0+Hm0UjUi1s3qNrn1kZULjzUYuaf6ck0ndLGJ7MxWLmgQ==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
if ($SYNTAXHIGHLIGHTING):
|
||||
@ -48,15 +44,13 @@ if ($SYNTAXHIGHLIGHTING):
|
||||
endif;
|
||||
if ($MARKDOWN):
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.8.6.js" integrity="sha512-YFg2sBCGT00I6X5KzgCLP4VqRlmPMRhkVvJS9oJKk5LxiUzzcjzV5m4fNf6mQMctLrhgS5LFKiFF3vzIuXbjAw==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.1.js" integrity="sha512-nRri7kqh3iRLdHbhtjfe8w9eAQPmt+ubH5U88UZyKbz6O9Q0q4haaXF0krOUclKmRJou/kKZYulgBHvHXPqOvg==" crossorigin="anonymous"></script>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.7.js" integrity="sha512-VnKJHLosO8z2ojNvWk9BEKYqnhZyWK9rM90FgZUUEp/PRnUqR5OLLKE0a3BkVmn7YgB7LXRrjHgFHQYKd6DAIA==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-5xT6WHyurvC0LFESbkycBMAjhsi0KL/Xhx2oU+d0bqiJPkWK6ZAZgZ7I02oQiXaLtFSLf7UqpBo5XEePlfhH7Q==" crossorigin="anonymous"></script>
|
||||
<!--[if lt IE 10]>
|
||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.7.js" integrity="sha512-XjNEK1xwh7SJ/7FouwV4VZcGW9cMySL3SwNpXgrURLBcXXQYtZdqhGoNdEwx9vwLvFjUGDQVNgpOrTsXlSTiQg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-wizOnILU1zHsTf7zI5sUykY0+hYrw0b43LaJv16fudk4K7t+nx2u3jRuGdjwhMZVSLQKb0dgiJ/IpXTaOCZslQ==" crossorigin="anonymous"></script>
|
||||
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
|
||||
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
|
||||
@ -66,7 +60,7 @@ endif;
|
||||
<meta name="msapplication-config" content="browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffe57e" />
|
||||
</head>
|
||||
<body>
|
||||
<body data-compression="<?php echo rawurlencode($COMPRESSION); ?>">
|
||||
<header>
|
||||
<div id="aboutbox">
|
||||
<?php echo I18n::_('%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://privatebin.info/">project page</a>.', I18n::_($NAME)); ?><br />
|
||||
@ -81,12 +75,24 @@ endif;
|
||||
<h2 class="title"><?php echo I18n::_('Because ignorance is bliss'); ?></h2><br />
|
||||
<h3 class="title"><?php echo $VERSION; ?></h3>
|
||||
<noscript><div id="noscript" class="nonworking"><?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)); ?></div></noscript>
|
||||
<div id="oldienotice" class="nonworking"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)); ?></div>
|
||||
<div id="ienotice"><?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
|
||||
<div id="oldnotice" class="nonworking hidden"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?>
|
||||
<a href="https://www.mozilla.org/firefox/">Firefox</a>,
|
||||
<a href="https://www.opera.com/">Opera</a>,
|
||||
<a href="https://www.google.com/chrome">Chrome</a>…
|
||||
</div>
|
||||
<?php
|
||||
if ($HTTPWARNING):
|
||||
?>
|
||||
<div id="httpnotice" class="errorMessage hidden">
|
||||
<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'); ?>
|
||||
<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection'); ?></span>
|
||||
</div>
|
||||
<div id="insecurecontextnotice" class="errorMessage hidden">
|
||||
<?php echo I18n::_('Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.', $HTTPSLINK); ?>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</header>
|
||||
<section>
|
||||
<article>
|
||||
@ -99,6 +105,7 @@ endif;
|
||||
<button id="sendbutton" class="hidden"><img src="img/icon_send.png" width="18" height="15" alt="" /><?php echo I18n::_('Send'); ?></button>
|
||||
<button id="clonebutton" class="hidden"><img src="img/icon_clone.png" width="15" height="17" alt="" /><?php echo I18n::_('Clone'); ?></button>
|
||||
<button id="rawtextbutton" class="hidden"><img src="img/icon_raw.png" width="15" height="15" alt="" /><?php echo I18n::_('Raw text'); ?></button>
|
||||
<button id="emaillink" class="hidden"><img src="img/icon_email.png" width="15" height="15" alt="" /><?php echo I18n::_('Email'); ?></button>
|
||||
<?php
|
||||
if ($QRCODE):
|
||||
?>
|
||||
@ -248,6 +255,13 @@ if ($DISCUSSION):
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<?php
|
||||
if ($FILEUPLOAD):
|
||||
?>
|
||||
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<section class="container">
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">
|
||||
|
3
vendor/composer/autoload_classmap.php
vendored
3
vendor/composer/autoload_classmap.php
vendored
@ -10,6 +10,7 @@ return array(
|
||||
'Identicon\\Generator\\GdGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/GdGenerator.php',
|
||||
'Identicon\\Generator\\GeneratorInterface' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php',
|
||||
'Identicon\\Generator\\ImageMagickGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php',
|
||||
'Identicon\\Generator\\SvgGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/SvgGenerator.php',
|
||||
'Identicon\\Identicon' => $vendorDir . '/yzalis/identicon/src/Identicon/Identicon.php',
|
||||
'PrivateBin\\Configuration' => $baseDir . '/lib/Configuration.php',
|
||||
'PrivateBin\\Controller' => $baseDir . '/lib/Controller.php',
|
||||
@ -17,6 +18,7 @@ return array(
|
||||
'PrivateBin\\Data\\Database' => $baseDir . '/lib/Data/Database.php',
|
||||
'PrivateBin\\Data\\Filesystem' => $baseDir . '/lib/Data/Filesystem.php',
|
||||
'PrivateBin\\Filter' => $baseDir . '/lib/Filter.php',
|
||||
'PrivateBin\\FormatV2' => $baseDir . '/lib/FormatV2.php',
|
||||
'PrivateBin\\I18n' => $baseDir . '/lib/I18n.php',
|
||||
'PrivateBin\\Json' => $baseDir . '/lib/Json.php',
|
||||
'PrivateBin\\Model' => $baseDir . '/lib/Model.php',
|
||||
@ -29,7 +31,6 @@ return array(
|
||||
'PrivateBin\\Persistence\\ServerSalt' => $baseDir . '/lib/Persistence/ServerSalt.php',
|
||||
'PrivateBin\\Persistence\\TrafficLimiter' => $baseDir . '/lib/Persistence/TrafficLimiter.php',
|
||||
'PrivateBin\\Request' => $baseDir . '/lib/Request.php',
|
||||
'PrivateBin\\Sjcl' => $baseDir . '/lib/Sjcl.php',
|
||||
'PrivateBin\\View' => $baseDir . '/lib/View.php',
|
||||
'PrivateBin\\Vizhash16x16' => $baseDir . '/lib/Vizhash16x16.php',
|
||||
);
|
||||
|
1
vendor/composer/autoload_namespaces.php
vendored
1
vendor/composer/autoload_namespaces.php
vendored
@ -6,5 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Identicon' => array($vendorDir . '/yzalis/identicon/src'),
|
||||
);
|
||||
|
1
vendor/composer/autoload_psr4.php
vendored
1
vendor/composer/autoload_psr4.php
vendored
@ -7,4 +7,5 @@ $baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'PrivateBin\\' => array($baseDir . '/lib'),
|
||||
'Identicon\\' => array($vendorDir . '/yzalis/identicon/src/Identicon'),
|
||||
);
|
||||
|
18
vendor/composer/autoload_static.php
vendored
18
vendor/composer/autoload_static.php
vendored
@ -15,6 +15,10 @@ class ComposerStaticInitDontChange
|
||||
array (
|
||||
'PrivateBin\\' => 11,
|
||||
),
|
||||
'I' =>
|
||||
array (
|
||||
'Identicon\\' => 10,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
@ -22,15 +26,9 @@ class ComposerStaticInitDontChange
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/lib',
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'I' =>
|
||||
'Identicon\\' =>
|
||||
array (
|
||||
'Identicon' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/yzalis/identicon/src',
|
||||
),
|
||||
0 => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon',
|
||||
),
|
||||
);
|
||||
|
||||
@ -39,6 +37,7 @@ class ComposerStaticInitDontChange
|
||||
'Identicon\\Generator\\GdGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/GdGenerator.php',
|
||||
'Identicon\\Generator\\GeneratorInterface' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php',
|
||||
'Identicon\\Generator\\ImageMagickGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php',
|
||||
'Identicon\\Generator\\SvgGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/SvgGenerator.php',
|
||||
'Identicon\\Identicon' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Identicon.php',
|
||||
'PrivateBin\\Configuration' => __DIR__ . '/../..' . '/lib/Configuration.php',
|
||||
'PrivateBin\\Controller' => __DIR__ . '/../..' . '/lib/Controller.php',
|
||||
@ -46,6 +45,7 @@ class ComposerStaticInitDontChange
|
||||
'PrivateBin\\Data\\Database' => __DIR__ . '/../..' . '/lib/Data/Database.php',
|
||||
'PrivateBin\\Data\\Filesystem' => __DIR__ . '/../..' . '/lib/Data/Filesystem.php',
|
||||
'PrivateBin\\Filter' => __DIR__ . '/../..' . '/lib/Filter.php',
|
||||
'PrivateBin\\FormatV2' => __DIR__ . '/../..' . '/lib/FormatV2.php',
|
||||
'PrivateBin\\I18n' => __DIR__ . '/../..' . '/lib/I18n.php',
|
||||
'PrivateBin\\Json' => __DIR__ . '/../..' . '/lib/Json.php',
|
||||
'PrivateBin\\Model' => __DIR__ . '/../..' . '/lib/Model.php',
|
||||
@ -58,7 +58,6 @@ class ComposerStaticInitDontChange
|
||||
'PrivateBin\\Persistence\\ServerSalt' => __DIR__ . '/../..' . '/lib/Persistence/ServerSalt.php',
|
||||
'PrivateBin\\Persistence\\TrafficLimiter' => __DIR__ . '/../..' . '/lib/Persistence/TrafficLimiter.php',
|
||||
'PrivateBin\\Request' => __DIR__ . '/../..' . '/lib/Request.php',
|
||||
'PrivateBin\\Sjcl' => __DIR__ . '/../..' . '/lib/Sjcl.php',
|
||||
'PrivateBin\\View' => __DIR__ . '/../..' . '/lib/View.php',
|
||||
'PrivateBin\\Vizhash16x16' => __DIR__ . '/../..' . '/lib/Vizhash16x16.php',
|
||||
);
|
||||
@ -68,7 +67,6 @@ class ComposerStaticInitDontChange
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitDontChange::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitDontChange::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInitDontChange::$prefixesPsr0;
|
||||
$loader->classMap = ComposerStaticInitDontChange::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
|
@ -28,8 +28,9 @@
|
||||
|
||||
if (!is_callable('RandomCompat_strlen')) {
|
||||
if (
|
||||
defined('MB_OVERLOAD_STRING') &&
|
||||
ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING
|
||||
defined('MB_OVERLOAD_STRING')
|
||||
&&
|
||||
((int) ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING
|
||||
) {
|
||||
/**
|
||||
* strlen() implementation that isn't brittle to mbstring.func_overload
|
||||
@ -82,8 +83,8 @@ if (!is_callable('RandomCompat_substr')) {
|
||||
|
||||
if (
|
||||
defined('MB_OVERLOAD_STRING')
|
||||
&&
|
||||
ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING
|
||||
&&
|
||||
((int) ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING
|
||||
) {
|
||||
/**
|
||||
* substr() implementation that isn't brittle to mbstring.func_overload
|
||||
@ -93,7 +94,7 @@ if (!is_callable('RandomCompat_substr')) {
|
||||
*
|
||||
* @param string $binary_string
|
||||
* @param int $start
|
||||
* @param int $length (optional)
|
||||
* @param int|null $length (optional)
|
||||
*
|
||||
* @throws TypeError
|
||||
*
|
||||
@ -118,6 +119,7 @@ if (!is_callable('RandomCompat_substr')) {
|
||||
* mb_substr($str, 0, NULL, '8bit') returns an empty string on
|
||||
* PHP 5.3, so we have to find the length ourselves.
|
||||
*/
|
||||
/** @var int $length */
|
||||
$length = RandomCompat_strlen($binary_string) - $start;
|
||||
} elseif (!is_int($length)) {
|
||||
throw new TypeError(
|
||||
@ -133,7 +135,12 @@ if (!is_callable('RandomCompat_substr')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string) mb_substr($binary_string, $start, $length, '8bit');
|
||||
return (string) mb_substr(
|
||||
(string) $binary_string,
|
||||
(int) $start,
|
||||
(int) $length,
|
||||
'8bit'
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -145,7 +152,7 @@ if (!is_callable('RandomCompat_substr')) {
|
||||
*
|
||||
* @param string $binary_string
|
||||
* @param int $start
|
||||
* @param int $length (optional)
|
||||
* @param int|null $length (optional)
|
||||
*
|
||||
* @throws TypeError
|
||||
*
|
||||
@ -172,10 +179,17 @@ if (!is_callable('RandomCompat_substr')) {
|
||||
);
|
||||
}
|
||||
|
||||
return (string) substr($binary_string, $start, $length);
|
||||
return (string) substr(
|
||||
(string )$binary_string,
|
||||
(int) $start,
|
||||
(int) $length
|
||||
);
|
||||
}
|
||||
|
||||
return (string) substr($binary_string, $start);
|
||||
return (string) substr(
|
||||
(string) $binary_string,
|
||||
(int) $start
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,14 +50,16 @@ if (!is_callable('RandomCompat_intval')) {
|
||||
if (is_int($number) || is_float($number)) {
|
||||
$number += 0;
|
||||
} elseif (is_numeric($number)) {
|
||||
/** @psalm-suppress InvalidOperand */
|
||||
$number += 0;
|
||||
}
|
||||
/** @var int|float $number */
|
||||
|
||||
if (
|
||||
is_float($number)
|
||||
&&
|
||||
&&
|
||||
$number > ~PHP_INT_MAX
|
||||
&&
|
||||
&&
|
||||
$number < PHP_INT_MAX
|
||||
) {
|
||||
$number = (int) $number;
|
||||
|
@ -3,8 +3,8 @@
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* @version 2.0.15
|
||||
* @released 2018-06-08
|
||||
* @version 2.0.17
|
||||
* @released 2018-07-04
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
@ -203,7 +203,6 @@ if (!is_callable('random_bytes')) {
|
||||
* and hope the developer won't let it fail silently.
|
||||
*
|
||||
* @param mixed $length
|
||||
* @psalm-suppress MissingReturnType
|
||||
* @psalm-suppress InvalidReturnType
|
||||
* @throws Exception
|
||||
* @return string
|
||||
|
@ -41,6 +41,7 @@ if (!is_callable('random_bytes')) {
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
@ -54,12 +55,14 @@ if (!is_callable('random_bytes')) {
|
||||
);
|
||||
}
|
||||
|
||||
/** @var string $buf */
|
||||
$buf = '';
|
||||
if (!class_exists('COM')) {
|
||||
throw new Error(
|
||||
'COM does not exist'
|
||||
);
|
||||
}
|
||||
/** @var COM $util */
|
||||
$util = new COM('CAPICOM.Utilities.1');
|
||||
$execCount = 0;
|
||||
|
||||
@ -68,12 +71,12 @@ if (!is_callable('random_bytes')) {
|
||||
* get N bytes of random data, then CAPICOM has failed us.
|
||||
*/
|
||||
do {
|
||||
$buf .= base64_decode($util->GetRandom($bytes, 0));
|
||||
$buf .= base64_decode((string) $util->GetRandom($bytes, 0));
|
||||
if (RandomCompat_strlen($buf) >= $bytes) {
|
||||
/**
|
||||
* Return our random entropy buffer here:
|
||||
*/
|
||||
return RandomCompat_substr($buf, 0, $bytes);
|
||||
return (string) RandomCompat_substr($buf, 0, $bytes);
|
||||
}
|
||||
++$execCount;
|
||||
} while ($execCount < $bytes);
|
||||
|
@ -36,6 +36,7 @@ if (!is_callable('random_bytes')) {
|
||||
* random numbers in accordance with best practices
|
||||
*
|
||||
* Why we use /dev/urandom and not /dev/random
|
||||
* @ref https://www.2uo.de/myths-about-urandom
|
||||
* @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers
|
||||
*
|
||||
* @param int $bytes
|
||||
@ -46,25 +47,47 @@ if (!is_callable('random_bytes')) {
|
||||
*/
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
/** @var resource $fp */
|
||||
static $fp = null;
|
||||
|
||||
/**
|
||||
* This block should only be run once
|
||||
*/
|
||||
if (empty($fp)) {
|
||||
/**
|
||||
* We use /dev/urandom if it is a char device.
|
||||
* We never fall back to /dev/random
|
||||
* We don't want to ever read C:\dev\random, only /dev/urandom on
|
||||
* Unix-like operating systems. While we guard against this
|
||||
* condition in random.php, it doesn't hurt to be defensive in depth
|
||||
* here.
|
||||
*
|
||||
* To that end, we only try to open /dev/urandom if we're on a Unix-
|
||||
* like operating system (which means the directory separator is set
|
||||
* to "/" not "\".
|
||||
*/
|
||||
$fp = fopen('/dev/urandom', 'rb');
|
||||
if (!empty($fp)) {
|
||||
$st = fstat($fp);
|
||||
if (($st['mode'] & 0170000) !== 020000) {
|
||||
fclose($fp);
|
||||
$fp = false;
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
if (!is_readable('/dev/urandom')) {
|
||||
throw new Exception(
|
||||
'Environment misconfiguration: ' .
|
||||
'/dev/urandom cannot be read.'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* We use /dev/urandom if it is a char device.
|
||||
* We never fall back to /dev/random
|
||||
*/
|
||||
/** @var resource|bool $fp */
|
||||
$fp = fopen('/dev/urandom', 'rb');
|
||||
if (is_resource($fp)) {
|
||||
/** @var array<string, int> $st */
|
||||
$st = fstat($fp);
|
||||
if (($st['mode'] & 0170000) !== 020000) {
|
||||
fclose($fp);
|
||||
$fp = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($fp)) {
|
||||
if (is_resource($fp)) {
|
||||
/**
|
||||
* stream_set_read_buffer() does not exist in HHVM
|
||||
*
|
||||
@ -83,6 +106,7 @@ if (!is_callable('random_bytes')) {
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
@ -103,7 +127,7 @@ if (!is_callable('random_bytes')) {
|
||||
* if (empty($fp)) line is logic that should only be run once per
|
||||
* page load.
|
||||
*/
|
||||
if (!empty($fp)) {
|
||||
if (is_resource($fp)) {
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
@ -123,29 +147,28 @@ if (!is_callable('random_bytes')) {
|
||||
*/
|
||||
$read = fread($fp, $remaining);
|
||||
if (!is_string($read)) {
|
||||
if ($read === false) {
|
||||
/**
|
||||
* We cannot safely read from the file. Exit the
|
||||
* do-while loop and trigger the exception condition
|
||||
*
|
||||
* @var string|bool
|
||||
*/
|
||||
$buf = false;
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* We cannot safely read from the file. Exit the
|
||||
* do-while loop and trigger the exception condition
|
||||
*
|
||||
* @var string|bool
|
||||
*/
|
||||
$buf = false;
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* Decrease the number of bytes returned from remaining
|
||||
*/
|
||||
$remaining -= RandomCompat_strlen($read);
|
||||
/**
|
||||
* @var string|bool
|
||||
* @var string $buf
|
||||
*/
|
||||
$buf = $buf . $read;
|
||||
$buf .= $read;
|
||||
} while ($remaining > 0);
|
||||
|
||||
/**
|
||||
* Is our result valid?
|
||||
* @var string|bool $buf
|
||||
*/
|
||||
if (is_string($buf)) {
|
||||
if (RandomCompat_strlen($buf) === $bytes) {
|
||||
|
@ -43,6 +43,7 @@ if (!is_callable('random_bytes')) {
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
@ -60,6 +61,7 @@ if (!is_callable('random_bytes')) {
|
||||
* \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
|
||||
* generated in one invocation.
|
||||
*/
|
||||
/** @var string|bool $buf */
|
||||
if ($bytes > 2147483647) {
|
||||
$buf = '';
|
||||
for ($i = 0; $i < $bytes; $i += 1073741824) {
|
||||
@ -69,10 +71,11 @@ if (!is_callable('random_bytes')) {
|
||||
$buf .= \Sodium\randombytes_buf($n);
|
||||
}
|
||||
} else {
|
||||
/** @var string|bool $buf */
|
||||
$buf = \Sodium\randombytes_buf($bytes);
|
||||
}
|
||||
|
||||
if ($buf !== false) {
|
||||
if (is_string($buf)) {
|
||||
if (RandomCompat_strlen($buf) === $bytes) {
|
||||
return $buf;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ if (!is_callable('random_bytes')) {
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
|
@ -42,6 +42,7 @@ if (!is_callable('random_bytes')) {
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
@ -55,10 +56,11 @@ if (!is_callable('random_bytes')) {
|
||||
);
|
||||
}
|
||||
|
||||
$buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
|
||||
/** @var string|bool $buf */
|
||||
$buf = @mcrypt_create_iv((int) $bytes, (int) MCRYPT_DEV_URANDOM);
|
||||
if (
|
||||
$buf !== false
|
||||
&&
|
||||
is_string($buf)
|
||||
&&
|
||||
RandomCompat_strlen($buf) === $bytes
|
||||
) {
|
||||
/**
|
||||
|
@ -51,6 +51,7 @@ if (!is_callable('random_int')) {
|
||||
*/
|
||||
|
||||
try {
|
||||
/** @var int $min */
|
||||
$min = RandomCompat_intval($min);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
@ -59,6 +60,7 @@ if (!is_callable('random_int')) {
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var int $max */
|
||||
$max = RandomCompat_intval($max);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
@ -90,11 +92,18 @@ if (!is_callable('random_int')) {
|
||||
* so we can minimize the number of discards
|
||||
*/
|
||||
$attempts = $bits = $bytes = $mask = $valueShift = 0;
|
||||
/** @var int $attempts */
|
||||
/** @var int $bits */
|
||||
/** @var int $bytes */
|
||||
/** @var int $mask */
|
||||
/** @var int $valueShift */
|
||||
|
||||
/**
|
||||
* At this point, $range is a positive number greater than 0. It might
|
||||
* overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
|
||||
* a float and we will lose some precision.
|
||||
*
|
||||
* @var int|float $range
|
||||
*/
|
||||
$range = $max - $min;
|
||||
|
||||
@ -115,6 +124,7 @@ if (!is_callable('random_int')) {
|
||||
* @ref http://3v4l.org/XX9r5 (64-bit)
|
||||
*/
|
||||
$bytes = PHP_INT_SIZE;
|
||||
/** @var int $mask */
|
||||
$mask = ~0;
|
||||
|
||||
} else {
|
||||
@ -129,16 +139,19 @@ if (!is_callable('random_int')) {
|
||||
}
|
||||
++$bits;
|
||||
$range >>= 1;
|
||||
/** @var int $mask */
|
||||
$mask = $mask << 1 | 1;
|
||||
}
|
||||
$valueShift = $min;
|
||||
}
|
||||
|
||||
/** @var int $val */
|
||||
$val = 0;
|
||||
/**
|
||||
* Now that we have our parameters set up, let's begin generating
|
||||
* random integers until one falls between $min and $max
|
||||
*/
|
||||
/** @psalm-suppress RedundantCondition */
|
||||
do {
|
||||
/**
|
||||
* The rejection probability is at most 0.5, so this corresponds
|
||||
@ -169,6 +182,7 @@ if (!is_callable('random_int')) {
|
||||
for ($i = 0; $i < $bytes; ++$i) {
|
||||
$val |= ord($randomByteString[$i]) << ($i * 8);
|
||||
}
|
||||
/** @var int $val */
|
||||
|
||||
/**
|
||||
* Apply mask
|
||||
|
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
$dist = dirname(__DIR__).'/dist';
|
||||
if (!is_dir($dist)) {
|
||||
mkdir($dist, 0755);
|
||||
}
|
||||
if (file_exists($dist.'/random_compat.phar')) {
|
||||
unlink($dist.'/random_compat.phar');
|
||||
}
|
||||
$phar = new Phar(
|
||||
$dist.'/random_compat.phar',
|
||||
FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME,
|
||||
'random_compat.phar'
|
||||
);
|
||||
rename(
|
||||
dirname(__DIR__).'/lib/random.php',
|
||||
dirname(__DIR__).'/lib/index.php'
|
||||
);
|
||||
$phar->buildFromDirectory(dirname(__DIR__).'/lib');
|
||||
rename(
|
||||
dirname(__DIR__).'/lib/index.php',
|
||||
dirname(__DIR__).'/lib/random.php'
|
||||
);
|
||||
|
||||
/**
|
||||
* If we pass an (optional) path to a private key as a second argument, we will
|
||||
* sign the Phar with OpenSSL.
|
||||
*
|
||||
* If you leave this out, it will produce an unsigned .phar!
|
||||
*/
|
||||
if ($argc > 1) {
|
||||
if (!@is_readable($argv[1])) {
|
||||
echo 'Could not read the private key file:', $argv[1], "\n";
|
||||
exit(255);
|
||||
}
|
||||
$pkeyFile = file_get_contents($argv[1]);
|
||||
|
||||
$private = openssl_get_privatekey($pkeyFile);
|
||||
if ($private !== false) {
|
||||
$pkey = '';
|
||||
openssl_pkey_export($private, $pkey);
|
||||
$phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
|
||||
|
||||
/**
|
||||
* Save the corresponding public key to the file
|
||||
*/
|
||||
if (!@is_readable($dist.'/random_compat.phar.pubkey')) {
|
||||
$details = openssl_pkey_get_details($private);
|
||||
file_put_contents(
|
||||
$dist.'/random_compat.phar.pubkey',
|
||||
$details['key']
|
||||
);
|
||||
}
|
||||
} else {
|
||||
echo 'An error occurred reading the private key from OpenSSL.', "\n";
|
||||
exit(255);
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once 'lib/byte_safe_strings.php';
|
||||
require_once 'lib/cast_to_int.php';
|
||||
require_once 'lib/error_polyfill.php';
|
||||
require_once 'other/ide_stubs/libsodium.php';
|
||||
require_once 'lib/random.php';
|
||||
|
||||
$int = random_int(0, 65536);
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Identicon\Generator;
|
||||
|
||||
use Identicon\Generator\GeneratorInterface;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @author Benjamin Laugueux <benjamin@yzalis.com>
|
||||
@ -15,22 +15,22 @@ class BaseGenerator
|
||||
protected $generatedImage;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
* @var array
|
||||
*/
|
||||
protected $color;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
* @var array
|
||||
*/
|
||||
protected $backgroundColor;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*/
|
||||
protected $size;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
* @var int
|
||||
*/
|
||||
protected $pixelRatio;
|
||||
|
||||
@ -42,14 +42,14 @@ class BaseGenerator
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $arrayOfSquare = array();
|
||||
private $arrayOfSquare = [];
|
||||
|
||||
/**
|
||||
* Set the image color
|
||||
* Set the image color.
|
||||
*
|
||||
* @param string|array $color The color in hexa (6 chars) or rgb array
|
||||
* @param string|array $color The color in hexa (3 or 6 chars) or rgb array
|
||||
*
|
||||
* @return this
|
||||
* @return $this
|
||||
*/
|
||||
public function setColor($color)
|
||||
{
|
||||
@ -63,11 +63,11 @@ class BaseGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image background color
|
||||
* Set the image background color.
|
||||
*
|
||||
* @param string|array $backgroundColor The color in hexa (6 chars) or rgb array
|
||||
* @param string|array $backgroundColor The color in hexa (3 or 6 chars) or rgb array
|
||||
*
|
||||
* @return this
|
||||
* @return $this
|
||||
*/
|
||||
public function setBackgroundColor($backgroundColor)
|
||||
{
|
||||
@ -80,27 +80,32 @@ class BaseGenerator
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $color
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function convertColor($color)
|
||||
{
|
||||
$convertedColor = array();
|
||||
if (is_array($color)) {
|
||||
$convertedColor[0] = $color[0];
|
||||
$convertedColor[1] = $color[1];
|
||||
$convertedColor[2] = $color[2];
|
||||
} else {
|
||||
if (false !== strpos($color, '#')) {
|
||||
$color = substr($color, 1);
|
||||
}
|
||||
$convertedColor[0] = hexdec(substr($color, 0, 2));
|
||||
$convertedColor[1] = hexdec(substr($color, 2, 2));
|
||||
$convertedColor[2] = hexdec(substr($color, 4, 2));
|
||||
return $color;
|
||||
}
|
||||
|
||||
return $convertedColor;
|
||||
if (preg_match('/^#?([a-z\d])([a-z\d])([a-z\d])$/i', $color, $matches)) {
|
||||
$color = $matches[1].$matches[1];
|
||||
$color .= $matches[2].$matches[2];
|
||||
$color .= $matches[3].$matches[3];
|
||||
}
|
||||
|
||||
preg_match('/#?([a-z\d]{2})([a-z\d]{2})([a-z\d]{2})$/i', $color, $matches);
|
||||
|
||||
return array_map(function ($value) {
|
||||
return hexdec($value);
|
||||
}, array_slice($matches, 1, 3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the color
|
||||
* Get the color.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@ -109,9 +114,8 @@ class BaseGenerator
|
||||
return $this->color;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the background color
|
||||
* Get the background color.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@ -121,48 +125,51 @@ class BaseGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the hash into an multidimensionnal array of boolean
|
||||
* Convert the hash into an multidimensional array of boolean.
|
||||
*
|
||||
* @return this
|
||||
* @return $this
|
||||
*/
|
||||
private function convertHashToArrayOfBoolean()
|
||||
{
|
||||
preg_match_all('/(\w)(\w)/', $this->hash, $chars);
|
||||
|
||||
foreach ($chars[1] as $i => $char) {
|
||||
if ($i % 3 == 0) {
|
||||
$this->arrayOfSquare[$i/3][0] = $this->convertHexaToBoolean($char);
|
||||
$this->arrayOfSquare[$i/3][4] = $this->convertHexaToBoolean($char);
|
||||
} elseif ($i % 3 == 1) {
|
||||
$this->arrayOfSquare[$i/3][1] = $this->convertHexaToBoolean($char);
|
||||
$this->arrayOfSquare[$i/3][3] = $this->convertHexaToBoolean($char);
|
||||
} else {
|
||||
$this->arrayOfSquare[$i/3][2] = $this->convertHexaToBoolean($char);
|
||||
$index = (int) ($i / 3);
|
||||
$data = $this->convertHexaToBoolean($char);
|
||||
|
||||
$items = [
|
||||
0 => [0, 4],
|
||||
1 => [1, 3],
|
||||
2 => [2],
|
||||
];
|
||||
|
||||
foreach ($items[$i % 3] as $item) {
|
||||
$this->arrayOfSquare[$index][$item] = $data;
|
||||
}
|
||||
ksort($this->arrayOfSquare[$i/3]);
|
||||
|
||||
ksort($this->arrayOfSquare[$index]);
|
||||
}
|
||||
|
||||
$this->color[0] = hexdec(array_pop($chars[1]))*16;
|
||||
$this->color[1] = hexdec(array_pop($chars[1]))*16;
|
||||
$this->color[2] = hexdec(array_pop($chars[1]))*16;
|
||||
$this->color = array_map(function ($data) {
|
||||
return hexdec($data) * 16;
|
||||
}, array_reverse($chars[1]));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an heaxecimal number into a boolean
|
||||
* Convert an hexadecimal number into a boolean.
|
||||
*
|
||||
* @param string $hexa
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
private function convertHexaToBoolean($hexa)
|
||||
{
|
||||
return (bool) intval(round(hexdec($hexa)/10));
|
||||
return (bool) round(hexdec($hexa) / 10);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getArrayOfSquare()
|
||||
@ -171,7 +178,7 @@ class BaseGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the identicon string hash
|
||||
* Get the identicon string hash.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -181,16 +188,18 @@ class BaseGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a hash fron the original string
|
||||
* Generate a hash from the original string.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return this
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setString($string)
|
||||
{
|
||||
if (null === $string) {
|
||||
throw new \Exception('The string cannot be null.');
|
||||
throw new Exception('The string cannot be null.');
|
||||
}
|
||||
|
||||
$this->hash = md5($string);
|
||||
@ -201,11 +210,11 @@ class BaseGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image size
|
||||
* Set the image size.
|
||||
*
|
||||
* @param integer $size
|
||||
* @param int $size
|
||||
*
|
||||
* @return this
|
||||
* @return $this
|
||||
*/
|
||||
public function setSize($size)
|
||||
{
|
||||
@ -214,15 +223,15 @@ class BaseGenerator
|
||||
}
|
||||
|
||||
$this->size = $size;
|
||||
$this->pixelRatio = round($size / 5);
|
||||
$this->pixelRatio = (int) round($size / 5);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image size
|
||||
* Get the image size.
|
||||
*
|
||||
* @return integer
|
||||
* @return int
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
@ -230,9 +239,9 @@ class BaseGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pixel ratio
|
||||
* Get the pixel ratio.
|
||||
*
|
||||
* @return array
|
||||
* @return int
|
||||
*/
|
||||
public function getPixelRatio()
|
||||
{
|
||||
|
@ -2,20 +2,34 @@
|
||||
|
||||
namespace Identicon\Generator;
|
||||
|
||||
use Identicon\Generator\GeneratorInterface;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @author Benjamin Laugueux <benjamin@yzalis.com>
|
||||
*/
|
||||
class GdGenerator extends BaseGenerator implements GeneratorInterface
|
||||
{
|
||||
/**
|
||||
* GdGenerator constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('gd')) {
|
||||
throw new \Exception('GD does not appear to be avaliable in your PHP installation. Please try another generator');
|
||||
if (!extension_loaded('gd') && !extension_loaded('ext-gd')) {
|
||||
throw new Exception('GD does not appear to be available in your PHP installation. Please try another generator');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMimeType()
|
||||
{
|
||||
return 'image/png';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
private function generateImage()
|
||||
{
|
||||
// prepare image
|
||||
@ -30,7 +44,7 @@ class GdGenerator extends BaseGenerator implements GeneratorInterface
|
||||
imagefill($this->generatedImage, 0, 0, $background);
|
||||
}
|
||||
|
||||
// prepage color
|
||||
// prepare color
|
||||
$rgbColor = $this->getColor();
|
||||
$gdColor = imagecolorallocate($this->generatedImage, $rgbColor[0], $rgbColor[1], $rgbColor[2]);
|
||||
|
||||
@ -47,7 +61,7 @@ class GdGenerator extends BaseGenerator implements GeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null)
|
||||
{
|
||||
@ -60,7 +74,7 @@ class GdGenerator extends BaseGenerator implements GeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getImageResource($string, $size = null, $color = null, $backgroundColor = null)
|
||||
{
|
||||
|
@ -8,26 +8,36 @@ namespace Identicon\Generator;
|
||||
interface GeneratorInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $string
|
||||
* @param integer $size
|
||||
* @param array|string $color
|
||||
* @param array|string $backgroundColor
|
||||
* @param string $string
|
||||
* @param int $size
|
||||
* @param array|string $color
|
||||
* @param array|string $backgroundColor
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null);
|
||||
public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null);
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $string
|
||||
* @param integer $size
|
||||
* @param array|string $color
|
||||
* @param array|string $backgroundColor
|
||||
* @param string $string
|
||||
* @param int $size
|
||||
* @param array|string $color
|
||||
* @param array|string $backgroundColor
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getImageResource($string, $size = null, $color = null, $backgroundColor = null);
|
||||
public function getImageResource($string, $size = null, $color = null, $backgroundColor = null);
|
||||
|
||||
/**
|
||||
* Return the mime-type of this identicon.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMimeType();
|
||||
|
||||
/**
|
||||
* Return the color of the created identicon.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColor();
|
||||
}
|
||||
|
@ -2,20 +2,38 @@
|
||||
|
||||
namespace Identicon\Generator;
|
||||
|
||||
use Identicon\Generator\GeneratorInterface;
|
||||
use Exception;
|
||||
use ImagickDraw;
|
||||
use ImagickPixel;
|
||||
|
||||
/**
|
||||
* @author Francis Chuang <francis.chuang@gmail.com>
|
||||
*/
|
||||
class ImageMagickGenerator extends BaseGenerator implements GeneratorInterface
|
||||
{
|
||||
/**
|
||||
* ImageMagickGenerator constructor.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('imagick')) {
|
||||
throw new \Exception('ImageMagick does not appear to be avaliable in your PHP installation. Please try another generator');
|
||||
throw new Exception('ImageMagick does not appear to be avaliable in your PHP installation. Please try another generator');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMimeType()
|
||||
{
|
||||
return 'image/png';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
private function generateImage()
|
||||
{
|
||||
$this->generatedImage = new \Imagick();
|
||||
@ -24,23 +42,23 @@ class ImageMagickGenerator extends BaseGenerator implements GeneratorInterface
|
||||
if (null === $rgbBackgroundColor) {
|
||||
$background = 'none';
|
||||
} else {
|
||||
$background = new \ImagickPixel("rgb($rgbBackgroundColor[0],$rgbBackgroundColor[1],$rgbBackgroundColor[2])");
|
||||
$background = new ImagickPixel("rgb($rgbBackgroundColor[0],$rgbBackgroundColor[1],$rgbBackgroundColor[2])");
|
||||
}
|
||||
|
||||
$this->generatedImage->newImage($this->pixelRatio * 5, $this->pixelRatio * 5, $background, 'png');
|
||||
|
||||
// prepare color
|
||||
$rgbColor = $this->getColor();
|
||||
$color = new \ImagickPixel("rgb($rgbColor[0],$rgbColor[1],$rgbColor[2])");
|
||||
$color = new ImagickPixel("rgb($rgbColor[0],$rgbColor[1],$rgbColor[2])");
|
||||
|
||||
$draw = new \ImagickDraw();
|
||||
$draw = new ImagickDraw();
|
||||
$draw->setFillColor($color);
|
||||
|
||||
// draw the content
|
||||
foreach ($this->getArrayOfSquare() as $lineKey => $lineValue) {
|
||||
foreach ($lineValue as $colKey => $colValue) {
|
||||
if (true === $colValue) {
|
||||
$draw->rectangle( $colKey * $this->pixelRatio, $lineKey * $this->pixelRatio, ($colKey + 1) * $this->pixelRatio, ($lineKey + 1) * $this->pixelRatio);
|
||||
$draw->rectangle($colKey * $this->pixelRatio, $lineKey * $this->pixelRatio, ($colKey + 1) * $this->pixelRatio, ($lineKey + 1) * $this->pixelRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,7 +69,7 @@ class ImageMagickGenerator extends BaseGenerator implements GeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null)
|
||||
{
|
||||
@ -64,7 +82,7 @@ class ImageMagickGenerator extends BaseGenerator implements GeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getImageResource($string, $size = null, $color = null, $backgroundColor = null)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user