Compare commits

..

17 Commits

Author SHA1 Message Date
El RIDO
978ab1a59f adapting configuration test generator to new INI model and point release support 2017-10-08 12:27:37 +02:00
El RIDO
f94f61a8c6 PHP < 5.6 compatibility and StyleCI recommendations 2017-10-08 11:31:41 +02:00
El RIDO
6b87a6e0e1 implemented JSON file conversion on purge and storage in PHP files for data leak protection 2017-10-08 11:03:17 +02:00
El RIDO
e326310c57 wrote a unit test to generate old style pastes and comments and check that the purge converts them to PHP files 2017-10-08 07:46:28 +02:00
El RIDO
22a061e01e adding correct HTTP error to response, as per @rugk's recommentation 2017-10-08 07:03:53 +02:00
El RIDO
b88d22a06a removing dead code 2017-10-04 22:06:39 +02:00
El RIDO
098ff786c8 making StyleCI happy 2017-10-04 22:02:27 +02:00
El RIDO
9215a9617e implemented INI cenversion functionality 2017-10-04 21:55:03 +02:00
El RIDO
7911b4f6a0 adding test for INI config file conversion 2017-10-04 20:31:37 +02:00
El RIDO
cfa8c83d61 updating SRI hashes 2017-10-04 20:27:43 +02:00
El RIDO
8c328aa9cf updated documentation, incremented version 2017-10-04 20:05:46 +02:00
El RIDO
9744c02b04 disabling two new options that do no match our style guidelines 2017-10-03 20:49:36 +02:00
El RIDO
3abb333d0b make travis use phpunit < 6 to avoid failing builds for PHP 7, see: https://github.com/travis-ci/travis-ci/issues/7226#issuecomment-285852088 2017-10-03 20:44:26 +02:00
El RIDO
0eaf803490 ask composer in TravisCI to use an oauth token to avoid rate limiting 2017-10-03 20:34:39 +02:00
El RIDO
dd32156c9b hiding INI contents from StyleCI 2017-10-03 20:33:24 +02:00
rugk
bb639d7894 changes the file extension to php and adds a small one-liner to stop PHP from presenting the file to any website visitor
Signed-off-by: El RIDO <elrido@gmx.net>
2017-10-03 20:03:00 +02:00
El RIDO
2c8a4c631b updating unit test in preparation for planned file name change, currently failing 2017-10-03 19:45:47 +02:00
93 changed files with 2579 additions and 2577 deletions

4
.gitattributes vendored
View File

@@ -1,9 +1,5 @@
doc/ export-ignore doc/ export-ignore
tst/ export-ignore tst/ export-ignore
js/.istanbul.yml export-ignore
js/test.js export-ignore
js/mocha-3.2.0.js export-ignore
css/mocha-3.2.0.css export-ignore
.codeclimate.yml export-ignore .codeclimate.yml export-ignore
.csslintrc export-ignore .csslintrc export-ignore
.dockerignore export-ignore .dockerignore export-ignore

View File

@@ -1,5 +1,5 @@
<!-- Please have a look at our FAQ before submitting an issue: https://github.com/PrivateBin/PrivateBin/wiki/FAQ --> <!-- Please have a look at our FAQ before submitting an issue: https://github.com/PrivateBin/PrivateBin/wiki/FAQ -->
<!-- This is a template for a bug report. If you would like to suggest a feature, feel free to delete the part below. --> <!-- This is a template for an bug report. If you would like to suggest a feature, feel free to delete the part below. -->
## Steps to reproduce ## Steps to reproduce
<!-- Tell us how to reproduce the problem. --> <!-- Tell us how to reproduce the problem. -->
@@ -18,6 +18,8 @@ Here you can add screenshots. If the issue is e.g. a client-side issue (= an iss
If you have access to the server log files, also copy them here. If you have access to the server log files, also copy them here.
--> -->
* I can reproduce this issue on <https://privatebin.net>: Yes / No
## Basic information ## Basic information
<!-- If you use a public server enter the address of it here. --> <!-- If you use a public server enter the address of it here. -->
@@ -34,6 +36,3 @@ If you have access to the server log files, also copy them here.
<!-- The version of PrivateBin, if you use an unstable version paste the commit hash or the GitHub link to the commit here (you can get it by running `git rev-parse HEAD`) --> <!-- The version of PrivateBin, if you use an unstable version paste the commit hash or the GitHub link to the commit here (you can get it by running `git rev-parse HEAD`) -->
**PrivateBin version:** **PrivateBin version:**
* I can reproduce this issue on <https://privatebin.net>: Yes / No

View File

@@ -1,5 +1,12 @@
<!-- This is a template for your Pull Request. This are just some suggestions for you. You do not have to use all of them. --> <!-- This is a template for your Pull Request. This are just some suggestions for you. You do not have to use all of them. -->
<!-- **Attention:** Please tick this box to agree to release your code under the projects license. Otherwise your PR cannot be accepted. -->
* [ ] I agree to release the changes in this PR under the Zlib/libpng license as shown in the [LICENSE file](https://github.com/PrivateBin/PrivateBin/blob/master/LICENSE.md#zliblibpng-license-for-privatebin).
<!-- Alternatively uncomment and tick this box to release your code under public domain:
* [ ] To the extent possible under law, I have waived all copyright and related or neighboring rights to this PR and publish it as public domain.
-->
<!-- If your PR fixes an issue, mention it here. You can also just copy the URL - GitHub will convert it for you. <!-- If your PR fixes an issue, mention it here. You can also just copy the URL - GitHub will convert it for you.
If this PR fixes several issues, please prepend each issue url/number with the word "fix"/"fixes" or "close"/"closes" as this automatically closes the issues you mentioned when the PR is merged. If this PR fixes several issues, please prepend each issue url/number with the word "fix"/"fixes" or "close"/"closes" as this automatically closes the issues you mentioned when the PR is merged.
--> -->

9
.gitignore vendored
View File

@@ -9,10 +9,6 @@ data/
doc/* doc/*
!doc/*.md !doc/*.md
# Ignore developers composer status so it isn't accidentally checked in,
# see https://github.com/PrivateBin/PrivateBin/issues/84
composer.lock
# Ignore vendor dir of Composer except PHP files # Ignore vendor dir of Composer except PHP files
vendor/*.* vendor/*.*
vendor/*/*.* vendor/*/*.*
@@ -27,8 +23,9 @@ vendor/**/tests
vendor/**/build_phar.php vendor/**/build_phar.php
!vendor/**/*.php !vendor/**/*.php
# Ignore local node modules, unit testing logs, api docs and eclipse project files composer.lock
js/node_modules/
# Ignore unit testing logs, api docs and eclipse project files
tst/log/ tst/log/
.settings .settings
.buildpath .buildpath

View File

@@ -1,3 +1,3 @@
RewriteEngine on RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} ^.*(bot|spider|crawl|https?://|WhatsApp|SkypeUriPreview|facebookexternalhit) [NC] RewriteCond %{HTTP_USER_AGENT} ^.*(bot|spider|crawl|https?://|WhatsApp|SkypeUriPreview) [NC]
RewriteRule .* - [R=403,L] RewriteRule .* - [R=403,L]

View File

@@ -11,6 +11,8 @@ enabled:
disabled: disabled:
- blank_line_after_opening_tag - blank_line_after_opening_tag
- blank_line_before_return - blank_line_before_return
- blank_line_before_throw
- blank_line_before_try
- concat_without_spaces - concat_without_spaces
- declare_equal_normalize - declare_equal_normalize
- heredoc_to_nowdoc - heredoc_to_nowdoc

View File

@@ -6,10 +6,11 @@ php:
- 7.0 - 7.0
before_script: before_script:
- composer config -g github-oauth.github.com "$GITHUB_TOKEN"
- composer install -n - composer install -n
script: script:
- cd tst && ../vendor/phpunit/phpunit/phpunit - cd tst && ../vendor/bin/phpunit
after_script: after_script:
- cd .. - cd ..

View File

@@ -1,9 +1,7 @@
# PrivateBin version history # PrivateBin version history
* **next (not yet released)** * **1.1.1 (2017-10-06)**
* ADDED: Translations for Spanish, Occitan and Norwegian * CHANGED: Switched to `.php` file extension for configuration file, to avoid leaking configuration data in unprotected installation.
* ADDED: Option in configuration to change the default "PrivateBin" title of the site
* CHANGED: Cleanup of bootstrap template variants and moved icons to `img` directory
* **1.1 (2016-12-26)** * **1.1 (2016-12-26)**
* ADDED: Translations for Italian and Russian * ADDED: Translations for Italian and Russian
* ADDED: Loading message displayed until decryption succeeded for slower (in terms of CPU or network) systems * ADDED: Loading message displayed until decryption succeeded for slower (in terms of CPU or network) systems

View File

@@ -32,6 +32,3 @@ Sébastien Sauvage - original idea and main developer
* Jiawei Zhou - Chinese * Jiawei Zhou - Chinese
* Stefano Marty - Italian * Stefano Marty - Italian
* R4SAS - Russian * R4SAS - Russian
* Alfredo Fabián Altamirano Tena - Spanish
* Quent-in - Occitan
* idarlund - Norwegian

View File

@@ -3,14 +3,15 @@
**TL;DR:** Download the **TL;DR:** Download the
[latest release archive](https://github.com/PrivateBin/PrivateBin/releases/latest) [latest release archive](https://github.com/PrivateBin/PrivateBin/releases/latest)
and extract it in your web hosts folder where you want to install your PrivateBin and extract it in your web hosts folder where you want to install your PrivateBin
instance. We try to provide a safe default configuration, but we advise you to instance. We try to provide a mostly safe default configuration, but we urge you to
check the options and adjust them as you see fit. check the [security section](#hardening-and-security) below and the [configuration
options](#configuration) to adjust as you see fit.
## Basic installation **NOTE:** See [our FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-can-i-securely-clonedownload-your-project) for information how to securely download the PrivateBin release files.
### Requirements ### Minimal requirements
- PHP version 5.3 or above - PHP version 5.4 or above
- _one_ of the following sources of cryptographically safe randomness is required: - _one_ of the following sources of cryptographically safe randomness is required:
- PHP 7 or higher - 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) - [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)
@@ -20,37 +21,11 @@ check the options and adjust them as you see fit.
Mcrypt needs to be able to access `/dev/urandom`. This means if `open_basedir` is set, it must include this file. Mcrypt needs to be able to access `/dev/urandom`. This means if `open_basedir` is set, it must include this file.
- GD extension - GD extension
- some disk space or (optional) a database supported by [PDO](https://secure.php.net/manual/book.pdo.php) - some disk space or (optionally) a database supported by [PDO](https://secure.php.net/manual/book.pdo.php)
- ability to create files and folders in the installation directory and the PATH - ability to create files and folders in the installation directory and the PATH defined in index.php
- A web browser with javascript support - A web browser with javascript support
### Configuration ## Hardening and security
In the file `cfg/conf.ini` you can configure PrivateBin. A `cfg/conf.ini.sample`
is provided containing all options and default values. You can copy it to
`cfg/conf.ini` and adapt it as needed. 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
you set a time limit in seconds. Users may not post more often then this limit
to your PrivateBin installation.
More details can be found in the
[configuration documentation](https://github.com/PrivateBin/PrivateBin/wiki/Configuration).
## Further configuration
After (or before) setting up PrivateBin, also set up HTTPS, as without HTTPS
PrivateBin is not secure. (
[More information](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-should-i-setup-https))
If you want to use PrivateBin behind Cloudflare, make sure you disabled Rocket
loader and unchecked "Javascript" for Auto Minify, found in your domain settings,
under "Speed". (More information
[in this FAQ entry](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#user-content-how-to-make-privatebin-work-when-using-cloudflare-for-ddos-protection))
## Advanced installation
### Changing the path ### Changing the path
@@ -75,6 +50,29 @@ process (see also
> PrivateBin will look for your includes / data here: > PrivateBin will look for your includes / data here:
> /home/example.com/secret/privatebin > /home/example.com/secret/privatebin
### Transport security
When setting up PrivateBin, also set up HTTPS, if you haven't already. Without HTTPS
PrivateBin is not secure, as the javascript files could be manipulated during transmission.
For more information on this, see our [FAQ entry on HTTPS setup](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-should-i-setup-https).
## Configuration
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.
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
you set a time limit in seconds. Users may not post more often then this limit
to your PrivateBin installation.
More details can be found in the
[configuration documentation](https://github.com/PrivateBin/PrivateBin/wiki/Configuration).
## Advanced installation
### Web server configuration ### Web server configuration
A `robots.txt` file is provided in the root dir of PrivateBin. It disallows all A `robots.txt` file is provided in the root dir of PrivateBin. It disallows all
@@ -88,6 +86,13 @@ some known robots and link-scanning bots. If you use Apache, you can rename the
file to `.htaccess` to enable this feature. If you use another webserver, you file to `.htaccess` to enable this feature. If you use another webserver, you
have to configure it manually to do the same. have to configure it manually to do the same.
### On using Cloudflare
If you want to use PrivateBin behind Cloudflare, make sure you have disabled the Rocket
loader and unchecked "Javascript" for Auto Minify, found in your domain settings,
under "Speed". (More information
[in this FAQ entry](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#user-content-how-to-make-privatebin-work-when-using-cloudflare-for-ddos-protection))
### Using a database instead of flat files ### Using a database instead of flat files
In the configuration file the `[model]` and `[model_options]` sections let you In the configuration file the `[model]` and `[model_options]` sections let you
@@ -118,32 +123,36 @@ For reference or if you want to create the table schema for yourself (replace
`prefix_` with your own table prefix and create the table schema with phpMyAdmin `prefix_` with your own table prefix and create the table schema with phpMyAdmin
or the MYSQL console): or the MYSQL console):
CREATE TABLE prefix_paste ( ```sql
dataid CHAR(16) NOT NULL, CREATE TABLE prefix_paste (
data BLOB, dataid CHAR(16) NOT NULL,
postdate INT, data BLOB,
expiredate INT, postdate INT,
opendiscussion INT, expiredate INT,
burnafterreading INT, opendiscussion INT,
meta TEXT, burnafterreading INT,
attachment MEDIUMBLOB, meta TEXT,
attachmentname BLOB, attachment MEDIUMBLOB,
PRIMARY KEY (dataid) attachmentname BLOB,
); PRIMARY KEY (dataid)
);
CREATE TABLE prefix_comment ( CREATE TABLE prefix_comment (
dataid CHAR(16), dataid CHAR(16),
pasteid CHAR(16), pasteid CHAR(16),
parentid CHAR(16), parentid CHAR(16),
data BLOB, data BLOB,
nickname BLOB, nickname BLOB,
vizhash BLOB, vizhash BLOB,
postdate INT, postdate INT,
PRIMARY KEY (dataid) PRIMARY KEY (dataid)
); );
CREATE INDEX parent ON prefix_comment(pasteid); CREATE INDEX parent ON prefix_comment(pasteid);
CREATE TABLE prefix_config ( CREATE TABLE prefix_config (
id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id) id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id)
); );
INSERT INTO prefix_config VALUES('VERSION', '1.1'); INSERT INTO prefix_config VALUES('VERSION', '1.1');
```
In PostgreSQL, the attachment column needs to be TEXT and not BLOB or MEDIUMBLOB.

View File

@@ -7,7 +7,7 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/094500f62abf4c9aa0c8a8a4520e4789)](https://www.codacy.com/app/PrivateBin/PrivateBin) [![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) [![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)
*Current version: 1.1* *Current version: 1.1.1*
**PrivateBin** is a minimalist, open source online pastebin where the server has **PrivateBin** is a minimalist, open source online pastebin where the server has
zero knowledge of pasted data. zero knowledge of pasted data.

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -2,9 +2,9 @@
<browserconfig> <browserconfig>
<msapplication> <msapplication>
<tile> <tile>
<square150x150logo src="img/mstile-150x150.png"/> <square150x150logo src="mstile-150x150.png"/>
<square310x310logo src="img/mstile-310x310.png"/> <square310x310logo src="mstile-310x310.png"/>
<wide310x150logo src="img/mstile-310x150.png"/> <wide310x150logo src="mstile-310x150.png"/>
<TileColor>#ffc40d</TileColor> <TileColor>#ffc40d</TileColor>
</tile> </tile>
</msapplication> </msapplication>

View File

@@ -1,11 +1,9 @@
;<?php http_response_code(403); /*
; config file for PrivateBin ; config file for PrivateBin
; ;
; An explanation of each setting can be find online at https://github.com/PrivateBin/PrivateBin/wiki/Configuration. ; An explanation of each setting can be find online at https://github.com/PrivateBin/PrivateBin/wiki/Configuration.
[main] [main]
; (optional) set a project name to be displayed on the website
; name = "PrivateBin"
; enable or disable the discussion feature, defaults to true ; enable or disable the discussion feature, defaults to true
discussion = true discussion = true
@@ -28,10 +26,10 @@ defaultformatter = "plaintext"
; (optional) set a syntax highlighting theme, as found in css/prettify/ ; (optional) set a syntax highlighting theme, as found in css/prettify/
; syntaxhighlightingtheme = "sons-of-obsidian" ; syntaxhighlightingtheme = "sons-of-obsidian"
; size limit per paste or comment in bytes, defaults to 2 Mebibytes ; size limit per paste or comment in bytes, defaults to 2 Mibibytes
sizelimit = 2097152 sizelimit = 2097152
; template to include, default is "bootstrap" (tpl/bootstrap.php) ; template to include, default is "bootstrap" (tpl/bootstrap.html)
template = "bootstrap" template = "bootstrap"
; (optional) notice to display ; (optional) notice to display
@@ -63,8 +61,7 @@ languageselection = false
; custom scripts from third-party domains to your templates, e.g. tracking ; custom scripts from third-party domains to your templates, e.g. tracking
; scripts or run your site behind certain DDoS-protection services. ; scripts or run your site behind certain DDoS-protection services.
; Check the documentation at https://content-security-policy.com/ ; 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. ; cspheader = "default-src 'none'; manifest-src 'self'; connect-src *; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; referrer no-referrer;"
; cspheader = "default-src 'none'; manifest-src 'self'; connect-src *; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups"
; stay compatible with PrivateBin Alpha 0.19, less secure ; 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 ; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of

View File

@@ -18,14 +18,14 @@
} }
], ],
"require": { "require": {
"php": "^5.3.0 || ^7.0", "php": "^5.2.6 || ^7.0",
"paragonie/random_compat": "2.0.4", "paragonie/random_compat": "^2.0",
"yzalis/identicon": "1.1.0" "yzalis/identicon": "^1.1"
}, },
"require-dev": { "require-dev": {
"codacy/coverage": "dev-master", "codacy/coverage": "dev-master",
"codeclimate/php-test-reporter": "dev-master", "codeclimate/php-test-reporter": "dev-master",
"giorgiosironi/eris": "dev-master" "phpunit/phpunit": "^4.6 || ^5.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
body { body {

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.0 * @version 1.1.1
*/ */
/* When there is no script at all other */ /* When there is no script at all other */

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved. /* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.

View File

@@ -1,5 +1,5 @@
Generating PHP documentation Generating documentation
============================ ========================
In order to generate the documentation, you will need to install the following In order to generate the documentation, you will need to install the following
packages and its dependencies: packages and its dependencies:
@@ -12,7 +12,7 @@ can be found in that projects documentation.
Example for Debian and Ubuntu: Example for Debian and Ubuntu:
```console ```console
$ sudo apt install php-pear graphviz $ sudo aptitude install php-pear graphviz
$ sudo pear channel-discover pear.phpdoc.org $ sudo pear channel-discover pear.phpdoc.org
$ sudo pear install phpdoc/phpDocumentor $ sudo pear install phpdoc/phpDocumentor
``` ```
@@ -20,41 +20,10 @@ $ sudo pear install phpdoc/phpDocumentor
To generate the documentation, change into the main directory and run phpdoc: To generate the documentation, change into the main directory and run phpdoc:
```console ```console
$ cd PrivateBin $ cd PrivateBin
$ phpdoc -t doc/phpdoc -d lib/ $ phpdoc -d lib/ -t doc/
``` ```
**Note:** When used with PHP 7, the prerelease of phpDocumentator 2.9 needs to be **Note:** When used with PHP 7, the prerelease of phpDocumentator 2.9 needs to be
manually installed by downloading it from manually installed by downloading it from
[GitHub](https://github.com/phpDocumentor/phpDocumentor2/releases/download/v2.9.0/phpDocumentor.phar) [GitHub](https://github.com/phpDocumentor/phpDocumentor2/releases/download/v2.9.0/phpDocumentor.phar)
and then manually moving it to e.g. `/usr/local/bin` and making it executable. and then manually moving it to e.g. `/usr/local/bin` and making it executable.
Generating JS documentation
============================
In order to generate the documentation, you will need to install the following
packages and its dependencies:
* npm
Then you can use the node package manager to install the latest stable release
of jsdoc globally:
```console
$ npm install -g jsdoc
```
Example for Debian and Ubuntu, including steps to allow current user to install
node modules globally:
```console
$ sudo apt install npm
$ sudo mkdir /usr/local/lib/node_modules
$ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
$ npm install -g jsdoc
$ ln -s /usr/bin/nodejs /usr/local/bin/node
```
To generate the documentation, change into the main directory and run phpdoc:
```console
$ cd PrivateBin
$ jsdoc -d doc/jsdoc js/privatebin.js
```

View File

Before

Width:  |  Height:  |  Size: 469 B

After

Width:  |  Height:  |  Size: 469 B

View File

Before

Width:  |  Height:  |  Size: 749 B

After

Width:  |  Height:  |  Size: 749 B

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,16 +1,11 @@
{ {
"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 ist ein minimalistischer, quelloffener \"Pastebin\"-artiger Dienst, bei dem der Server keinerlei Kenntnis der Inhalte hat. Die Daten werden <i>im Browser</i> mit 256 Bit AES ver- und entschlüsselt. Weitere Informationen sind auf der <a href=\"https://privatebin.info/\">Projektseite</a> zu finden.",
"Because ignorance is bliss":
"Unwissenheit ist ein Segen",
"en": "de", "en": "de",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Diesen Text gibt es nicht, er ist abgelaufen oder wurde gelöscht.", "Diesen Text gibt es nicht, er ist abgelaufen oder wurde gelöscht.",
"%s requires php 5.3.0 or above to work. Sorry.": "PrivateBin requires php 5.3.0 or above to work. Sorry.":
"%s benötigt PHP 5.3.0 oder höher, um zu funktionieren. Sorry.", "PrivateBin benötigt PHP 5.3.0 oder höher, um zu funktionieren. Sorry.",
"%s requires configuration section [%s] to be present in configuration file.": "PrivateBin requires configuration section [%s] to be present in configuration file.":
"%s benötigt den Konfigurationsabschnitt [%s] in der Konfigurationsdatei um zu funktionieren.", "PrivateBin benötigt den Konfigurationsabschnitt [%s] in der Konfigurationsdatei um zu funktionieren.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
"Bitte warte %d Sekunden zwischen dem Absenden.", "Bitte warte %d Sekunden zwischen dem Absenden.",
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.":
@@ -31,10 +26,15 @@
"Falscher Lösch-Code. Text wurde nicht gelöscht.", "Falscher Lösch-Code. Text wurde nicht gelöscht.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Text wurde erfolgreich gelöscht.", "Text wurde erfolgreich gelöscht.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "PrivateBin": "PrivateBin",
"JavaScript ist eine Voraussetzung, um %s zu nutzen.<br />Bitte entschuldige die Unannehmlichkeiten.", "PrivateBin 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 requires a modern browser to work.": "PrivateBin ist ein minimalistischer, quelloffener \"Pastebin\"-artiger Dienst, bei dem der Server keinerlei Kenntnis der Inhalte hat. Die Daten werden <i>im Browser</i> mit 256 Bit AES ver- und entschlüsselt. Weitere Informationen sind auf der <a href=\"https://privatebin.info/\">Projektseite</a> zu finden.",
"%s setzt einen modernen Browser voraus, um funktionieren zu können.", "Because ignorance is bliss":
"Unwissenheit ist ein Segen",
"JavaScript is required for PrivateBin to work.<br />Sorry for the inconvenience.":
"JavaScript ist eine Voraussetzung, um PrivateBin zu nutzen.<br />Bitte entschuldige die Unannehmlichkeiten.",
"PrivateBin requires a modern browser to work.":
"PrivateBin setzt einen modernen Browser voraus, um funktionieren zu können.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": "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:", "Du benutzt immer noch den Internet Explorer? Tu Dir einen Gefallen und wechsle zu einem moderneren Browser:",
"New": "New":
@@ -139,8 +139,8 @@
"Shorten URL": "URL verkürzen", "Shorten URL": "URL verkürzen",
"Editor": "Bearbeiten", "Editor": "Bearbeiten",
"Preview": "Vorschau", "Preview": "Vorschau",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
"Der PATH muss bei %s mit einem \"%s\" enden. Bitte passe Deinen PATH in Deiner index.php an.", "Der PATH muss bei PrivateBin mit einem \"%s\" enden. Bitte passe Deinen PATH in Deiner index.php an.",
"Decrypt": "Decrypt":
"Entschlüsseln", "Entschlüsseln",
"Enter password": "Enter password":

View File

@@ -1,151 +0,0 @@
{
"PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <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>.",
"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.",
"%s requires php 5.3.0 or above to work. Sorry.":
"%s requiere php 5.3.0 o superior para funcionar. Lo siento.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s requiere que la sección de configuración [% s] esté presente en el archivo de configuración.",
"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.",
"Invalid data.":
"Datos inválidos.",
"You are unlucky. Try again.":
"Tienes mala suerte. Inténtalo de nuevo",
"Error saving comment. Sorry.":
"Error al guardar el comentario. Lo siento.",
"Error saving paste. Sorry.":
"Error al guardar el texto. Lo siento",
"Invalid paste ID.":
"ID del texto inválido.",
"Paste is not of burn-after-reading type.":
"El texto 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.",
"Paste was properly deleted.":
"El texto 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":
"Enviar",
"Clone":
"Clonar",
"Raw text":
"Texto sin formato",
"Expires":
"Caducar en",
"Burn after reading":
"Destruir después de leer",
"Open discussion":
"Discusión abierta",
"Password (recommended)":
"Contraseña (recomendado)",
"Discussion":
"Discusión",
"Toggle navigation":
"Cambiar navegación",
"%d seconds": ["%d segundo", "%d segundos"],
"%d minutes": ["%d minuto", "%d minutos"],
"%d hours": ["%d hora", "%d horas"],
"%d days": ["%d día", "%d días"],
"%d weeks": ["%d semana", "%d semanas"],
"%d months": ["%d mes", "%d meses"],
"%d years": ["%d año", "%d años"],
"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.",
"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.":
["Este documento caducará en un minuto.", "Este documento caducará en %d minutos."],
"This document will expire in %d hours.":
["Este documento caducará en una hora.", "Este documento caducará en %d horas."],
"This document will expire in %d days.":
["Este documento caducará en un día.", "Este documento caducará en %d días."],
"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:",
"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.",
"Could not decrypt comment; Wrong key?":
"No se pudo descifrar el comentario; ¿Llave incorrecta?",
"Reply":
"Responder",
"Anonymous":
"Anónimo",
"Anonymous avatar (Vizhash of the IP address)":
"Avatar anónimo (Vizhash de la dirección IP)",
"Add comment":
"Añadir comentario",
"Optional nickname...":
"Seudónimo opcional...",
"Post comment":
"Publicar comentario",
"Sending comment...":
"Enviando comentario...",
"Comment posted.":
"Comentario publicado.",
"Could not refresh display: %s":
"No se pudo actualizar la vista: %s",
"unknown status":
"Estado desconocido",
"server error or not responding":
"Error del servidor o el servidor no responde",
"Could not post comment: %s":
"No fue posible publicar comentario: %s",
"Sending paste (Please move your mouse for more entropy)...":
"Enviando texto (Por favor, mueva el ratón para mayor entropía)...",
"Sending paste...":
"Enviando texto...",
"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":
"Eliminar datos",
"Could not create paste: %s":
"No fue posible crear el archivo: %s",
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
"No es posible descifrar el documento: Falta la clave de descifrado en la URL (¿Utilizó un redirector o un acortador de URL que quite parte de la URL?)",
"Format": "Formato",
"Plain Text": "Texto sin formato",
"Source Code": "Código fuente",
"Markdown": "Markdown",
"Download attachment": "Descargar adjunto",
"Cloned file attached.": "Archivo clonado adjunto.",
"Attach a file": "Adjuntar archivo",
"Remove attachment": "Remover adjunto",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
"Tu navegador no admite la carga de archivos cifrados. Utilice un navegador más reciente.",
"Invalid attachment.": "Adjunto inválido.",
"Options": "Opciones",
"Shorten URL": "Acortar URL",
"Editor": "Editor",
"Preview": "Previsualización",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
"%s requiere que el PATH termine en \"%s\". Por favor, actualice el PATH en su index.php.",
"Decrypt":
"Descifrar",
"Enter password":
"Ingrese contraseña",
"Loading…": "Cargando…",
"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>."
}

View File

@@ -1,16 +1,11 @@
{ {
"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 est un 'pastebin' (ou gestionnaire d'extraits de texte et de code source) minimaliste et open source, dans lequel le serveur n'a aucune connaissance des données envoyées. Les données sont chiffrées/déchiffrées <i>dans le navigateur</i> par un chiffrage AES 256 bits. Plus d'informations sur <a href=\"https://privatebin.info/\">la page du projet</a>.",
"Because ignorance is bliss":
"Parce que l'ignorance c'est le bonheur",
"en": "fr", "en": "fr",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Le paste n'existe pas, a expiré, ou a été supprimé.", "Le paste n'existe pas, a expiré, ou a été supprimé.",
"%s requires php 5.3.0 or above to work. Sorry.": "PrivateBin requires php 5.3.0 or above to work. Sorry.":
"Désolé, %s nécessite php 5.3.0 ou supérieur pour fonctionner.", "Désolé, PrivateBin nécessite php 5.3.0 ou supérieur pour fonctionner.",
"%s requires configuration section [%s] to be present in configuration file.": "PrivateBin requires configuration section [%s] to be present in configuration file.":
"%s a besoin de la section de configuration [%s] dans le fichier de configuration pour fonctionner.", "PrivateBin a besoin de la section de configuration [%s] dans le fichier de configuration pour fonctionner.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
"Merci d'attendre %d secondes entre chaque publication.", "Merci d'attendre %d secondes entre chaque publication.",
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.":
@@ -31,10 +26,15 @@
"Jeton de suppression incorrect. Le paste n'a pas été supprimé.", "Jeton de suppression incorrect. Le paste n'a pas été supprimé.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Le paste a été correctement supprimé.", "Le paste a été correctement supprimé.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "PrivateBin": "PrivateBin",
"JavaScript est requis pour faire fonctionner %s. <br />Désolé pour cet inconvénient.", "PrivateBin 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 requires a modern browser to work.": "PrivateBin est un 'pastebin' (ou gestionnaire d'extraits de texte et de code source) minimaliste et open source, dans lequel le serveur n'a aucune connaissance des données envoyées. Les données sont chiffrées/déchiffrées <i>dans le navigateur</i> par un chiffrage AES 256 bits. Plus d'informations sur <a href=\"https://privatebin.info/\">la page du projet</a>.",
"%s nécessite un navigateur moderne pour fonctionner.", "Because ignorance is bliss":
"Parce que l'ignorance c'est le bonheur",
"JavaScript is required for PrivateBin to work.<br />Sorry for the inconvenience.":
"JavaScript est requis pour faire fonctionner PrivateBin. <br />Désolé pour cet inconvénient.",
"PrivateBin requires a modern browser to work.":
"PrivateBin nécessite un navigateur moderne pour fonctionner.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": "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 :", "Encore sur Internet Explorer ? Faites-vous une faveur, passez à un navigateur moderne :",
"New": "New":
@@ -148,8 +148,8 @@
"Shorten URL": "Raccourcir URL", "Shorten URL": "Raccourcir URL",
"Editor": "Éditer", "Editor": "Éditer",
"Preview": "Prévisualiser", "Preview": "Prévisualiser",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "PrivateBin 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.", "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
"Decrypt": "Decrypt":
"Decrypt", "Decrypt",
"Enter password": "Enter password":

View File

@@ -1,16 +1,11 @@
{ {
"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 è un sistema di tipo \"Pastebin\" online, open source, minimalista. Il server non possiede alcuna conoscenza (\"Zero Knowledge\") del contenuto dei dati inviati. I dati sono cifrati/decifrati <i>nel Browser</i> con algoritmo AES a 256 Bit. Per ulteriori informazioni, vedi <a href=\"https://privatebin.info/\">Sito del progetto</a>.",
"Because ignorance is bliss":
"Perché l'ignoranza è una benedizione (Because ignorance is bliss)",
"en": "it", "en": "it",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Questo messaggio non esiste, è scaduto o è stato cancellato.", "Questo messaggio non esiste, è scaduto o è stato cancellato.",
"%s requires php 5.3.0 or above to work. Sorry.": "PrivateBin requires php 5.3.0 or above to work. Sorry.":
"%s richiede PHP 5.3.0 o superiore.", "PrivateBin richiede PHP 5.3.0 o superiore.",
"%s requires configuration section [%s] to be present in configuration file.": "PrivateBin requires configuration section [%s] to be present in configuration file.":
"%s richiede la presenza della sezione [%s] nei file di configurazione.", "PrivateBin richiede la presenza della sezione [%s] nei file di configurazione.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
"Attendi per favore %d secondi prima di ciascun invio.", "Attendi per favore %d secondi prima di ciascun invio.",
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.":
@@ -31,10 +26,15 @@
"Codice cancellazione errato. Il messaggio NON è stato cancellato.", "Codice cancellazione errato. Il messaggio NON è stato cancellato.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Il messaggio è stato correttamente cancellato.", "Il messaggio è stato correttamente cancellato.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "PrivateBin": "PrivateBin",
"%s funziona solo con JavaScript attivo.<br />Ci dispiace per l'inconveniente.", "PrivateBin 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 requires a modern browser to work.": "PrivateBin è un sistema di tipo \"Pastebin\" online, open source, minimalista. Il server non possiede alcuna conoscenza (\"Zero Knowledge\") del contenuto dei dati inviati. I dati sono cifrati/decifrati <i>nel Browser</i> con algoritmo AES a 256 Bit. Per ulteriori informazioni, vedi <a href=\"https://privatebin.info/\">Sito del progetto</a>.",
"%s richiede un browser moderno e aggiornato per funzionare.", "Because ignorance is bliss":
"Perché l'ignoranza è una benedizione (Because ignorance is bliss)",
"JavaScript is required for PrivateBin to work.<br />Sorry for the inconvenience.":
"PrivateBin funziona solo con JavaScript attivo.<br />Ci dispiace per l'inconveniente.",
"PrivateBin requires a modern browser to work.":
"PrivateBin richiede un browser moderno e aggiornato per funzionare.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": "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:", "Usi ancora Internet Explorer? Ti consigliamo di passare ad un browser più sicuro:",
"New": "New":
@@ -139,8 +139,8 @@
"Shorten URL": "Accorcia URL", "Shorten URL": "Accorcia URL",
"Editor": "Editor", "Editor": "Editor",
"Preview": "Preview", "Preview": "Preview",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
"%s necessita che PATH termini con \"%s\". Aggiorna la variabile PATH nel tuo index.php.", "PrivateBin necessita che PATH termini con \"%s\". Aggiorna la variabile PATH nel tuo index.php.",
"Decrypt": "Decrypt":
"Decrypt", "Decrypt",
"Enter password": "Enter password":

View File

@@ -1,151 +0,0 @@
{
"PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
"%s er en minimalistisk, åpen kildekode, elektronisk tilgjengelig pastebin hvor serveren ikke har kunnskap om dataene som limes inn. Dataene krypteres/dekrypteres <i>i nettleseren</i> ved hjelp av 256 bits AES. Mer informasjon om prosjektet på <a href=\"https://privatebin.info/\">prosjektsiden</a>.",
"Because ignorance is bliss":
"Fordi uvitenhet er lykke",
"en": "no",
"Paste does not exist, has expired or has been deleted.":
"Innlegget eksisterer ikke, er utløpt eller har blitt slettet.",
"%s requires php 5.3.0 or above to work. Sorry.":
"Beklager, %s krever php 5.3.0 eller nyere for å kjøre.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s krever konfigurasjonsdel [%s] å være til stede i konfigurasjonsfilen .",
"Please wait %d seconds between each post.":
"Vennligst vent %d sekunder mellom hvert innlegg.",
"Paste is limited to %s of encrypted data.":
"Innlegg er begrenset til %s av kryptert data.",
"Invalid data.":
"Ugyldige data.",
"You are unlucky. Try again.":
"Du er uheldig. Prøv igjen.",
"Error saving comment. Sorry.":
"Beklager, det oppstod en feil ved lagring kommentar.",
"Error saving paste. Sorry.":
"Beklager, det oppstod en feil ved lagring innlegg.",
"Invalid paste ID.":
"Feil innlegg ID.",
"Paste is not of burn-after-reading type.":
"Innlegg er ikke av type slett-etter-lesing.",
"Wrong deletion token. Paste was not deleted.":
"Feil slettingsnøkkel. Innlegg ble ikke fjernet.",
"Paste was properly deleted.":
"Innlegget er slettet.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"Javascript kreves for at %s skal fungere<br />Beklager ulempene.",
"%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":
"Send",
"Clone":
"Kopier",
"Raw text":
"Ren tekst",
"Expires":
"Utgår",
"Burn after reading":
"Slett etter lesing",
"Open discussion":
"Åpen diskusjon",
"Password (recommended)":
"Passord (anbefalt)",
"Discussion":
"Diskusjon",
"Toggle navigation":
"Veksle navigasjon",
"%d seconds": ["%d sekund", "%d sekunder"],
"%d minutes": ["%d minutt", "%d minutter"],
"%d hours": ["%d time", "%d timer"],
"%d days": ["%d dag", "%d dager"],
"%d weeks": ["%d uke", "%d uker"],
"%d months": ["%d måned", "%d måneder"],
"%d years": ["%d år", "%d år"],
"Never":
"Aldri",
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
"Merk: Dette er en test tjeneste: Data kan slettes når som helst. Kattunger vil dø hvis du misbruker denne tjenesten.",
"This document will expire in %d seconds.":
["Dette dokumentet vil utløpe om %d sekund.", "Dette dokumentet vil utløpe om %d sekunder."],
"This document will expire in %d minutes.":
["Dette dokumentet vil utløpe om %d minutt.", "Dette dokumentet vil utløpe om %d minutter."],
"This document will expire in %d hours.":
["Dette dokumentet vil utløpe om %d time.", "Dette dokumentet vil utløpe om %d timer."],
"This document will expire in %d days.":
["Dette dokumentet vil utløpe om %d dag.", "Dette dokumentet vil utløpe om %d dager."],
"This document will expire in %d months.":
["Dette dokumentet vil utløpe om %d måned.", "Dette dokumentet vil utløpe om %d måneder."],
"Please enter the password for this paste:":
"Vennligst skriv inn passordet for dette innlegget:",
"Could not decrypt data (Wrong key?)":
"Kunne ikke dekryptere data (Feil nøkkel?)",
"Could not delete the paste, it was not stored in burn after reading mode.":
"Kan ikke slette innlegget, det ble ikke lagret i slett-etter-les modus.",
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
"KUN FOR DINE ØYNE. Ikke lukk dette vinduet, denne meldingen kan ikke bli vist igjen.",
"Could not decrypt comment; Wrong key?":
"Kan ikke dekryptere kommentar; Feil nøkkel?",
"Reply":
"Svar",
"Anonymous":
"Anonym",
"Anonymous avatar (Vizhash of the IP address)":
"Anonym avatar (Vizhash av IP adressen)",
"Add comment":
"Legg til kommentar",
"Optional nickname...":
"Valgfritt kallenavn...",
"Post comment":
"Send kommentar",
"Sending comment...":
"Sender Kommentar...",
"Comment posted.":
"Kommentar sendt.",
"Could not refresh display: %s":
"Kunne ikke oppdatere skjermen: %s",
"unknown status":
"ukjent status",
"server error or not responding":
"server feilet eller svarer ikke",
"Could not post comment: %s":
"Kunne ikke sende kommentar: %s",
"Sending paste (Please move your mouse for more entropy)...":
"Sender innlegg (Flytt musen for mere entropi)...",
"Sending paste...":
"Sender innlegg...",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
"Ditt innlegg er <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Trykk [Ctrl]+[c] for å kopiere)</span>",
"Delete data":
"Slett data",
"Could not create paste: %s":
"Kunne ikke opprette innlegg: %s",
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
"Kan ikke dekryptere innlegg: Dekrypteringsnøkkelen mangler i adressen (Har du bruket en redirector eller en URL forkorter som fjerner en del av addressen?)",
"Format": "Format",
"Plain Text": "Ren Tekst",
"Source Code": "Kildekode",
"Markdown": "Oppmerket",
"Download attachment": "Last ned vedlegg",
"Cloned file attached.": "Kopier vedlegg.",
"Attach a file": "Legg til fil",
"Remove attachment": "Slett vedlegg",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
"Nettleseren din støtter ikke å laste opp krypterte filer. Vennligst bruk en nyere nettleser.",
"Invalid attachment.": "Ugyldig vedlegg.",
"Options": "Alternativer",
"Shorten URL": "Adresse-forkorter",
"Editor": "Rediger",
"Preview": "Forhåndsvis",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
"%s krever at PATH ender på \"%s\". Vennligst oppdater PATH i index.php.",
"Decrypt":
"Dekrypter",
"Enter password":
"Skriv inn passord",
"Loading…": "Laster…",
"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."
}

View File

@@ -1,160 +0,0 @@
{
"PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
"%s es un 'pastebin' (o gestionari d'extrachs de tèxte e còdi font) minimalista e open source, dins lo qual lo servidor a pas cap de coneissença de las donadas mandadas. Las donadas son chifradas/deschifradas <i>dins lo navigator</i> per un chiframent AES 256 bits. Mai informacions sus <a href=\"https://privatebin.info/\">la pagina del projècte</a>.",
"Because ignorance is bliss":
"Perque l'ignorància es bonaür",
"en": "oc",
"Paste does not exist, has expired or has been deleted.":
"Lo tèxte existís pas, a expirat, o es estat suprimit.",
"%s requires php 5.3.0 or above to work. Sorry.":
"O planhèm, %s necessita php 5.3.0 o superior per foncionar.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s fa besonh de la seccion de configuracion [%s] dins lo fichièr de configuracion per foncionar.",
"Please wait %d seconds between each post.":
"Mercés d'esperar %d segondas entre cada publicacion.",
"Paste is limited to %s of encrypted data.":
"Lo tèxte es limitat a %s de donadas chifradas.",
"Invalid data.":
"Donadas invalidas.",
"You are unlucky. Try again.":
"Pas cap de fortuna. Tornatz ensajar.",
"Error saving comment. Sorry.":
"Error al moment de salvagardar lo comentari. O planhèm.",
"Error saving paste. Sorry.":
"Error al moment de salvagardar lo tèxte. O planhèm.",
"Invalid paste ID.":
"ID del tèxte invalid.",
"Paste is not of burn-after-reading type.":
"Lo tèxte es pas del tip \"Escafar aprèp lectura\".",
"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.",
"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":
"Mandar",
"Clone":
"Clonar",
"Raw text":
"Tèxte brut",
"Expires":
"Expira",
"Burn after reading":
"Escafar aprèp lectura",
"Open discussion":
"Autorizar la discussion",
"Password (recommended)":
"Senhal (recomandat)",
"Discussion":
"Discussion",
"Toggle navigation":
"Virar la navigacion",
"%d seconds": ["%d segonda", "%d segondas"],
"%d minutes": ["%d minuta", "%d minutas"],
"%d hours": ["%d ora", "%d oras"],
"%d days": ["%d jorn", "%d jorns"],
"%d weeks": ["%d setmana", "%d setmanas"],
"%d months": ["%d mes", "%d meses"],
"%d years": ["%d an", "%d ans"],
"Never":
"Jamai",
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
"Nota : Aquò es un servici d'espròva : las donadas pòdon èsser suprimidas a cada moment. De catons moriràn s'abusatz d'aqueste servici.",
"This document will expire in %d seconds.":
["Ce document expirera dans %d seconde.", "Aqueste document expirarà dins %d segondas."],
"This document will expire in %d minutes.":
["Ce document expirera dans %d minute.", "Aqueste document expirarà dins %d minutas."],
"This document will expire in %d hours.":
["Ce document expirera dans %d heure.", "Aqueste document expirarà dins %d oras."],
"This document will expire in %d days.":
["Ce document expirera dans %d jour.", "Aqueste document expirarà dins %d jorns."],
"This document will expire in %d months.":
["Ce document expirera dans %d mois.", "Aqueste document expirarà dins %d meses."],
"Please enter the password for this paste:":
"Picatz lo senhal per aqueste tèxte :",
"Could not decrypt data (Wrong key?)":
"Impossible de deschifrar las donadas (marrida clau ?)",
"Could not delete the paste, it was not stored in burn after reading mode.":
"Impossible de suprimir lo tèxte, perque es pas estat gardat en mòde \"Escafar aprèp lectura\".",
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
"PER VÒSTRES UÈLHS SOLAMENT. Tampetz pas aquesta fenèstra, aqueste tèxte poirà pas mai èsser afichat.",
"Could not decrypt comment; Wrong key?":
"Impossible de deschifrar lo comentari ; marrida clau ?",
"Reply":
"Respondre",
"Anonymous":
"Anonime",
"Anonymous avatar (Vizhash of the IP address)":
"Avatar anonime (Vizhash de l'adreça IP)",
"Add comment":
"Apondre un comentari",
"Optional nickname...":
"Escais opcional...",
"Post comment":
"Mandar lo comentari",
"Sending comment...":
"Mandadís del comentari...",
"Comment posted.":
"Comentari mandat.",
"Could not refresh display: %s":
"Impossible d'actualizar l'afichatge : %s",
"unknown status":
"Estatut desconegut",
"server error or not responding":
"Lo servidor respond pas o a rencontrat una error",
"Could not post comment: %s":
"Impossible de mandar lo comentari : %s",
"Sending paste (Please move your mouse for more entropy)...":
"Mandadís del tèxte (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>":
"Vòstre tèxte es disponible a l'adreça <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Picatz sus [Ctrl]+[c] per copiar)</span>",
"Delete data":
"Supprimir las donadas del tèxte",
"Could not create paste: %s":
"Impossible de crear lo tèxte : %s",
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
"Impossible de deschifrar lo tèxte : Clau de deschiframent absenta de l'URL (Avètz utilizat un redirector o un site de reduccion d'URL que suprimís una partida de l'URL ?)",
"B": "o",
"KiB": "Kio",
"MiB": "Mio",
"GiB": "Gio",
"TiB": "Tio",
"PiB": "Pio",
"EiB": "Eio",
"ZiB": "Zio",
"YiB": "Yio",
"Format": "Format",
"Plain Text": "Tèxte brut",
"Source Code": "Còdi font",
"Markdown": "Markdown",
"Download attachment": "Telecargar la pèça junta",
"Cloned file attached.": "Clonar lo fichièr junt.",
"Attach a file": "Juntar un fichièr ",
"Remove attachment": "Levar la pèca junta",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
"Vòstre navigator es pas compatible amb lo mandadís de fichièrs chifrats. Mercés d'emplegar un navigator mai recent.",
"Invalid attachment.": "Pèça junta invalida.",
"Options": "Opcions",
"Shorten URL": "Acorchir l'URL",
"Editor": "Editar",
"Preview": "Previsualizar",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
"%s demanda que lo PATH termine en \"%s\". Mercés de metre a jorn lo PATH dins vòstre index.php.",
"Decrypt":
"Deschifrar",
"Enter password":
"Picatz lo senhal",
"Loading…": "Cargament…",
"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)."
}

View File

@@ -1,16 +1,11 @@
{ {
"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 jest minimalistycznym, otwartoźródłowym serwisem typu pastebin, w którym serwer nie ma jakichkolwiek informacji o tym, co jest wklejane. Dane są szyfrowane i deszyfrowane <i>w przeglądarce</i> z użyciem 256-bitowego klucza AES. Więcej informacji na <a href=\"https://privatebin.info/\">stronie projektu</a>.",
"Because ignorance is bliss":
"Ponieważ ignorancja jest cnotą",
"en": "pl", "en": "pl",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Wklejka nie istnieje, wygasła albo została usunięta.", "Wklejka nie istnieje, wygasła albo została usunięta.",
"%s requires php 5.3.0 or above to work. Sorry.": "PrivateBin requires php 5.3.0 or above to work. Sorry.":
"%s wymaga PHP w wersji 5.3.0 lub nowszej, sorry.", "PrivateBin wymaga PHP w wersji 5.3.0 lub nowszej, sorry.",
"%s requires configuration section [%s] to be present in configuration file.": "PrivateBin requires configuration section [%s] to be present in configuration file.":
"%s wymaga obecności sekcji [%s] w pliku konfiguracyjnym.", "PrivateBin wymaga obecności sekcji [%s] w pliku konfiguracyjnym.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
"Poczekaj %d sekund pomiędzy każdą wklejką.", "Poczekaj %d sekund pomiędzy każdą wklejką.",
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.":
@@ -31,10 +26,15 @@
"Nieprawidłowy token usuwania. Wklejka nie została usunięta.", "Nieprawidłowy token usuwania. Wklejka nie została usunięta.",
"Paste was properly deleted.": "Paste was properly deleted.":
"Wklejka usunięta poprawnie.", "Wklejka usunięta poprawnie.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "PrivateBin": "PrivateBin",
"Do działania %sa jest wymagany JavaScript. Przepraszamy za tę niedogodność.", "PrivateBin 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 requires a modern browser to work.": "PrivateBin jest minimalistycznym, otwartoźródłowym serwisem typu pastebin, w którym serwer nie ma jakichkolwiek informacji o tym, co jest wklejane. Dane są szyfrowane i deszyfrowane <i>w przeglądarce</i> z użyciem 256-bitowego klucza AES. Więcej informacji na <a href=\"https://privatebin.info/\">stronie projektu</a>.",
"%s wymaga do działania nowoczesnej przeglądarki.", "Because ignorance is bliss":
"Ponieważ ignorancja jest cnotą",
"JavaScript is required for PrivateBin to work.<br />Sorry for the inconvenience.":
"Do działania PrivateBina jest wymagany JavaScript. Przepraszamy za tę niedogodność.",
"PrivateBin requires a modern browser to work.":
"PrivateBin wymaga do działania nowoczesnej przeglądarki.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": "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ę:", "Cały czas używasz Internet Explorera? Zrób sobie przysługę, przesiądź się na nowoczesną przeglądarkę:",
"New": "New":
@@ -139,8 +139,8 @@
"Shorten URL": "Skróć adres URL", "Shorten URL": "Skróć adres URL",
"Editor": "Edytować", "Editor": "Edytować",
"Preview": "Zapowiedź", "Preview": "Zapowiedź",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "PrivateBin 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.", "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
"Decrypt": "Decrypt":
"Decrypt", "Decrypt",
"Enter password": "Enter password":

View File

@@ -1,16 +1,11 @@
{ {
"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": "ru", "en": "ru",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Запись не существует, просрочена или была удалена.", "Запись не существует, просрочена или была удалена.",
"%s requires php 5.3.0 or above to work. Sorry.": "PrivateBin requires php 5.3.0 or above to work. Sorry.":
"Для работы %s требуется PHP 5.3.0 или выше. Извините.", "Для работы PrivateBin требуется PHP 5.3.0 или выше. Извините.",
"%s requires configuration section [%s] to be present in configuration file.": "PrivateBin requires configuration section [%s] to be present in configuration file.":
"%s необходимо наличие секции [%s] в конфигурационном файле.", "PrivateBin необходимо наличие секции [%s] в конфигурационном файле.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
["Пожалуйста ожидайте %d секунду между каждыми записями.", "Пожалуйста ожидайте %d секунды между каждыми записями.", "Пожалуйста ожидайте %d секунд между каждыми записями."], ["Пожалуйста ожидайте %d секунду между каждыми записями.", "Пожалуйста ожидайте %d секунды между каждыми записями.", "Пожалуйста ожидайте %d секунд между каждыми записями."],
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.":
@@ -31,10 +26,15 @@
"Неверный ключ удаления записи. Запись не удалена", "Неверный ключ удаления записи. Запись не удалена",
"Paste was properly deleted.": "Paste was properly deleted.":
"Запись была успешно удалена.", "Запись была успешно удалена.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "PrivateBin": "PrivateBin",
"Для работы %s требуется включенный JavaScript.<br />Приносим извинения за неудобства..", "PrivateBin 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 requires a modern browser to work.": "PrivateBin это минималистичный Open Source проект для создания заметок, где сервер не знает ничего о сохраняемых данных. Данные шифруются/расшифровываются <i>в браузере</i> с использованием 256 битного шифрования AES. Подробнее можно узнать на <a href=\"https://privatebin.info/\">сайте проекта</a>.",
"Для работы %s требуется более современный браузер.", "Because ignorance is bliss":
"Потому что неведение - благо",
"JavaScript is required for PrivateBin to work.<br />Sorry for the inconvenience.":
"Для работы PrivateBin требуется включенный JavaScript.<br />Приносим извинения за неудобства..",
"PrivateBin requires a modern browser to work.":
"Для работы PrivateBin требуется более современный браузер.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"До сих пор используете Internet Explorer? Пожалейте себя, перейдите на более современный браузер:", "До сих пор используете Internet Explorer? Пожалейте себя, перейдите на более современный браузер:",
"New": "New":
@@ -148,12 +148,10 @@
"Shorten URL": "Короткая ссылка", "Shorten URL": "Короткая ссылка",
"Editor": "Редактор", "Editor": "Редактор",
"Preview": "Предпросмотр", "Preview": "Предпросмотр",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
"Переменная PATH необходима %s в конце \"%s\". Пожалуйста обновите переменную PATH в вашем index.php.", "Переменная PATH необходима PrivateBin в конце \"%s\". Пожалуйста обновите переменную PATH в вашем index.php.",
"Decrypt": "Decrypt":
"Расшифровать", "Расшифровать",
"Enter password": "Enter password":
"Введите пароль", "Введите пароль"
"Uploading paste… Please wait.":
"Отправка записи... Пожалуйста подождите."
} }

View File

@@ -1,16 +1,11 @@
{ {
"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 minimalističen, odprtokodni spletni 'pastebin', kjer server ne ve ničesar o prilepljenih podatkih. Podatki so zakodirani/odkodirani <i>v brskalniku</i> z uporabo 256 bitnega AES. Več informacij na < href=\"https://privatebin.info/\">spletni strani projekta.</a>.",
"Because ignorance is bliss":
"Ker kar ne veš ne boli.",
"en": "sl", "en": "sl",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Prilepek ne obstaja, mu je potekla življenjska doba, ali pa je izbrisan.", "Prilepek ne obstaja, mu je potekla življenjska doba, ali pa je izbrisan.",
"%s requires php 5.3.0 or above to work. Sorry.": "PrivateBin requires php 5.3.0 or above to work. Sorry.":
"Oprosti, %s za delovanje potrebuje vsaj php 5.3.0.", "Oprosti, PrivateBin za delovanje potrebuje vsaj php 5.3.0.",
"%s requires configuration section [%s] to be present in configuration file.": "PrivateBin requires configuration section [%s] to be present in configuration file.":
"%s potrebuje sekcijo konfiguracij [%s] v konfiguracijski datoteki.", "PrivateBin potrebuje sekcijo konfiguracij [%s] v konfiguracijski datoteki.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
"Prosim počakaj vsaj %d sekund pred vsako naslednjo objavo.", "Prosim počakaj vsaj %d sekund pred vsako naslednjo objavo.",
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.":
@@ -31,10 +26,15 @@
"Napačen token za izbris. Prilepek ni bil izbrisan..", "Napačen token za izbris. Prilepek ni bil izbrisan..",
"Paste was properly deleted.": "Paste was properly deleted.":
"Prilepek je uspešno izbrisan.", "Prilepek je uspešno izbrisan.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "PrivateBin": "PrivateBin",
"Da %s deluje, moraš vklopiti JavaScript.<br />Oprosti za povročene nevšečnosti.", "PrivateBin 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 requires a modern browser to work.": "PrivateBin je minimalističen, odprtokodni spletni 'pastebin', kjer server ne ve ničesar o prilepljenih podatkih. Podatki so zakodirani/odkodirani <i>v brskalniku</i> z uporabo 256 bitnega AES. Več informacij na < href=\"https://privatebin.info/\">spletni strani projekta.</a>.",
"%s za svoje delovanje potrebuje moderen brskalnik.", "Because ignorance is bliss":
"Ker kar ne veš ne boli.",
"JavaScript is required for PrivateBin to work.<br />Sorry for the inconvenience.":
"Da PrivateBin deluje, moraš vklopiti JavaScript.<br />Oprosti za povročene nevšečnosti.",
"PrivateBin requires a modern browser to work.":
"PrivateBin za svoje delovanje potrebuje moderen brskalnik.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": "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:", "Še vedno uporabljaš Internet Explorer? Naredi si uslugo, preklopi na moderen brskalnik:",
"New": "New":
@@ -148,8 +148,8 @@
"Shorten URL": "Skrajšajte URL", "Shorten URL": "Skrajšajte URL",
"Editor": "Uredi", "Editor": "Uredi",
"Preview": "Predogled", "Preview": "Predogled",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "PrivateBin 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.", "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
"Decrypt": "Decrypt":
"Decrypt", "Decrypt",
"Enter password": "Enter password":

View File

@@ -1,16 +1,11 @@
{ {
"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>。",
"Because ignorance is bliss":
"因为无知是福",
"en": "zh", "en": "zh",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"粘贴不存在,已过期或者已被删除。", "粘贴不存在,已过期或者已被删除。",
"%s requires php 5.3.0 or above to work. Sorry.": "PrivateBin requires php 5.3.0 or above to work. Sorry.":
"%s需要工作于PHP 5.3.0及以上版本,抱歉。", "PrivateBin需要工作于PHP 5.3.0及以上版本,抱歉。",
"%s requires configuration section [%s] to be present in configuration file.": "PrivateBin requires configuration section [%s] to be present in configuration file.":
"%s需要设置配置文件中 [%s] 的部分。", "PrivateBin需要设置配置文件中 [%s] 的部分。",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
"每 %d 秒只能粘贴一次。", "每 %d 秒只能粘贴一次。",
"Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.":
@@ -31,10 +26,15 @@
"错误的删除token粘贴没有被删除。", "错误的删除token粘贴没有被删除。",
"Paste was properly deleted.": "Paste was properly deleted.":
"粘贴已被正确删除。", "粘贴已被正确删除。",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "PrivateBin": "PrivateBin",
"%s需要JavaScript来进行加解密。<br />带来的不便敬请谅解。", "PrivateBin 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 requires a modern browser to work.": "PrivateBin是一个极简开源对粘贴内容毫不知情的在线粘贴板数据<i>在浏览器内</i>进行AES-256加密。更多信息请查看<a href=\"https://privatebin.info/\">项目主页</a>。",
"%s需要工作于现代化的浏览器。", "Because ignorance is bliss":
"因为无知是福",
"JavaScript is required for PrivateBin to work.<br />Sorry for the inconvenience.":
"PrivateBin需要JavaScript来进行加解密。<br />带来的不便敬请谅解。",
"PrivateBin requires a modern browser to work.":
"PrivateBin需要工作于现代化的浏览器。",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"还在使用Internet Explorer帮自己个忙换上一个现代化的浏览器", "还在使用Internet Explorer帮自己个忙换上一个现代化的浏览器",
"New": "New":
@@ -139,8 +139,8 @@
"Shorten URL": "缩短链接", "Shorten URL": "缩短链接",
"Editor": "編輯", "Editor": "編輯",
"Preview": "預習", "Preview": "預習",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "PrivateBin 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.", "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
"Decrypt": "Decrypt":
"Decrypt", "Decrypt",
"Enter password": "Enter password":

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.0
*/ */
// change this, if your php files and data is outside of your webservers document root // change this, if your php files and data is outside of your webservers document root

View File

@@ -1,7 +0,0 @@
---
instrumentation:
excludes:
- jquery-3.1.1.js
baseline-file: ../tst/log/js-coverage-baseline.json
reporting:
dir: ../tst/log/js-coverage-report

7
js/bootstrap-3.3.5.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

File diff suppressed because it is too large Load Diff

1
js/showdown-1.4.1.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

58
js/sjcl-1.0.4.js Normal file
View File

@@ -0,0 +1,58 @@
"use strict";function q(a){throw a;}var s=void 0,u=!1;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}}};
"undefined"!==typeof module&&module.exports&&(module.exports=sjcl);"function"===typeof define&&define([],function(){return sjcl});
sjcl.cipher.aes=function(a){this.l[0][0][0]||this.G();var b,c,d,e,g=this.l[0][4],f=this.l[1];b=a.length;var h=1;4!==b&&(6!==b&&8!==b)&&q(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=g[c>>>24]<<24^g[c>>16&255]<<16^g[c>>8&255]<<8^g[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:f[0][g[c>>>24]]^f[1][g[c>>16&255]]^f[2][g[c>>8&255]]^f[3][g[c&
255]]};
sjcl.cipher.aes.prototype={encrypt:function(a){return w(this,a,0)},decrypt:function(a){return w(this,a,1)},l:[[[],[],[],[],[]],[[],[],[],[],[]]],G:function(){var a=this.l[0],b=this.l[1],c=a[4],d=b[4],e,g,f,h=[],l=[],k,m,n,p;for(e=0;0x100>e;e++)l[(h[e]=e<<1^283*(e>>7))^e]=e;for(g=f=0;!c[g];g^=k||1,f=l[f]||1){n=f^f<<1^f<<2^f<<3^f<<4;n=n>>8^n&255^99;c[g]=n;d[n]=g;m=h[e=h[k=h[g]]];p=0x1010101*m^0x10001*e^0x101*k^0x1010100*g;m=0x101*h[n]^0x1010100*n;for(e=0;4>e;e++)a[e][g]=m=m<<24^m>>>8,b[e][n]=p=p<<24^p>>>8}for(e=
0;5>e;e++)a[e]=a[e].slice(0),b[e]=b[e].slice(0)}};
function w(a,b,c){4!==b.length&&q(new sjcl.exception.invalid("invalid aes block size"));var d=a.b[c],e=b[0]^d[0],g=b[c?3:1]^d[1],f=b[2]^d[2];b=b[c?1:3]^d[3];var h,l,k,m=d.length/4-2,n,p=4,t=[0,0,0,0];h=a.l[c];a=h[0];var r=h[1],v=h[2],y=h[3],z=h[4];for(n=0;n<m;n++)h=a[e>>>24]^r[g>>16&255]^v[f>>8&255]^y[b&255]^d[p],l=a[g>>>24]^r[f>>16&255]^v[b>>8&255]^y[e&255]^d[p+1],k=a[f>>>24]^r[b>>16&255]^v[e>>8&255]^y[g&255]^d[p+2],b=a[b>>>24]^r[e>>16&255]^v[g>>8&255]^y[f&255]^d[p+3],p+=4,e=h,g=l,f=k;for(n=0;4>
n;n++)t[c?3&-n:n]=z[e>>>24]<<24^z[g>>16&255]<<16^z[f>>8&255]<<8^z[b&255]^d[p++],h=e,e=g,g=f,f=b,b=h;return t}
sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.R(a.slice(b/32),32-(b&31)).slice(1);return c===s?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.R(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&=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 u;var c=0,d;for(d=0;d<a.length;d++)c|=a[d]^b[d];return 0===
c},R:function(a,b,c,d){var e;e=0;for(d===s&&(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},g: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>>>24),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+="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={p:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",O:"0123456789ABCDEFGHIJKLMNOPQRSTUV",BITS:32,BASE:5,REMAINING:27,fromBits:function(a,b,c){var d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,g="",f=0,h=sjcl.codec.base32.p,l=0,k=sjcl.bitArray.bitLength(a);c&&(h=sjcl.codec.base32.O);for(c=0;g.length*d<k;)g+=h.charAt((l^a[c]>>>f)>>>e),f<d?(l=a[c]<<d-f,f+=e,c++):(l<<=d,f-=d);for(;g.length&7&&!b;)g+="=";return g},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,g=[],f,h=0,l=sjcl.codec.base32.p,k=0,m,n="base32";b&&(l=sjcl.codec.base32.O,n="base32hex");for(f=0;f<a.length;f++){m=l.indexOf(a.charAt(f));if(0>m){if(!b)try{return sjcl.codec.base32hex.toBits(a)}catch(p){}q(new sjcl.exception.invalid("this isn't "+n+"!"))}h>e?(h-=e,g.push(k^m>>>h),k=m<<c-h):(h+=d,k^=m<<c-h)}h&56&&g.push(sjcl.bitArray.partial(h&56,k,1));return g}};
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={p:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b,c){var d="",e=0,g=sjcl.codec.base64.p,f=0,h=sjcl.bitArray.bitLength(a);c&&(g=g.substr(0,62)+"-_");for(c=0;6*d.length<h;)d+=g.charAt((f^a[c]>>>e)>>>26),6>e?(f=a[c]<<6-e,e+=26,c++):(f<<=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,g=sjcl.codec.base64.p,f=0,h;b&&(g=g.substr(0,62)+"-_");for(d=0;d<a.length;d++)h=g.indexOf(a.charAt(d)),
0>h&&q(new sjcl.exception.invalid("this isn't base64!")),26<e?(e-=26,c.push(f^h>>>e),f=h<<32-e):(e+=6,f^=h<<32-e);e&56&&c.push(sjcl.bitArray.partial(e&56,f,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.G();a?(this.s=a.s.slice(0),this.o=a.o.slice(0),this.i=a.i):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.s=this.P.slice(0);this.o=[];this.i=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.o=sjcl.bitArray.concat(this.o,a);b=this.i;a=this.i=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)x(this,c.splice(0,16));return this},finalize:function(){var a,b=this.o,c=this.s,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.i/
4294967296));for(b.push(this.i|0);b.length;)x(this,b.splice(0,16));this.reset();return c},P:[],b:[],G:function(){function a(a){return 0x100000000*(a-Math.floor(a))|0}var b=0,c=2,d;a:for(;64>b;c++){for(d=2;d*d<=c;d++)if(0===c%d)continue a;8>b&&(this.P[b]=a(Math.pow(c,0.5)));this.b[b]=a(Math.pow(c,1/3));b++}}};
function x(a,b){var c,d,e,g=b.slice(0),f=a.s,h=a.b,l=f[0],k=f[1],m=f[2],n=f[3],p=f[4],t=f[5],r=f[6],v=f[7];for(c=0;64>c;c++)16>c?d=g[c]:(d=g[c+1&15],e=g[c+14&15],d=g[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+g[c&15]+g[c+9&15]|0),d=d+v+(p>>>6^p>>>11^p>>>25^p<<26^p<<21^p<<7)+(r^p&(t^r))+h[c],v=r,r=t,t=p,p=n+d|0,n=m,m=k,k=l,l=d+(k&m^n&(k^m))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;f[0]=f[0]+l|0;f[1]=f[1]+k|0;f[2]=f[2]+m|0;f[3]=f[3]+n|0;f[4]=f[4]+p|0;f[5]=f[5]+t|0;f[6]=
f[6]+r|0;f[7]=f[7]+v|0}
sjcl.mode.ccm={name:"ccm",t:[],listenProgress:function(a){sjcl.mode.ccm.t.push(a)},unListenProgress:function(a){a=sjcl.mode.ccm.t.indexOf(a);-1<a&&sjcl.mode.ccm.t.splice(a,1)},X:function(a){var b=sjcl.mode.ccm.t.slice(),c;for(c=0;c<b.length;c+=1)b[c](a)},encrypt:function(a,b,c,d,e){var g,f=b.slice(0),h=sjcl.bitArray,l=h.bitLength(c)/8,k=h.bitLength(f)/8;e=e||64;d=d||[];7>l&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(g=2;4>g&&k>>>8*g;g++);g<15-l&&(g=15-l);c=h.clamp(c,8*(15-
g));b=sjcl.mode.ccm.M(a,b,c,d,e,g);f=sjcl.mode.ccm.q(a,f,c,b,e,g);return h.concat(f.data,f.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var g=sjcl.bitArray,f=g.bitLength(c)/8,h=g.bitLength(b),l=g.clamp(b,h-e),k=g.bitSlice(b,h-e),h=(h-e)/8;7>f&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(b=2;4>b&&h>>>8*b;b++);b<15-f&&(b=15-f);c=g.clamp(c,8*(15-b));l=sjcl.mode.ccm.q(a,l,c,k,e,b);a=sjcl.mode.ccm.M(a,l.data,c,d,e,b);g.equal(l.tag,a)||q(new sjcl.exception.corrupt("ccm: tag doesn't match"));
return l.data},ea:function(a,b,c,d,e,g){var f=[],h=sjcl.bitArray,l=h.g;d=[h.partial(8,(b.length?64:0)|d-2<<2|g-1)];d=h.concat(d,c);d[3]|=e;d=a.encrypt(d);if(b.length){c=h.bitLength(b)/8;65279>=c?f=[h.partial(16,c)]:0xffffffff>=c&&(f=h.concat([h.partial(16,65534)],[c]));f=h.concat(f,b);for(b=0;b<f.length;b+=4)d=a.encrypt(l(d,f.slice(b,b+4).concat([0,0,0])))}return d},M:function(a,b,c,d,e,g){var f=sjcl.bitArray,h=f.g;e/=8;(e%2||4>e||16<e)&&q(new sjcl.exception.invalid("ccm: invalid tag length"));(0xffffffff<
d.length||0xffffffff<b.length)&&q(new sjcl.exception.bug("ccm: can't deal with 4GiB or more data"));c=sjcl.mode.ccm.ea(a,d,c,e,f.bitLength(b)/8,g);for(d=0;d<b.length;d+=4)c=a.encrypt(h(c,b.slice(d,d+4).concat([0,0,0])));return f.clamp(c,8*e)},q:function(a,b,c,d,e,g){var f,h=sjcl.bitArray;f=h.g;var l=b.length,k=h.bitLength(b),m=l/50,n=m;c=h.concat([h.partial(8,g-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(f(d,a.encrypt(c)),0,e);if(!l)return{tag:d,data:[]};for(f=0;f<l;f+=4)f>m&&(sjcl.mode.ccm.X(f/
l),m+=n),c[3]++,e=a.encrypt(c),b[f]^=e[0],b[f+1]^=e[1],b[f+2]^=e[2],b[f+3]^=e[3];return{tag:d,data:h.clamp(b,k)}}};
sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,g){128!==sjcl.bitArray.bitLength(c)&&q(new sjcl.exception.invalid("ocb iv must be 128 bits"));var f,h=sjcl.mode.ocb2.J,l=sjcl.bitArray,k=l.g,m=[0,0,0,0];c=h(a.encrypt(c));var n,p=[];d=d||[];e=e||64;for(f=0;f+4<b.length;f+=4)n=b.slice(f,f+4),m=k(m,n),p=p.concat(k(c,a.encrypt(k(c,n)))),c=h(c);n=b.slice(f);b=l.bitLength(n);f=a.encrypt(k(c,[0,0,0,b]));n=l.clamp(k(n.concat([0,0,0]),f),b);m=k(m,k(n.concat([0,0,0]),f));m=a.encrypt(k(m,k(c,h(c))));d.length&&
(m=k(m,g?d:sjcl.mode.ocb2.pmac(a,d)));return p.concat(l.concat(n,l.clamp(m,e)))},decrypt:function(a,b,c,d,e,g){128!==sjcl.bitArray.bitLength(c)&&q(new sjcl.exception.invalid("ocb iv must be 128 bits"));e=e||64;var f=sjcl.mode.ocb2.J,h=sjcl.bitArray,l=h.g,k=[0,0,0,0],m=f(a.encrypt(c)),n,p,t=sjcl.bitArray.bitLength(b)-e,r=[];d=d||[];for(c=0;c+4<t/32;c+=4)n=l(m,a.decrypt(l(m,b.slice(c,c+4)))),k=l(k,n),r=r.concat(n),m=f(m);p=t-32*c;n=a.encrypt(l(m,[0,0,0,p]));n=l(n,h.clamp(b.slice(c),p).concat([0,0,0]));
k=l(k,n);k=a.encrypt(l(k,l(m,f(m))));d.length&&(k=l(k,g?d:sjcl.mode.ocb2.pmac(a,d)));h.equal(h.clamp(k,e),h.bitSlice(b,t))||q(new sjcl.exception.corrupt("ocb: tag doesn't match"));return r.concat(h.clamp(n,p))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.J,e=sjcl.bitArray,g=e.g,f=[0,0,0,0],h=a.encrypt([0,0,0,0]),h=g(h,d(d(h)));for(c=0;c+4<b.length;c+=4)h=d(h),f=g(f,a.encrypt(g(h,b.slice(c,c+4))));c=b.slice(c);128>e.bitLength(c)&&(h=g(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));f=g(f,c);return a.encrypt(g(d(g(h,
d(h))),f))},J: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 g=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.q(!0,a,g,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var g=b.slice(0),f=sjcl.bitArray,h=f.bitLength(g);e=e||128;d=d||[];e<=h?(b=f.bitSlice(g,h-e),g=f.bitSlice(g,0,h-e)):(b=g,g=[]);a=sjcl.mode.gcm.q(u,a,g,d,c,e);f.equal(a.tag,b)||q(new sjcl.exception.corrupt("gcm: tag doesn't match"));return a.data},ba:function(a,b){var c,d,e,g,f,h=sjcl.bitArray.g;e=[0,0,0,0];g=
b.slice(0);for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,g));f=0!==(g[3]&1);for(d=3;0<d;d--)g[d]=g[d]>>>1|(g[d-1]&1)<<31;g[0]>>>=1;f&&(g[0]^=-0x1f000000)}return e},h: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.ba(b,a);return b},q:function(a,b,c,d,e,g){var f,h,l,k,m,n,p,t,r=sjcl.bitArray;n=c.length;p=r.bitLength(c);t=r.bitLength(d);h=r.bitLength(e);f=
b.encrypt([0,0,0,0]);96===h?(e=e.slice(0),e=r.concat(e,[1])):(e=sjcl.mode.gcm.h(f,[0,0,0,0],e),e=sjcl.mode.gcm.h(f,e,[0,0,Math.floor(h/0x100000000),h&0xffffffff]));h=sjcl.mode.gcm.h(f,[0,0,0,0],d);m=e.slice(0);d=h.slice(0);a||(d=sjcl.mode.gcm.h(f,h,c));for(k=0;k<n;k+=4)m[3]++,l=b.encrypt(m),c[k]^=l[0],c[k+1]^=l[1],c[k+2]^=l[2],c[k+3]^=l[3];c=r.clamp(c,p);a&&(d=sjcl.mode.gcm.h(f,h,c));a=[Math.floor(t/0x100000000),t&0xffffffff,Math.floor(p/0x100000000),p&0xffffffff];d=sjcl.mode.gcm.h(f,d,a);l=b.encrypt(e);
d[0]^=l[0];d[1]^=l[1];d[2]^=l[2];d[3]^=l[3];return{tag:r.bitSlice(d,0,g),data:c}}};sjcl.misc.hmac=function(a,b){this.N=b=b||sjcl.hash.sha256;var c=[[],[]],d,e=b.prototype.blockSize/32;this.n=[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.n[0].update(c[0]);this.n[1].update(c[1]);this.I=new b(this.n[0])};
sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a){this.S&&q(new sjcl.exception.invalid("encrypt on already updated hmac called!"));this.update(a);return this.digest(a)};sjcl.misc.hmac.prototype.reset=function(){this.I=new this.N(this.n[0]);this.S=u};sjcl.misc.hmac.prototype.update=function(a){this.S=!0;this.I.update(a)};sjcl.misc.hmac.prototype.digest=function(){var a=this.I.finalize(),a=(new this.N(this.n[1])).update(a).finalize();this.reset();return a};
sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E3;(0>d||0>c)&&q(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 g,f,h,l,k=[],m=sjcl.bitArray;for(l=1;32*k.length<(d||1);l++){e=g=a.encrypt(m.concat(b,[l]));for(f=1;f<c;f++){g=a.encrypt(g);for(h=0;h<g.length;h++)e[h]^=g[h]}k=k.concat(e)}d&&(k=m.clamp(k,d));return k};
sjcl.prng=function(a){this.c=[new sjcl.hash.sha256];this.j=[0];this.H=0;this.u={};this.F=0;this.L={};this.Q=this.d=this.k=this.Z=0;this.b=[0,0,0,0,0,0,0,0];this.f=[0,0,0,0];this.C=s;this.D=a;this.r=u;this.B={progress:{},seeded:{}};this.m=this.Y=0;this.w=1;this.A=2;this.U=0x10000;this.K=[0,48,64,96,128,192,0x100,384,512,768,1024];this.V=3E4;this.T=80};
sjcl.prng.prototype={randomWords:function(a,b){var c=[],d;d=this.isReady(b);var e;d===this.m&&q(new sjcl.exception.notReady("generator isn't seeded"));if(d&this.A){d=!(d&this.w);e=[];var g=0,f;this.Q=e[0]=(new Date).valueOf()+this.V;for(f=0;16>f;f++)e.push(0x100000000*Math.random()|0);for(f=0;f<this.c.length&&!(e=e.concat(this.c[f].finalize()),g+=this.j[f],this.j[f]=0,!d&&this.H&1<<f);f++);this.H>=1<<this.c.length&&(this.c.push(new sjcl.hash.sha256),this.j.push(0));this.d-=g;g>this.k&&(this.k=g);this.H++;
this.b=sjcl.hash.sha256.hash(this.b.concat(e));this.C=new sjcl.cipher.aes(this.b);for(d=0;4>d&&!(this.f[d]=this.f[d]+1|0,this.f[d]);d++);}for(d=0;d<a;d+=4)0===(d+1)%this.U&&A(this),e=B(this),c.push(e[0],e[1],e[2],e[3]);A(this);return c.slice(0,a)},setDefaultParanoia:function(a,b){0===a&&"Setting paranoia=0 will ruin your security; use it only for testing"!==b&&q("Setting paranoia=0 will ruin your security; use it only for testing");this.D=a},addEntropy:function(a,b,c){c=c||"user";var d,e,g=(new Date).valueOf(),
f=this.u[c],h=this.isReady(),l=0;d=this.L[c];d===s&&(d=this.L[c]=this.Z++);f===s&&(f=this.u[c]=0);this.u[c]=(this.u[c]+1)%this.c.length;switch(typeof a){case "number":b===s&&(b=1);this.c[f].update([d,this.F++,1,b,g,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{"[object Array]"!==c&&(l=1);for(c=0;c<a.length&&!l;c++)"number"!==typeof a[c]&&(l=1)}if(!l){if(b===s)for(c=b=0;c<a.length;c++)for(e=a[c];0<e;)b++,
e>>>=1;this.c[f].update([d,this.F++,2,b,g,a.length].concat(a))}break;case "string":b===s&&(b=a.length);this.c[f].update([d,this.F++,3,b,g,a.length]);this.c[f].update(a);break;default:l=1}l&&q(new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string"));this.j[f]+=b;this.d+=b;h===this.m&&(this.isReady()!==this.m&&C("seeded",Math.max(this.k,this.d)),C("progress",this.getProgress()))},isReady:function(a){a=this.K[a!==s?a:this.D];return this.k&&this.k>=a?this.j[0]>this.T&&
(new Date).valueOf()>this.Q?this.A|this.w:this.w:this.d>=a?this.A|this.m:this.m},getProgress:function(a){a=this.K[a?a:this.D];return this.k>=a?1:this.d>a?1:this.d/a},startCollectors:function(){this.r||(this.a={loadTimeCollector:D(this,this.da),mouseCollector:D(this,this.fa),keyboardCollector:D(this,this.ca),accelerometerCollector:D(this,this.W),touchCollector:D(this,this.ha)},window.addEventListener?(window.addEventListener("load",this.a.loadTimeCollector,u),window.addEventListener("mousemove",this.a.mouseCollector,
u),window.addEventListener("keypress",this.a.keyboardCollector,u),window.addEventListener("devicemotion",this.a.accelerometerCollector,u),window.addEventListener("touchmove",this.a.touchCollector,u)):document.attachEvent?(document.attachEvent("onload",this.a.loadTimeCollector),document.attachEvent("onmousemove",this.a.mouseCollector),document.attachEvent("keypress",this.a.keyboardCollector)):q(new sjcl.exception.bug("can't attach event")),this.r=!0)},stopCollectors:function(){this.r&&(window.removeEventListener?
(window.removeEventListener("load",this.a.loadTimeCollector,u),window.removeEventListener("mousemove",this.a.mouseCollector,u),window.removeEventListener("keypress",this.a.keyboardCollector,u),window.removeEventListener("devicemotion",this.a.accelerometerCollector,u),window.removeEventListener("touchmove",this.a.touchCollector,u)):document.detachEvent&&(document.detachEvent("onload",this.a.loadTimeCollector),document.detachEvent("onmousemove",this.a.mouseCollector),document.detachEvent("keypress",
this.a.keyboardCollector)),this.r=u)},addEventListener:function(a,b){this.B[a][this.Y++]=b},removeEventListener:function(a,b){var c,d,e=this.B[a],g=[];for(d in e)e.hasOwnProperty(d)&&e[d]===b&&g.push(d);for(c=0;c<g.length;c++)d=g[c],delete e[d]},ca:function(){E(1)},fa: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&&sjcl.random.addEntropy([b,c],2,"mouse");E(0)},ha:function(a){a=a.touches[0]||a.changedTouches[0];sjcl.random.addEntropy([a.pageX||
a.clientX,a.pageY||a.clientY],1,"touch");E(0)},da:function(){E(2)},W:function(a){a=a.accelerationIncludingGravity.x||a.accelerationIncludingGravity.y||a.accelerationIncludingGravity.z;if(window.orientation){var b=window.orientation;"number"===typeof b&&sjcl.random.addEntropy(b,1,"accelerometer")}a&&sjcl.random.addEntropy(a,2,"accelerometer");E(0)}};function C(a,b){var c,d=sjcl.random.B[a],e=[];for(c in d)d.hasOwnProperty(c)&&e.push(d[c]);for(c=0;c<e.length;c++)e[c](b)}
function E(a){"undefined"!==typeof window&&window.performance&&"function"===typeof window.performance.now?sjcl.random.addEntropy(window.performance.now(),a,"loadtime"):sjcl.random.addEntropy((new Date).valueOf(),a,"loadtime")}function A(a){a.b=B(a).concat(B(a));a.C=new sjcl.cipher.aes(a.b)}function B(a){for(var b=0;4>b&&!(a.f[b]=a.f[b]+1|0,a.f[b]);b++);return a.C.encrypt(a.f)}function D(a,b){return function(){b.apply(a,arguments)}}sjcl.random=new sjcl.prng(6);
a:try{var F,G,H,I;if(I="undefined"!==typeof module){var J;if(J=module.exports){var K;try{K=require("crypto")}catch(L){K=null}J=(G=K)&&G.randomBytes}I=J}if(I)F=G.randomBytes(128),F=new Uint32Array((new Uint8Array(F)).buffer),sjcl.random.addEntropy(F,1024,"crypto['randomBytes']");else if("undefined"!==typeof window&&"undefined"!==typeof Uint32Array){H=new Uint32Array(32);if(window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(H);else if(window.msCrypto&&window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(H);
else break a;sjcl.random.addEntropy(H,1024,"crypto['getRandomValues']")}}catch(M){"undefined"!==typeof window&&window.console&&(console.log("There was an error collecting entropy from the browser:"),console.log(M))}
sjcl.json={defaults:{v:1,iter:1E3,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},aa:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,g=e.e({iv:sjcl.random.randomWords(4,0)},e.defaults),f;e.e(g,c);c=g.adata;"string"===typeof g.salt&&(g.salt=sjcl.codec.base64.toBits(g.salt));"string"===typeof g.iv&&(g.iv=sjcl.codec.base64.toBits(g.iv));(!sjcl.mode[g.mode]||!sjcl.cipher[g.cipher]||"string"===typeof a&&100>=g.iter||64!==g.ts&&96!==g.ts&&128!==g.ts||128!==g.ks&&192!==g.ks&&0x100!==g.ks||2>g.iv.length||
4<g.iv.length)&&q(new sjcl.exception.invalid("json encrypt: invalid parameters"));"string"===typeof a?(f=sjcl.misc.cachedPbkdf2(a,g),a=f.key.slice(0,g.ks/32),g.salt=f.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.publicKey&&(f=a.kem(),g.kemtag=f.tag,a=f.key.slice(0,g.ks/32));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));"string"===typeof c&&(g.adata=c=sjcl.codec.utf8String.toBits(c));f=new sjcl.cipher[g.cipher](a);e.e(d,g);d.key=a;g.ct="ccm"===g.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&
b instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.encrypt(f,b,g.iv,c,g.ts):sjcl.mode[g.mode].encrypt(f,b,g.iv,c,g.ts);return g},encrypt:function(a,b,c,d){var e=sjcl.json,g=e.aa.apply(e,arguments);return e.encode(g)},$:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.e(e.e(e.e({},e.defaults),b),c,!0);var g,f;g=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));(!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)&&q(new sjcl.exception.invalid("json decrypt: invalid parameters"));"string"===typeof a?(f=sjcl.misc.cachedPbkdf2(a,b),a=f.key.slice(0,b.ks/32),b.salt=f.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 g&&(g=sjcl.codec.utf8String.toBits(g));f=new sjcl.cipher[b.cipher](a);g="ccm"===
b.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&b.ct instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.decrypt(f,b.ct,b.iv,b.tag,g,b.ts):sjcl.mode[b.mode].decrypt(f,b.ct,b.iv,g,b.ts);e.e(d,b);d.key=a;return 1===c.raw?g:sjcl.codec.utf8String.fromBits(g)},decrypt:function(a,b,c,d){var e=sjcl.json;return e.$(a,e.decode(b),c,d)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b))switch(b.match(/^[a-z0-9]+$/i)||q(new sjcl.exception.invalid("json encode: invalid property name")),c+=d+'"'+b+
'":',d=",",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:q(new sjcl.exception.bug("json encode: unsupported type"))}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");a.match(/^\{.*\}$/)||q(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++)(d=a[c].match(/^\s*(?:(["']?)([a-z][a-z0-9]*)\1)\s*:\s*(?:(-?\d+)|"([a-z0-9+\/%*_.@=\-]*)"|(true|false))$/i))||
q(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},e:function(a,b,c){a===s&&(a={});if(b===s)return a;for(var d in b)b.hasOwnProperty(d)&&(c&&(a[d]!==s&&a[d]!==b[d])&&q(new sjcl.exception.invalid("required parameter overridden")),a[d]=b[d]);return a},ja:function(a,b){var c={},d;for(d in a)a.hasOwnProperty(d)&&
a[d]!==b[d]&&(c[d]=a[d]);return c},ia:function(a,b){var c={},d;for(d=0;d<b.length;d++)a[b[d]]!==s&&(c[b[d]]=a[b[d]]);return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.ga={};sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.ga,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=b.salt===s?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)}};

View File

@@ -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>>>24),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});

View File

@@ -1,158 +0,0 @@
'use strict';
var jsc = require('jsverify'),
jsdom = require('jsdom-global'),
cleanup = jsdom(),
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(['+','%','&','.','*','-','_']),
base64String = alnumString.concat(['+','/','=']).concat(
a2zString.map(function(c) {
return c.toUpperCase();
})
);
global.$ = global.jQuery = require('./jquery-3.1.1');
global.sjcl = require('./sjcl-1.0.6');
global.Base64 = require('./base64-2.1.9');
global.RawDeflate = require('./rawdeflate-0.5');
require('./rawinflate-0.3');
require('./privatebin');
describe('helper', function () {
describe('secondsToHuman', function () {
after(function () {
cleanup();
});
jsc.property('returns an array with a number and a word', 'integer', function (number) {
var result = $.PrivateBin.helper.secondsToHuman(number);
return Array.isArray(result) &&
result.length === 2 &&
result[0] === parseInt(result[0], 10) &&
typeof result[1] === 'string';
});
jsc.property('returns seconds on the first array position', 'integer 59', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[0] === number;
});
jsc.property('returns seconds on the second array position', 'integer 59', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'second';
});
jsc.property('returns minutes on the first array position', 'integer 60 3599', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[0] === Math.floor(number / 60);
});
jsc.property('returns minutes on the second array position', 'integer 60 3599', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'minute';
});
jsc.property('returns hours on the first array position', 'integer 3600 86399', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[0] === Math.floor(number / (60 * 60));
});
jsc.property('returns hours on the second array position', 'integer 3600 86399', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'hour';
});
jsc.property('returns days on the first array position', 'integer 86400 5184000', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[0] === Math.floor(number / (60 * 60 * 24));
});
jsc.property('returns days on the second array position', 'integer 86400 5184000', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'day';
});
// max safe integer as per http://ecma262-5.com/ELS5_HTML.htm#Section_8.5
jsc.property('returns months on the first array position', 'integer 5184000 9007199254740991', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[0] === Math.floor(number / (60 * 60 * 24 * 30));
});
jsc.property('returns months on the second array position', 'integer 5184000 9007199254740991', function (number) {
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'month';
});
});
describe('scriptLocation', function () {
jsc.property(
'returns the URL without query & fragment',
jsc.nearray(jsc.elements(a2zString)),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
'string',
function (schema, address, query, fragment) {
var expected = schema.join('') + '://' + address.join('') + '/',
clean = jsdom('', {url: expected + '?' + query.join('') + '#' + fragment}),
result = $.PrivateBin.helper.scriptLocation();
clean();
return expected === result;
}
);
});
describe('pasteId', function () {
jsc.property(
'returns the query string without separator, if any',
jsc.nearray(jsc.elements(a2zString)),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
'string',
function (schema, address, query, fragment) {
var queryString = query.join(''),
clean = jsdom('', {
url: schema.join('') + '://' + address.join('') +
'/?' + queryString + '#' + fragment
}),
result = $.PrivateBin.helper.pasteId();
clean();
return queryString === result;
}
);
});
describe('pageKey', function () {
jsc.property(
'returns the fragment of the URL',
jsc.nearray(jsc.elements(a2zString)),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
jsc.array(jsc.elements(base64String)),
function (schema, address, query, fragment) {
var fragmentString = fragment.join(''),
clean = jsdom('', {
url: schema.join('') + '://' + address.join('') +
'/?' + query.join('') + '#' + fragmentString
}),
result = $.PrivateBin.helper.pageKey();
clean();
return fragmentString === result;
}
);
jsc.property(
'returns the fragment stripped of trailing query parts',
jsc.nearray(jsc.elements(a2zString)),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
jsc.array(jsc.elements(base64String)),
jsc.array(jsc.elements(queryString)),
function (schema, address, query, fragment, trail) {
var fragmentString = fragment.join(''),
clean = jsdom('', {
url: schema.join('') + '://' + address.join('') + '/?' +
query.join('') + '#' + fragmentString + '&' + trail.join('')
}),
result = $.PrivateBin.helper.pageKey();
clean();
return fragmentString === result;
}
);
});
describe('htmlEntities', function () {
after(function () {
cleanup();
});
jsc.property(
'removes all HTML entities from any given string',
'string',
function (string) {
var result = $.PrivateBin.helper.htmlEntities(string);
return !(/[<>"'`=\/]/.test(result)) && !(string.indexOf('&') > -1 && !(/&amp;/.test(result)));
}
);
});
});

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;
@@ -22,6 +22,13 @@ use PDO;
*/ */
class Configuration class Configuration
{ {
/**
* First line in INI file, to hide contents
*
* @const string
*/
const PROTECTION_LINE = ';<?php http_response_code(403); /*';
/** /**
* parsed configuration * parsed configuration
* *
@@ -36,7 +43,6 @@ class Configuration
*/ */
private static $_defaults = array( private static $_defaults = array(
'main' => array( 'main' => array(
'name' => 'PrivateBin',
'discussion' => true, 'discussion' => true,
'opendiscussion' => false, 'opendiscussion' => false,
'password' => true, 'password' => true,
@@ -51,7 +57,7 @@ class Configuration
'languagedefault' => '', 'languagedefault' => '',
'urlshortener' => '', 'urlshortener' => '',
'icon' => 'identicon', 'icon' => 'identicon',
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups', 'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; referrer no-referrer;',
'zerobincompatibility' => false, 'zerobincompatibility' => false,
), ),
'expire' => array( 'expire' => array(
@@ -99,7 +105,35 @@ class Configuration
public function __construct() public function __construct()
{ {
$config = array(); $config = array();
$configFile = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini'; $configFile = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php';
$configIni = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini';
// rename INI files to avoid configuration leakage
if (is_readable($configIni)) {
$context = stream_context_create();
// don't overwrite already converted file
if (!is_file($configFile)) {
$iniHandle = fopen($configIni, 'r', false, $context);
file_put_contents($configFile, self::PROTECTION_LINE . PHP_EOL);
file_put_contents($configFile, $iniHandle, FILE_APPEND);
fclose($iniHandle);
}
unlink($configIni);
// cleanup sample, too
$configSample = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.sample.php';
$configIniSample = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini.sample';
if (is_readable($configIniSample)) {
if (!is_readable($configSample)) {
$iniSampleHandle = fopen($configIniSample, 'r', false, $context);
file_put_contents($configSample, self::PROTECTION_LINE . PHP_EOL);
file_put_contents($configSample, $iniSampleHandle, FILE_APPEND);
fclose($iniSampleHandle);
}
unlink($configIniSample);
}
}
if (is_readable($configFile)) { if (is_readable($configFile)) {
$config = parse_ini_file($configFile, true); $config = parse_ini_file($configFile, true);
foreach (array('main', 'model', 'model_options') as $section) { foreach (array('main', 'model', 'model_options') as $section) {
@@ -108,6 +142,7 @@ class Configuration
} }
} }
} }
$opts = '_options'; $opts = '_options';
foreach (self::getDefaults() as $section => $values) { foreach (self::getDefaults() as $section => $values) {
// fill missing sections with default values // fill missing sections with default values
@@ -240,7 +275,7 @@ class Configuration
public function getSection($section) public function getSection($section)
{ {
if (!array_key_exists($section, $this->_configuration)) { if (!array_key_exists($section, $this->_configuration)) {
throw new Exception(I18n::_('%s requires configuration section [%s] to be present in configuration file.', I18n::_($this->getKey('name')), $section), 3); throw new Exception(I18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 3);
} }
return $this->_configuration[$section]; return $this->_configuration[$section];
} }

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Data; namespace PrivateBin\Data;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Data; namespace PrivateBin\Data;
@@ -699,9 +699,8 @@ class Database extends AbstractData
'CREATE INDEX IF NOT EXISTS comment_parent ON ' . 'CREATE INDEX IF NOT EXISTS comment_parent ON ' .
self::_sanitizeIdentifier('comment') . '(pasteid);' self::_sanitizeIdentifier('comment') . '(pasteid);'
); );
// no break, continue with updates for 0.22 // no break, continue with updates for 0.22 and later
case '0.22': default:
case '1.0':
self::_exec( self::_exec(
'UPDATE ' . self::_sanitizeIdentifier('config') . 'UPDATE ' . self::_sanitizeIdentifier('config') .
' SET value = ? WHERE id = ?', ' SET value = ? WHERE id = ?',

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Data; namespace PrivateBin\Data;
@@ -22,6 +22,13 @@ use PrivateBin\Model\Paste;
*/ */
class Filesystem extends AbstractData class Filesystem extends AbstractData
{ {
/**
* First line in JSON files, to hide contents
*
* @const string
*/
const PROTECTION_LINE = '<?php http_response_code(403); /*';
/** /**
* directory where data is stored * directory where data is stored
* *
@@ -68,13 +75,13 @@ class Filesystem extends AbstractData
public function create($pasteid, $paste) public function create($pasteid, $paste)
{ {
$storagedir = self::_dataid2path($pasteid); $storagedir = self::_dataid2path($pasteid);
if (is_file($storagedir . $pasteid)) { if (is_file($storagedir . $pasteid . '.php')) {
return false; return false;
} }
if (!is_dir($storagedir)) { if (!is_dir($storagedir)) {
mkdir($storagedir, 0700, true); mkdir($storagedir, 0700, true);
} }
return (bool) file_put_contents($storagedir . $pasteid, Json::encode($paste)); return (bool) file_put_contents($storagedir . $pasteid . '.php', self::PROTECTION_LINE . PHP_EOL . Json::encode($paste));
} }
/** /**
@@ -89,9 +96,7 @@ class Filesystem extends AbstractData
if (!$this->exists($pasteid)) { if (!$this->exists($pasteid)) {
return false; return false;
} }
$paste = json_decode( $paste = self::_decodeFile(self::_dataid2path($pasteid) . $pasteid . '.php');
file_get_contents(self::_dataid2path($pasteid) . $pasteid)
);
if (property_exists($paste->meta, 'attachment')) { if (property_exists($paste->meta, 'attachment')) {
$paste->attachment = $paste->meta->attachment; $paste->attachment = $paste->meta->attachment;
unset($paste->meta->attachment); unset($paste->meta->attachment);
@@ -115,8 +120,8 @@ class Filesystem extends AbstractData
$pastedir = self::_dataid2path($pasteid); $pastedir = self::_dataid2path($pasteid);
if (is_dir($pastedir)) { if (is_dir($pastedir)) {
// Delete the paste itself. // Delete the paste itself.
if (is_file($pastedir . $pasteid)) { if (is_file($pastedir . $pasteid . '.php')) {
unlink($pastedir . $pasteid); unlink($pastedir . $pasteid . '.php');
} }
// Delete discussion if it exists. // Delete discussion if it exists.
@@ -144,7 +149,41 @@ class Filesystem extends AbstractData
*/ */
public function exists($pasteid) public function exists($pasteid)
{ {
return is_file(self::_dataid2path($pasteid) . $pasteid); $basePath = self::_dataid2path($pasteid) . $pasteid;
$pastePath = $basePath . '.php';
// convert to PHP protected files if needed
if (is_readable($basePath)) {
$context = stream_context_create();
// don't overwrite already converted file
if (!is_file($pastePath)) {
$handle = fopen($basePath, 'r', false, $context);
file_put_contents($pastePath, self::PROTECTION_LINE . PHP_EOL);
file_put_contents($pastePath, $handle, FILE_APPEND);
fclose($handle);
}
unlink($basePath);
// convert comments, too
$discdir = self::_dataid2discussionpath($pasteid);
if (is_dir($discdir)) {
$dir = dir($discdir);
while (false !== ($filename = $dir->read())) {
if (substr($filename, -4) !== '.php' && strlen($filename) >= 16) {
$commentFilename = $discdir . $filename . '.php';
// don't overwrite already converted file
if (!is_file($commentFilename)) {
$handle = fopen($discdir . $filename, 'r', false, $context);
file_put_contents($commentFilename, self::PROTECTION_LINE . PHP_EOL);
file_put_contents($commentFilename, $handle, FILE_APPEND);
fclose($handle);
}
unlink($discdir . $filename);
}
}
$dir->close();
}
}
return is_readable($pastePath);
} }
/** /**
@@ -161,14 +200,14 @@ class Filesystem extends AbstractData
public function createComment($pasteid, $parentid, $commentid, $comment) public function createComment($pasteid, $parentid, $commentid, $comment)
{ {
$storagedir = self::_dataid2discussionpath($pasteid); $storagedir = self::_dataid2discussionpath($pasteid);
$filename = $pasteid . '.' . $commentid . '.' . $parentid; $filename = $pasteid . '.' . $commentid . '.' . $parentid . '.php';
if (is_file($storagedir . $filename)) { if (is_file($storagedir . $filename)) {
return false; return false;
} }
if (!is_dir($storagedir)) { if (!is_dir($storagedir)) {
mkdir($storagedir, 0700, true); mkdir($storagedir, 0700, true);
} }
return (bool) file_put_contents($storagedir . $filename, Json::encode($comment)); return (bool) file_put_contents($storagedir . $filename, self::PROTECTION_LINE . PHP_EOL . Json::encode($comment));
} }
/** /**
@@ -183,15 +222,14 @@ class Filesystem extends AbstractData
$comments = array(); $comments = array();
$discdir = self::_dataid2discussionpath($pasteid); $discdir = self::_dataid2discussionpath($pasteid);
if (is_dir($discdir)) { if (is_dir($discdir)) {
// Delete all files in discussion directory
$dir = dir($discdir); $dir = dir($discdir);
while (false !== ($filename = $dir->read())) { while (false !== ($filename = $dir->read())) {
// Filename is in the form pasteid.commentid.parentid: // Filename is in the form pasteid.commentid.parentid.php:
// - pasteid is the paste this reply belongs to. // - pasteid is the paste this reply belongs to.
// - commentid is the comment identifier itself. // - commentid is the comment identifier itself.
// - parentid is the comment this comment replies to (It can be pasteid) // - parentid is the comment this comment replies to (It can be pasteid)
if (is_file($discdir . $filename)) { if (is_file($discdir . $filename)) {
$comment = json_decode(file_get_contents($discdir . $filename)); $comment = self::_decodeFile($discdir . $filename);
$items = explode('.', $filename); $items = explode('.', $filename);
// Add some meta information not contained in file. // Add some meta information not contained in file.
$comment->id = $items[1]; $comment->id = $items[1];
@@ -223,7 +261,7 @@ class Filesystem extends AbstractData
{ {
return is_file( return is_file(
self::_dataid2discussionpath($pasteid) . self::_dataid2discussionpath($pasteid) .
$pasteid . '.' . $commentid . '.' . $parentid $pasteid . '.' . $commentid . '.' . $parentid . '.php'
); );
} }
@@ -263,7 +301,14 @@ class Filesystem extends AbstractData
continue; continue;
} }
$thirdLevel = array_filter( $thirdLevel = array_filter(
scandir($path), array_map(
function ($filename) {
return strlen($filename) >= 20 ?
substr($filename, 0, -4) :
$filename;
},
scandir($path)
),
'PrivateBin\\Model\\Paste::isValidId' 'PrivateBin\\Model\\Paste::isValidId'
); );
if (count($thirdLevel) == 0) { if (count($thirdLevel) == 0) {
@@ -378,4 +423,17 @@ class Filesystem extends AbstractData
{ {
return (bool) preg_match('/^[a-f0-9]{2}$/', $element); return (bool) preg_match('/^[a-f0-9]{2}$/', $element);
} }
/**
* Decodes a paste or comment file.
*
* @access private
* @static
* @param string $file
* @return array
*/
private static function _decodeFile($file)
{
return json_decode(substr(file_get_contents($file), strlen(self::PROTECTION_LINE . PHP_EOL)));
}
} }

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;
@@ -39,9 +39,7 @@ class Filter
/** /**
* format a given time string into a human readable label (localized) * format a given time string into a human readable label (localized)
* *
* accepts times in the format "[integer][time unit]", valid time units are: * accepts times in the format "[integer][time unit]"
* sec, second, seconds, min, minute, minutes, hour, hours, day, days, week,
* weeks, month, months, year, years
* *
* @access public * @access public
* @static * @static

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;
@@ -295,16 +295,13 @@ class I18n
{ {
switch (self::$_language) { switch (self::$_language) {
case 'fr': case 'fr':
case 'oc':
case 'zh': case 'zh':
return $n > 1 ? 1 : 0; return $n > 1 ? 1 : 0;
case 'pl': case 'pl':
return $n == 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); return $n == 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
case 'ru': case 'ru':
return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
case 'sl': // en, de
return $n % 100 == 1 ? 1 : ($n % 100 == 2 ? 2 : ($n % 100 == 3 || $n % 100 == 4 ? 3 : 0));
// de, en, es, it, no
default: default:
return $n != 1 ? 1 : 0; return $n != 1 ? 1 : 0;
} }

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Model; namespace PrivateBin\Model;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Model; namespace PrivateBin\Model;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Model; namespace PrivateBin\Model;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Persistence; namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Persistence; namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Persistence; namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin\Persistence; namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;
@@ -28,7 +28,7 @@ class PrivateBin
* *
* @const string * @const string
*/ */
const VERSION = '1.1'; const VERSION = '1.1.1';
/** /**
* show the same error message if the paste expired or does not exist * show the same error message if the paste expired or does not exist
@@ -121,10 +121,10 @@ class PrivateBin
public function __construct() public function __construct()
{ {
if (version_compare(PHP_VERSION, '5.3.0') < 0) { if (version_compare(PHP_VERSION, '5.3.0') < 0) {
throw new Exception(I18n::_('%s requires php 5.3.0 or above to work. Sorry.', I18n::_('PrivateBin')), 1); throw new Exception(I18n::_('PrivateBin requires php 5.3.0 or above to work. Sorry.'), 1);
} }
if (strlen(PATH) < 0 && substr(PATH, -1) !== DIRECTORY_SEPARATOR) { if (strlen(PATH) < 0 && substr(PATH, -1) !== DIRECTORY_SEPARATOR) {
throw new Exception(I18n::_('%s requires the PATH to end in a "%s". Please update the PATH in your index.php.', I18n::_('PrivateBin'), DIRECTORY_SEPARATOR), 5); throw new Exception(I18n::_('PrivateBin requires the PATH to end in a "%s". Please update the PATH in your index.php.', DIRECTORY_SEPARATOR), 5);
} }
// load config from ini file, initialize required classes // load config from ini file, initialize required classes
@@ -334,16 +334,19 @@ class PrivateBin
// accessing this property ensures that the paste would be // accessing this property ensures that the paste would be
// deleted if it has already expired // deleted if it has already expired
$burnafterreading = $paste->isBurnafterreading(); $burnafterreading = $paste->isBurnafterreading();
if ( if ($deletetoken == 'burnafterreading') {
($burnafterreading && $deletetoken == 'burnafterreading') || if ($burnafterreading) {
Filter::slowEquals($deletetoken, $paste->getDeleteToken()) $paste->delete();
) { $this->_return_message(0, $dataid);
// Paste exists and deletion token is valid: Delete the paste. } else {
$paste->delete(); $this->_return_message(1, 'Paste is not of burn-after-reading type.');
$this->_status = 'Paste was properly deleted.'; }
} else { } else {
if (!$burnafterreading && $deletetoken == 'burnafterreading') { // Make sure the token is valid.
$this->_error = 'Paste is not of burn-after-reading type.'; if (Filter::slowEquals($deletetoken, $paste->getDeleteToken())) {
// Paste exists and deletion token is valid: Delete the paste.
$paste->delete();
$this->_status = 'Paste was properly deleted.';
} else { } else {
$this->_error = 'Wrong deletion token. Paste was not deleted.'; $this->_error = 'Wrong deletion token. Paste was not deleted.';
} }
@@ -354,13 +357,6 @@ class PrivateBin
} catch (Exception $e) { } catch (Exception $e) {
$this->_error = $e->getMessage(); $this->_error = $e->getMessage();
} }
if ($this->_request->isJsonApiCall()) {
if (strlen($this->_error)) {
$this->_return_message(1, $this->_error);
} else {
$this->_return_message(0, $dataid);
}
}
} }
/** /**
@@ -434,7 +430,6 @@ class PrivateBin
} }
$page = new View; $page = new View;
$page->assign('NAME', $this->_conf->getKey('name'));
$page->assign('CIPHERDATA', $this->_data); $page->assign('CIPHERDATA', $this->_data);
$page->assign('ERROR', I18n::_($this->_error)); $page->assign('ERROR', I18n::_($this->_error));
$page->assign('STATUS', I18n::_($this->_status)); $page->assign('STATUS', I18n::_($this->_status));

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin * @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1 * @version 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;
@@ -52,8 +52,7 @@ class View
*/ */
public function draw($template) public function draw($template)
{ {
$file = substr($template, 0, 9) === 'bootstrap' ? 'bootstrap' : $template; $path = PATH . 'tpl' . DIRECTORY_SEPARATOR . $template . '.php';
$path = PATH . 'tpl' . DIRECTORY_SEPARATOR . $file . '.php';
if (!file_exists($path)) { if (!file_exists($path)) {
throw new Exception('Template ' . $template . ' not found!', 80); throw new Exception('Template ' . $template . ' not found!', 80);
} }

View File

@@ -8,7 +8,7 @@
* @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd * @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 0.0.5 beta PrivateBin 1.1 * @version 0.0.5 beta PrivateBin 1.1.1
*/ */
namespace PrivateBin; namespace PrivateBin;
@@ -80,7 +80,7 @@ class Vizhash16x16
*/ */
public function generate($text) public function generate($text)
{ {
if (!function_exists('gd_info') || strlen($text) < 1) { if (!function_exists('gd_info')) {
return ''; return '';
} }

View File

@@ -2,12 +2,12 @@
"name": "PrivateBin", "name": "PrivateBin",
"icons": [ "icons": [
{ {
"src": "img/android-chrome-192x192.png", "src": "android-chrome-192x192.png",
"sizes": "192x192", "sizes": "192x192",
"type": "image\/png" "type": "image\/png"
}, },
{ {
"src": "img/android-chrome-512x512.png", "src": "android-chrome-512x512.png",
"sizes": "512x512", "sizes": "512x512",
"type": "image\/png" "type": "image\/png"
} }

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,9 +0,0 @@
# editorconfig.org
root = false
# special format for PHP templates
[*.php]
indent_style = tab
indent_size = 4

364
tpl/bootstrap-compact.php Normal file
View File

@@ -0,0 +1,364 @@
<?php
use PrivateBin\I18n;
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<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">
<title><?php echo I18n::_('PrivateBin'); ?></title>
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.3.5.css" />
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if ($SYNTAXHIGHLIGHTING):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
endif;
endif;
?>
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/sjcl-1.0.4.js" integrity="sha512-BqVQ8GgWfMCcdsDuP6Ggm1BV7+mmoWH3PC4UqcYpEKSdEq1rthy6NUsa6gu5sydewbi/ilI3E3ohdCxlPPF9ww==" crossorigin="anonymous"></script>
<?php
if ($ZEROBINCOMPATIBILITY):
?>
<script type="text/javascript" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
<?php
else:
?>
<script type="text/javascript" src="js/base64-2.1.9.js" integrity="sha512-rbqAby7hObftbEoGQzkhUbEh5YkUn2MtekTLs4btvo2oly4CZ3DxhJzEh0u/rNzS54tcJdqi5Ug1ruugEd2U1g==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" src="js/rawdeflate-0.5.js" integrity="sha512-tTdZ7qMr7tt5VQy4iCHu6/aGB12eRwbUy+AEI5rXntfsjcRfBeeqJloMsBU9FrGk1bIYLiuND/FhU42LO1bi0g==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/bootstrap-3.3.5.js" integrity="sha512-/W33QnLmSAP1fwINS9iXgB6s/VOIG9GVdIuIYaUtbSvKPMv5S08PtT3PqnT2WjwBgB8DFeDN2nqJroqQYF7SwQ==" crossorigin="anonymous"></script>
<?php
if ($SYNTAXHIGHLIGHTING):
?>
<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-m8iHxoN+Fe12xxFwWNdY/TS4KoFntHp29qY0xUzBnPd0bkKMOR/dFhEdTWydpt0b/fIXyhB+znGYUvgjfJ2RzQ==" crossorigin="anonymous"></script>
<?php
endif;
if ($MARKDOWN):
?>
<script type="text/javascript" src="js/showdown-1.4.1.js" integrity="sha512-Kbz1FIlDnqUJu/3yW8H8USzURA3JuUqSKRwz13lM4kWt6C0n6s4tjl81PCfnWtE4gBIzyj5uGePcfUyotk/icw==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-6To0UBu7oCGa0oX6b669PoOK6vB5P8InWcV6OcBJt8v+RO6QJgP5RF6tiPlE5YSMlXtFpJz8bohe84saAgRspg==" 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]-->
<link rel="apple-touch-icon" href="apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
<link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" />
<link rel="mask-icon" href="safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" />
<link rel="shortcut icon" href="favicon.ico">
<meta name="msapplication-config" content="browserconfig.xml">
<meta name="theme-color" content="#ffe57e" />
</head>
<body role="document" class="navbar-spacing">
<div id="passwordmodal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form id="passwordform" role="form">
<div class="form-group">
<label for="passworddecrypt"><span class="glyphicon glyphicon-eye-open"></span> <?php echo I18n::_('Please enter the password for this paste:') ?></label>
<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>" autofocus>
</div>
<button type="submit" class="btn btn-success btn-block"><span class="glyphicon glyphicon-off"></span> <?php echo I18n::_('Decrypt') ?></button>
</form>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="reloadlink navbar-brand" href="">
<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="38" />
</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>
<button id="sendbutton" type="button" class="hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL; ?>
</button>
<?php
if ($EXPIRECLONE):
?>
<button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'), PHP_EOL; ?>
</button>
<?php
endif;
?>
<button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
</button>
</li>
<li class="dropdown">
<select id="pasteExpiration" name="pasteExpiration" class="hidden">
<?php
foreach ($EXPIRE as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $EXPIREDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($EXPIRE as $key => $value):
?>
<li>
<a href="#" data-expiration="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<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>
<ul class="dropdown-menu">
<li id="burnafterreadingoption" class="checkbox hidden">
<label>
<input type="checkbox" id="burnafterreading" name="burnafterreading"<?php
if ($BURNAFTERREADINGSELECTED):
?> checked="checked"<?php
endif;
?> />
<?php echo I18n::_('Burn after reading'), PHP_EOL; ?>
</label>
</li>
<?php
if ($DISCUSSION):
?>
<li id="opendisc" class="checkbox hidden">
<label>
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
if ($OPENDISCUSSION):
?> checked="checked"<?php
endif;
?> />
<?php echo I18n::_('Open discussion'), PHP_EOL; ?>
</label>
</li>
<?php
endif;
?>
<li role="separator" class="divider"></li>
<li>
<div>
<?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span>
</div>
</li>
<?php
foreach ($FORMATTER as $key => $value):
?>
<li>
<a href="#" data-format="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php
foreach ($FORMATTER as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
</li>
<?php
if ($PASSWORD):
?>
<li>
<div id="password" class="navbar-form hidden">
<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19"/>
</div>
</li>
<?php
endif;
if ($FILEUPLOAD):
?>
<li id="attach" class="hidden dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li id="filewrap">
<div>
<input type="file" id="file" name="file" />
</div>
</li>
<li>
<a id="fileremovebutton" href="#">
<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
</a>
</li>
</ul>
</li>
<?php
endif;
?>
</ul>
<ul class="nav navbar-nav pull-right">
<?php
if (strlen($LANGUAGESELECTION)):
?>
<li id="language" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($LANGUAGES as $key => $value):
?>
<li>
<a href="#" data-lang="<?php echo $key; ?>">
<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<?php
endif;
?>
<li>
<button id="newbutton" type="button" class="reloadlink hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL; ?>
</button>
</li>
</ul>
</div>
</div>
</nav>
<header class="container">
<?php
if (strlen($NOTICE)):
?>
<div role="alert" class="alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE), PHP_EOL; ?>
</div>
<?php
endif;
?>
<div id="remainingtime" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
</div>
<?php
if ($FILEUPLOAD):
?>
<div id="attachment" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
</div>
<?php
endif;
if (strlen($STATUS)):
?>
<div id="status" role="alert" class="alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
</div>
<?php
endif;
?>
<div id="errormessage" role="alert" class="<?php
if (!strlen($ERROR)):
?>hidden <?php
endif;
?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
<noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
<div id="ienotice" role="alert" class="hidden alert alert-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>,
<a href="https://www.apple.com/safari">Safari</a>...
</div>
<div id="pasteresult" role="alert" class="hidden alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
<div id="deletelink"></div>
<div id="pastelink">
<?php
if (strlen($URLSHORTENER)):
?>
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-primary">
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
<?php
endif;
?>
</div>
</div>
<ul id="preview" 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>
</ul>
</header>
<section class="container">
<article class="row">
<div id="image" class="col-md-12 text-center hidden"></div>
<div id="prettymessage" class="col-md-12 hidden">
<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
</div>
<div id="cleartext" class="col-md-12 hidden"></div>
<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
</article>
</section>
<section class="container">
<div id="discussion" class="hidden">
<h4><?php echo I18n::_('Discussion'); ?></h4>
<div id="comments"></div>
</div>
</section>
<section class="container">
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">
<span> <?php echo I18n::_('Loading…'); ?></span><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>
</div>
</section>
<footer class="container">
<div class="row">
<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
<p id="aboutbox" class="col-md-6 col-xs-12">
<?php echo I18n::_('PrivateBin 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>.'), PHP_EOL; ?>
</p>
</div>
</footer>
<div id="cipherdata" class="hidden"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>
</body>
</html>

358
tpl/bootstrap-dark-page.php Normal file
View File

@@ -0,0 +1,358 @@
<?php
use PrivateBin\I18n;
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<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">
<title><?php echo I18n::_('PrivateBin'); ?></title>
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
<link type="text/css" rel="stylesheet" href="css/bootstrap/darkstrap-0.9.3.css" />
<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if ($SYNTAXHIGHLIGHTING):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
endif;
endif;
?>
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/sjcl-1.0.4.js" integrity="sha512-BqVQ8GgWfMCcdsDuP6Ggm1BV7+mmoWH3PC4UqcYpEKSdEq1rthy6NUsa6gu5sydewbi/ilI3E3ohdCxlPPF9ww==" crossorigin="anonymous"></script>
<?php
if ($ZEROBINCOMPATIBILITY):
?>
<script type="text/javascript" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
<?php
else:
?>
<script type="text/javascript" src="js/base64-2.1.9.js" integrity="sha512-rbqAby7hObftbEoGQzkhUbEh5YkUn2MtekTLs4btvo2oly4CZ3DxhJzEh0u/rNzS54tcJdqi5Ug1ruugEd2U1g==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" src="js/rawdeflate-0.5.js" integrity="sha512-tTdZ7qMr7tt5VQy4iCHu6/aGB12eRwbUy+AEI5rXntfsjcRfBeeqJloMsBU9FrGk1bIYLiuND/FhU42LO1bi0g==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/bootstrap-3.3.5.js" integrity="sha512-/W33QnLmSAP1fwINS9iXgB6s/VOIG9GVdIuIYaUtbSvKPMv5S08PtT3PqnT2WjwBgB8DFeDN2nqJroqQYF7SwQ==" crossorigin="anonymous"></script>
<?php
if ($SYNTAXHIGHLIGHTING):
?>
<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-m8iHxoN+Fe12xxFwWNdY/TS4KoFntHp29qY0xUzBnPd0bkKMOR/dFhEdTWydpt0b/fIXyhB+znGYUvgjfJ2RzQ==" crossorigin="anonymous"></script>
<?php
endif;
if ($MARKDOWN):
?>
<script type="text/javascript" src="js/showdown-1.4.1.js" integrity="sha512-Kbz1FIlDnqUJu/3yW8H8USzURA3JuUqSKRwz13lM4kWt6C0n6s4tjl81PCfnWtE4gBIzyj5uGePcfUyotk/icw==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-6To0UBu7oCGa0oX6b669PoOK6vB5P8InWcV6OcBJt8v+RO6QJgP5RF6tiPlE5YSMlXtFpJz8bohe84saAgRspg==" 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]-->
<link rel="apple-touch-icon" href="apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
<link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" />
<link rel="mask-icon" href="safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" />
<link rel="shortcut icon" href="favicon.ico">
<meta name="msapplication-config" content="browserconfig.xml">
<meta name="theme-color" content="#ffe57e" />
</head>
<body role="document">
<div id="passwordmodal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form id="passwordform" role="form">
<div class="form-group">
<label for="passworddecrypt"><span class="glyphicon glyphicon-eye-open"></span> <?php echo I18n::_('Please enter the password for this paste:') ?></label>
<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>" autofocus>
</div>
<button type="submit" class="btn btn-success btn-block"><span class="glyphicon glyphicon-off"></span> <?php echo I18n::_('Decrypt') ?></button>
</form>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-inverse navbar-static-top">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="reloadlink navbar-brand" href="">
<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="38" />
</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>
<button id="sendbutton" type="button" class="hidden btn btn-warning navbar-btn">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL; ?>
</button>
<?php
if ($EXPIRECLONE):
?>
<button id="clonebutton" type="button" class="hidden btn btn-warning navbar-btn">
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'), PHP_EOL; ?>
</button>
<?php
endif;
?>
<button id="rawtextbutton" type="button" class="hidden btn btn-warning navbar-btn">
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
</button>
</li>
<li class="dropdown">
<select id="pasteExpiration" name="pasteExpiration" class="hidden">
<?php
foreach ($EXPIRE as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $EXPIREDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($EXPIRE as $key => $value):
?>
<li>
<a href="#" data-expiration="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<li>
<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
<label>
<input type="checkbox" id="burnafterreading" name="burnafterreading"<?php
if ($BURNAFTERREADINGSELECTED):
?> checked="checked"<?php
endif;
?> />
<?php echo I18n::_('Burn after reading'), PHP_EOL; ?>
</label>
</div>
</li>
<?php
if ($DISCUSSION):
?>
<li>
<div id="opendisc" class="navbar-text checkbox hidden">
<label>
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
if ($OPENDISCUSSION):
?> checked="checked"<?php
endif;
?> />
<?php echo I18n::_('Open discussion'), PHP_EOL; ?>
</label>
</div>
</li>
<?php
endif;
if ($PASSWORD):
?>
<li>
<div id="password" class="navbar-form hidden">
<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
</div>
</li>
<?php
endif;
if ($FILEUPLOAD):
?>
<li id="attach" class="hidden dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li id="filewrap">
<div>
<input type="file" id="file" name="file" />
</div>
</li>
<li>
<a id="fileremovebutton" href="#">
<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
</a>
</li>
</ul>
</li>
<?php
endif;
?>
<li class="dropdown">
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php
foreach ($FORMATTER as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($FORMATTER as $key => $value):
?>
<li>
<a href="#" data-format="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
</ul>
<ul class="nav navbar-nav pull-right">
<?php
if (strlen($LANGUAGESELECTION)):
?>
<li id="language" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($LANGUAGES as $key => $value):
?>
<li>
<a href="#" data-lang="<?php echo $key; ?>">
<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<?php
endif;
?>
<li>
<button id="newbutton" type="button" class="reloadlink hidden btn btn-warning navbar-btn">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL; ?>
</button>
</li>
</ul>
</div>
</nav>
<header class="container">
<?php
if (strlen($NOTICE)):
?>
<div role="alert" class="alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE), PHP_EOL; ?>
</div>
<?php
endif;
?>
<div id="remainingtime" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
</div>
<?php
if ($FILEUPLOAD):
?>
<div id="attachment" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
</div>
<?php
endif;
if (strlen($STATUS)):
?>
<div id="status" role="alert" class="alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
</div>
<?php
endif;
?>
<div id="errormessage" role="alert" class="<?php
if (!strlen($ERROR)):
?>hidden <?php
endif;
?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
<noscript><div id="noscript" role="alert" class="nonworking alert alert-error"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
<div id="ienotice" role="alert" class="hidden alert alert-error"><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>,
<a href="https://www.apple.com/safari">Safari</a>...
</div>
<div id="pasteresult" role="alert" class="hidden alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
<div id="deletelink"></div>
<div id="pastelink">
<?php
if (strlen($URLSHORTENER)):
?>
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-warning">
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
<?php
endif;
?>
</div>
</div>
<ul id="preview" 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>
</ul>
</header>
<section class="container">
<article class="row">
<div id="image" class="col-md-12 text-center hidden"></div>
<div id="prettymessage" class="col-md-12 hidden">
<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
</div>
<div id="cleartext" class="col-md-12 hidden"></div>
<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
</article>
</section>
<section class="container">
<div id="discussion" class="hidden">
<h4><?php echo I18n::_('Discussion'); ?></h4>
<div id="comments"></div>
</div>
</section>
<section class="container">
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">
<span> <?php echo I18n::_('Loading…'); ?></span><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>
</div>
</section>
<footer class="container">
<div class="row">
<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
<p id="aboutbox" class="col-md-6 col-xs-12">
<?php echo I18n::_('PrivateBin 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>.'), PHP_EOL; ?>
</p>
</div>
</footer>
<div id="cipherdata" class="hidden"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>
</body>
</html>

359
tpl/bootstrap-dark.php Normal file
View File

@@ -0,0 +1,359 @@
<?php
use PrivateBin\I18n;
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<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">
<title><?php echo I18n::_('PrivateBin'); ?></title>
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
<link type="text/css" rel="stylesheet" href="css/bootstrap/darkstrap-0.9.3.css" />
<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if ($SYNTAXHIGHLIGHTING):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
endif;
endif;
?>
<noscript><link type="text/css" rel="stylesheet" href="css/noscript.css" /></noscript>
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/sjcl-1.0.4.js" integrity="sha512-BqVQ8GgWfMCcdsDuP6Ggm1BV7+mmoWH3PC4UqcYpEKSdEq1rthy6NUsa6gu5sydewbi/ilI3E3ohdCxlPPF9ww==" crossorigin="anonymous"></script>
<?php
if ($ZEROBINCOMPATIBILITY):
?>
<script type="text/javascript" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
<?php
else:
?>
<script type="text/javascript" src="js/base64-2.1.9.js" integrity="sha512-rbqAby7hObftbEoGQzkhUbEh5YkUn2MtekTLs4btvo2oly4CZ3DxhJzEh0u/rNzS54tcJdqi5Ug1ruugEd2U1g==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" src="js/rawdeflate-0.5.js" integrity="sha512-tTdZ7qMr7tt5VQy4iCHu6/aGB12eRwbUy+AEI5rXntfsjcRfBeeqJloMsBU9FrGk1bIYLiuND/FhU42LO1bi0g==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/bootstrap-3.3.5.js" integrity="sha512-/W33QnLmSAP1fwINS9iXgB6s/VOIG9GVdIuIYaUtbSvKPMv5S08PtT3PqnT2WjwBgB8DFeDN2nqJroqQYF7SwQ==" crossorigin="anonymous"></script>
<?php
if ($SYNTAXHIGHLIGHTING):
?>
<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-m8iHxoN+Fe12xxFwWNdY/TS4KoFntHp29qY0xUzBnPd0bkKMOR/dFhEdTWydpt0b/fIXyhB+znGYUvgjfJ2RzQ==" crossorigin="anonymous"></script>
<?php
endif;
if ($MARKDOWN):
?>
<script type="text/javascript" src="js/showdown-1.4.1.js" integrity="sha512-Kbz1FIlDnqUJu/3yW8H8USzURA3JuUqSKRwz13lM4kWt6C0n6s4tjl81PCfnWtE4gBIzyj5uGePcfUyotk/icw==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-6To0UBu7oCGa0oX6b669PoOK6vB5P8InWcV6OcBJt8v+RO6QJgP5RF6tiPlE5YSMlXtFpJz8bohe84saAgRspg==" 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]-->
<link rel="apple-touch-icon" href="apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
<link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" />
<link rel="mask-icon" href="safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" />
<link rel="shortcut icon" href="favicon.ico">
<meta name="msapplication-config" content="browserconfig.xml">
<meta name="theme-color" content="#ffe57e" />
</head>
<body role="document">
<div id="passwordmodal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form id="passwordform" role="form">
<div class="form-group">
<label for="passworddecrypt"><span class="glyphicon glyphicon-eye-open"></span> <?php echo I18n::_('Please enter the password for this paste:') ?></label>
<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>" autofocus>
</div>
<button type="submit" class="btn btn-success btn-block"><span class="glyphicon glyphicon-off"></span> <?php echo I18n::_('Decrypt') ?></button>
</form>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-inverse navbar-static-top">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="reloadlink navbar-brand" href="">
<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="38" />
</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>
<button id="newbutton" type="button" class="reloadlink hidden btn btn-warning navbar-btn">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL; ?>
</button>
<?php
if ($EXPIRECLONE):
?>
<button id="clonebutton" type="button" class="hidden btn btn-warning navbar-btn">
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'), PHP_EOL; ?>
</button>
<?php
endif;
?>
<button id="rawtextbutton" type="button" class="hidden btn btn-warning navbar-btn">
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
</button>
</li>
<li class="dropdown">
<select id="pasteExpiration" name="pasteExpiration" class="hidden">
<?php
foreach ($EXPIRE as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $EXPIREDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($EXPIRE as $key => $value):
?>
<li>
<a href="#" data-expiration="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<li>
<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
<label>
<input type="checkbox" id="burnafterreading" name="burnafterreading"<?php
if ($BURNAFTERREADINGSELECTED):
?> checked<?php
endif;
?> />
<?php echo I18n::_('Burn after reading'), PHP_EOL; ?>
</label>
</div>
</li>
<?php
if ($DISCUSSION):
?>
<li>
<div id="opendisc" class="navbar-text checkbox hidden">
<label>
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
if ($OPENDISCUSSION):
?> checked<?php
endif;
?> />
<?php echo I18n::_('Open discussion'), PHP_EOL; ?>
</label>
</div>
</li>
<?php
endif;
if ($PASSWORD):
?>
<li>
<div id="password" class="navbar-form hidden">
<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
</div>
</li>
<?php
endif;
if ($FILEUPLOAD):
?>
<li id="attach" class="hidden dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li id="filewrap">
<div>
<input type="file" id="file" name="file" />
</div>
</li>
<li>
<a id="fileremovebutton" href="#">
<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
</a>
</li>
</ul>
</li>
<?php
endif;
?>
<li class="dropdown">
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php
foreach ($FORMATTER as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($FORMATTER as $key => $value):
?>
<li>
<a href="#" data-format="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
</ul>
<ul class="nav navbar-nav pull-right">
<?php
if (strlen($LANGUAGESELECTION)):
?>
<li id="language" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($LANGUAGES as $key => $value):
?>
<li>
<a href="#" data-lang="<?php echo $key; ?>">
<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<?php
endif;
?>
<li>
<button id="sendbutton" type="button" class="hidden btn btn-warning navbar-btn">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL; ?>
</button>
</li>
</ul>
</div>
</nav>
<header class="container">
<?php
if (strlen($NOTICE)):
?>
<div role="alert" class="alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE), PHP_EOL; ?>
</div>
<?php
endif;
?>
<div id="remainingtime" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
</div>
<?php
if ($FILEUPLOAD):
?>
<div id="attachment" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
</div>
<?php
endif;
if (strlen($STATUS)):
?>
<div id="status" role="alert" class="alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
</div>
<?php
endif;
?>
<div id="errormessage" role="alert" class="<?php
if (!strlen($ERROR)):
?>hidden <?php
endif;
?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
<noscript><div id="noscript" role="alert" class="nonworking alert alert-error"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
<div id="ienotice" role="alert" class="hidden alert alert-error"><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>,
<a href="https://www.apple.com/safari">Safari</a>...
</div>
<div id="pasteresult" role="alert" class="hidden alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
<div id="deletelink"></div>
<div id="pastelink">
<?php
if (strlen($URLSHORTENER)):
?>
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-warning">
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
<?php
endif;
?>
</div>
</div>
<ul id="preview" 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>
</ul>
</header>
<section class="container">
<article class="row">
<div id="image" class="col-md-12 text-center hidden"></div>
<div id="prettymessage" class="col-md-12 hidden">
<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
</div>
<div id="cleartext" class="col-md-12 hidden"></div>
<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
</article>
</section>
<section class="container">
<div id="discussion" class="hidden">
<h4><?php echo I18n::_('Discussion'); ?></h4>
<div id="comments"></div>
</div>
</section>
<section class="container">
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">
<span> <?php echo I18n::_('Loading…'); ?></span><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>
</div>
</section>
<footer class="container">
<div class="row">
<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
<p id="aboutbox" class="col-md-6 col-xs-12">
<?php echo I18n::_('PrivateBin 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>.'), PHP_EOL; ?>
</p>
</div>
</footer>
<div id="cipherdata" class="hidden"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>
</body>
</html>

358
tpl/bootstrap-page.php Normal file
View File

@@ -0,0 +1,358 @@
<?php
use PrivateBin\I18n;
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<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">
<title><?php echo I18n::_('PrivateBin'); ?></title>
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.3.5.css" />
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if ($SYNTAXHIGHLIGHTING):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
endif;
endif;
?>
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/sjcl-1.0.4.js" integrity="sha512-BqVQ8GgWfMCcdsDuP6Ggm1BV7+mmoWH3PC4UqcYpEKSdEq1rthy6NUsa6gu5sydewbi/ilI3E3ohdCxlPPF9ww==" crossorigin="anonymous"></script>
<?php
if ($ZEROBINCOMPATIBILITY):
?>
<script type="text/javascript" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
<?php
else:
?>
<script type="text/javascript" src="js/base64-2.1.9.js" integrity="sha512-rbqAby7hObftbEoGQzkhUbEh5YkUn2MtekTLs4btvo2oly4CZ3DxhJzEh0u/rNzS54tcJdqi5Ug1ruugEd2U1g==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" src="js/rawdeflate-0.5.js" integrity="sha512-tTdZ7qMr7tt5VQy4iCHu6/aGB12eRwbUy+AEI5rXntfsjcRfBeeqJloMsBU9FrGk1bIYLiuND/FhU42LO1bi0g==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/bootstrap-3.3.5.js" integrity="sha512-/W33QnLmSAP1fwINS9iXgB6s/VOIG9GVdIuIYaUtbSvKPMv5S08PtT3PqnT2WjwBgB8DFeDN2nqJroqQYF7SwQ==" crossorigin="anonymous"></script>
<?php
if ($SYNTAXHIGHLIGHTING):
?>
<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-m8iHxoN+Fe12xxFwWNdY/TS4KoFntHp29qY0xUzBnPd0bkKMOR/dFhEdTWydpt0b/fIXyhB+znGYUvgjfJ2RzQ==" crossorigin="anonymous"></script>
<?php
endif;
if ($MARKDOWN):
?>
<script type="text/javascript" src="js/showdown-1.4.1.js" integrity="sha512-Kbz1FIlDnqUJu/3yW8H8USzURA3JuUqSKRwz13lM4kWt6C0n6s4tjl81PCfnWtE4gBIzyj5uGePcfUyotk/icw==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-6To0UBu7oCGa0oX6b669PoOK6vB5P8InWcV6OcBJt8v+RO6QJgP5RF6tiPlE5YSMlXtFpJz8bohe84saAgRspg==" 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]-->
<link rel="apple-touch-icon" href="apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
<link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" />
<link rel="mask-icon" href="safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" />
<link rel="shortcut icon" href="favicon.ico">
<meta name="msapplication-config" content="browserconfig.xml">
<meta name="theme-color" content="#ffe57e" />
</head>
<body role="document">
<div id="passwordmodal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form id="passwordform" role="form">
<div class="form-group">
<label for="passworddecrypt"><span class="glyphicon glyphicon-eye-open"></span> <?php echo I18n::_('Please enter the password for this paste:') ?></label>
<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>" autofocus>
</div>
<button type="submit" class="btn btn-success btn-block"><span class="glyphicon glyphicon-off"></span> <?php echo I18n::_('Decrypt') ?></button>
</form>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-default navbar-static-top">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="reloadlink navbar-brand" href="">
<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="38" />
</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>
<button id="sendbutton" type="button" class="hidden btn btn-primary navbar-btn">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL; ?>
</button>
<?php
if ($EXPIRECLONE):
?>
<button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'), PHP_EOL; ?>
</button>
<?php
endif;
?>
<button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
</button>
</li>
<li class="dropdown">
<select id="pasteExpiration" name="pasteExpiration" class="hidden">
<?php
foreach ($EXPIRE as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $EXPIREDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($EXPIRE as $key => $value):
?>
<li>
<a href="#" data-expiration="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<li>
<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
<label>
<input type="checkbox" id="burnafterreading" name="burnafterreading"<?php
if ($BURNAFTERREADINGSELECTED):
?> checked="checked"<?php
endif;
?> />
<?php echo I18n::_('Burn after reading'), PHP_EOL; ?>
</label>
</div>
</li>
<?php
if ($DISCUSSION):
?>
<li>
<div id="opendisc" class="navbar-text checkbox hidden">
<label>
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
if ($OPENDISCUSSION):
?> checked="checked"<?php
endif;
?> />
<?php echo I18n::_('Open discussion'), PHP_EOL; ?>
</label>
</div>
</li>
<?php
endif;
if ($PASSWORD):
?>
<li>
<div id="password" class="navbar-form hidden">
<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
</div>
</li>
<?php
endif;
if ($FILEUPLOAD):
?>
<li id="attach" class="hidden dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li id="filewrap">
<div>
<input type="file" id="file" name="file" />
</div>
</li>
<li>
<a id="fileremovebutton" href="#">
<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
</a>
</li>
</ul>
</li>
<?php
endif;
?>
<li class="dropdown">
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php
foreach ($FORMATTER as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($FORMATTER as $key => $value):
?>
<li>
<a href="#" data-format="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
</ul>
<ul class="nav navbar-nav pull-right">
<?php
if (strlen($LANGUAGESELECTION)):
?>
<li id="language" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($LANGUAGES as $key => $value):
?>
<li>
<a href="#" data-lang="<?php echo $key; ?>">
<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
</a>
</li>
<?php
endforeach;
?>
</ul>
</li>
<?php
endif;
?>
<li>
<button id="newbutton" type="button" class="reloadlink hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL; ?>
</button>
</li>
</ul>
</div>
</nav>
<header class="container">
<?php
if (strlen($NOTICE)):
?>
<div role="alert" class="alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE), PHP_EOL; ?>
</div>
<?php
endif;
?>
<div id="remainingtime" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
</div>
<?php
if ($FILEUPLOAD):
?>
<div id="attachment" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
</div>
<?php
endif;
if (strlen($STATUS)):
?>
<div id="status" role="alert" class="alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
</div>
<?php
endif;
?>
<div id="errormessage" role="alert" class="<?php
if (!strlen($ERROR)):
?>hidden <?php
endif;
?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
<noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
<div id="ienotice" role="alert" class="hidden alert alert-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>,
<a href="https://www.apple.com/safari">Safari</a>...
</div>
<div id="pasteresult" role="alert" class="hidden alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
<div id="deletelink"></div>
<div id="pastelink">
<?php
if (strlen($URLSHORTENER)):
?>
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-primary">
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
<?php
endif;
?>
</div>
</div>
<ul id="preview" 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>
</ul>
</header>
<section class="container">
<article class="row">
<div id="image" class="col-md-12 text-center hidden"></div>
<div id="prettymessage" class="col-md-12 hidden">
<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
</div>
<div id="cleartext" class="col-md-12 hidden"></div>
<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
</article>
</section>
<section class="container">
<div id="discussion" class="hidden">
<h4><?php echo I18n::_('Discussion'); ?></h4>
<div id="comments"></div>
</div>
</section>
<section class="container">
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">
<span> <?php echo I18n::_('Loading…'); ?></span><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>
</div>
</section>
<footer class="container">
<div class="row">
<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
<p id="aboutbox" class="col-md-6 col-xs-12">
<?php echo I18n::_('PrivateBin 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>.'), PHP_EOL; ?>
</p>
</div>
</footer>
<div id="cipherdata" class="hidden"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>
</body>
</html>

View File

@@ -1,8 +1,5 @@
<?php <?php
use PrivateBin\I18n; use PrivateBin\I18n;
$isCpct = substr($template, 9, 8) === '-compact';
$isDark = substr($template, 9, 5) === '-dark';
$isPage = substr($template, -5) === '-page';
?><!DOCTYPE html> ?><!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@@ -11,22 +8,9 @@ $isPage = substr($template, -5) === '-page';
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex" /> <meta name="robots" content="noindex" />
<meta name="referrer" content="no-referrer"> <meta name="referrer" content="no-referrer">
<title><?php echo I18n::_($NAME); ?></title> <title><?php echo I18n::_('PrivateBin'); ?></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.3.5.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.3.5.css" />
<?php
if ($isDark):
?>
<link type="text/css" rel="stylesheet" href="css/bootstrap/darkstrap-0.9.3.css" />
<?php
endif;
?>
<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" /> <link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
<?php <?php
if ($SYNTAXHIGHLIGHTING): if ($SYNTAXHIGHLIGHTING):
@@ -42,7 +26,7 @@ endif;
?> ?>
<noscript><link type="text/css" rel="stylesheet" href="css/noscript.css" /></noscript> <noscript><link type="text/css" rel="stylesheet" href="css/noscript.css" /></noscript>
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/sjcl-1.0.6.js" integrity="sha512-DsyxLV/uBoQlRTJmW5Gb2SxXUXB+aYeZ6zk+NuXy8LuLyi8oGti9AGn6He5fUY2DtgQ2//RjfaZog8exFuunUQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/sjcl-1.0.4.js" integrity="sha512-BqVQ8GgWfMCcdsDuP6Ggm1BV7+mmoWH3PC4UqcYpEKSdEq1rthy6NUsa6gu5sydewbi/ilI3E3ohdCxlPPF9ww==" crossorigin="anonymous"></script>
<?php <?php
if ($ZEROBINCOMPATIBILITY): if ($ZEROBINCOMPATIBILITY):
?> ?>
@@ -56,7 +40,7 @@ endif;
?> ?>
<script type="text/javascript" src="js/rawdeflate-0.5.js" integrity="sha512-tTdZ7qMr7tt5VQy4iCHu6/aGB12eRwbUy+AEI5rXntfsjcRfBeeqJloMsBU9FrGk1bIYLiuND/FhU42LO1bi0g==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/rawdeflate-0.5.js" integrity="sha512-tTdZ7qMr7tt5VQy4iCHu6/aGB12eRwbUy+AEI5rXntfsjcRfBeeqJloMsBU9FrGk1bIYLiuND/FhU42LO1bi0g==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/bootstrap-3.3.7.js" integrity="sha512-iztkobsvnjKfAtTNdHkGVjAYTrrtlC7mGp/54c40wowO7LhURYl3gVzzcEqGl/qKXQltJ2HwMrdLcNUdo+N/RQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/bootstrap-3.3.5.js" integrity="sha512-/W33QnLmSAP1fwINS9iXgB6s/VOIG9GVdIuIYaUtbSvKPMv5S08PtT3PqnT2WjwBgB8DFeDN2nqJroqQYF7SwQ==" crossorigin="anonymous"></script>
<?php <?php
if ($SYNTAXHIGHLIGHTING): if ($SYNTAXHIGHLIGHTING):
?> ?>
@@ -65,28 +49,24 @@ if ($SYNTAXHIGHLIGHTING):
endif; endif;
if ($MARKDOWN): if ($MARKDOWN):
?> ?>
<script type="text/javascript" src="js/showdown-1.6.1.js" integrity="sha512-e6kAsBTgFnTBnEQXrq8BV6+XFwxb3kyWHeEPOl+KhxaWt3xImE2zAW2+yP3E2CQ7F9yoJl1poVU9qxkOEtVsTQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/showdown-1.4.1.js" integrity="sha512-Kbz1FIlDnqUJu/3yW8H8USzURA3JuUqSKRwz13lM4kWt6C0n6s4tjl81PCfnWtE4gBIzyj5uGePcfUyotk/icw==" crossorigin="anonymous"></script>
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-vYYJYraxQNOf41XtehLBU2JbIQ2Uffe+n8TjHyWkpqoZdZX4aL5zyABrUNvRUP02+AxoRsmNJkpvIbmeQqcIXg==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-6To0UBu7oCGa0oX6b669PoOK6vB5P8InWcV6OcBJt8v+RO6QJgP5RF6tiPlE5YSMlXtFpJz8bohe84saAgRspg==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" /> <link rel="apple-touch-icon" href="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="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" /> <link rel="icon" type="image/png" href="favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
<link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" /> <link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" />
<link rel="mask-icon" href="img/safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" /> <link rel="mask-icon" href="safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" />
<link rel="shortcut icon" href="img/favicon.ico"> <link rel="shortcut icon" href="favicon.ico">
<meta name="msapplication-config" content="browserconfig.xml"> <meta name="msapplication-config" content="browserconfig.xml">
<meta name="theme-color" content="#ffe57e" /> <meta name="theme-color" content="#ffe57e" />
</head> </head>
<body role="document"<?php <body role="document">
if ($isCpct):
?> class="navbar-spacing"<?php
endif;
?>>
<div id="passwordmodal" class="modal fade" role="dialog"> <div id="passwordmodal" class="modal fade" role="dialog">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
@@ -102,11 +82,7 @@ endif;
</div> </div>
</div> </div>
</div> </div>
<nav class="navbar navbar-<?php echo $isDark ? 'inverse' : 'default'; ?> navbar-<?php echo $isCpct ? 'fixed' : 'static'; ?>-top"><?php <nav class="navbar navbar-default navbar-static-top">
if ($isCpct):
?><div class="container"><?php
endif;
?>
<div class="navbar-header"> <div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span> <span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
@@ -115,38 +91,25 @@ endif;
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="reloadlink navbar-brand" href=""> <a class="reloadlink navbar-brand" href="">
<img alt="<?php echo I18n::_($NAME); ?>" src="img/icon.svg" width="38" /> <img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="38" />
</a> </a>
</div> </div>
<div id="navbar" class="navbar-collapse collapse"> <div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li id="loadingindicator" class="navbar-text hidden">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span>
<?php echo I18n::_('Uploading paste… Please wait.'), PHP_EOL; ?>
</li>
<li> <li>
<?php <button id="newbutton" type="button" class="reloadlink hidden btn btn-default navbar-btn">
if ($isPage): <span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL; ?>
?>
<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;
else:
?>
<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;
endif;
?>
</button> </button>
<?php <?php
if ($EXPIRECLONE): if ($EXPIRECLONE):
?> ?>
<button id="clonebutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn"> <button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'), PHP_EOL; ?> <span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'), PHP_EOL; ?>
</button> </button>
<?php <?php
endif; endif;
?> ?>
<button id="rawtextbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn"> <button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn">
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?> <span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
</button> </button>
</li> </li>
@@ -179,102 +142,34 @@ endforeach;
?> ?>
</ul> </ul>
</li> </li>
<?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>
<ul class="dropdown-menu">
<li id="burnafterreadingoption" class="checkbox hidden">
<label>
<input type="checkbox" id="burnafterreading" name="burnafterreading"<?php
if ($BURNAFTERREADINGSELECTED):
?> checked="checked"<?php
endif;
?> />
<?php echo I18n::_('Burn after reading'), PHP_EOL; ?>
</label>
</li>
<?php
if ($DISCUSSION):
?>
<li id="opendisc" class="checkbox hidden">
<label>
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
if ($OPENDISCUSSION):
?> checked="checked"<?php
endif;
?> />
<?php echo I18n::_('Open discussion'), PHP_EOL; ?>
</label>
</li>
<?php
endif;
?>
<li role="separator" class="divider"></li>
<li>
<div>
<?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span>
</div>
</li>
<?php
foreach ($FORMATTER as $key => $value):
?>
<li>
<a href="#" data-format="<?php echo $key; ?>">
<?php echo $value, PHP_EOL; ?>
</a>
</li>
<?php
endforeach;
?>
</ul>
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php
foreach ($FORMATTER as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select>
</li>
<?php
else:
?>
<li> <li>
<div id="burnafterreadingoption" class="navbar-text checkbox hidden"> <div id="burnafterreadingoption" class="navbar-text checkbox hidden">
<label> <label>
<input type="checkbox" id="burnafterreading" name="burnafterreading"<?php <input type="checkbox" id="burnafterreading" name="burnafterreading"<?php
if ($BURNAFTERREADINGSELECTED): if ($BURNAFTERREADINGSELECTED):
?> checked="checked"<?php ?> checked="checked"<?php
endif; endif;
?> /> ?> />
<?php echo I18n::_('Burn after reading'), PHP_EOL; ?> <?php echo I18n::_('Burn after reading'), PHP_EOL; ?>
</label> </label>
</div> </div>
</li> </li>
<?php <?php
if ($DISCUSSION): if ($DISCUSSION):
?> ?>
<li> <li>
<div id="opendisc" class="navbar-text checkbox hidden"> <div id="opendisc" class="navbar-text checkbox hidden">
<label> <label>
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php <input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
if ($OPENDISCUSSION): if ($OPENDISCUSSION):
?> checked="checked"<?php ?> checked="checked"<?php
endif; endif;
?> /> ?> />
<?php echo I18n::_('Open discussion'), PHP_EOL; ?> <?php echo I18n::_('Open discussion'), PHP_EOL; ?>
</label> </label>
</div> </div>
</li> </li>
<?php <?php
endif;
endif; endif;
if ($PASSWORD): if ($PASSWORD):
?> ?>
@@ -304,26 +199,25 @@ if ($FILEUPLOAD):
</li> </li>
<?php <?php
endif; endif;
if (!$isCpct):
?> ?>
<li class="dropdown"> <li class="dropdown">
<select id="pasteFormatter" name="pasteFormatter" class="hidden"> <select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php <?php
foreach ($FORMATTER as $key => $value): foreach ($FORMATTER as $key => $value):
?> ?>
<option value="<?php echo $key; ?>"<?php <option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT): if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php ?> selected="selected"<?php
endif; endif;
?>><?php echo $value; ?></option> ?>><?php echo $value; ?></option>
<?php <?php
endforeach; endforeach;
?> ?>
</select> </select>
<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a> <a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<?php <?php
foreach ($FORMATTER as $key => $value): foreach ($FORMATTER as $key => $value):
?> ?>
<li> <li>
<a href="#" data-format="<?php echo $key; ?>"> <a href="#" data-format="<?php echo $key; ?>">
@@ -331,13 +225,10 @@ if (!$isCpct):
</a> </a>
</li> </li>
<?php <?php
endforeach; endforeach;
?> ?>
</ul> </ul>
</li> </li>
<?php
endif;
?>
</ul> </ul>
<ul class="nav navbar-nav pull-right"> <ul class="nav navbar-nav pull-right">
<?php <?php
@@ -363,26 +254,13 @@ if (strlen($LANGUAGESELECTION)):
endif; endif;
?> ?>
<li> <li>
<?php <button id="sendbutton" type="button" class="hidden btn btn-primary navbar-btn">
if ($isPage): <span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL; ?>
?>
<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> </button>
</li> </li>
</ul> </ul>
</div> </div>
<?php </nav>
if ($isCpct):
?></div><?php
endif;
?></nav>
<header class="container"> <header class="container">
<?php <?php
if (strlen($NOTICE)): if (strlen($NOTICE)):
@@ -417,9 +295,9 @@ if (!strlen($ERROR)):
?>hidden <?php ?>hidden <?php
endif; endif;
?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div> ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
<noscript><div id="noscript" role="alert" class="nonworking 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)); ?></div></noscript> <noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('JavaScript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)); ?></div> <div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></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; ?> <div id="ienotice" role="alert" class="hidden alert alert-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.mozilla.org/firefox/">Firefox</a>,
<a href="https://www.opera.com/">Opera</a>, <a href="https://www.opera.com/">Opera</a>,
<a href="https://www.google.com/chrome">Chrome</a>, <a href="https://www.google.com/chrome">Chrome</a>,
@@ -432,7 +310,7 @@ endif;
<?php <?php
if (strlen($URLSHORTENER)): if (strlen($URLSHORTENER)):
?> ?>
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?>"> <button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-primary">
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?> <span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button> </button>
<?php <?php
@@ -469,10 +347,10 @@ endif;
</section> </section>
<footer class="container"> <footer class="container">
<div class="row"> <div class="row">
<h4 class="col-md-5 col-xs-8"><?php echo I18n::_($NAME); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4> <h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p> <p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
<p id="aboutbox" class="col-md-6 col-xs-12"> <p id="aboutbox" class="col-md-6 col-xs-12">
<?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)), PHP_EOL; ?> <?php echo I18n::_('PrivateBin 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>.'), PHP_EOL; ?>
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -6,7 +6,7 @@ use PrivateBin\I18n;
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="robots" content="noindex" /> <meta name="robots" content="noindex" />
<meta name="referrer" content="no-referrer"> <meta name="referrer" content="no-referrer">
<title><?php echo I18n::_($NAME); ?></title> <title><?php echo I18n::_('PrivateBin'); ?></title>
<link type="text/css" rel="stylesheet" href="css/privatebin.css?<?php echo rawurlencode($VERSION); ?>" /> <link type="text/css" rel="stylesheet" href="css/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
<?php <?php
if ($SYNTAXHIGHLIGHTING): if ($SYNTAXHIGHLIGHTING):
@@ -21,7 +21,7 @@ if ($SYNTAXHIGHLIGHTING):
endif; endif;
?> ?>
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="js/sjcl-1.0.6.js" integrity="sha512-DsyxLV/uBoQlRTJmW5Gb2SxXUXB+aYeZ6zk+NuXy8LuLyi8oGti9AGn6He5fUY2DtgQ2//RjfaZog8exFuunUQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/sjcl-1.0.4.js" integrity="sha512-BqVQ8GgWfMCcdsDuP6Ggm1BV7+mmoWH3PC4UqcYpEKSdEq1rthy6NUsa6gu5sydewbi/ilI3E3ohdCxlPPF9ww==" crossorigin="anonymous"></script>
<?php <?php
if ($ZEROBINCOMPATIBILITY): if ($ZEROBINCOMPATIBILITY):
?> ?>
@@ -43,27 +43,27 @@ if ($SYNTAXHIGHLIGHTING):
endif; endif;
if ($MARKDOWN): if ($MARKDOWN):
?> ?>
<script type="text/javascript" src="js/showdown-1.6.1.js" integrity="sha512-e6kAsBTgFnTBnEQXrq8BV6+XFwxb3kyWHeEPOl+KhxaWt3xImE2zAW2+yP3E2CQ7F9yoJl1poVU9qxkOEtVsTQ==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/showdown-1.4.1.js" integrity="sha512-Kbz1FIlDnqUJu/3yW8H8USzURA3JuUqSKRwz13lM4kWt6C0n6s4tjl81PCfnWtE4gBIzyj5uGePcfUyotk/icw==" crossorigin="anonymous"></script>
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-vYYJYraxQNOf41XtehLBU2JbIQ2Uffe+n8TjHyWkpqoZdZX4aL5zyABrUNvRUP02+AxoRsmNJkpvIbmeQqcIXg==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-6To0UBu7oCGa0oX6b669PoOK6vB5P8InWcV6OcBJt8v+RO6QJgP5RF6tiPlE5YSMlXtFpJz8bohe84saAgRspg==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" /> <link rel="apple-touch-icon" href="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="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" /> <link rel="icon" type="image/png" href="favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
<link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" /> <link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" />
<link rel="mask-icon" href="img/safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" /> <link rel="mask-icon" href="safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" />
<link rel="shortcut icon" href="img/favicon.ico"> <link rel="shortcut icon" href="favicon.ico">
<meta name="msapplication-config" content="browserconfig.xml"> <meta name="msapplication-config" content="browserconfig.xml">
<meta name="theme-color" content="#ffe57e" /> <meta name="theme-color" content="#ffe57e" />
</head> </head>
<body> <body>
<header> <header>
<div id="aboutbox"> <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 /> <?php echo I18n::_('PrivateBin 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>.'); ?><br />
<?php <?php
if (strlen($NOTICE)): if (strlen($NOTICE)):
?> ?>
@@ -71,11 +71,11 @@ if (strlen($NOTICE)):
endif; endif;
?> ?>
</div> </div>
<h1 class="title reloadlink"><?php echo I18n::_($NAME); ?></h1><br /> <h1 class="title reloadlink"><?php echo I18n::_('PrivateBin'); ?></h1><br />
<h2 class="title"><?php echo I18n::_('Because ignorance is bliss'); ?></h2><br /> <h2 class="title"><?php echo I18n::_('Because ignorance is bliss'); ?></h2><br />
<h3 class="title"><?php echo $VERSION; ?></h3> <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> <noscript><div id="noscript" class="nonworking"><?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
<div id="oldienotice" class="nonworking"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)); ?></div> <div id="oldienotice" class="nonworking"><?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
<div id="ienotice"><?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?> <div id="ienotice"><?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.mozilla.org/firefox/">Firefox</a>,
<a href="https://www.opera.com/">Opera</a>, <a href="https://www.opera.com/">Opera</a>,

View File

@@ -1,6 +1,5 @@
<?php <?php
use Eris\Generator;
use PrivateBin\Persistence\ServerSalt; use PrivateBin\Persistence\ServerSalt;
error_reporting(E_ALL | E_STRICT); error_reporting(E_ALL | E_STRICT);
@@ -13,10 +12,10 @@ if (!defined('PATH')) {
define('PATH', '..' . DIRECTORY_SEPARATOR); define('PATH', '..' . DIRECTORY_SEPARATOR);
} }
if (!defined('CONF')) { if (!defined('CONF')) {
define('CONF', PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini'); define('CONF', PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php');
} }
if (!is_file(CONF)) { if (!defined('CONF_SAMPLE')) {
copy(CONF . '.sample', CONF); define('CONF_SAMPLE', PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.sample.php');
} }
require PATH . 'vendor/autoload.php'; require PATH . 'vendor/autoload.php';
@@ -111,7 +110,7 @@ class Helper
} }
/** /**
* get example paste as JSON * get example paste
* *
* @return array * @return array
*/ */
@@ -130,68 +129,6 @@ class Helper
return json_encode($example); return json_encode($example);
} }
/**
* get paste generator
*
* @return array
*/
public static function getPasteGenerator($meta = array(), $withAttachment = false)
{
$generatedMeta = array(
'salt' => ServerSalt::generate(),
'formatter' => Generator\elements('plaintext', 'syntaxhighlighting', 'markdown'),
'postdate' => Generator\int(),
'opendiscussion' => Generator\elements(true, false),
);
$generatedMeta = array_merge($generatedMeta, $meta);
$example = array(
'data' => Generator\associative(array(
'iv' => Generator\vector(16, Generator\byte()),
'v' => 1,
'iter' => Generator\choose(100, 100000),
'ks' => Generator\elements(128, 192, 256),
'ts' => Generator\elements(64, 96, 128),
'mode' => Generator\elements('ccm', 'ocb2', 'gcm'),
'adata' => Generator\string(),
'cipher'=> 'aes',
'salt' => Generator\vector(8, Generator\byte()),
'ct' => Generator\seq(Generator\byte()),
)),
'meta' => Generator\associative($generatedMeta),
);
if ($withAttachment) {
$example['attachment'] = $example['attachmentname'] = $example['data'];
}
return Generator\associative($example);
}
/**
* get paste from generated random array
*
* @return array
*/
public static function getPasteFromGeneratedArray($paste)
{
$paste['data']['iv'] = self::byteArray2Base64($paste['data']['iv']);
$paste['data']['salt'] = self::byteArray2Base64($paste['data']['salt']);
// deflate cipher text to maximize entropy
$paste['data']['ct'] = self::byteArray2Base64($paste['data']['ct'], true);
$paste['data'] = json_encode($paste['data']);
if (array_key_exists('attachment', $paste)) {
$paste['attachment']['iv'] = self::byteArray2Base64($paste['attachment']['iv']);
$paste['attachment']['salt'] = self::byteArray2Base64($paste['attachment']['salt']);
$paste['attachment']['ct'] = self::byteArray2Base64($paste['attachment']['ct'], true);
$paste['attachment'] = json_encode($paste['attachment']);
}
if (array_key_exists('attachmentname', $paste)) {
$paste['attachmentname']['iv'] = self::byteArray2Base64($paste['attachmentname']['iv']);
$paste['attachmentname']['salt'] = self::byteArray2Base64($paste['attachmentname']['salt']);
$paste['attachmentname']['ct'] = self::byteArray2Base64($paste['attachmentname']['ct'], true);
$paste['attachmentname'] = json_encode($paste['attachmentname']);
}
return $paste;
}
/** /**
* get example paste ID * get example paste ID
* *
@@ -264,6 +201,9 @@ class Helper
if (!is_file(CONF . '.bak') && is_file(CONF)) { if (!is_file(CONF . '.bak') && is_file(CONF)) {
rename(CONF, CONF . '.bak'); rename(CONF, CONF . '.bak');
} }
if (!is_file(CONF_SAMPLE . '.bak') && is_file(CONF_SAMPLE)) {
copy(CONF_SAMPLE, CONF_SAMPLE . '.bak');
}
} }
/** /**
@@ -276,6 +216,9 @@ class Helper
if (is_file(CONF . '.bak')) { if (is_file(CONF . '.bak')) {
rename(CONF . '.bak', CONF); rename(CONF . '.bak', CONF);
} }
if (is_file(CONF_SAMPLE . '.bak')) {
rename(CONF_SAMPLE . '.bak', CONF_SAMPLE);
}
} }
/** /**
@@ -345,24 +288,6 @@ class Helper
} }
} }
/**
* get example paste ID
*
* @param array $bytes
* @return string
*/
public static function byteArray2Base64($bytes, $deflate = false)
{
$string = implode(
array_map('chr', $bytes)
);
// optional deflate to maximize entropy
if ($deflate) {
$string = gzdeflate($string);
}
return base64_encode($string);
}
/** /**
* update all templates with the latest SRI hashes for all JS files * update all templates with the latest SRI hashes for all JS files
* *

View File

@@ -12,7 +12,7 @@ class ConfigurationTest extends PHPUnit_Framework_TestCase
{ {
/* Setup Routine */ /* Setup Routine */
Helper::confBackup(); Helper::confBackup();
$this->_options = configuration::getDefaults(); $this->_options = Configuration::getDefaults();
$this->_options['model_options']['dir'] = PATH . $this->_options['model_options']['dir']; $this->_options['model_options']['dir'] = PATH . $this->_options['model_options']['dir'];
$this->_options['traffic']['dir'] = PATH . $this->_options['traffic']['dir']; $this->_options['traffic']['dir'] = PATH . $this->_options['traffic']['dir'];
$this->_options['purge']['dir'] = PATH . $this->_options['purge']['dir']; $this->_options['purge']['dir'] = PATH . $this->_options['purge']['dir'];
@@ -22,12 +22,14 @@ class ConfigurationTest extends PHPUnit_Framework_TestCase
public function tearDown() public function tearDown()
{ {
/* Tear Down Routine */ /* Tear Down Routine */
if (is_file(CONF)) {
unlink(CONF);
}
Helper::confRestore(); Helper::confRestore();
} }
public function testDefaultConfigFile() public function testDefaultConfigFile()
{ {
$this->assertTrue(copy(CONF . '.bak', CONF), 'copy default configuration file');
$conf = new Configuration; $conf = new Configuration;
$this->assertEquals($this->_options, $conf->get(), 'default configuration is correct'); $this->assertEquals($this->_options, $conf->get(), 'default configuration is correct');
} }
@@ -41,7 +43,9 @@ class ConfigurationTest extends PHPUnit_Framework_TestCase
public function testHandleMissingConfigFile() public function testHandleMissingConfigFile()
{ {
@unlink(CONF); if (is_file(CONF)) {
unlink(CONF);
}
$conf = new Configuration; $conf = new Configuration;
$this->assertEquals($this->_options, $conf->get(), 'returns correct defaults on missing file'); $this->assertEquals($this->_options, $conf->get(), 'returns correct defaults on missing file');
} }
@@ -135,4 +139,42 @@ class ConfigurationTest extends PHPUnit_Framework_TestCase
$conf = new Configuration; $conf = new Configuration;
$this->assertEquals('Database', $conf->getKey('class', 'model'), 'old db class gets renamed'); $this->assertEquals('Database', $conf->getKey('class', 'model'), 'old db class gets renamed');
} }
public function testHandleConfigFileRename()
{
$options = $this->_options;
Helper::createIniFile(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini.sample', $options);
$options['main']['opendiscussion'] = true;
$options['main']['fileupload'] = true;
$options['main']['template'] = 'darkstrap';
Helper::createIniFile(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', $options);
$conf = new Configuration;
$this->assertFileExists(CONF, 'old configuration file gets converted');
$this->assertFileNotExists(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', 'old configuration file gets removed');
$this->assertFileNotExists(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini.sample', 'old configuration sample file gets removed');
$this->assertTrue(
$conf->getKey('opendiscussion') &&
$conf->getKey('fileupload') &&
$conf->getKey('template') === 'darkstrap',
'configuration values get converted'
);
}
public function testRenameIniSample()
{
$iniSample = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini.sample';
Helper::createIniFile(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', $this->_options);
if (is_file(CONF)) {
unlink(CONF);
}
rename(CONF_SAMPLE, $iniSample);
new Configuration;
$this->assertFileNotExists($iniSample, 'old sample file gets removed');
$this->assertFileExists(CONF_SAMPLE, 'new sample file gets created');
$this->assertFileExists(CONF, 'old configuration file gets converted');
$this->assertFileNotExists(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', 'old configuration file gets removed');
}
} }

View File

@@ -159,7 +159,7 @@ new ConfigurationTestGenerator(array(
array( array(
'type' => 'RegExp', 'type' => 'RegExp',
'args' => array( 'args' => array(
'#<link[^>]+type="text/css"[^>]+rel="stylesheet"[^>]+href="css/privatebin\.css\\?\d+\.\d+"[^>]*/>#', '#<link[^>]+type="text/css"[^>]+rel="stylesheet"[^>]+href="css/privatebin\.css\\?\d[\d\.]+\d+"[^>]*/>#',
'$content', '$content',
'outputs "page" stylesheet correctly', 'outputs "page" stylesheet correctly',
), ),
@@ -179,7 +179,7 @@ new ConfigurationTestGenerator(array(
array( array(
'type' => 'NotRegExp', 'type' => 'NotRegExp',
'args' => array( 'args' => array(
'#<link[^>]+type="text/css"[^>]+rel="stylesheet"[^>]+href="css/privatebin\.css\\?\d+\.\d+"[^>]*/>#', '#<link[^>]+type="text/css"[^>]+rel="stylesheet"[^>]+href="css/privatebin\.css\\?\d[\d\.]+\d+"[^>]*/>#',
'$content', '$content',
'removes "page" stylesheet correctly', 'removes "page" stylesheet correctly',
), ),
@@ -344,7 +344,7 @@ class ConfigurationTestGenerator
*/ */
private function _writeConfigurationTest() private function _writeConfigurationTest()
{ {
$defaultOptions = parse_ini_file(CONF, true); $defaultOptions = parse_ini_file(CONF_SAMPLE, true);
$code = $this->_getHeader(); $code = $this->_getHeader();
foreach ($this->_configurations as $key => $conf) { foreach ($this->_configurations as $key => $conf) {
$fullOptions = array_replace_recursive($defaultOptions, $conf['options']); $fullOptions = array_replace_recursive($defaultOptions, $conf['options']);
@@ -425,7 +425,7 @@ class ConfigurationCombinationsTest extends PHPUnit_Framework_TestCase
{ {
/* Setup Routine */ /* Setup Routine */
Helper::confBackup(); Helper::confBackup();
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
$this->_model = Filesystem::getInstance(array('dir' => $this->_path)); $this->_model = Filesystem::getInstance(array('dir' => $this->_path));
ServerSalt::setPath($this->_path); ServerSalt::setPath($this->_path);
TrafficLimiter::setPath($this->_path); TrafficLimiter::setPath($this->_path);
@@ -435,9 +435,10 @@ class ConfigurationCombinationsTest extends PHPUnit_Framework_TestCase
public function tearDown() public function tearDown()
{ {
/* Tear Down Routine */ /* Tear Down Routine */
unlink(CONF);
Helper::confRestore(); Helper::confRestore();
Helper::rmDir($this->_path); Helper::rmDir($this->_path);
} }
public function reset($configuration = array()) public function reset($configuration = array())
{ {

View File

@@ -127,4 +127,49 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
$this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), $comment), 'unable to store broken comment'); $this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), $comment), 'unable to store broken comment');
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does still not exist'); $this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does still not exist');
} }
public function testOldFilesGetConverted()
{
// generate 10 (default purge batch size) pastes in the old format
$paste = Helper::getPaste();
$comment = Helper::getComment();
$commentid = Helper::getCommentId();
$ids = array();
for ($i = 0, $max = 10; $i < $max; ++$i) {
// PHPs mt_rand only supports 32 bit or up 0x7fffffff on 64 bit systems to be precise :-/
$dataid = str_pad(dechex(mt_rand(0, mt_getrandmax())), 8, '0', STR_PAD_LEFT) .
str_pad(dechex(mt_rand(0, mt_getrandmax())), 8, '0', STR_PAD_LEFT);
$storagedir = $this->_path . DIRECTORY_SEPARATOR . substr($dataid, 0, 2) .
DIRECTORY_SEPARATOR . substr($dataid, 2, 2) . DIRECTORY_SEPARATOR;
$ids[$dataid] = $storagedir;
if (!is_dir($storagedir)) {
mkdir($storagedir, 0700, true);
}
file_put_contents($storagedir . $dataid, json_encode($paste));
$storagedir .= $dataid . '.discussion' . DIRECTORY_SEPARATOR;
if (!is_dir($storagedir)) {
mkdir($storagedir, 0700, true);
}
file_put_contents($storagedir . $dataid . '.' . $commentid . '.' . $dataid, json_encode($comment));
}
// check that all 10 pastes were converted after the purge
$this->_model->purge(10);
foreach ($ids as $dataid => $storagedir) {
$this->assertFileExists($storagedir . $dataid . '.php', "paste $dataid exists in new format");
$this->assertFileNotExists($storagedir . $dataid, "old format paste $dataid got removed");
$this->assertTrue($this->_model->exists($dataid), "paste $dataid exists");
$this->assertEquals($this->_model->read($dataid), json_decode(json_encode($paste)), "paste $dataid wasn't modified in the conversion");
$storagedir .= $dataid . '.discussion' . DIRECTORY_SEPARATOR;
$this->assertFileExists($storagedir . $dataid . '.' . $commentid . '.' . $dataid . '.php', "comment of $dataid exists in new format");
$this->assertFileNotExists($storagedir . $dataid . '.' . $commentid . '.' . $dataid, "old format comment of $dataid got removed");
$this->assertTrue($this->_model->existsComment($dataid, $dataid, $commentid), "comment in paste $dataid exists");
$comment = json_decode(json_encode($comment));
$comment->id = $commentid;
$comment->parentid = $dataid;
$this->assertEquals($this->_model->readComments($dataid), array($comment->meta->postdate => $comment), "comment of $dataid wasn't modified in the conversion");
}
}
} }

View File

@@ -1,12 +1,9 @@
<?php <?php
use Eris\Generator;
use PrivateBin\Filter; use PrivateBin\Filter;
class FilterTest extends PHPUnit_Framework_TestCase class FilterTest extends PHPUnit_Framework_TestCase
{ {
use Eris\TestTrait;
public function testFilterStripsSlashesDeeply() public function testFilterStripsSlashesDeeply()
{ {
$this->assertEquals( $this->assertEquals(
@@ -17,40 +14,10 @@ class FilterTest extends PHPUnit_Framework_TestCase
public function testFilterMakesTimesHumanlyReadable() public function testFilterMakesTimesHumanlyReadable()
{ {
$this->forAll( $this->assertEquals('5 minutes', Filter::formatHumanReadableTime('5min'));
Generator\nat(), $this->assertEquals('90 seconds', Filter::formatHumanReadableTime('90sec'));
Generator\oneOf( $this->assertEquals('1 week', Filter::formatHumanReadableTime('1week'));
'sec', 'second', 'seconds' $this->assertEquals('6 months', Filter::formatHumanReadableTime('6months'));
)
)->then(
function ($int, $unit) {
$suffix = $int === 1 ? '' : 's';
$this->assertEquals($int . ' second' . $suffix, Filter::formatHumanReadableTime($int . $unit));
}
);
$this->forAll(
Generator\nat(),
Generator\oneOf(
'min', 'minute', 'minutes'
)
)->then(
function ($int, $unit) {
$suffix = $int === 1 ? '' : 's';
$this->assertEquals($int . ' minute' . $suffix, Filter::formatHumanReadableTime($int . $unit));
}
);
$this->forAll(
Generator\nat(),
Generator\oneOf(
'hour', 'hours', 'day', 'days', 'week', 'weeks',
'month', 'months', 'year', 'years'
)
)->then(
function ($int, $unit) {
$suffix = $int === 1 ? '' : 's';
$this->assertEquals($int . ' ' . rtrim($unit, 's') . $suffix, Filter::formatHumanReadableTime($int . $unit));
}
);
} }
/** /**
@@ -59,228 +26,55 @@ class FilterTest extends PHPUnit_Framework_TestCase
*/ */
public function testFilterFailTimesHumanlyReadable() public function testFilterFailTimesHumanlyReadable()
{ {
$this->forAll( Filter::formatHumanReadableTime('five_minutes');
Generator\string()
)->then(
function ($string) {
Filter::formatHumanReadableTime($string);
}
);
} }
public function testFilterMakesSizesHumanlyReadable() public function testFilterMakesSizesHumanlyReadable()
{ {
$this->forAll( $this->assertEquals('1 B', Filter::formatHumanReadableSize(1));
Generator\neg() $this->assertEquals('1 000 B', Filter::formatHumanReadableSize(1000));
)->then( $this->assertEquals('1.00 KiB', Filter::formatHumanReadableSize(1024));
function ($int) { $this->assertEquals('1.21 KiB', Filter::formatHumanReadableSize(1234));
$this->assertEquals(number_format($int, 0, '.', ' ') . ' B', Filter::formatHumanReadableSize($int));
}
);
$from = 0;
$exponent = 1024; $exponent = 1024;
$to = $exponent - 1; $this->assertEquals('1 000.00 KiB', Filter::formatHumanReadableSize(1000 * $exponent));
$this->forAll( $this->assertEquals('1.00 MiB', Filter::formatHumanReadableSize(1024 * $exponent));
Generator\choose($from, $to) $this->assertEquals('1.21 MiB', Filter::formatHumanReadableSize(1234 * $exponent));
)->then(
function ($int) {
$this->assertEquals(number_format($int, 0, '.', ' ') . ' B', Filter::formatHumanReadableSize($int));
}
);
$from = $exponent;
$exponent *= 1024; $exponent *= 1024;
$to = $exponent - 1; $this->assertEquals('1 000.00 MiB', Filter::formatHumanReadableSize(1000 * $exponent));
$this->forAll( $this->assertEquals('1.00 GiB', Filter::formatHumanReadableSize(1024 * $exponent));
Generator\choose($from, $to), $this->assertEquals('1.21 GiB', Filter::formatHumanReadableSize(1234 * $exponent));
$from
)->then(
function ($int, $divisor) {
$this->assertEquals(number_format($int / $divisor, 2, '.', ' ') . ' KiB', Filter::formatHumanReadableSize($int));
}
);
$from = $exponent;
$exponent *= 1024; $exponent *= 1024;
$to = $exponent - 1; $this->assertEquals('1 000.00 GiB', Filter::formatHumanReadableSize(1000 * $exponent));
$this->forAll( $this->assertEquals('1.00 TiB', Filter::formatHumanReadableSize(1024 * $exponent));
Generator\choose($from, $to), $this->assertEquals('1.21 TiB', Filter::formatHumanReadableSize(1234 * $exponent));
$from
)->then(
function ($int, $divisor) {
$this->assertEquals(number_format($int / $divisor, 2, '.', ' ') . ' MiB', Filter::formatHumanReadableSize($int));
}
);
$from = $exponent;
$exponent *= 1024; $exponent *= 1024;
$to = $exponent - 1; $this->assertEquals('1 000.00 TiB', Filter::formatHumanReadableSize(1000 * $exponent));
$this->forAll( $this->assertEquals('1.00 PiB', Filter::formatHumanReadableSize(1024 * $exponent));
Generator\choose($from, $to), $this->assertEquals('1.21 PiB', Filter::formatHumanReadableSize(1234 * $exponent));
$from
)->then(
function ($int, $divisor) {
$this->assertEquals(number_format($int / $divisor, 2, '.', ' ') . ' GiB', Filter::formatHumanReadableSize($int));
}
);
$from = $exponent;
$exponent *= 1024; $exponent *= 1024;
$to = $exponent - 1; $this->assertEquals('1 000.00 PiB', Filter::formatHumanReadableSize(1000 * $exponent));
$this->forAll( $this->assertEquals('1.00 EiB', Filter::formatHumanReadableSize(1024 * $exponent));
Generator\choose($from, $to), $this->assertEquals('1.21 EiB', Filter::formatHumanReadableSize(1234 * $exponent));
$from
)->then(
function ($int, $divisor) {
$this->assertEquals(number_format($int / $divisor, 2, '.', ' ') . ' TiB', Filter::formatHumanReadableSize($int));
}
);
$from = $exponent;
$exponent *= 1024; $exponent *= 1024;
$to = $exponent - 1; $this->assertEquals('1 000.00 EiB', Filter::formatHumanReadableSize(1000 * $exponent));
$this->forAll( $this->assertEquals('1.00 ZiB', Filter::formatHumanReadableSize(1024 * $exponent));
Generator\choose($from, $to), $this->assertEquals('1.21 ZiB', Filter::formatHumanReadableSize(1234 * $exponent));
$from
)->then(
function ($int, $divisor) {
$this->assertEquals(number_format($int / $divisor, 2, '.', ' ') . ' PiB', Filter::formatHumanReadableSize($int));
}
);
$from = $exponent;
$exponent *= 1024; $exponent *= 1024;
$to = $exponent - 1; $this->assertEquals('1 000.00 ZiB', Filter::formatHumanReadableSize(1000 * $exponent));
$this->assertEquals('1.00 YiB', Filter::formatHumanReadableSize(1024 * $exponent));
// on 64bit systems, this gets larger then PHP_INT_MAX, so PHP casts it $this->assertEquals('1.21 YiB', Filter::formatHumanReadableSize(1234 * $exponent));
// to double and the "choose" generator can't handle it
if ($to > PHP_INT_MAX) {
$this->assertEquals('1.00 EiB', Filter::formatHumanReadableSize($from));
$this->assertEquals('1.23 EiB', Filter::formatHumanReadableSize(1.234 * $from));
$this->assertEquals('1 000.00 EiB', Filter::formatHumanReadableSize(1000 * $from));
$this->assertEquals('1.00 ZiB', Filter::formatHumanReadableSize($exponent));
$this->assertEquals('1.23 ZiB', Filter::formatHumanReadableSize(1.234 * $exponent));
$this->assertEquals('1 000.00 ZiB', Filter::formatHumanReadableSize(1000 * $exponent));
$exponent *= 1024;
$this->assertEquals('1.00 YiB', Filter::formatHumanReadableSize($exponent));
$this->assertEquals('1.23 YiB', Filter::formatHumanReadableSize(1.234 * $exponent));
} else {
$this->forAll(
Generator\choose($from, $to),
$from
)->then(
function ($int, $divisor) {
$this->assertEquals(number_format($int / $divisor, 2, '.', ' ') . ' EiB', Filter::formatHumanReadableSize($int));
}
);
$from = $exponent;
$exponent *= 1024;
$to = $exponent - 1;
$this->forAll(
Generator\choose($from, $to),
$from
)->then(
function ($int, $divisor) {
$this->assertEquals(number_format($int / $divisor, 2, '.', ' ') . ' ZiB', Filter::formatHumanReadableSize($int));
}
);
$from = $exponent;
$exponent *= 1024;
$to = $exponent - 1;
$this->forAll(
Generator\choose($from, $to),
$from
)->then(
function ($int, $divisor) {
$this->assertEquals(number_format($int / $divisor, 2, '.', ' ') . ' YiB', Filter::formatHumanReadableSize($int));
}
);
}
} }
public function testSlowEquals() public function testSlowEquals()
{ {
$this->forAll( $this->assertTrue(Filter::slowEquals('foo', 'foo'), 'same string');
Generator\string() $this->assertFalse(Filter::slowEquals('foo', true), 'string and boolean');
)->then( $this->assertFalse(Filter::slowEquals('foo', 0), 'string and integer');
function ($string) { $this->assertFalse(Filter::slowEquals('123foo', 123), 'string and integer');
$this->assertTrue(Filter::slowEquals($string, $string), 'same string'); $this->assertFalse(Filter::slowEquals('123foo', '123'), 'different strings');
} $this->assertFalse(Filter::slowEquals('6', ' 6'), 'strings with space');
); $this->assertFalse(Filter::slowEquals('4.2', '4.20'), 'floats as strings');
$this->forAll( $this->assertFalse(Filter::slowEquals('1e3', '1000'), 'integers as strings');
Generator\int()
)->then(
function ($int) {
$this->assertTrue(Filter::slowEquals($int, $int), 'same integer');
}
);
$this->forAll(
Generator\float()
)->then(
function ($float) {
$this->assertTrue(Filter::slowEquals($float, $float), 'same float');
}
);
$this->forAll(
Generator\string()
)->then(
function ($string) {
$this->assertFalse(Filter::slowEquals($string, true), 'string and boolean true');
}
);
$this->forAll(
Generator\string()
)->then(
function ($string) {
// false is casted into an empty string
if ($string !== '') {
$this->assertFalse(Filter::slowEquals($string, false), 'string and boolean false');
}
}
);
$this->forAll(
Generator\string(),
Generator\int()
)->then(
function ($string, $int) {
$this->assertFalse(Filter::slowEquals($string, $int), 'string and integer');
}
);
$this->forAll(
Generator\string(),
Generator\float()
)->then(
function ($string, $float) {
$this->assertFalse(Filter::slowEquals($string, $float), 'string and float');
}
);
$this->forAll(
Generator\string(),
Generator\string()
)->then(
function ($string1, $string2) {
if ($string1 !== $string2) {
$this->assertFalse(Filter::slowEquals($string1, $string2), 'different strings');
}
}
);
$this->forAll(
Generator\string()
)->then(
function ($string) {
$this->assertFalse(Filter::slowEquals($string, ' ' . $string), 'strings with space');
}
);
$this->forAll(
Generator\float()
)->then(
function ($float) {
$this->assertFalse(Filter::slowEquals(strval($float), $float . '0'), 'floats as strings');
}
);
$this->forAll(
Generator\int()
)->then(
function ($int) {
$this->assertFalse(Filter::slowEquals($int . 'e3', $int . '000'), 'integers as strings');
}
);
// these two tests would be compared equal if casted to integers as they are larger then PHP_INT_MAX
$this->assertFalse(Filter::slowEquals('9223372036854775807', '9223372036854775808'), 'large integers as strings'); $this->assertFalse(Filter::slowEquals('9223372036854775807', '9223372036854775808'), 'large integers as strings');
$this->assertFalse(Filter::slowEquals('61529519452809720693702583126814', '61529519452809720000000000000000'), 'larger integers as strings'); $this->assertFalse(Filter::slowEquals('61529519452809720693702583126814', '61529519452809720000000000000000'), 'larger integers as strings');
} }

View File

@@ -33,9 +33,9 @@ class I18nTest extends PHPUnit_Framework_TestCase
$_COOKIE['lang'] = 'de'; $_COOKIE['lang'] = 'de';
I18n::loadTranslations(); I18n::loadTranslations();
$this->assertEquals($this->_translations['en'], I18n::_('en'), 'browser language de'); $this->assertEquals($this->_translations['en'], I18n::_('en'), 'browser language de');
$this->assertEquals('0 Stunden', I18n::_('%d hours', 0), '0 hours in German'); $this->assertEquals('0 Stunden', I18n::_('%d hours', 0), '0 hours in german');
$this->assertEquals('1 Stunde', I18n::_('%d hours', 1), '1 hour in German'); $this->assertEquals('1 Stunde', I18n::_('%d hours', 1), '1 hour in german');
$this->assertEquals('2 Stunden', I18n::_('%d hours', 2), '2 hours in German'); $this->assertEquals('2 Stunden', I18n::_('%d hours', 2), '2 hours in french');
} }
public function testBrowserLanguageDeDetection() public function testBrowserLanguageDeDetection()
@@ -43,9 +43,9 @@ class I18nTest extends PHPUnit_Framework_TestCase
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-CH,de;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2'; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-CH,de;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations(); I18n::loadTranslations();
$this->assertEquals($this->_translations['en'], I18n::_('en'), 'browser language de'); $this->assertEquals($this->_translations['en'], I18n::_('en'), 'browser language de');
$this->assertEquals('0 Stunden', I18n::_('%d hours', 0), '0 hours in German'); $this->assertEquals('0 Stunden', I18n::_('%d hours', 0), '0 hours in german');
$this->assertEquals('1 Stunde', I18n::_('%d hours', 1), '1 hour in German'); $this->assertEquals('1 Stunde', I18n::_('%d hours', 1), '1 hour in german');
$this->assertEquals('2 Stunden', I18n::_('%d hours', 2), '2 hours in German'); $this->assertEquals('2 Stunden', I18n::_('%d hours', 2), '2 hours in french');
} }
public function testBrowserLanguageFrDetection() public function testBrowserLanguageFrDetection()
@@ -53,39 +53,9 @@ class I18nTest extends PHPUnit_Framework_TestCase
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'fr-CH,fr;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2'; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'fr-CH,fr;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations(); I18n::loadTranslations();
$this->assertEquals('fr', I18n::_('en'), 'browser language fr'); $this->assertEquals('fr', I18n::_('en'), 'browser language fr');
$this->assertEquals('0 heure', I18n::_('%d hours', 0), '0 hours in French'); $this->assertEquals('0 heure', I18n::_('%d hours', 0), '0 hours in french');
$this->assertEquals('1 heure', I18n::_('%d hours', 1), '1 hour in French'); $this->assertEquals('1 heure', I18n::_('%d hours', 1), '1 hour in french');
$this->assertEquals('2 heures', I18n::_('%d hours', 2), '2 hours in French'); $this->assertEquals('2 heures', I18n::_('%d hours', 2), '2 hours in french');
}
public function testBrowserLanguageNoDetection()
{
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'no;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations();
$this->assertEquals('no', I18n::_('en'), 'browser language no');
$this->assertEquals('0 timer', I18n::_('%d hours', 0), '0 hours in Norwegian');
$this->assertEquals('1 time', I18n::_('%d hours', 1), '1 hour in Norwegian');
$this->assertEquals('2 timer', I18n::_('%d hours', 2), '2 hours in Norwegian');
}
public function testBrowserLanguageOcDetection()
{
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'oc;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations();
$this->assertEquals('oc', I18n::_('en'), 'browser language oc');
$this->assertEquals('0 ora', I18n::_('%d hours', 0), '0 hours in Occitan');
$this->assertEquals('1 ora', I18n::_('%d hours', 1), '1 hour in Occitan');
$this->assertEquals('2 oras', I18n::_('%d hours', 2), '2 hours in Occitan');
}
public function testBrowserLanguageZhDetection()
{
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'zh;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations();
$this->assertEquals('zh', I18n::_('en'), 'browser language zh');
$this->assertEquals('0 小时', I18n::_('%d hours', 0), '0 hours in Chinese');
$this->assertEquals('1 小时', I18n::_('%d hours', 1), '1 hour in Chinese');
$this->assertEquals('2 小时', I18n::_('%d hours', 2), '2 hours in Chinese');
} }
public function testBrowserLanguagePlDetection() public function testBrowserLanguagePlDetection()
@@ -93,14 +63,14 @@ class I18nTest extends PHPUnit_Framework_TestCase
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'pl;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2'; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'pl;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations(); I18n::loadTranslations();
$this->assertEquals('pl', I18n::_('en'), 'browser language pl'); $this->assertEquals('pl', I18n::_('en'), 'browser language pl');
$this->assertEquals('1 godzina', I18n::_('%d hours', 1), '1 hour in Polish'); $this->assertEquals('1 godzina', I18n::_('%d hours', 1), '1 hour in polish');
$this->assertEquals('2 godzina', I18n::_('%d hours', 2), '2 hours in Polish'); $this->assertEquals('2 godzina', I18n::_('%d hours', 2), '2 hours in polish');
$this->assertEquals('12 godzinę', I18n::_('%d hours', 12), '12 hours in Polish'); $this->assertEquals('12 godzinę', I18n::_('%d hours', 12), '12 hours in polish');
$this->assertEquals('22 godzina', I18n::_('%d hours', 22), '22 hours in Polish'); $this->assertEquals('22 godzina', I18n::_('%d hours', 22), '22 hours in polish');
$this->assertEquals('1 minut', I18n::_('%d minutes', 1), '1 minute in Polish'); $this->assertEquals('1 minut', I18n::_('%d minutes', 1), '1 minute in polish');
$this->assertEquals('3 minut', I18n::_('%d minutes', 3), '3 minutes in Polish'); $this->assertEquals('3 minut', I18n::_('%d minutes', 3), '3 minutes in polish');
$this->assertEquals('13 minut', I18n::_('%d minutes', 13), '13 minutes in Polish'); $this->assertEquals('13 minut', I18n::_('%d minutes', 13), '13 minutes in polish');
$this->assertEquals('23 minut', I18n::_('%d minutes', 23), '23 minutes in Polish'); $this->assertEquals('23 minut', I18n::_('%d minutes', 23), '23 minutes in polish');
} }
public function testBrowserLanguageRuDetection() public function testBrowserLanguageRuDetection()
@@ -108,25 +78,10 @@ class I18nTest extends PHPUnit_Framework_TestCase
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'ru;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2'; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'ru;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations(); I18n::loadTranslations();
$this->assertEquals('ru', I18n::_('en'), 'browser language ru'); $this->assertEquals('ru', I18n::_('en'), 'browser language ru');
$this->assertEquals('1 минуту', I18n::_('%d minutes', 1), '1 minute in Russian'); $this->assertEquals('1 минуту', I18n::_('%d minutes', 1), '1 minute in russian');
$this->assertEquals('3 минуты', I18n::_('%d minutes', 3), '3 minutes in Russian'); $this->assertEquals('3 минуты', I18n::_('%d minutes', 3), '3 minutes in russian');
$this->assertEquals('10 минут', I18n::_('%d minutes', 10), '10 minutes in Russian'); $this->assertEquals('10 минут', I18n::_('%d minutes', 10), '10 minutes in russian');
$this->assertEquals('21 минуту', I18n::_('%d minutes', 21), '21 minutes in Russian'); $this->assertEquals('21 минуту', I18n::_('%d minutes', 21), '21 minutes in russian');
}
public function testBrowserLanguageSlDetection()
{
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'sl;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations();
$this->assertEquals('sl', I18n::_('en'), 'browser language sl');
$this->assertEquals('0 ura', I18n::_('%d hours', 0), '0 hours in Slowene');
$this->assertEquals('1 uri', I18n::_('%d hours', 1), '1 hour in Slowene');
$this->assertEquals('2 ure', I18n::_('%d hours', 2), '2 hours in Slowene');
$this->assertEquals('3 ur', I18n::_('%d hours', 3), '3 hours in Slowene');
$this->assertEquals('11 ura', I18n::_('%d hours', 11), '11 hours in Slowene');
$this->assertEquals('101 uri', I18n::_('%d hours', 101), '101 hours in Slowene');
$this->assertEquals('102 ure', I18n::_('%d hours', 102), '102 hours in Slowene');
$this->assertEquals('104 ur', I18n::_('%d hours', 104), '104 hours in Slowene');
} }
public function testBrowserLanguageAnyDetection() public function testBrowserLanguageAnyDetection()

View File

@@ -14,30 +14,17 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
public function setUp() public function setUp()
{ {
/* Setup Routine */ /* Setup Routine */
Helper::confBackup();
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
$this->_model = Filesystem::getInstance(array('dir' => $this->_path)); $this->_model = Filesystem::getInstance(array('dir' => $this->_path));
ServerSalt::setPath($this->_path); ServerSalt::setPath($this->_path);
$this->reset();
}
public function tearDown()
{
/* Tear Down Routine */
Helper::confRestore();
Helper::rmDir($this->_path);
}
public function reset()
{
$_POST = array(); $_POST = array();
$_GET = array(); $_GET = array();
$_SERVER = array(); $_SERVER = array();
if ($this->_model->exists(Helper::getPasteId())) { if ($this->_model->exists(Helper::getPasteId())) {
$this->_model->delete(Helper::getPasteId()); $this->_model->delete(Helper::getPasteId());
} }
Helper::confRestore(); $options = parse_ini_file(CONF_SAMPLE, true);
$options = parse_ini_file(CONF, true);
$options['purge']['dir'] = $this->_path; $options['purge']['dir'] = $this->_path;
$options['traffic']['dir'] = $this->_path; $options['traffic']['dir'] = $this->_path;
$options['model_options']['dir'] = $this->_path; $options['model_options']['dir'] = $this->_path;
@@ -45,15 +32,21 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
} }
public function tearDown()
{
/* Tear Down Routine */
unlink(CONF);
Helper::confRestore();
Helper::rmDir($this->_path);
}
/** /**
* @runInSeparateProcess * @runInSeparateProcess
*/ */
public function testCreate() public function testCreate()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest'; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
@@ -80,10 +73,8 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testPut() public function testPut()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$paste = Helper::getPaste(); $paste = Helper::getPaste();
unset($paste['meta']); unset($paste['meta']);
@@ -116,7 +107,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testDelete() public function testDelete()
{ {
$this->reset();
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data'); $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
$paste = $this->_model->read(Helper::getPasteId()); $paste = $this->_model->read(Helper::getPasteId());
@@ -142,14 +132,14 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testDeleteWithPost() public function testDeleteWithPost()
{ {
$this->reset();
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data'); $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
$paste = $this->_model->read(Helper::getPasteId()); $paste = $this->_model->read(Helper::getPasteId());
$_POST = array( $_POST = array(
'pasteid' => Helper::getPasteId(), 'action' => 'delete',
'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste->meta->salt), 'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste->meta->salt),
); );
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest'; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST'; $_SERVER['REQUEST_METHOD'] = 'POST';
ob_start(); ob_start();
@@ -166,7 +156,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testRead() public function testRead()
{ {
$this->reset();
$paste = Helper::getPasteWithAttachment(); $paste = Helper::getPasteWithAttachment();
$paste['meta']['attachment'] = $paste['attachment']; $paste['meta']['attachment'] = $paste['attachment'];
$paste['meta']['attachmentname'] = $paste['attachmentname']; $paste['meta']['attachmentname'] = $paste['attachmentname'];
@@ -198,7 +187,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testJsonLdPaste() public function testJsonLdPaste()
{ {
$this->reset();
$paste = Helper::getPasteWithAttachment(); $paste = Helper::getPasteWithAttachment();
$this->_model->create(Helper::getPasteId(), $paste); $this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = 'paste'; $_GET['jsonld'] = 'paste';
@@ -218,7 +206,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testJsonLdComment() public function testJsonLdComment()
{ {
$this->reset();
$paste = Helper::getPasteWithAttachment(); $paste = Helper::getPasteWithAttachment();
$this->_model->create(Helper::getPasteId(), $paste); $this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = 'comment'; $_GET['jsonld'] = 'comment';
@@ -238,7 +225,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testJsonLdPasteMeta() public function testJsonLdPasteMeta()
{ {
$this->reset();
$paste = Helper::getPasteWithAttachment(); $paste = Helper::getPasteWithAttachment();
$this->_model->create(Helper::getPasteId(), $paste); $this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = 'pastemeta'; $_GET['jsonld'] = 'pastemeta';
@@ -258,7 +244,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testJsonLdCommentMeta() public function testJsonLdCommentMeta()
{ {
$this->reset();
$paste = Helper::getPasteWithAttachment(); $paste = Helper::getPasteWithAttachment();
$this->_model->create(Helper::getPasteId(), $paste); $this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = 'commentmeta'; $_GET['jsonld'] = 'commentmeta';
@@ -278,10 +263,9 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/ */
public function testJsonLdInvalid() public function testJsonLdInvalid()
{ {
$this->reset();
$paste = Helper::getPasteWithAttachment(); $paste = Helper::getPasteWithAttachment();
$this->_model->create(Helper::getPasteId(), $paste); $this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = '../cfg/conf.ini'; $_GET['jsonld'] = CONF;
ob_start(); ob_start();
new PrivateBin; new PrivateBin;
$content = ob_get_contents(); $content = ob_get_contents();

View File

@@ -20,13 +20,12 @@ class ModelTest extends PHPUnit_Framework_TestCase
public function setUp() public function setUp()
{ {
/* Setup Routine */ /* Setup Routine */
Helper::confRestore();
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
if (!is_dir($this->_path)) { if (!is_dir($this->_path)) {
mkdir($this->_path); mkdir($this->_path);
} }
ServerSalt::setPath($this->_path); ServerSalt::setPath($this->_path);
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF_SAMPLE, true);
$options['purge']['limit'] = 0; $options['purge']['limit'] = 0;
$options['model'] = array( $options['model'] = array(
'class' => 'Database', 'class' => 'Database',
@@ -47,6 +46,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
public function tearDown() public function tearDown()
{ {
/* Tear Down Routine */ /* Tear Down Routine */
unlink(CONF);
Helper::confRestore(); Helper::confRestore();
Helper::rmDir($this->_path); Helper::rmDir($this->_path);
} }
@@ -274,7 +274,6 @@ class ModelTest extends PHPUnit_Framework_TestCase
'pwd' => null, 'pwd' => null,
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
); );
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$model = new Model(new Configuration); $model = new Model(new Configuration);
@@ -329,7 +328,6 @@ class ModelTest extends PHPUnit_Framework_TestCase
'pwd' => null, 'pwd' => null,
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
); );
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$model = new Model(new Configuration); $model = new Model(new Configuration);
@@ -367,7 +365,6 @@ class ModelTest extends PHPUnit_Framework_TestCase
'pwd' => null, 'pwd' => null,
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
); );
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$model = new Model(new Configuration); $model = new Model(new Configuration);

View File

@@ -16,13 +16,13 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
/* Setup Routine */ /* Setup Routine */
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
$this->_model = Filesystem::getInstance(array('dir' => $this->_path)); $this->_model = Filesystem::getInstance(array('dir' => $this->_path));
ServerSalt::setPath($this->_path);
$this->reset(); $this->reset();
} }
public function tearDown() public function tearDown()
{ {
/* Tear Down Routine */ /* Tear Down Routine */
unlink(CONF);
Helper::confRestore(); Helper::confRestore();
Helper::rmDir($this->_path); Helper::rmDir($this->_path);
} }
@@ -35,13 +35,13 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
if ($this->_model->exists(Helper::getPasteId())) { if ($this->_model->exists(Helper::getPasteId())) {
$this->_model->delete(Helper::getPasteId()); $this->_model->delete(Helper::getPasteId());
} }
Helper::confRestore(); $options = parse_ini_file(CONF_SAMPLE, true);
$options = parse_ini_file(CONF, true);
$options['purge']['dir'] = $this->_path; $options['purge']['dir'] = $this->_path;
$options['traffic']['dir'] = $this->_path; $options['traffic']['dir'] = $this->_path;
$options['model_options']['dir'] = $this->_path; $options['model_options']['dir'] = $this->_path;
Helper::confBackup(); Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
ServerSalt::setPath($this->_path);
} }
/** /**
@@ -49,7 +49,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testView() public function testView()
{ {
$this->reset();
ob_start(); ob_start();
new PrivateBin; new PrivateBin;
$content = ob_get_contents(); $content = ob_get_contents();
@@ -71,10 +70,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testViewLanguageSelection() public function testViewLanguageSelection()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['main']['languageselection'] = true; $options['main']['languageselection'] = true;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_COOKIE['lang'] = 'de'; $_COOKIE['lang'] = 'de';
ob_start(); ob_start();
@@ -93,11 +90,9 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testViewForceLanguageDefault() public function testViewForceLanguageDefault()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['main']['languageselection'] = false; $options['main']['languageselection'] = false;
$options['main']['languagedefault'] = 'fr'; $options['main']['languagedefault'] = 'fr';
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_COOKIE['lang'] = 'de'; $_COOKIE['lang'] = 'de';
ob_start(); ob_start();
@@ -116,11 +111,9 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testViewUrlShortener() public function testViewUrlShortener()
{ {
$shortener = 'https://shortener.example.com/api?link='; $shortener = 'https://shortener.example.com/api?link=';
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['main']['urlshortener'] = $shortener; $options['main']['urlshortener'] = $shortener;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_COOKIE['lang'] = 'de'; $_COOKIE['lang'] = 'de';
ob_start(); ob_start();
@@ -139,7 +132,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testHtaccess() public function testHtaccess()
{ {
$this->reset();
$dirs = array('cfg', 'lib'); $dirs = array('cfg', 'lib');
foreach ($dirs as $dir) { foreach ($dirs as $dir) {
$file = PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess'; $file = PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess';
@@ -163,8 +155,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testConf() public function testConf()
{ {
$this->reset();
Helper::confBackup();
file_put_contents(CONF, ''); file_put_contents(CONF, '');
new PrivateBin; new PrivateBin;
} }
@@ -174,10 +164,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreate() public function testCreate()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest'; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
@@ -203,10 +191,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateInvalidTimelimit() public function testCreateInvalidTimelimit()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(array('expire' => 25)); $_POST = Helper::getPaste(array('expire' => 25));
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest'; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
@@ -233,11 +219,9 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateInvalidSize() public function testCreateInvalidSize()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['main']['sizelimit'] = 10; $options['main']['sizelimit'] = 10;
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest'; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
@@ -257,10 +241,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateProxyHeader() public function testCreateProxyHeader()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['header'] = 'X_FORWARDED_FOR'; $options['traffic']['header'] = 'X_FORWARDED_FOR';
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_SERVER['HTTP_X_FORWARDED_FOR'] = '::2'; $_SERVER['HTTP_X_FORWARDED_FOR'] = '::2';
@@ -287,10 +269,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateDuplicateId() public function testCreateDuplicateId()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
@@ -311,10 +291,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateValidExpire() public function testCreateValidExpire()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_POST['expire'] = '5min'; $_POST['expire'] = '5min';
@@ -344,10 +322,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateValidExpireWithDiscussion() public function testCreateValidExpireWithDiscussion()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_POST['expire'] = '5min'; $_POST['expire'] = '5min';
@@ -378,10 +354,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateInvalidExpire() public function testCreateInvalidExpire()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_POST['expire'] = 'foo'; $_POST['expire'] = 'foo';
@@ -408,10 +382,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateInvalidBurn() public function testCreateInvalidBurn()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_POST['burnafterreading'] = 'neither 1 nor 0'; $_POST['burnafterreading'] = 'neither 1 nor 0';
@@ -432,10 +404,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateInvalidOpenDiscussion() public function testCreateInvalidOpenDiscussion()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_POST['opendiscussion'] = 'neither 1 nor 0'; $_POST['opendiscussion'] = 'neither 1 nor 0';
@@ -456,11 +426,9 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateAttachment() public function testCreateAttachment()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
$options['main']['fileupload'] = true; $options['main']['fileupload'] = true;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPasteWithAttachment(); $_POST = Helper::getPasteWithAttachment();
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest'; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
@@ -494,11 +462,9 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateBrokenAttachmentUpload() public function testCreateBrokenAttachmentUpload()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
$options['main']['fileupload'] = true; $options['main']['fileupload'] = true;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPasteWithAttachment(); $_POST = Helper::getPasteWithAttachment();
unset($_POST['attachment']); unset($_POST['attachment']);
@@ -520,7 +486,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateTooSoon() public function testCreateTooSoon()
{ {
$this->reset();
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest'; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST'; $_SERVER['REQUEST_METHOD'] = 'POST';
@@ -543,10 +508,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateValidNick() public function testCreateValidNick()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste(); $_POST = Helper::getPaste();
$_POST['nickname'] = Helper::getComment()['meta']['nickname']; $_POST['nickname'] = Helper::getComment()['meta']['nickname'];
@@ -573,10 +536,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateInvalidNick() public function testCreateInvalidNick()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getCommentPost(); $_POST = Helper::getCommentPost();
$_POST['pasteid'] = Helper::getPasteId(); $_POST['pasteid'] = Helper::getPasteId();
@@ -600,10 +561,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateComment() public function testCreateComment()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getCommentPost(); $_POST = Helper::getCommentPost();
$_POST['pasteid'] = Helper::getPasteId(); $_POST['pasteid'] = Helper::getPasteId();
@@ -626,10 +585,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateInvalidComment() public function testCreateInvalidComment()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getCommentPost(); $_POST = Helper::getCommentPost();
$_POST['pasteid'] = Helper::getPasteId(); $_POST['pasteid'] = Helper::getPasteId();
@@ -652,10 +609,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateCommentDiscussionDisabled() public function testCreateCommentDiscussionDisabled()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getCommentPost(); $_POST = Helper::getCommentPost();
$_POST['pasteid'] = Helper::getPasteId(); $_POST['pasteid'] = Helper::getPasteId();
@@ -679,10 +634,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateCommentInvalidPaste() public function testCreateCommentInvalidPaste()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$_POST = Helper::getCommentPost(); $_POST = Helper::getCommentPost();
$_POST['pasteid'] = Helper::getPasteId(); $_POST['pasteid'] = Helper::getPasteId();
@@ -704,10 +657,8 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testCreateDuplicateComment() public function testCreateDuplicateComment()
{ {
$this->reset();
$options = parse_ini_file(CONF, true); $options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0; $options['traffic']['limit'] = 0;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()); $this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment());
@@ -732,7 +683,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testRead() public function testRead()
{ {
$this->reset();
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$_SERVER['QUERY_STRING'] = Helper::getPasteId(); $_SERVER['QUERY_STRING'] = Helper::getPasteId();
ob_start(); ob_start();
@@ -753,7 +703,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testReadInvalidId() public function testReadInvalidId()
{ {
$this->reset();
$_SERVER['QUERY_STRING'] = 'foo'; $_SERVER['QUERY_STRING'] = 'foo';
ob_start(); ob_start();
new PrivateBin; new PrivateBin;
@@ -771,7 +720,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testReadNonexisting() public function testReadNonexisting()
{ {
$this->reset();
$_SERVER['QUERY_STRING'] = Helper::getPasteId(); $_SERVER['QUERY_STRING'] = Helper::getPasteId();
ob_start(); ob_start();
new PrivateBin; new PrivateBin;
@@ -789,7 +737,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testReadExpired() public function testReadExpired()
{ {
$this->reset();
$expiredPaste = Helper::getPaste(array('expire_date' => 1344803344)); $expiredPaste = Helper::getPaste(array('expire_date' => 1344803344));
$this->_model->create(Helper::getPasteId(), $expiredPaste); $this->_model->create(Helper::getPasteId(), $expiredPaste);
$_SERVER['QUERY_STRING'] = Helper::getPasteId(); $_SERVER['QUERY_STRING'] = Helper::getPasteId();
@@ -809,7 +756,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testReadBurn() public function testReadBurn()
{ {
$this->reset();
$burnPaste = Helper::getPaste(array('burnafterreading' => true)); $burnPaste = Helper::getPaste(array('burnafterreading' => true));
$this->_model->create(Helper::getPasteId(), $burnPaste); $this->_model->create(Helper::getPasteId(), $burnPaste);
$_SERVER['QUERY_STRING'] = Helper::getPasteId(); $_SERVER['QUERY_STRING'] = Helper::getPasteId();
@@ -832,7 +778,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testReadJson() public function testReadJson()
{ {
$this->reset();
$paste = Helper::getPaste(); $paste = Helper::getPaste();
$this->_model->create(Helper::getPasteId(), $paste); $this->_model->create(Helper::getPasteId(), $paste);
$_SERVER['QUERY_STRING'] = Helper::getPasteId(); $_SERVER['QUERY_STRING'] = Helper::getPasteId();
@@ -858,7 +803,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testReadInvalidJson() public function testReadInvalidJson()
{ {
$this->reset();
$_SERVER['QUERY_STRING'] = Helper::getPasteId(); $_SERVER['QUERY_STRING'] = Helper::getPasteId();
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest'; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
ob_start(); ob_start();
@@ -874,7 +818,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testReadOldSyntax() public function testReadOldSyntax()
{ {
$this->reset();
$oldPaste = Helper::getPaste(); $oldPaste = Helper::getPaste();
$meta = array( $meta = array(
'syntaxcoloring' => true, 'syntaxcoloring' => true,
@@ -903,7 +846,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testReadOldFormat() public function testReadOldFormat()
{ {
$this->reset();
$oldPaste = Helper::getPaste(); $oldPaste = Helper::getPaste();
unset($oldPaste['meta']['formatter']); unset($oldPaste['meta']['formatter']);
$this->_model->create(Helper::getPasteId(), $oldPaste); $this->_model->create(Helper::getPasteId(), $oldPaste);
@@ -928,7 +870,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testDelete() public function testDelete()
{ {
$this->reset();
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data'); $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
$paste = $this->_model->read(Helper::getPasteId()); $paste = $this->_model->read(Helper::getPasteId());
@@ -951,7 +892,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testDeleteInvalidId() public function testDeleteInvalidId()
{ {
$this->reset();
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$_GET['pasteid'] = 'foo'; $_GET['pasteid'] = 'foo';
$_GET['deletetoken'] = 'bar'; $_GET['deletetoken'] = 'bar';
@@ -972,7 +912,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testDeleteInexistantId() public function testDeleteInexistantId()
{ {
$this->reset();
$_GET['pasteid'] = Helper::getPasteId(); $_GET['pasteid'] = Helper::getPasteId();
$_GET['deletetoken'] = 'bar'; $_GET['deletetoken'] = 'bar';
ob_start(); ob_start();
@@ -991,7 +930,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testDeleteInvalidToken() public function testDeleteInvalidToken()
{ {
$this->reset();
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$_GET['pasteid'] = Helper::getPasteId(); $_GET['pasteid'] = Helper::getPasteId();
$_GET['deletetoken'] = 'bar'; $_GET['deletetoken'] = 'bar';
@@ -1012,7 +950,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testDeleteBurnAfterReading() public function testDeleteBurnAfterReading()
{ {
$this->reset();
$burnPaste = Helper::getPaste(array('burnafterreading' => true)); $burnPaste = Helper::getPaste(array('burnafterreading' => true));
$this->_model->create(Helper::getPasteId(), $burnPaste); $this->_model->create(Helper::getPasteId(), $burnPaste);
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data'); $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
@@ -1034,7 +971,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testDeleteInvalidBurnAfterReading() public function testDeleteInvalidBurnAfterReading()
{ {
$this->reset();
$this->_model->create(Helper::getPasteId(), Helper::getPaste()); $this->_model->create(Helper::getPasteId(), Helper::getPaste());
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data'); $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
$_POST['deletetoken'] = 'burnafterreading'; $_POST['deletetoken'] = 'burnafterreading';
@@ -1047,7 +983,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
ob_end_clean(); ob_end_clean();
$response = json_decode($content, true); $response = json_decode($content, true);
$this->assertEquals(1, $response['status'], 'outputs status'); $this->assertEquals(1, $response['status'], 'outputs status');
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after failing to delete data'); $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
} }
/** /**
@@ -1055,7 +991,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testDeleteExpired() public function testDeleteExpired()
{ {
$this->reset();
$expiredPaste = Helper::getPaste(array('expire_date' => 1000)); $expiredPaste = Helper::getPaste(array('expire_date' => 1000));
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not exist before being created'); $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not exist before being created');
$this->_model->create(Helper::getPasteId(), $expiredPaste); $this->_model->create(Helper::getPasteId(), $expiredPaste);
@@ -1079,7 +1014,6 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
*/ */
public function testDeleteMissingPerPasteSalt() public function testDeleteMissingPerPasteSalt()
{ {
$this->reset();
$paste = Helper::getPaste(); $paste = Helper::getPaste();
unset($paste['meta']['salt']); unset($paste['meta']['salt']);
$this->_model->create(Helper::getPasteId(), $paste); $this->_model->create(Helper::getPasteId(), $paste);

View File

@@ -1,7 +1,6 @@
<?php <?php
use PrivateBin\Data\Database; use PrivateBin\Data\Database;
use PrivateBin\Persistence\ServerSalt;
require_once 'PrivateBinTest.php'; require_once 'PrivateBinTest.php';
@@ -23,7 +22,6 @@ class PrivateBinWithDbTest extends PrivateBinTest
if (!is_dir($this->_path)) { if (!is_dir($this->_path)) {
mkdir($this->_path); mkdir($this->_path);
} }
ServerSalt::setPath($this->_path);
$this->_options['dsn'] = 'sqlite:' . $this->_path . DIRECTORY_SEPARATOR . 'tst.sq3'; $this->_options['dsn'] = 'sqlite:' . $this->_path . DIRECTORY_SEPARATOR . 'tst.sq3';
$this->_model = Database::getInstance($this->_options); $this->_model = Database::getInstance($this->_options);
$this->reset(); $this->reset();
@@ -37,10 +35,7 @@ class PrivateBinWithDbTest extends PrivateBinTest
$options['model'] = array( $options['model'] = array(
'class' => 'Database', 'class' => 'Database',
); );
$options['purge']['dir'] = $this->_path;
$options['traffic']['dir'] = $this->_path;
$options['model_options'] = $this->_options; $options['model_options'] = $this->_options;
Helper::confBackup();
Helper::createIniFile(CONF, $options); Helper::createIniFile(CONF, $options);
} }
} }

View File

@@ -1,66 +1,20 @@
Running PHP unit tests Running unit tests
====================== ==================
In order to run these tests, you will need to install the following packages In order to run these tests, you will need to install the following packages
and its dependencies: and its dependencies:
* phpunit * phpunit
* php-gd * php-gd
* php-sqlite3 * php-sqlite3
* php-curl (optional, for codeclimate test reporter) * php-xdebug
* php-xdebug (optional, for code coverage reports)
* composer (to install eris property based unit tests)
Example for Debian and Ubuntu: Example for Debian and Ubuntu:
```console ```sh
$ sudo apt install phpunit php-gd php-sqlite php-curl php-xdebug composer $ sudo aptitude install phpunit php-gd php-sqlite php-xdebug
$ cd PrivateBin
$ composer update
``` ```
To run the tests, just change into this directory and run phpunit: To run the tests, just change into this directory and run phpunit:
```console ```sh
$ cd PrivateBin/tst $ cd PrivateBin/tst
$ phpunit $ phpunit
``` ```
Or you can also use the phpunit installed as dependency of eris by composer:
```console
$ cd PrivateBin/tst
$ ../vendor/phpunit/phpunit/phpunit
```
Running JavaScript unit tests
=============================
In order to run these tests, you will need to install the following packages
and its dependencies:
* npm
Then you can use the node package manager to install the latest stable release
of mocha and istanbul (for code coverage reports) globally and jsVerify, jsdom
and jsdom-global locally:
```console
$ npm install -g mocha istanbul
$ cd PrivateBin/js
$ npm install jsverify jsdom jsdom-global
```
Example for Debian and Ubuntu, including steps to allow current user to install
node modules globally:
```console
$ sudo apt install npm
$ sudo mkdir /usr/local/lib/node_modules
$ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
$ ln -s /usr/bin/nodejs /usr/local/bin/node
$ npm install -g mocha istanbul
$ cd PrivateBin/js
$ npm install jsverify jsdom jsdom-global
```
To run the tests, just change into the `js` directory and run istanbul:
```console
$ cd PrivateBin/js
$ istanbul cover _mocha
```

View File

@@ -1,88 +1,31 @@
<?php <?php
use Eris\Generator;
use PrivateBin\Sjcl; use PrivateBin\Sjcl;
class SjclTest extends PHPUnit_Framework_TestCase class SjclTest extends PHPUnit_Framework_TestCase
{ {
use Eris\TestTrait;
public function testSjclValidatorValidatesCorrectly() public function testSjclValidatorValidatesCorrectly()
{ {
$this->minimumEvaluationRatio(0.01)->forAll( $paste = Helper::getPasteWithAttachment();
Helper::getPasteGenerator(array(), true), $this->assertTrue(Sjcl::isValid($paste['data']), 'valid sjcl');
Generator\string(), $this->assertTrue(Sjcl::isValid($paste['attachment']), 'valid sjcl');
Generator\string(), $this->assertTrue(Sjcl::isValid($paste['attachmentname']), 'valid sjcl');
Generator\choose(0,100)
)->then(
function ($pasteArray, $key, $value, $lowInt) {
$paste = Helper::getPasteFromGeneratedArray($pasteArray);
$this->assertTrue(Sjcl::isValid($paste['data']), 'valid sjcl');
$this->assertTrue(Sjcl::isValid($paste['attachment']), 'valid sjcl');
$this->assertTrue(Sjcl::isValid($paste['attachmentname']), 'valid sjcl');
// common error cases
$this->assertFalse(Sjcl::isValid($value), 'non-json data');
$sjclArray = json_decode($paste['data'], true);
$sjclError = $sjclArray;
$sjclError['iv'] = '$' . $value;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'invalid base64 encoding of iv');
$sjclError = $sjclArray;
$sjclError['salt'] = '$' . $value;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'invalid base64 encoding of salt');
$sjclError = $sjclArray;
$sjclError['ct'] = '$' . $value;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'invalid base64 encoding of ct');
$sjclError = $sjclArray;
$sjclError['ct'] = 'bm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhCg==';
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'low ct entropy');
$sjclError = $sjclArray;
$sjclError['iv'] = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=';
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'iv to long');
$sjclError = $sjclArray;
$sjclError['salt'] = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=';
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'salt to long');
$sjclError = $sjclArray;
$sjclError[$key] = $value;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'invalid additional key');
if (!in_array($key, array('1', 'ccm', 'ocb2', 'gcm', 'aes'))) {
$sjclError = $sjclArray;
$sjclError['v'] = $key;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'unsupported version');
$sjclError = $sjclArray;
$sjclError['mode'] = $key;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'invalid mode');
$sjclError = $sjclArray;
$sjclError['cipher'] = $key;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'invalid cipher');
}
$sjclError = $sjclArray;
$sjclError['iter'] = $lowInt;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'not enough iterations');
if (!in_array($lowInt, array(64, 96))) {
$sjclError = $sjclArray;
$sjclError['ks'] = $lowInt;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'invalid key size');
$sjclError = $sjclArray;
$sjclError['ts'] = $lowInt;
$this->assertFalse(Sjcl::isValid(json_encode($sjclError)), 'invalid authentication strength');
}
// @note adata is not validated, except as part of the total message length
}
);
$this->assertTrue(Sjcl::isValid(Helper::getComment()['data']), 'valid sjcl'); $this->assertTrue(Sjcl::isValid(Helper::getComment()['data']), 'valid sjcl');
$this->assertTrue(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'valid sjcl');
$this->assertFalse(Sjcl::isValid('{"iv":"$","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of iv');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"$","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of salt');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"$"}'), 'invalid base64 encoding of ct');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"bm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhCg=="}'), 'low ct entropy');
$this->assertFalse(Sjcl::isValid('{"iv":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'iv to long');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'salt to long');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA","foo":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA="}'), 'invalid additional key');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":0.9,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'unsupported version');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":100,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'not enough iterations');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":127,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid key size');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":63,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid tag length');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"!#@","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid mode');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"!#@","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid cipher');
// @note adata is not validated, except as part of the total message length
} }
} }

View File

@@ -27,13 +27,12 @@ class ViewTest extends PHPUnit_Framework_TestCase
private static $version = 'Version 1.2.3'; private static $version = 'Version 1.2.3';
private $_content = array(); private $_content;
public function setUp() public function setUp()
{ {
/* Setup Routine */ /* Setup Routine */
$page = new View; $page = new View;
$page->assign('NAME', 'PrivateBinTest');
$page->assign('CIPHERDATA', Helper::getPaste()['data']); $page->assign('CIPHERDATA', Helper::getPaste()['data']);
$page->assign('ERROR', self::$error); $page->assign('ERROR', self::$error);
$page->assign('STATUS', self::$status); $page->assign('STATUS', self::$status);
@@ -51,41 +50,15 @@ class ViewTest extends PHPUnit_Framework_TestCase
$page->assign('ZEROBINCOMPATIBILITY', false); $page->assign('ZEROBINCOMPATIBILITY', false);
$page->assign('NOTICE', 'example'); $page->assign('NOTICE', 'example');
$page->assign('LANGUAGESELECTION', ''); $page->assign('LANGUAGESELECTION', '');
$page->assign('LANGUAGES', I18n::getLanguageLabels(I18n::getAvailableLanguages())); $page->assign('LANGUAGES', I18n::getLanguageLabels(i18n::getAvailableLanguages()));
$page->assign('EXPIRE', self::$expire); $page->assign('EXPIRE', self::$expire);
$page->assign('EXPIREDEFAULT', self::$expire_default); $page->assign('EXPIREDEFAULT', self::$expire_default);
$page->assign('EXPIRECLONE', true); $page->assign('EXPIRECLONE', true);
$page->assign('URLSHORTENER', ''); $page->assign('URLSHORTENER', '');
$dir = dir(PATH . 'tpl');
while (false !== ($file = $dir->read())) {
if (substr($file, -4) === '.php') {
$template = substr($file, 0, -4);
ob_start();
$page->draw($template);
$this->_content[$template] = ob_get_contents();
ob_end_clean();
}
}
// check bootstrap variants
$template = 'bootstrap-page';
ob_start(); ob_start();
$page->draw($template); $page->draw('page');
$this->_content[$template] = ob_get_contents(); $this->_content = ob_get_contents();
ob_end_clean(); ob_end_clean();
foreach (array('-dark', '-compact') as $suffix) {
$template = 'bootstrap' . $suffix;
ob_start();
$page->draw($template);
$this->_content[$template] = ob_get_contents();
ob_end_clean();
$template .= '-page';
ob_start();
$page->draw($template);
$this->_content[$template] = ob_get_contents();
ob_end_clean();
}
} }
public function tearDown() public function tearDown()
@@ -95,41 +68,39 @@ class ViewTest extends PHPUnit_Framework_TestCase
public function testTemplateRendersCorrectly() public function testTemplateRendersCorrectly()
{ {
foreach ($this->_content as $template => $content) { $this->assertContains(
$this->assertContains( '<div id="cipherdata" class="hidden">' .
'<div id="cipherdata" class="hidden">' . htmlspecialchars(Helper::getPaste()['data'], ENT_NOQUOTES) .
htmlspecialchars(Helper::getPaste()['data'], ENT_NOQUOTES) . '</div>',
'</div>', $this->_content,
$content, 'outputs data correctly'
$template . ': outputs data correctly' );
); $this->assertRegExp(
$this->assertRegExp( '#<div[^>]+id="errormessage"[^>]*>.*' . self::$error . '</div>#',
'#<div[^>]+id="errormessage"[^>]*>.*' . self::$error . '</div>#', $this->_content,
$content, 'outputs error correctly'
$template . ': outputs error correctly' );
); $this->assertRegExp(
$this->assertRegExp( '#<[^>]+id="password"[^>]*>#',
'#<[^>]+id="password"[^>]*>#', $this->_content,
$content, 'password available if configured'
$template . ': password available if configured' );
); $this->assertRegExp(
$this->assertRegExp( '#<input[^>]+id="opendiscussion"[^>]*checked="checked"[^>]*>#',
'#<input[^>]+id="opendiscussion"[^>]*checked="checked"[^>]*>#', $this->_content,
$content, 'checked discussion if configured'
$template . ': checked discussion if configured' );
); $this->assertRegExp(
$this->assertRegExp( '#<[^>]+id="opendisc"[^>]*>#',
'#<[^>]+id="opendisc"[^>]*>#', $this->_content,
$content, 'discussions available if configured'
$template . ': discussions available if configured' );
); // testing version number in JS address, since other instances may not be present in different templates
// testing version number in JS address, since other instances may not be present in different templates $this->assertRegExp(
$this->assertRegExp( '#<script[^>]+src="js/privatebin.js\\?' . rawurlencode(self::$version) . '"[^>]*>#',
'#<script[^>]+src="js/privatebin.js\\?' . rawurlencode(self::$version) . '"[^>]*>#', $this->_content,
$content, 'outputs version correctly'
$template . ': outputs version correctly' );
);
}
} }
/** /**

View File

@@ -1,13 +1,10 @@
<?php <?php
use Eris\Generator;
use PrivateBin\Persistence\ServerSalt; use PrivateBin\Persistence\ServerSalt;
use PrivateBin\Vizhash16x16; use PrivateBin\Vizhash16x16;
class Vizhash16x16Test extends PHPUnit_Framework_TestCase class Vizhash16x16Test extends PHPUnit_Framework_TestCase
{ {
use Eris\TestTrait;
private $_file; private $_file;
private $_path; private $_path;
@@ -30,71 +27,14 @@ class Vizhash16x16Test extends PHPUnit_Framework_TestCase
Helper::rmDir($this->_path); Helper::rmDir($this->_path);
} }
public function testVizhashGeneratesPngs() public function testVizhashGeneratesUniquePngsPerIp()
{ {
$this->forAll( $vz = new Vizhash16x16();
Generator\string(), $pngdata = $vz->generate(hash('sha512', '127.0.0.1'));
Generator\string() file_put_contents($this->_file, $pngdata);
)->then( $finfo = new finfo(FILEINFO_MIME_TYPE);
function ($string1, $string2) { $this->assertEquals('image/png', $finfo->file($this->_file));
$vz = new Vizhash16x16(); $this->assertNotEquals($pngdata, $vz->generate(hash('sha512', '2001:1620:2057:dead:beef::cafe:babe')));
$pngdata = $vz->generate($string1); $this->assertEquals($pngdata, $vz->generate(hash('sha512', '127.0.0.1')));
if (empty($string1)) {
$this->assertEquals($pngdata, '');
} else {
$this->assertNotEquals($pngdata, '');
file_put_contents($this->_file, $pngdata);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$this->assertEquals('image/png', $finfo->file($this->_file));
if ($string1 !== $string2) {
$this->assertNotEquals($pngdata, $string2);
}
}
$this->assertEquals($pngdata, $vz->generate($string1));
}
);
}
public function testVizhashGeneratesUniquePngsPerIpv4Hash()
{
$this->forAll(
Generator\vector(2, Generator\vector(4, Generator\byte()))
)->then(
function ($ips) {
$hash1 = hash('sha512', implode('.', $ips[0]));
$hash2 = hash('sha512', implode('.', $ips[1]));
$vz = new Vizhash16x16();
$pngdata = $vz->generate($hash1);
file_put_contents($this->_file, $pngdata);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$this->assertEquals('image/png', $finfo->file($this->_file));
if ($hash1 !== $hash2) {
$this->assertNotEquals($pngdata, $vz->generate($hash2));
}
$this->assertEquals($pngdata, $vz->generate($hash1));
}
);
}
public function testVizhashGeneratesUniquePngsPerIpv6Hash()
{
$this->forAll(
Generator\vector(2, Generator\vector(16, Generator\byte()))
)->then(
function ($ips) {
$hash1 = hash('sha512', inet_ntop(implode(array_map('chr', $ips[0]))));
$hash2 = hash('sha512', inet_ntop(implode(array_map('chr', $ips[1]))));
$vz = new Vizhash16x16();
$pngdata = $vz->generate($hash1);
file_put_contents($this->_file, $pngdata);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$this->assertEquals('image/png', $finfo->file($this->_file));
if ($hash1 !== $hash2) {
$this->assertNotEquals($pngdata, $vz->generate($hash2));
}
$this->assertEquals($pngdata, $vz->generate($hash1));
}
);
} }
} }

View File

@@ -13,7 +13,7 @@
</filter> </filter>
<logging> <logging>
<log type="coverage-clover" target="log/coverage-clover.xml" /> <log type="coverage-clover" target="log/coverage-clover.xml" />
<log type="coverage-html" target="log/php-coverage-report" charset="UTF-8" yui="true" highlight="true" lowUpperBound="50" highLowerBound="80" /> <log type="coverage-html" target="log/coverage-report" charset="UTF-8" yui="true" highlight="true" lowUpperBound="50" highLowerBound="80" />
<log type="testdox-html" target="log/testdox.html" /> <log type="testdox-html" target="log/testdox.html" />
</logging> </logging>
</phpunit> </phpunit>