From 4312f77385903978c2c6d8130a75b1063352e5ac Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 10 Oct 2020 11:21:53 +0200 Subject: [PATCH 001/506] experimentally enable PHP 8 beta unit testing --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a6f0f6d5..d695510f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4'] + php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] name: PHP ${{ matrix.php-versions }} unit tests on ${{ matrix.operating-system }} steps: - name: Checkout From 50f81e1d2e59a60e5a48ee19099770a1b8dd4cb2 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 10 Oct 2020 11:24:36 +0200 Subject: [PATCH 002/506] unlock PHP 8 for composer --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c1086acf..2f7cc85b 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "docs" : "https://privatebin.info/codedoc/" }, "require" : { - "php" : "^5.6.0 || ^7.0", + "php" : "^5.6.0 || ^7.0 || ^8.0", "paragonie/random_compat" : "2.0.18", "yzalis/identicon" : "2.0.0" }, From 99f50f6de31d5230fcd9a2da3081f43fc909838f Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 10 Oct 2020 11:50:48 +0200 Subject: [PATCH 003/506] update composer dependencies - test phpunit 9 --- composer.json | 6 +- composer.lock | 1520 ++++++++++++++++++++--------- vendor/composer/ClassLoader.php | 4 +- vendor/composer/autoload_real.php | 3 + 4 files changed, 1053 insertions(+), 480 deletions(-) diff --git a/composer.json b/composer.json index 2f7cc85b..756c0f4c 100644 --- a/composer.json +++ b/composer.json @@ -25,11 +25,11 @@ }, "require" : { "php" : "^5.6.0 || ^7.0 || ^8.0", - "paragonie/random_compat" : "2.0.18", - "yzalis/identicon" : "2.0.0" + "paragonie/random_compat" : "<9.99", + "yzalis/identicon" : "^2.0.0" }, "require-dev" : { - "phpunit/phpunit" : "^4.6 || ^5.0" + "phpunit/phpunit" : "^4.6 || ^5 || ^9" }, "autoload" : { "psr-4" : { diff --git a/composer.lock b/composer.lock index d8bf1cce..4a680dbb 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "203b93e3e8cb37cc45988bb0ca1364bc", + "content-hash": "a0e6ddfb640e9d613dfb4bddd578cc94", "packages": [ { "name": "paragonie/random_compat", @@ -111,20 +111,20 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^6.0", @@ -163,24 +163,38 @@ "constructor", "instantiate" ], - "time": "2019-10-21T16:45:58+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-05-29T17:27:14+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.9.5", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" + "reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", - "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5", + "reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "replace": { "myclabs/deep-copy": "self.version" @@ -211,32 +225,190 @@ "object", "object graph" ], - "time": "2020-01-17T21:11:47+00:00" + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2020-06-29T13:22:24+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "2.0.0", + "name": "nikic/php-parser", + "version": "v4.10.2", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "658f1be311a230e0907f5dfe0213742aff0596de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/658f1be311a230e0907f5dfe0213742aff0596de", + "reference": "658f1be311a230e0907f5dfe0213742aff0596de", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-tokenizer": "*", + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "~6" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2020-09-26T10:30:38+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2020-06-27T14:33:11+00:00" + }, + { + "name": "phar-io/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/c6bb6825def89e0a32220f88337f8ceaf1975fa0", + "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2020-06-27T14:39:04+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" } }, "autoload": { @@ -263,45 +435,41 @@ "reflection", "static analysis" ], - "time": "2018-08-07T13:53:10+00:00" + "time": "2020-06-27T09:03:43+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.4", + "version": "5.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", - "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", - "webmozart/assert": "^1.0" + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" }, "require-dev": { - "doctrine/instantiator": "^1.0.5", - "mockery/mockery": "^1.0", - "phpdocumentor/type-resolver": "0.4.*", - "phpunit/phpunit": "^6.4" + "mockery/mockery": "~1.3.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -312,38 +480,40 @@ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-12-28T18:55:12+00:00" + "time": "2020-09-03T19:13:55+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.0.1", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", "shasum": "" }, "require": { - "php": "^7.1", + "php": "^7.2 || ^8.0", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "^7.1", - "mockery/mockery": "~1", - "phpunit/phpunit": "^7.0" + "ext-tokenizer": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-1.x": "1.x-dev" } }, "autoload": { @@ -362,37 +532,37 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2019-08-22T18:11:29+00:00" + "time": "2020-09-17T18:55:26+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.10.2", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9" + "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b4400efc9d206e83138e2bb97ed7f5b14b831cd9", - "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", + "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", - "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + "doctrine/instantiator": "^1.2", + "php": "^7.2 || ~8.0, <8.1", + "phpdocumentor/reflection-docblock": "^5.2", + "sebastian/comparator": "^3.0 || ^4.0", + "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5 || ^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + "phpspec/phpspec": "^6.0", + "phpunit/phpunit": "^8.0 || ^9.0 <9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.10.x-dev" + "dev-master": "1.11.x-dev" } }, "autoload": { @@ -425,44 +595,48 @@ "spy", "stub" ], - "time": "2020-01-20T15:57:02+00:00" + "time": "2020-09-29T09:10:42+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.8", + "version": "9.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + "reference": "53a4b737e83be724efd2bc4e7b929b9a30c48972" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/53a4b737e83be724efd2bc4e7b929b9a30c48972", + "reference": "53a4b737e83be724efd2bc4e7b929b9a30c48972", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" + "nikic/php-parser": "^4.8", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-xdebug": "^2.5.1" + "ext-pcov": "*", + "ext-xdebug": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "9.2-dev" } }, "autoload": { @@ -477,7 +651,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -488,29 +662,38 @@ "testing", "xunit" ], - "time": "2017-04-02T07:44:40+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-02T03:37:32+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", + "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -525,7 +708,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -535,26 +718,99 @@ "filesystem", "iterator" ], - "time": "2017-11-27T13:52:08+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:57:25+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "18c887016e60e52477e54534956d7b47bc52cd84" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/18c887016e60e52477e54534956d7b47bc52cd84", + "reference": "18c887016e60e52477e54534956d7b47bc52cd84", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -576,27 +832,187 @@ "keywords": [ "template" ], - "time": "2015-06-21T13:50:34+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:03:05+00:00" }, { "name": "phpunit/php-timer", - "version": "1.0.9", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "reference": "c9ff14f493699e2f6adee9fd06a0245b276643b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/c9ff14f493699e2f6adee9fd06a0245b276643b7", + "reference": "c9ff14f493699e2f6adee9fd06a0245b276643b7", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:00:25+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "ef533467a7974c4b6c354f3eff42a115910bd4e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ef533467a7974c4b6c354f3eff42a115910bd4e5", + "reference": "ef533467a7974c4b6c354f3eff42a115910bd4e5", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.1", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpspec/prophecy": "^1.11.1", + "phpunit/php-code-coverage": "^9.2", + "phpunit/php-file-iterator": "^3.0.4", + "phpunit/php-invoker": "^3.1", + "phpunit/php-text-template": "^2.0.2", + "phpunit/php-timer": "^5.0.1", + "sebastian/cli-parser": "^1.0", + "sebastian/code-unit": "^1.0.5", + "sebastian/comparator": "^4.0.3", + "sebastian/diff": "^4.0.2", + "sebastian/environment": "^5.1.2", + "sebastian/exporter": "^4.0.2", + "sebastian/global-state": "^5.0", + "sebastian/object-enumerator": "^4.0.2", + "sebastian/resource-operations": "^3.0.2", + "sebastian/type": "^2.2.1", + "sebastian/version": "^3.0.1" + }, + "require-dev": { + "ext-pdo": "*", + "phpspec/prophecy-phpunit": "^2.0.1" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "funding": [ + { + "url": "https://phpunit.de/donate.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-02T03:54:37+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -616,37 +1032,91 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-02-26T11:10:40+00:00" + "time": "2020-09-28T06:08:49+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "2.0.2", + "name": "sebastian/code-unit", + "version": "1.0.7", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "59236be62b1bb9919e6d7f60b0b832dc05cef9ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/59236be62b1bb9919e6d7f60b0b832dc05cef9ab", + "reference": "59236be62b1bb9919e6d7f60b0b832dc05cef9ab", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-02T14:47:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -669,68 +1139,111 @@ "email": "sebastian@phpunit.de" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-11-27T05:48:46+00:00" + "time": "2020-09-28T05:30:19+00:00" }, { - "name": "phpunit/phpunit", - "version": "5.7.27", + "name": "sebastian/comparator", + "version": "4.0.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "7a8ff306445707539c1a6397372a982a1ec55120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/7a8ff306445707539c1a6397372a982a1ec55120", + "reference": "7a8ff306445707539c1a6397372a982a1ec55120", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.4", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "^1.2.4", - "sebastian/diff": "^1.4.3", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "~2.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "^1.0.6|^2.0.1", - "symfony/yaml": "~2.1|~3.0|~4.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "ext-pdo": "*" + "phpunit/phpunit": "^9.3" }, - "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7.x-dev" + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-30T06:47:25+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ba8cc2da0c0bfbc813d03b56406734030c7f1eff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ba8cc2da0c0bfbc813d03b56406734030c7f1eff", + "reference": "ba8cc2da0c0bfbc813d03b56406734030c7f1eff", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" } }, "autoload": { @@ -749,208 +1262,41 @@ "role": "lead" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2018-02-01T05:50:59+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "3.4.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "funding": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "abandoned": true, - "time": "2017-06-30T09:13:00+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" - }, - { - "name": "sebastian/comparator", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-01-29T09:50:25+00:00" + "time": "2020-09-28T06:05:03+00:00" }, { "name": "sebastian/diff", - "version": "1.4.3", + "version": "4.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "reference": "ffc949a1a2aae270ea064453d7535b82e4c32092" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ffc949a1a2aae270ea064453d7535b82e4c32092", + "reference": "ffc949a1a2aae270ea064453d7535b82e4c32092", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -963,46 +1309,58 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "diff" + "diff", + "udiff", + "unidiff", + "unified diff" ], - "time": "2017-05-22T07:24:03+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:32:55+00:00" }, { "name": "sebastian/environment", - "version": "2.0.0", + "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + "reference": "388b6ced16caa751030f6a69e588299fa09200ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", + "reference": "388b6ced16caa751030f6a69e588299fa09200ac", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -1027,34 +1385,40 @@ "environment", "hhvm" ], - "time": "2016-11-26T07:53:53+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:52:38+00:00" }, { "name": "sebastian/exporter", - "version": "2.0.0", + "version": "4.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~2.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1067,6 +1431,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -1075,17 +1443,13 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -1094,27 +1458,36 @@ "export", "exporter" ], - "time": "2016-11-19T08:54:04+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:24:23+00:00" }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "ea779cb749a478b22a2564ac41cd7bda79c78dc7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/ea779cb749a478b22a2564ac41cd7bda79c78dc7", + "reference": "ea779cb749a478b22a2564ac41cd7bda79c78dc7", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "ext-dom": "*", + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-uopz": "*" @@ -1122,7 +1495,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -1145,33 +1518,93 @@ "keywords": [ "global state" ], - "time": "2015-10-12T03:26:01+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:54:06+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "2.0.1", + "name": "sebastian/lines-of-code", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "6514b8f21906b8b46f520d1fbd17a4523fa59a54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/6514b8f21906b8b46f520d1fbd17a4523fa59a54", + "reference": "6514b8f21906b8b46f520d1fbd17a4523fa59a54", "shasum": "" }, "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~2.0" + "nikic/php-parser": "^4.6", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:07:27+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f6f5957013d84725427d361507e13513702888a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f6f5957013d84725427d361507e13513702888a4", + "reference": "f6f5957013d84725427d361507e13513702888a4", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -1191,32 +1624,38 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-02-18T15:18:39+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:55:06+00:00" }, { - "name": "sebastian/recursion-context", - "version": "2.0.0", + "name": "sebastian/object-reflector", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5", + "reference": "d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1230,13 +1669,64 @@ ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:56:16+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "ed8c9cd355089134bc9cba421b5cfdd58f0eaef7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/ed8c9cd355089134bc9cba421b5cfdd58f0eaef7", + "reference": "ed8c9cd355089134bc9cba421b5cfdd58f0eaef7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, { "name": "Adam Harvey", "email": "aharvey@php.net" @@ -1244,29 +1734,38 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-19T07:33:16+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:17:32+00:00" }, { "name": "sebastian/resource-operations", - "version": "1.0.0", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1286,29 +1785,87 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" }, { - "name": "sebastian/version", - "version": "2.0.1", + "name": "sebastian/type", + "version": "2.3.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "fa592377f3923946cb90bf1f6a71ba2e5f229909" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fa592377f3923946cb90bf1f6a71ba2e5f229909", + "reference": "fa592377f3923946cb90bf1f6a71ba2e5f229909", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-06T08:41:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" } }, "autoload": { @@ -1329,20 +1886,26 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.17.0", + "version": "v1.18.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" + "reference": "1c302646f6efc070cd46856e600e5e0684d6b454" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", - "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454", + "reference": "1c302646f6efc070cd46856e600e5e0684d6b454", "shasum": "" }, "require": { @@ -1354,7 +1917,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.17-dev" + "dev-master": "1.18-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { @@ -1387,87 +1954,89 @@ "polyfill", "portable" ], - "time": "2020-05-12T16:14:59+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-07-14T12:35:20+00:00" }, { - "name": "symfony/yaml", - "version": "v4.4.9", + "name": "theseer/tokenizer", + "version": "1.2.0", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "c2d2cc66e892322cfcc03f8f12f8340dbd7a3f8a" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "75a63c33a8577608444246075ea0af0d052e452a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/c2d2cc66e892322cfcc03f8f12f8340dbd7a3f8a", - "reference": "c2d2cc66e892322cfcc03f8f12f8340dbd7a3f8a", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", + "reference": "75a63c33a8577608444246075ea0af0d052e452a", "shasum": "" }, "require": { - "php": ">=7.1.3", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2020-05-20T08:37:50+00:00" + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2020-07-12T23:59:07+00:00" }, { "name": "webmozart/assert", - "version": "1.6.0", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", - "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0", + "php": "^5.3.3 || ^7.0 || ^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "vimeo/psalm": "<3.6.0" + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<3.9.1" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^7.5.13" @@ -1494,7 +2063,7 @@ "check", "validate" ], - "time": "2019-11-24T13:36:37+00:00" + "time": "2020-07-08T17:02:28+00:00" } ], "aliases": [], @@ -1503,7 +2072,8 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^5.6.0 || ^7.0" + "php": "^5.6.0 || ^7.0 || ^8.0" }, - "platform-dev": [] + "platform-dev": [], + "plugin-api-version": "1.1.0" } diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index dc02dfb1..fce8549f 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -279,7 +279,7 @@ class ClassLoader */ public function setApcuPrefix($apcuPrefix) { - $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** @@ -377,7 +377,7 @@ class ClassLoader $subPath = $class; while (false !== $lastPos = strrpos($subPath, '\\')) { $subPath = substr($subPath, 0, $lastPos); - $search = $subPath.'\\'; + $search = $subPath . '\\'; if (isset($this->prefixDirsPsr4[$search])) { $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 2e234b96..7a6fd4c0 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -13,6 +13,9 @@ class ComposerAutoloaderInitDontChange } } + /** + * @return \Composer\Autoload\ClassLoader + */ public static function getLoader() { if (null !== self::$loader) { From 6f90df9545b4f74a4f86d720bec57d54d351cb98 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 10 Oct 2020 12:08:58 +0200 Subject: [PATCH 004/506] updating tests by dropping PHPunit 4.6 support --- composer.json | 2 +- composer.lock | 2 +- tst/ConfigurationTest.php | 3 ++- tst/ConfigurationTestGenerator.php | 3 ++- tst/ControllerTest.php | 3 ++- tst/ControllerWithDbTest.php | 1 + tst/Data/DatabaseTest.php | 3 ++- tst/Data/FilesystemTest.php | 3 ++- tst/FilterTest.php | 3 ++- tst/FormatV2Test.php | 3 ++- tst/I18nTest.php | 3 ++- tst/JsonApiTest.php | 3 ++- tst/ModelTest.php | 3 ++- tst/Persistence/PurgeLimiterTest.php | 3 ++- tst/Persistence/ServerSaltTest.php | 3 ++- tst/Persistence/TrafficLimiterTest.php | 3 ++- tst/RequestTest.php | 3 ++- tst/ViewTest.php | 3 ++- tst/Vizhash16x16Test.php | 3 ++- 19 files changed, 35 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index 756c0f4c..9d3cd9a5 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "yzalis/identicon" : "^2.0.0" }, "require-dev" : { - "phpunit/phpunit" : "^4.6 || ^5 || ^9" + "phpunit/phpunit" : "^5 || ^9" }, "autoload" : { "psr-4" : { diff --git a/composer.lock b/composer.lock index 4a680dbb..7149b7e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a0e6ddfb640e9d613dfb4bddd578cc94", + "content-hash": "c5e5c4d3d99ae93c94cc75e225aa50f5", "packages": [ { "name": "paragonie/random_compat", diff --git a/tst/ConfigurationTest.php b/tst/ConfigurationTest.php index bb4ce36f..d52027a3 100644 --- a/tst/ConfigurationTest.php +++ b/tst/ConfigurationTest.php @@ -1,8 +1,9 @@ Date: Sat, 10 Oct 2020 12:22:20 +0200 Subject: [PATCH 005/506] return type void is required as of PHPunit 7, breaking test compatibility with PHP < 7.1 --- tst/ConfigurationTest.php | 4 ++-- tst/ConfigurationTestGenerator.php | 4 ++-- tst/ControllerTest.php | 4 ++-- tst/ControllerWithDbTest.php | 2 +- tst/Data/DatabaseTest.php | 4 ++-- tst/Data/FilesystemTest.php | 4 ++-- tst/I18nTest.php | 4 ++-- tst/JsonApiTest.php | 4 ++-- tst/ModelTest.php | 4 ++-- tst/Persistence/PurgeLimiterTest.php | 4 ++-- tst/Persistence/ServerSaltTest.php | 4 ++-- tst/Persistence/TrafficLimiterTest.php | 4 ++-- tst/RequestTest.php | 10 ---------- tst/ViewTest.php | 7 +------ tst/Vizhash16x16Test.php | 4 ++-- 15 files changed, 26 insertions(+), 41 deletions(-) diff --git a/tst/ConfigurationTest.php b/tst/ConfigurationTest.php index d52027a3..9afa829b 100644 --- a/tst/ConfigurationTest.php +++ b/tst/ConfigurationTest.php @@ -11,7 +11,7 @@ class ConfigurationTest extends TestCase private $_path; - public function setUp() + public function setUp(): void { /* Setup Routine */ Helper::confBackup(); @@ -26,7 +26,7 @@ class ConfigurationTest extends TestCase } } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ Helper::rmDir($this->_path); diff --git a/tst/ConfigurationTestGenerator.php b/tst/ConfigurationTestGenerator.php index 098fae7f..b5551c0a 100755 --- a/tst/ConfigurationTestGenerator.php +++ b/tst/ConfigurationTestGenerator.php @@ -423,7 +423,7 @@ class ConfigurationCombinationsTest extends TestCase private $_path; - public function setUp() + public function setUp(): void { /* Setup Routine */ Helper::confBackup(); @@ -434,7 +434,7 @@ class ConfigurationCombinationsTest extends TestCase $this->reset(); } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ unlink(CONF); diff --git a/tst/ControllerTest.php b/tst/ControllerTest.php index 43556448..8610dd9b 100644 --- a/tst/ControllerTest.php +++ b/tst/ControllerTest.php @@ -13,7 +13,7 @@ class ControllerTest extends TestCase protected $_path; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; @@ -21,7 +21,7 @@ class ControllerTest extends TestCase $this->reset(); } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ unlink(CONF); diff --git a/tst/ControllerWithDbTest.php b/tst/ControllerWithDbTest.php index cfa08172..a8ecaf10 100644 --- a/tst/ControllerWithDbTest.php +++ b/tst/ControllerWithDbTest.php @@ -16,7 +16,7 @@ class ControllerWithDbTest extends ControllerTest ), ); - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; diff --git a/tst/Data/DatabaseTest.php b/tst/Data/DatabaseTest.php index 24bbfa7b..8820b341 100644 --- a/tst/Data/DatabaseTest.php +++ b/tst/Data/DatabaseTest.php @@ -17,14 +17,14 @@ class DatabaseTest extends TestCase 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), ); - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_model = Database::getInstance($this->_options); } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ if (is_dir($this->_path)) { diff --git a/tst/Data/FilesystemTest.php b/tst/Data/FilesystemTest.php index 1961a813..64b83962 100644 --- a/tst/Data/FilesystemTest.php +++ b/tst/Data/FilesystemTest.php @@ -11,7 +11,7 @@ class FilesystemTest extends TestCase private $_invalidPath; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; @@ -25,7 +25,7 @@ class FilesystemTest extends TestCase } } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ chmod($this->_invalidPath, 0700); diff --git a/tst/I18nTest.php b/tst/I18nTest.php index c527ac57..d5732420 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -7,7 +7,7 @@ class I18nTest extends TestCase { private $_translations = array(); - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_translations = json_decode( @@ -16,7 +16,7 @@ class I18nTest extends TestCase ); } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ } diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index 4173b384..c51badef 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -12,7 +12,7 @@ class JsonApiTest extends TestCase protected $_path; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; @@ -33,7 +33,7 @@ class JsonApiTest extends TestCase Helper::createIniFile(CONF, $options); } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ unlink(CONF); diff --git a/tst/ModelTest.php b/tst/ModelTest.php index 4fbbb5b9..cbfd9cea 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -19,7 +19,7 @@ class ModelTest extends TestCase protected $_path; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; @@ -45,7 +45,7 @@ class ModelTest extends TestCase $_SERVER['REMOTE_ADDR'] = '::1'; } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ unlink(CONF); diff --git a/tst/Persistence/PurgeLimiterTest.php b/tst/Persistence/PurgeLimiterTest.php index 68bac020..25f854a6 100644 --- a/tst/Persistence/PurgeLimiterTest.php +++ b/tst/Persistence/PurgeLimiterTest.php @@ -7,7 +7,7 @@ class PurgeLimiterTest extends TestCase { private $_path; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; @@ -17,7 +17,7 @@ class PurgeLimiterTest extends TestCase PurgeLimiter::setPath($this->_path); } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ Helper::rmDir($this->_path); diff --git a/tst/Persistence/ServerSaltTest.php b/tst/Persistence/ServerSaltTest.php index 34199d68..216e6c62 100644 --- a/tst/Persistence/ServerSaltTest.php +++ b/tst/Persistence/ServerSaltTest.php @@ -13,7 +13,7 @@ class ServerSaltTest extends TestCase private $_invalidFile; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; @@ -31,7 +31,7 @@ class ServerSaltTest extends TestCase $this->_invalidFile = $this->_invalidPath . DIRECTORY_SEPARATOR . 'salt.php'; } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ chmod($this->_invalidPath, 0700); diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index b2f5746a..027dbb25 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -7,14 +7,14 @@ class TrafficLimiterTest extends TestCase { private $_path; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'trafficlimit'; TrafficLimiter::setPath($this->_path); } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ Helper::rmDir($this->_path . DIRECTORY_SEPARATOR); diff --git a/tst/RequestTest.php b/tst/RequestTest.php index f323d8f1..bf7edfb3 100644 --- a/tst/RequestTest.php +++ b/tst/RequestTest.php @@ -5,16 +5,6 @@ use PrivateBin\Request; class RequestTest extends TestCase { - public function setUp() - { - /* Setup Routine */ - } - - public function tearDown() - { - /* Tear Down Routine */ - } - public function reset() { $_SERVER = array(); diff --git a/tst/ViewTest.php b/tst/ViewTest.php index d46f63bd..4094c03d 100644 --- a/tst/ViewTest.php +++ b/tst/ViewTest.php @@ -30,7 +30,7 @@ class ViewTest extends TestCase private $_content = array(); - public function setUp() + public function setUp(): void { /* Setup Routine */ $page = new View; @@ -92,11 +92,6 @@ class ViewTest extends TestCase } } - public function tearDown() - { - /* Tear Down Routine */ - } - public function testTemplateRendersCorrectly() { foreach ($this->_content as $template => $content) { diff --git a/tst/Vizhash16x16Test.php b/tst/Vizhash16x16Test.php index 95a29681..cc7da086 100644 --- a/tst/Vizhash16x16Test.php +++ b/tst/Vizhash16x16Test.php @@ -10,7 +10,7 @@ class Vizhash16x16Test extends TestCase private $_path; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; @@ -21,7 +21,7 @@ class Vizhash16x16Test extends TestCase ServerSalt::setPath($this->_path); } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ chmod($this->_path, 0700); From 17c3cb35c0f6743901460c854996d9257317ff1c Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 11 Oct 2020 10:31:24 +0200 Subject: [PATCH 006/506] change tests for phpunit 9 support, breaking support with phpunit 5.6 --- composer.json | 2 +- composer.lock | 44 +++++++++++------------ tst/ConfigurationTest.php | 32 +++++++---------- tst/ConfigurationTestGenerator.php | 2 +- tst/ControllerTest.php | 32 ++++++++--------- tst/Data/DatabaseTest.php | 54 +++++++++------------------- tst/Data/FilesystemTest.php | 4 +-- tst/FilterTest.php | 6 ++-- tst/I18nTest.php | 2 +- tst/ModelTest.php | 57 ++++++++++-------------------- tst/Persistence/ServerSaltTest.php | 24 +++++-------- tst/ViewTest.php | 16 ++++----- tst/phpunit.xml | 39 ++++++++++---------- 13 files changed, 128 insertions(+), 186 deletions(-) diff --git a/composer.json b/composer.json index 9d3cd9a5..88640d50 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "yzalis/identicon" : "^2.0.0" }, "require-dev" : { - "phpunit/phpunit" : "^5 || ^9" + "phpunit/phpunit" : "^9" }, "autoload" : { "psr-4" : { diff --git a/composer.lock b/composer.lock index 7149b7e7..fa0c7b51 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c5e5c4d3d99ae93c94cc75e225aa50f5", + "content-hash": "f8f346748370d0efd672270571c4aa74", "packages": [ { "name": "paragonie/random_compat", @@ -897,16 +897,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.4.0", + "version": "9.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ef533467a7974c4b6c354f3eff42a115910bd4e5" + "reference": "1f09a12726593737e8a228ebb1c8647305d07c41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ef533467a7974c4b6c354f3eff42a115910bd4e5", - "reference": "ef533467a7974c4b6c354f3eff42a115910bd4e5", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1f09a12726593737e8a228ebb1c8647305d07c41", + "reference": "1f09a12726593737e8a228ebb1c8647305d07c41", "shasum": "" }, "require": { @@ -921,23 +921,23 @@ "phar-io/manifest": "^2.0.1", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpspec/prophecy": "^1.11.1", + "phpspec/prophecy": "^1.12.1", "phpunit/php-code-coverage": "^9.2", - "phpunit/php-file-iterator": "^3.0.4", - "phpunit/php-invoker": "^3.1", - "phpunit/php-text-template": "^2.0.2", - "phpunit/php-timer": "^5.0.1", - "sebastian/cli-parser": "^1.0", - "sebastian/code-unit": "^1.0.5", - "sebastian/comparator": "^4.0.3", - "sebastian/diff": "^4.0.2", - "sebastian/environment": "^5.1.2", - "sebastian/exporter": "^4.0.2", - "sebastian/global-state": "^5.0", - "sebastian/object-enumerator": "^4.0.2", - "sebastian/resource-operations": "^3.0.2", - "sebastian/type": "^2.2.1", - "sebastian/version": "^3.0.1" + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.5", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.3", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^2.3", + "sebastian/version": "^3.0.2" }, "require-dev": { "ext-pdo": "*", @@ -992,7 +992,7 @@ "type": "github" } ], - "time": "2020-10-02T03:54:37+00:00" + "time": "2020-10-11T07:41:19+00:00" }, { "name": "sebastian/cli-parser", diff --git a/tst/ConfigurationTest.php b/tst/ConfigurationTest.php index 9afa829b..5e694885 100644 --- a/tst/ConfigurationTest.php +++ b/tst/ConfigurationTest.php @@ -58,13 +58,11 @@ class ConfigurationTest extends TestCase $this->assertEquals($this->_options, $conf->get(), 'returns correct defaults on missing file'); } - /** - * @expectedException Exception - * @expectedExceptionCode 2 - */ public function testHandleBlankConfigFile() { file_put_contents(CONF, ''); + $this->expectException(Exception::class); + $this->expectExceptionCode(2); new Configuration; } @@ -75,25 +73,21 @@ class ConfigurationTest extends TestCase $this->assertEquals($this->_options, $conf->get(), 'returns correct defaults on empty file'); } - /** - * @expectedException Exception - * @expectedExceptionCode 3 - */ public function testHandleInvalidSection() { file_put_contents(CONF, $this->_minimalConfig); $conf = new Configuration; + $this->expectException(Exception::class); + $this->expectExceptionCode(3); $conf->getKey('foo', 'bar'); } - /** - * @expectedException Exception - * @expectedExceptionCode 4 - */ public function testHandleInvalidKey() { file_put_contents(CONF, $this->_minimalConfig); $conf = new Configuration; + $this->expectException(Exception::class); + $this->expectExceptionCode(4); $conf->getKey('foo'); } @@ -160,8 +154,8 @@ class ConfigurationTest extends TestCase $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->assertFileDoesNotExist(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', 'old configuration file gets removed'); + $this->assertFileDoesNotExist(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini.sample', 'old configuration sample file gets removed'); $this->assertTrue( $conf->getKey('opendiscussion') && $conf->getKey('fileupload') && @@ -180,10 +174,10 @@ class ConfigurationTest extends TestCase } rename(CONF_SAMPLE, $iniSample); new Configuration; - $this->assertFileNotExists($iniSample, 'old sample file gets removed'); + $this->assertFileDoesNotExist($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'); + $this->assertFileDoesNotExist(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', 'old configuration file gets removed'); } public function testConfigPath() @@ -214,15 +208,15 @@ class ConfigurationTest extends TestCase $options = $this->_options; $options['main']['name'] = 'OtherBin'; Helper::createIniFile($configFile, $options); - $this->assertFileNotExists(CONF, 'configuration in the default location is non existing'); + $this->assertFileDoesNotExist(CONF, 'configuration in the default location is non existing'); // test putenv('CONFIG_PATH=' . $this->_path); $conf = new Configuration; $this->assertEquals('OtherBin', $conf->getKey('name'), 'changing config path is supported for ini files as well'); $this->assertFileExists($configMigrated, 'old configuration file gets converted'); - $this->assertFileNotExists($configFile, 'old configuration file gets removed'); - $this->assertFileNotExists(CONF, 'configuration is not created in the default location'); + $this->assertFileDoesNotExist($configFile, 'old configuration file gets removed'); + $this->assertFileDoesNotExist(CONF, 'configuration is not created in the default location'); // cleanup environment if (is_file($configFile)) { diff --git a/tst/ConfigurationTestGenerator.php b/tst/ConfigurationTestGenerator.php index b5551c0a..611181cc 100755 --- a/tst/ConfigurationTestGenerator.php +++ b/tst/ConfigurationTestGenerator.php @@ -565,7 +565,7 @@ EOT; case 'Delete': $code .= <<<'EOT' - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]*id="status"[^>]*>.*Paste was properly deleted[^<]*#s', $content, 'outputs deleted status correctly' diff --git a/tst/ControllerTest.php b/tst/ControllerTest.php index 8610dd9b..b199f7b2 100644 --- a/tst/ControllerTest.php +++ b/tst/ControllerTest.php @@ -54,12 +54,12 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertContains( + $this->assertStringContainsString( 'PrivateBin', $content, 'outputs title correctly' ); - $this->assertNotContains( + $this->assertStringNotContainsString( 'id="shortenbutton"', $content, 'doesn\'t output shortener button' @@ -79,7 +79,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertContains( + $this->assertStringContainsString( 'PrivateBin', $content, 'outputs title correctly' @@ -100,7 +100,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertContains( + $this->assertStringContainsString( 'PrivateBin', $content, 'outputs title correctly' @@ -121,7 +121,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#id="shortenbutton"[^>]*data-shortener="' . preg_quote($shortener) . '"#', $content, 'outputs configured shortener URL correctly' @@ -150,13 +150,11 @@ class ControllerTest extends TestCase $this->assertFileExists($htaccess, 'htaccess recreated'); } - /** - * @expectedException Exception - * @expectedExceptionCode 2 - */ public function testConf() { file_put_contents(CONF, ''); + $this->expectException(Exception::class); + $this->expectExceptionCode(2); new Controller; } @@ -452,8 +450,6 @@ class ControllerTest extends TestCase * silently removed, check that this case is handled * * @runInSeparateProcess - * @expectedException Exception - * @expectedExceptionCode 90 */ public function testCreateBrokenUpload() { @@ -465,6 +461,8 @@ class ControllerTest extends TestCase $_SERVER['REQUEST_METHOD'] = 'POST'; $_SERVER['REMOTE_ADDR'] = '::1'; $this->assertFalse($this->_data->exists(Helper::getPasteId()), 'paste does not exists before posting data'); + $this->expectException(Exception::class); + $this->expectExceptionCode(90); new Controller; $this->assertFalse($this->_data->exists(Helper::getPasteId()), 'paste exists after posting data'); } @@ -799,7 +797,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]*id="status"[^>]*>.*Paste was properly deleted\.#s', $content, 'outputs deleted status correctly' @@ -819,7 +817,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]*id="errormessage"[^>]*>.*Invalid paste ID\.#s', $content, 'outputs delete error correctly' @@ -838,7 +836,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]*id="errormessage"[^>]*>.*Paste does not exist, has expired or has been deleted\.#s', $content, 'outputs delete error correctly' @@ -857,7 +855,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]*id="errormessage"[^>]*>.*Wrong deletion token\. Paste was not deleted\.#s', $content, 'outputs delete error correctly' @@ -905,7 +903,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]*id="errormessage"[^>]*>.*Paste does not exist, has expired or has been deleted\.#s', $content, 'outputs error correctly' @@ -928,7 +926,7 @@ class ControllerTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]*id="status"[^>]*>.*Paste was properly deleted\.#s', $content, 'outputs deleted status correctly' diff --git a/tst/Data/DatabaseTest.php b/tst/Data/DatabaseTest.php index 8820b341..1d61cb71 100644 --- a/tst/Data/DatabaseTest.php +++ b/tst/Data/DatabaseTest.php @@ -122,124 +122,102 @@ class DatabaseTest extends TestCase } } - /** - * @expectedException PDOException - */ public function testGetIbmInstance() { + $this->expectException(PDOException::class); Database::getInstance(array( 'dsn' => 'ibm:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); } - /** - * @expectedException PDOException - */ public function testGetInformixInstance() { + $this->expectException(PDOException::class); Database::getInstance(array( 'dsn' => 'informix:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); } - /** - * @expectedException PDOException - */ public function testGetMssqlInstance() { + $this->expectException(PDOException::class); Database::getInstance(array( 'dsn' => 'mssql:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); } - /** - * @expectedException PDOException - */ public function testGetMysqlInstance() { + $this->expectException(PDOException::class); Database::getInstance(array( 'dsn' => 'mysql:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); } - /** - * @expectedException PDOException - */ public function testGetOciInstance() { + $this->expectException(PDOException::class); Database::getInstance(array( 'dsn' => 'oci:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); } - /** - * @expectedException PDOException - */ public function testGetPgsqlInstance() { + $this->expectException(PDOException::class); Database::getInstance(array( 'dsn' => 'pgsql:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); } - /** - * @expectedException Exception - * @expectedExceptionCode 5 - */ public function testGetFooInstance() { + $this->expectException(Exception::class); + $this->expectExceptionCode(5); Database::getInstance(array( 'dsn' => 'foo:', 'usr' => null, 'pwd' => null, 'opt' => null, )); } - /** - * @expectedException Exception - * @expectedExceptionCode 6 - */ public function testMissingDsn() { $options = $this->_options; unset($options['dsn']); + $this->expectException(Exception::class); + $this->expectExceptionCode(6); Database::getInstance($options); } - /** - * @expectedException Exception - * @expectedExceptionCode 6 - */ public function testMissingUsr() { $options = $this->_options; unset($options['usr']); + $this->expectException(Exception::class); + $this->expectExceptionCode(6); Database::getInstance($options); } - /** - * @expectedException Exception - * @expectedExceptionCode 6 - */ public function testMissingPwd() { $options = $this->_options; unset($options['pwd']); + $this->expectException(Exception::class); + $this->expectExceptionCode(6); Database::getInstance($options); } - /** - * @expectedException Exception - * @expectedExceptionCode 6 - */ public function testMissingOpt() { $options = $this->_options; unset($options['opt']); + $this->expectException(Exception::class); + $this->expectExceptionCode(6); Database::getInstance($options); } diff --git a/tst/Data/FilesystemTest.php b/tst/Data/FilesystemTest.php index 64b83962..0388ffcb 100644 --- a/tst/Data/FilesystemTest.php +++ b/tst/Data/FilesystemTest.php @@ -162,13 +162,13 @@ class FilesystemTest extends TestCase $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->assertFileDoesNotExist($storagedir . $dataid, "old format paste $dataid got removed"); $this->assertTrue($this->_model->exists($dataid), "paste $dataid exists"); $this->assertEquals($this->_model->read($dataid), $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->assertFileDoesNotExist($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 = $comment; $comment['id'] = $commentid; diff --git a/tst/FilterTest.php b/tst/FilterTest.php index df9581b4..39c4f5df 100644 --- a/tst/FilterTest.php +++ b/tst/FilterTest.php @@ -13,12 +13,10 @@ class FilterTest extends TestCase $this->assertEquals('6 months', Filter::formatHumanReadableTime('6months')); } - /** - * @expectedException Exception - * @expectedExceptionCode 30 - */ public function testFilterFailTimesHumanlyReadable() { + $this->expectException(Exception::class); + $this->expectExceptionCode(30); Filter::formatHumanReadableTime('five_minutes'); } diff --git a/tst/I18nTest.php b/tst/I18nTest.php index d5732420..8ccf125d 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -18,7 +18,7 @@ class I18nTest extends TestCase public function tearDown(): void { - /* Tear Down Routine */ + unset($_COOKIE['lang'], $_SERVER['HTTP_ACCEPT_LANGUAGE']); } public function testTranslationFallback() diff --git a/tst/ModelTest.php b/tst/ModelTest.php index cbfd9cea..de7ec74b 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -116,10 +116,6 @@ class ModelTest extends TestCase $this->assertEquals(Helper::getPasteId(), $comment->getParentId(), 'comment parent ID gets initialized to paste ID'); } - /** - * @expectedException Exception - * @expectedExceptionCode 75 - */ public function testPasteDuplicate() { $pasteData = Helper::getPastePost(); @@ -131,13 +127,11 @@ class ModelTest extends TestCase $paste = $this->_model->getPaste(); $paste->setData($pasteData); + $this->expectException(Exception::class); + $this->expectExceptionCode(75); $paste->store(); } - /** - * @expectedException Exception - * @expectedExceptionCode 69 - */ public function testCommentDuplicate() { $pasteData = Helper::getPastePost(); @@ -154,6 +148,8 @@ class ModelTest extends TestCase $comment = $paste->getComment(Helper::getPasteId()); $comment->setData($commentData); + $this->expectException(Exception::class); + $this->expectExceptionCode(69); $comment->store(); } @@ -185,40 +181,30 @@ class ModelTest extends TestCase $this->assertFalse(Paste::isValidId('../bar/baz'), 'path attack'); } - /** - * @expectedException Exception - * @expectedExceptionCode 64 - */ public function testInvalidPaste() { $this->_model->getPaste(Helper::getPasteId())->delete(); $paste = $this->_model->getPaste(Helper::getPasteId()); + $this->expectException(Exception::class); + $this->expectExceptionCode(64); $paste->get(); } - /** - * @expectedException Exception - * @expectedExceptionCode 60 - */ public function testInvalidPasteId() { + $this->expectException(Exception::class); + $this->expectExceptionCode(60); $this->_model->getPaste(''); } - /** - * @expectedException Exception - * @expectedExceptionCode 62 - */ public function testInvalidComment() { $paste = $this->_model->getPaste(); + $this->expectException(Exception::class); + $this->expectExceptionCode(62); $paste->getComment(Helper::getPasteId()); } - /** - * @expectedException Exception - * @expectedExceptionCode 67 - */ public function testInvalidCommentDeletedPaste() { $pasteData = Helper::getPastePost(); @@ -228,13 +214,11 @@ class ModelTest extends TestCase $comment = $paste->getComment(Helper::getPasteId()); $paste->delete(); + $this->expectException(Exception::class); + $this->expectExceptionCode(67); $comment->store(); } - /** - * @expectedException Exception - * @expectedExceptionCode 68 - */ public function testInvalidCommentData() { $pasteData = Helper::getPastePost(); @@ -244,18 +228,17 @@ class ModelTest extends TestCase $paste->store(); $comment = $paste->getComment(Helper::getPasteId()); + $this->expectException(Exception::class); + $this->expectExceptionCode(68); $comment->store(); } - /** - * @expectedException Exception - * @expectedExceptionCode 65 - */ public function testInvalidCommentParent() { $paste = $this->_model->getPaste(Helper::getPasteId()); - $comment = $paste->getComment(''); - $comment->store(); + $this->expectException(Exception::class); + $this->expectExceptionCode(65); + $paste->getComment(''); } public function testExpiration() @@ -273,10 +256,6 @@ class ModelTest extends TestCase $this->assertEquals((float) 300, (float) $paste['meta']['time_to_live'], 'remaining time is set correctly', 1.0); } - /** - * @expectedException Exception - * @expectedExceptionCode 64 - */ public function testCommentDeletion() { $pasteData = Helper::getPastePost(); @@ -285,6 +264,8 @@ class ModelTest extends TestCase $paste = $this->_model->getPaste(); $paste->setData($pasteData); $paste->store(); + $this->expectException(Exception::class); + $this->expectExceptionCode(64); $paste->getComment(Helper::getPasteId())->delete(); } diff --git a/tst/Persistence/ServerSaltTest.php b/tst/Persistence/ServerSaltTest.php index 216e6c62..36486cb4 100644 --- a/tst/Persistence/ServerSaltTest.php +++ b/tst/Persistence/ServerSaltTest.php @@ -51,22 +51,16 @@ class ServerSaltTest extends TestCase $this->assertEquals($salt, ServerSalt::get()); } - /** - * @expectedException Exception - * @expectedExceptionCode 11 - */ public function testPathShenanigans() { // try setting an invalid path chmod($this->_invalidPath, 0000); ServerSalt::setPath($this->_invalidPath); + $this->expectException(Exception::class); + $this->expectExceptionCode(11); ServerSalt::get(); } - /** - * @expectedException Exception - * @expectedExceptionCode 20 - */ public function testFileRead() { // try setting an invalid file @@ -74,13 +68,11 @@ class ServerSaltTest extends TestCase file_put_contents($this->_invalidFile, ''); chmod($this->_invalidFile, 0000); ServerSalt::setPath($this->_invalidPath); + $this->expectException(Exception::class); + $this->expectExceptionCode(20); ServerSalt::get(); } - /** - * @expectedException Exception - * @expectedExceptionCode 13 - */ public function testFileWrite() { // try setting an invalid file @@ -92,18 +84,18 @@ class ServerSaltTest extends TestCase file_put_contents($this->_invalidPath . DIRECTORY_SEPARATOR . '.htaccess', ''); chmod($this->_invalidPath, 0500); ServerSalt::setPath($this->_invalidPath); + $this->expectException(Exception::class); + $this->expectExceptionCode(13); ServerSalt::get(); } - /** - * @expectedException Exception - * @expectedExceptionCode 10 - */ public function testPermissionShenanigans() { // try creating an invalid path chmod($this->_invalidPath, 0000); ServerSalt::setPath($this->_invalidPath . DIRECTORY_SEPARATOR . 'baz'); + $this->expectException(Exception::class); + $this->expectExceptionCode(10); ServerSalt::get(); } } diff --git a/tst/ViewTest.php b/tst/ViewTest.php index 4094c03d..dd6f3bbc 100644 --- a/tst/ViewTest.php +++ b/tst/ViewTest.php @@ -95,28 +95,28 @@ class ViewTest extends TestCase public function testTemplateRendersCorrectly() { foreach ($this->_content as $template => $content) { - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]+id="errormessage"[^>]*>.*' . self::$error . '#s', $content, $template . ': outputs error correctly' ); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#<[^>]+id="password"[^>]*>#', $content, $template . ': password available if configured' ); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]+id="opendiscussion"[^>]*checked="checked"[^>]*>#', $content, $template . ': checked discussion if configured' ); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#<[^>]+id="opendiscussionoption"[^>]*>#', $content, $template . ': discussions available if configured' ); // testing version number in JS address, since other instances may not be present in different templates - $this->assertRegExp( + $this->assertMatchesRegularExpression( '#]+src="js/privatebin.js\\?' . rawurlencode(self::$version) . '"[^>]*>#', $content, $template . ': outputs version correctly' @@ -124,13 +124,11 @@ class ViewTest extends TestCase } } - /** - * @expectedException Exception - * @expectedExceptionCode 80 - */ public function testMissingTemplate() { $test = new View; + $this->expectException(Exception::class); + $this->expectExceptionCode(80); $test->draw('123456789 does not exist!'); } } diff --git a/tst/phpunit.xml b/tst/phpunit.xml index caaa67d7..504ba1b8 100644 --- a/tst/phpunit.xml +++ b/tst/phpunit.xml @@ -1,19 +1,22 @@ - - - ./ - ConfigurationTestGenerator.php - - - - ../lib - - ../lib/Data/AbstractData.php - - - - - - - - + + + + + ../lib + + + ../lib/Data/AbstractData.php + + + + + + + + ./ + ConfigurationTestGenerator.php + + + + From ec190fdcf68535ccb7f0b1d787f656d88cd70bf9 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 11 Oct 2020 10:34:03 +0200 Subject: [PATCH 007/506] phpunit 9 requires php >= 7.3 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d695510f..e4cd7417 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + php-versions: ['7.3', '7.4', '8.0'] name: PHP ${{ matrix.php-versions }} unit tests on ${{ matrix.operating-system }} steps: - name: Checkout From 09133f4f10982ab88506f859a77ab8fe537393d4 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 11 Oct 2020 11:39:36 +0200 Subject: [PATCH 008/506] kudos StyleCI for spotting the unneccessary namespace --- tst/ControllerWithDbTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tst/ControllerWithDbTest.php b/tst/ControllerWithDbTest.php index a8ecaf10..8be1ec9c 100644 --- a/tst/ControllerWithDbTest.php +++ b/tst/ControllerWithDbTest.php @@ -1,6 +1,5 @@ Date: Sat, 5 Jun 2021 00:21:48 +0200 Subject: [PATCH 009/506] Add Siftleft scan It seems [to cover](https://slscan.io/en/latest/#supported-languages-frameworks) PHP including license check in addition to dependency scanning. --- .github/workflows/shiftleft-analysis.yml | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/shiftleft-analysis.yml diff --git a/.github/workflows/shiftleft-analysis.yml b/.github/workflows/shiftleft-analysis.yml new file mode 100644 index 00000000..18d412a6 --- /dev/null +++ b/.github/workflows/shiftleft-analysis.yml @@ -0,0 +1,35 @@ +# This workflow integrates Scan with GitHub's code scanning feature +# Scan is a free open-source security tool for modern DevOps teams from ShiftLeft +# Visit https://slscan.io/en/latest/integrations/code-scan for help +name: SL Scan + +on: + push: + branches: [ master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '16 22 * * 4' + +jobs: + Scan-Build: + # Scan runs on ubuntu, mac and windows + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # potentially add composer install steo here + - name: Perform Scan + uses: ShiftLeftSecurity/scan-action@master + env: + WORKSPACE: "" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SCAN_AUTO_BUILD: true + with: + output: reports + # Scan auto-detects the languages. + + - name: Upload report + uses: github/codeql-action/upload-sarif@v1 + with: + sarif_file: reports From a2e479192f1fb86886d7b21db3ff73cf743f75ab Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 7 Oct 2021 22:20:25 +0200 Subject: [PATCH 010/506] phpunit compatibility --- tst/Data/GoogleCloudStorageTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tst/Data/GoogleCloudStorageTest.php b/tst/Data/GoogleCloudStorageTest.php index 3b101c40..42402cf8 100644 --- a/tst/Data/GoogleCloudStorageTest.php +++ b/tst/Data/GoogleCloudStorageTest.php @@ -2,9 +2,10 @@ use Google\Auth\HttpHandler\HttpHandlerFactory; use GuzzleHttp\Client; +use PHPUnit\Framework\TestCase; use PrivateBin\Data\GoogleCloudStorage; -class GoogleCloudStorageTest extends PHPUnit_Framework_TestCase +class GoogleCloudStorageTest extends TestCase { private static $_client; private static $_bucket; From 1f95f57be9bfd4ea733fc25a8bd738f29c1e5bbc Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 7 Oct 2021 22:22:32 +0200 Subject: [PATCH 011/506] phpunit compatibility --- tst/Data/GoogleCloudStorageTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tst/Data/GoogleCloudStorageTest.php b/tst/Data/GoogleCloudStorageTest.php index 42402cf8..3df5719d 100644 --- a/tst/Data/GoogleCloudStorageTest.php +++ b/tst/Data/GoogleCloudStorageTest.php @@ -10,7 +10,7 @@ class GoogleCloudStorageTest extends TestCase private static $_client; private static $_bucket; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { $httpClient = new Client(array('debug'=>false)); $handler = HttpHandlerFactory::build($httpClient); @@ -24,7 +24,7 @@ class GoogleCloudStorageTest extends TestCase self::$_bucket = self::$_client->createBucket($name); } - public function setUp() + public function setUp(): void { ini_set('error_log', stream_get_meta_data(tmpfile())['uri']); $this->_model = GoogleCloudStorage::getInstance(array( @@ -33,7 +33,7 @@ class GoogleCloudStorageTest extends TestCase )); } - public function tearDown() + public function tearDown(): void { foreach (self::$_bucket->objects() as $object) { $object->delete(); From 1f6b962468991eb2cb260389f598249cd61e8214 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 7 Oct 2021 22:24:30 +0200 Subject: [PATCH 012/506] phpunit compatibility --- tst/ControllerWithGcsTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tst/ControllerWithGcsTest.php b/tst/ControllerWithGcsTest.php index 39833417..9921d106 100644 --- a/tst/ControllerWithGcsTest.php +++ b/tst/ControllerWithGcsTest.php @@ -14,7 +14,7 @@ class ControllerWithGcsTest extends ControllerTest private static $_bucket; private $_options = array(); - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { $httpClient = new Client(array('debug'=>false)); $handler = HttpHandlerFactory::build($httpClient); @@ -28,7 +28,7 @@ class ControllerWithGcsTest extends ControllerTest self::$_bucket = self::$_client->createBucket($name); } - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; From 168ce1d85c6ae01bc2bb20b42dc2657b044b3454 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 7 Oct 2021 22:25:51 +0200 Subject: [PATCH 013/506] phpunit compatibility --- tst/Data/GoogleCloudStorageTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/Data/GoogleCloudStorageTest.php b/tst/Data/GoogleCloudStorageTest.php index 3df5719d..4e13ee2a 100644 --- a/tst/Data/GoogleCloudStorageTest.php +++ b/tst/Data/GoogleCloudStorageTest.php @@ -40,7 +40,7 @@ class GoogleCloudStorageTest extends TestCase } } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { self::$_bucket->delete(); } From 9c81d85bb7d11e9c4eb12fe3ca9d947703b2fdbe Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 7 Oct 2021 22:34:15 +0200 Subject: [PATCH 014/506] phpunit compatibility --- tst/Data/DatabaseTest.php | 2 +- tst/ModelTest.php | 16 ++++------------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/tst/Data/DatabaseTest.php b/tst/Data/DatabaseTest.php index 2edf136e..a5be6c4a 100644 --- a/tst/Data/DatabaseTest.php +++ b/tst/Data/DatabaseTest.php @@ -43,7 +43,7 @@ class DatabaseTest extends TestCase $this->assertNotEquals($salt, ''); ServerSalt::setStore($this->_model); ServerSalt::get(); - $this->assertFileNotExists($file, 'legacy ServerSalt got removed'); + $this->assertFileDoesNotExist($file, 'legacy ServerSalt got removed'); $this->assertEquals($salt, ServerSalt::get(), 'ServerSalt got preserved & migrated'); } diff --git a/tst/ModelTest.php b/tst/ModelTest.php index 63c42411..f947c291 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -184,10 +184,6 @@ class ModelTest extends TestCase $paste->store(); } - /** - * @expectedException Exception - * @expectedExceptionCode 76 - */ public function testStoreFail() { $path = $this->_path . DIRECTORY_SEPARATOR . 'model-store-test.sq3'; @@ -224,13 +220,11 @@ class ModelTest extends TestCase $paste = $model->getPaste(); $paste->setData($pasteData); + $this->expectException(Exception::class); + $this->expectExceptionCode(76); $paste->store(); } - /** - * @expectedException Exception - * @expectedExceptionCode 70 - */ public function testCommentStoreFail() { $path = $this->_path . DIRECTORY_SEPARATOR . 'model-test.sq3'; @@ -272,13 +266,11 @@ class ModelTest extends TestCase $comment = $paste->getComment(Helper::getPasteId()); $comment->setData($commentData); + $this->expectException(Exception::class); + $this->expectExceptionCode(70); $comment->store(); } - /** - * @expectedException Exception - * @expectedExceptionCode 69 - */ public function testCommentDuplicate() { $pasteData = Helper::getPastePost(); From 5c61a442a081476f85e2a68a23b58837d44e369c Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 7 Oct 2021 22:36:11 +0200 Subject: [PATCH 015/506] phpunit compatibility --- tst/ModelTest.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tst/ModelTest.php b/tst/ModelTest.php index f947c291..751d3a8b 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -329,22 +329,16 @@ class ModelTest extends TestCase $paste->get(); } - /** - * @expectedException Exception - * @expectedExceptionCode 75 - */ public function testInvalidPasteFormat() { $pasteData = Helper::getPastePost(); $pasteData['adata'][1] = 'format does not exist'; $paste = $this->_model->getPaste(); + $this->expectException(Exception::class); + $this->expectExceptionCode(75); $paste->setData($pasteData); } - /** - * @expectedException Exception - * @expectedExceptionCode 60 - */ public function testInvalidPasteId() { $this->expectException(Exception::class); From 91462da29d8f17b37d10248026c1a2964c88ce20 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 7 Oct 2021 22:39:57 +0200 Subject: [PATCH 016/506] update composer --- composer.lock | 251 ++++++++++++-------------- vendor/composer/autoload_classmap.php | 1 - vendor/composer/autoload_static.php | 1 - 3 files changed, 118 insertions(+), 135 deletions(-) diff --git a/composer.lock b/composer.lock index 5bb6a15e..d331a77e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "217f0ba9bdac1014a332a8ba390be949", + "content-hash": "6b57b0aff04a146abea686470f5c5d2d", "packages": [ { "name": "mlocati/ip-lib", @@ -295,20 +295,20 @@ "type": "tidelift" } ], - "time": "2020-06-29T13:22:24+00:00" + "time": "2020-11-13T09:40:50+00:00" }, { "name": "nikic/php-parser", - "version": "v4.10.2", + "version": "v4.13.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "658f1be311a230e0907f5dfe0213742aff0596de" + "reference": "50953a2691a922aa1769461637869a0a2faa3f53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/658f1be311a230e0907f5dfe0213742aff0596de", - "reference": "658f1be311a230e0907f5dfe0213742aff0596de", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", + "reference": "50953a2691a922aa1769461637869a0a2faa3f53", "shasum": "" }, "require": { @@ -347,20 +347,20 @@ "parser", "php" ], - "time": "2020-09-26T10:30:38+00:00" + "time": "2021-09-20T12:20:58+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { @@ -403,20 +403,20 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2020-06-27T14:33:11+00:00" + "time": "2021-07-20T11:28:43+00:00" }, { "name": "phar-io/version", - "version": "3.0.2", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0" + "reference": "bae7c545bef187884426f042434e561ab1ddb182" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/c6bb6825def89e0a32220f88337f8ceaf1975fa0", - "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0", + "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", + "reference": "bae7c545bef187884426f042434e561ab1ddb182", "shasum": "" }, "require": { @@ -450,7 +450,7 @@ } ], "description": "Library for handling version information and constraints", - "time": "2020-06-27T14:39:04+00:00" + "time": "2021-02-23T14:00:09+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -555,16 +555,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.4.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" + "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/a12f7e301eb7258bb68acd89d4aefa05c2906cae", + "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae", "shasum": "" }, "require": { @@ -572,7 +572,8 @@ "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "*" + "ext-tokenizer": "*", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -596,37 +597,37 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2020-09-17T18:55:26+00:00" + "time": "2021-10-02T14:08:47+00:00" }, { "name": "phpspec/prophecy", - "version": "1.12.1", + "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" + "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", + "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", "shasum": "" }, "require": { "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", + "php": "^7.2 || ~8.0, <8.2", "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0", "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { - "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0 <9.3" + "phpspec/phpspec": "^6.0 || ^7.0", + "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { @@ -659,34 +660,34 @@ "spy", "stub" ], - "time": "2020-09-29T09:10:42+00:00" + "time": "2021-09-10T09:02:12+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.0", + "version": "9.2.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "53a4b737e83be724efd2bc4e7b929b9a30c48972" + "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/53a4b737e83be724efd2bc4e7b929b9a30c48972", - "reference": "53a4b737e83be724efd2bc4e7b929b9a30c48972", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218", + "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.8", + "nikic/php-parser": "^4.12.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", "sebastian/code-unit-reverse-lookup": "^2.0.2", "sebastian/complexity": "^2.0", "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0", + "sebastian/lines-of-code": "^1.0.3", "sebastian/version": "^3.0.1", "theseer/tokenizer": "^1.2.0" }, @@ -732,7 +733,7 @@ "type": "github" } ], - "time": "2020-10-02T03:37:32+00:00" + "time": "2021-09-17T05:39:03+00:00" }, { "name": "phpunit/php-file-iterator", @@ -851,16 +852,16 @@ }, { "name": "phpunit/php-text-template", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "18c887016e60e52477e54534956d7b47bc52cd84" + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/18c887016e60e52477e54534956d7b47bc52cd84", - "reference": "18c887016e60e52477e54534956d7b47bc52cd84", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "shasum": "" }, "require": { @@ -902,20 +903,20 @@ "type": "github" } ], - "time": "2020-09-28T06:03:05+00:00" + "time": "2020-10-26T05:33:50+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.2", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "c9ff14f493699e2f6adee9fd06a0245b276643b7" + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/c9ff14f493699e2f6adee9fd06a0245b276643b7", - "reference": "c9ff14f493699e2f6adee9fd06a0245b276643b7", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { @@ -957,20 +958,20 @@ "type": "github" } ], - "time": "2020-09-28T06:00:25+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", - "version": "9.4.1", + "version": "9.5.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1f09a12726593737e8a228ebb1c8647305d07c41" + "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1f09a12726593737e8a228ebb1c8647305d07c41", - "reference": "1f09a12726593737e8a228ebb1c8647305d07c41", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c814a05837f2edb0d1471d6e3f4ab3501ca3899a", + "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a", "shasum": "" }, "require": { @@ -982,11 +983,11 @@ "ext-xml": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.1", + "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2", + "phpunit/php-code-coverage": "^9.2.7", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -1000,7 +1001,7 @@ "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3", + "sebastian/type": "^2.3.4", "sebastian/version": "^3.0.2" }, "require-dev": { @@ -1017,7 +1018,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.4-dev" + "dev-master": "9.5-dev" } }, "autoload": { @@ -1056,7 +1057,7 @@ "type": "github" } ], - "time": "2020-10-11T07:41:19+00:00" + "time": "2021-09-25T07:38:51+00:00" }, { "name": "sebastian/cli-parser", @@ -1112,16 +1113,16 @@ }, { "name": "sebastian/code-unit", - "version": "1.0.7", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "59236be62b1bb9919e6d7f60b0b832dc05cef9ab" + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/59236be62b1bb9919e6d7f60b0b832dc05cef9ab", - "reference": "59236be62b1bb9919e6d7f60b0b832dc05cef9ab", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", "shasum": "" }, "require": { @@ -1152,15 +1153,15 @@ "role": "lead" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2020-11-30T08:15:22+00:00" + "time": "2020-10-26T13:08:54+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1215,16 +1216,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "7a8ff306445707539c1a6397372a982a1ec55120" + "reference": "55f4261989e546dc112258c7a75935a81a7ce382" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/7a8ff306445707539c1a6397372a982a1ec55120", - "reference": "7a8ff306445707539c1a6397372a982a1ec55120", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", + "reference": "55f4261989e546dc112258c7a75935a81a7ce382", "shasum": "" }, "require": { @@ -1281,20 +1282,20 @@ "type": "github" } ], - "time": "2020-09-30T06:47:25+00:00" + "time": "2020-10-26T15:49:45+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "ba8cc2da0c0bfbc813d03b56406734030c7f1eff" + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ba8cc2da0c0bfbc813d03b56406734030c7f1eff", - "reference": "ba8cc2da0c0bfbc813d03b56406734030c7f1eff", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", "shasum": "" }, "require": { @@ -1334,20 +1335,20 @@ "type": "github" } ], - "time": "2020-09-28T06:05:03+00:00" + "time": "2020-10-26T15:52:27+00:00" }, { "name": "sebastian/diff", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ffc949a1a2aae270ea064453d7535b82e4c32092" + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ffc949a1a2aae270ea064453d7535b82e4c32092", - "reference": "ffc949a1a2aae270ea064453d7535b82e4c32092", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", "shasum": "" }, "require": { @@ -1396,7 +1397,7 @@ "type": "github" } ], - "time": "2020-09-28T05:32:55+00:00" + "time": "2020-10-26T13:10:38+00:00" }, { "name": "sebastian/environment", @@ -1532,16 +1533,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.1", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "ea779cb749a478b22a2564ac41cd7bda79c78dc7" + "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/ea779cb749a478b22a2564ac41cd7bda79c78dc7", - "reference": "ea779cb749a478b22a2564ac41cd7bda79c78dc7", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", + "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", "shasum": "" }, "require": { @@ -1588,20 +1589,20 @@ "type": "github" } ], - "time": "2020-09-28T05:54:06+00:00" + "time": "2021-06-11T13:31:12+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "6514b8f21906b8b46f520d1fbd17a4523fa59a54" + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/6514b8f21906b8b46f520d1fbd17a4523fa59a54", - "reference": "6514b8f21906b8b46f520d1fbd17a4523fa59a54", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", "shasum": "" }, "require": { @@ -1641,20 +1642,20 @@ "type": "github" } ], - "time": "2020-09-28T06:07:27+00:00" + "time": "2020-11-28T06:42:11+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "f6f5957013d84725427d361507e13513702888a4" + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f6f5957013d84725427d361507e13513702888a4", - "reference": "f6f5957013d84725427d361507e13513702888a4", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", "shasum": "" }, "require": { @@ -1694,20 +1695,20 @@ "type": "github" } ], - "time": "2020-09-28T05:55:06+00:00" + "time": "2020-10-26T13:12:34+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5" + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5", - "reference": "d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { @@ -1745,20 +1746,20 @@ "type": "github" } ], - "time": "2020-09-28T05:56:16+00:00" + "time": "2020-10-26T13:14:26+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "ed8c9cd355089134bc9cba421b5cfdd58f0eaef7" + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/ed8c9cd355089134bc9cba421b5cfdd58f0eaef7", - "reference": "ed8c9cd355089134bc9cba421b5cfdd58f0eaef7", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", "shasum": "" }, "require": { @@ -1804,7 +1805,7 @@ "type": "github" } ], - "time": "2020-09-28T05:17:32+00:00" + "time": "2020-10-26T13:17:30+00:00" }, { "name": "sebastian/resource-operations", @@ -1859,16 +1860,16 @@ }, { "name": "sebastian/type", - "version": "2.3.0", + "version": "2.3.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fa592377f3923946cb90bf1f6a71ba2e5f229909" + "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fa592377f3923946cb90bf1f6a71ba2e5f229909", - "reference": "fa592377f3923946cb90bf1f6a71ba2e5f229909", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", + "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", "shasum": "" }, "require": { @@ -1907,7 +1908,7 @@ "type": "github" } ], - "time": "2020-10-06T08:41:03+00:00" + "time": "2021-06-15T12:49:02+00:00" }, { "name": "sebastian/version", @@ -2035,17 +2036,17 @@ "time": "2021-02-19T12:13:01+00:00" }, { - "name": "symfony/yaml", - "version": "v4.4.24", + "name": "theseer/tokenizer", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "8b6d1b97521e2f125039b3fcb4747584c6dfa0ef" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/8b6d1b97521e2f125039b3fcb4747584c6dfa0ef", - "reference": "8b6d1b97521e2f125039b3fcb4747584c6dfa0ef", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { @@ -2078,23 +2079,7 @@ "type": "github" } ], - "description": "Loads and dumps YAML files", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-05-16T09:52:47+00:00" + "time": "2021-07-28T10:34:58+00:00" }, { "name": "webmozart/assert", diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 2693674f..55c71993 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -41,7 +41,6 @@ return array( 'PrivateBin\\Model\\Comment' => $baseDir . '/lib/Model/Comment.php', 'PrivateBin\\Model\\Paste' => $baseDir . '/lib/Model/Paste.php', 'PrivateBin\\Persistence\\AbstractPersistence' => $baseDir . '/lib/Persistence/AbstractPersistence.php', - 'PrivateBin\\Persistence\\DataStore' => $baseDir . '/lib/Persistence/DataStore.php', 'PrivateBin\\Persistence\\PurgeLimiter' => $baseDir . '/lib/Persistence/PurgeLimiter.php', 'PrivateBin\\Persistence\\ServerSalt' => $baseDir . '/lib/Persistence/ServerSalt.php', 'PrivateBin\\Persistence\\TrafficLimiter' => $baseDir . '/lib/Persistence/TrafficLimiter.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 58f7a58a..3ca8c044 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -73,7 +73,6 @@ class ComposerStaticInitDontChange 'PrivateBin\\Model\\Comment' => __DIR__ . '/../..' . '/lib/Model/Comment.php', 'PrivateBin\\Model\\Paste' => __DIR__ . '/../..' . '/lib/Model/Paste.php', 'PrivateBin\\Persistence\\AbstractPersistence' => __DIR__ . '/../..' . '/lib/Persistence/AbstractPersistence.php', - 'PrivateBin\\Persistence\\DataStore' => __DIR__ . '/../..' . '/lib/Persistence/DataStore.php', 'PrivateBin\\Persistence\\PurgeLimiter' => __DIR__ . '/../..' . '/lib/Persistence/PurgeLimiter.php', 'PrivateBin\\Persistence\\ServerSalt' => __DIR__ . '/../..' . '/lib/Persistence/ServerSalt.php', 'PrivateBin\\Persistence\\TrafficLimiter' => __DIR__ . '/../..' . '/lib/Persistence/TrafficLimiter.php', From fa7aa3e88c2040e2e43ef852bd457b2c955cfb03 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 26 Feb 2022 07:22:32 +0100 Subject: [PATCH 017/506] fix composer lock --- composer.lock | 118 +++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/composer.lock b/composer.lock index c5cdefc9..28696436 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fa52d4988bfe17d4b27e3a4789a1ec49", + "content-hash": "958706639ca351590ba7dfa57f1992ac", "packages": [ { "name": "mlocati/ip-lib", @@ -298,16 +298,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.13.0", + "version": "v4.13.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53" + "reference": "210577fe3cf7badcc5814d99455df46564f3c077" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077", "shasum": "" }, "require": { @@ -346,7 +346,7 @@ "parser", "php" ], - "time": "2021-09-20T12:20:58+00:00" + "time": "2021-11-30T19:35:32+00:00" }, { "name": "phar-io/manifest", @@ -406,16 +406,16 @@ }, { "name": "phar-io/version", - "version": "3.1.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "bae7c545bef187884426f042434e561ab1ddb182" + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", - "reference": "bae7c545bef187884426f042434e561ab1ddb182", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { @@ -449,7 +449,7 @@ } ], "description": "Library for handling version information and constraints", - "time": "2021-02-23T14:00:09+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -601,16 +601,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.14.0", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e" + "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", - "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", + "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", "shasum": "" }, "require": { @@ -660,27 +660,27 @@ "spy", "stub" ], - "time": "2021-09-10T09:02:12+00:00" + "time": "2021-12-08T12:19:24+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.7", + "version": "9.2.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218" + "reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/deac8540cb7bd40b2b8cfa679b76202834fd04e8", + "reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.12.0", + "nikic/php-parser": "^4.13.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -733,20 +733,20 @@ "type": "github" } ], - "time": "2021-09-17T05:39:03+00:00" + "time": "2022-02-23T17:02:38+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.5", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { @@ -789,7 +789,7 @@ "type": "github" } ], - "time": "2020-09-28T05:57:25+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { "name": "phpunit/php-invoker", @@ -962,16 +962,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.10", + "version": "9.5.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a" + "reference": "5ff8c545a50226c569310a35f4fa89d79f1ddfdc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c814a05837f2edb0d1471d6e3f4ab3501ca3899a", - "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5ff8c545a50226c569310a35f4fa89d79f1ddfdc", + "reference": "5ff8c545a50226c569310a35f4fa89d79f1ddfdc", "shasum": "" }, "require": { @@ -987,7 +987,7 @@ "phar-io/version": "^3.0.2", "php": ">=7.3", "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.7", + "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -1022,11 +1022,11 @@ } }, "autoload": { - "classmap": [ - "src/" - ], "files": [ "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1049,7 +1049,7 @@ ], "funding": [ { - "url": "https://phpunit.de/donate.html", + "url": "https://phpunit.de/sponsors.html", "type": "custom" }, { @@ -1057,7 +1057,7 @@ "type": "github" } ], - "time": "2021-09-25T07:38:51+00:00" + "time": "2022-02-23T17:10:58+00:00" }, { "name": "sebastian/cli-parser", @@ -1460,16 +1460,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", "shasum": "" }, "require": { @@ -1518,7 +1518,7 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" @@ -1529,20 +1529,20 @@ "type": "github" } ], - "time": "2020-09-28T05:24:23+00:00" + "time": "2021-11-11T14:18:36+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.3", + "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", "shasum": "" }, "require": { @@ -1589,7 +1589,7 @@ "type": "github" } ], - "time": "2021-06-11T13:31:12+00:00" + "time": "2022-02-14T08:28:10+00:00" }, { "name": "sebastian/lines-of-code", @@ -1993,12 +1993,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2039,17 +2039,17 @@ "time": "2021-10-20T20:35:02+00:00" }, { - "name": "symfony/yaml", - "version": "v4.4.37", + "name": "theseer/tokenizer", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "d7f637cc0f0cc14beb0984f2bb50da560b271311" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/d7f637cc0f0cc14beb0984f2bb50da560b271311", - "reference": "d7f637cc0f0cc14beb0984f2bb50da560b271311", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { @@ -2082,7 +2082,7 @@ "type": "github" } ], - "time": "2022-01-24T20:11:01+00:00" + "time": "2021-07-28T10:34:58+00:00" }, { "name": "webmozart/assert", From 2ad79ebf71b46f52e643d7efaf0847a3499558ae Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 1 Jun 2022 20:50:38 +0200 Subject: [PATCH 018/506] add php 8.1 unit tests --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b11913d1..75d35a61 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['7.3', '7.4', '8.0'] + php-versions: ['7.3', '7.4', '8.0', '8.1'] name: PHP ${{ matrix.php-versions }} unit tests on ${{ matrix.operating-system }} env: extensions: gd, sqlite3 From b7cffbddd07447ff4b3d79c8f0907e513d8e5b8f Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 27 Jun 2022 19:05:57 +0200 Subject: [PATCH 019/506] CREATE INDEX IF NOT EXISTS is not supported as of MySQL <= 8.0, fixes #943 --- lib/Data/Database.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index f9a8ae8a..a5b51362 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -837,8 +837,9 @@ class Database extends AbstractData end;' ); } else { + // CREATE INDEX IF NOT EXISTS not supported as of MySQL <= 8.0 self::$_db->exec( - 'CREATE INDEX IF NOT EXISTS "comment_parent" ON "' . + 'CREATE INDEX "comment_parent" ON "' . self::_sanitizeIdentifier('comment') . '" ("pasteid")' ); } @@ -949,8 +950,9 @@ class Database extends AbstractData self::_sanitizeIdentifier('comment') . '" ("dataid")' ); } + // CREATE INDEX IF NOT EXISTS not supported as of MySQL <= 8.0 self::$_db->exec( - 'CREATE INDEX IF NOT EXISTS "comment_parent" ON "' . + 'CREATE INDEX "comment_parent" ON "' . self::_sanitizeIdentifier('comment') . '" ("pasteid")' ); // no break, continue with updates for 0.22 and later From 4ad4aed875e0af79b3bbe4b1ae8060567c101c8a Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 28 Jun 2022 06:51:21 +0200 Subject: [PATCH 020/506] apply table prefix to indexes as well, to support multiple instances sharing a single database --- CHANGELOG.md | 2 ++ lib/Data/Database.php | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c036ad4..1343024c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ * **1.4.1 (not yet released)** * ADDED: Translations for Turkish * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) + * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) + * FIXED: Apply table prefix to indexes as well, to support multiple instances sharing a single database (#943) * **1.4 (2022-04-09)** * ADDED: Translations for Corsican, Estonian, Finnish and Lojban * ADDED: new HTTP headers improving security (#765) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index a5b51362..b42c76b9 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -839,7 +839,8 @@ class Database extends AbstractData } else { // CREATE INDEX IF NOT EXISTS not supported as of MySQL <= 8.0 self::$_db->exec( - 'CREATE INDEX "comment_parent" ON "' . + 'CREATE INDEX "' . + self::_sanitizeIdentifier('comment_parent') . '" ON "' . self::_sanitizeIdentifier('comment') . '" ("pasteid")' ); } @@ -942,17 +943,20 @@ class Database extends AbstractData ); } else { self::$_db->exec( - 'CREATE UNIQUE INDEX IF NOT EXISTS "paste_dataid" ON "' . + 'CREATE UNIQUE INDEX IF NOT EXISTS "' . + self::_sanitizeIdentifier('paste_dataid') . '" ON "' . self::_sanitizeIdentifier('paste') . '" ("dataid")' ); self::$_db->exec( - 'CREATE UNIQUE INDEX IF NOT EXISTS "comment_dataid" ON "' . + 'CREATE UNIQUE INDEX IF NOT EXISTS "' . + self::_sanitizeIdentifier('comment_dataid') . '" ON "' . self::_sanitizeIdentifier('comment') . '" ("dataid")' ); } // CREATE INDEX IF NOT EXISTS not supported as of MySQL <= 8.0 self::$_db->exec( - 'CREATE INDEX "comment_parent" ON "' . + 'CREATE INDEX "' . + self::_sanitizeIdentifier('comment_parent') . '" ON "' . self::_sanitizeIdentifier('comment') . '" ("pasteid")' ); // no break, continue with updates for 0.22 and later From e6d606ba8812b9780f8030238bd17901a7b6f81a Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 29 Jun 2022 22:25:54 +0200 Subject: [PATCH 021/506] clarify that it is only unsupported by Oracle MySQL, while supported in MariaDB, Postgres, SQLite, ... --- lib/Data/Database.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index b42c76b9..c34ee131 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -837,7 +837,7 @@ class Database extends AbstractData end;' ); } else { - // CREATE INDEX IF NOT EXISTS not supported as of MySQL <= 8.0 + // CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0 self::$_db->exec( 'CREATE INDEX "' . self::_sanitizeIdentifier('comment_parent') . '" ON "' . @@ -953,7 +953,7 @@ class Database extends AbstractData self::_sanitizeIdentifier('comment') . '" ("dataid")' ); } - // CREATE INDEX IF NOT EXISTS not supported as of MySQL <= 8.0 + // CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0 self::$_db->exec( 'CREATE INDEX "' . self::_sanitizeIdentifier('comment_parent') . '" ON "' . From 29b8215332257de43cb4327c4abecfbf324273f8 Mon Sep 17 00:00:00 2001 From: rugk Date: Sat, 9 Jul 2022 16:44:35 +0200 Subject: [PATCH 022/506] Add missing package-json.lock NodeJS v16.14.0 --- js/package-lock.json | 1785 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1785 insertions(+) create mode 100644 js/package-lock.json diff --git a/js/package-lock.json b/js/package-lock.json new file mode 100644 index 00000000..31c4a3a3 --- /dev/null +++ b/js/package-lock.json @@ -0,0 +1,1785 @@ +{ + "name": "privatebin", + "version": "1.4.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "privatebin", + "version": "1.4.0", + "license": "zlib-acknowledgement", + "devDependencies": { + "@peculiar/webcrypto": "^1.1.1", + "jsdom": "^9.12.0", + "jsdom-global": "^2.1.1", + "jsdom-url": "^2.2.1", + "jsverify": "^0.8.3" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.2.0.tgz", + "integrity": "sha512-1ENEJNY7Lwlua/1wvzpYP194WtjQBfFxvde2FlzfBFh/ln6wvChrtxlORhbKEnYswzn6fOC4c7HdC5izLPMTJg==", + "dev": true, + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dev": true, + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.0.tgz", + "integrity": "sha512-U58N44b2m3OuTgpmKgf0LPDOmP3bhwNz01vAnj1mBwxBASRhptWYK+M3zG+HBkDqGQM+bFsoIihTW8MdmPXEqg==", + "dev": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0", + "webcrypto-core": "^1.7.4" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/abab": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", + "integrity": "sha512-I+Wi+qiE2kUXyrRhNsWv6XsjUTBJjSoVSctKNBfLG5zG/Xe7Rjbxf13+vqYHNTwHaFU+FtSlVxOCTiMEVtPv0A==", + "dev": true + }, + "node_modules/acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==", + "dev": true, + "dependencies": { + "acorn": "^4.0.4" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==", + "dev": true + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dev": true, + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/class-proxy": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/class-proxy/-/class-proxy-1.1.2.tgz", + "integrity": "sha512-kowpC1EGn0b5ZxOMbF8f7IO03gg6dtI1rwBIHMfG5dEAeOVpZpukN9cT4K9cxv+IG8JihVdsqPr0V5bitB+pqQ==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-type-parser": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.2.tgz", + "integrity": "sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "integrity": "sha512-FUpKc+1FNBsHUr9IsfSGCovr8VuGOiiuzlgCyppKBjJi2jYTOFLN3oiiNRMIvYqbFzF38mqKj4BgcevzU5/kIA==", + "dev": true, + "dependencies": { + "cssom": "0.3.x" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^1.0.1" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsdom": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.12.0.tgz", + "integrity": "sha512-Qw4oqNxo4LyzkSqVIyCnEltTc4xV3g1GBaI88AvYTesWzmWHUSoMNmhBjUBa+6ldXIBJS9xoeLNJPfUAykTyxw==", + "dev": true, + "dependencies": { + "abab": "^1.0.3", + "acorn": "^4.0.4", + "acorn-globals": "^3.1.0", + "array-equal": "^1.0.0", + "content-type-parser": "^1.0.1", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": ">= 0.2.37 < 0.3.0", + "escodegen": "^1.6.1", + "html-encoding-sniffer": "^1.0.1", + "nwmatcher": ">= 1.3.9 < 2.0.0", + "parse5": "^1.5.1", + "request": "^2.79.0", + "sax": "^1.2.1", + "symbol-tree": "^3.2.1", + "tough-cookie": "^2.3.2", + "webidl-conversions": "^4.0.0", + "whatwg-encoding": "^1.0.1", + "whatwg-url": "^4.3.0", + "xml-name-validator": "^2.0.1" + } + }, + "node_modules/jsdom-global": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-2.1.1.tgz", + "integrity": "sha512-nVZiKQhXZzmkFSF+AfpvErIYuzPEuBV684gYpWagtwWTLiy0p5EgQbP7gmNNA6/qxFb8l1E5w1NjES5nSBCw5A==", + "dev": true + }, + "node_modules/jsdom-url": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jsdom-url/-/jsdom-url-2.2.1.tgz", + "integrity": "sha512-+wha7QGq/vPR97R/wz5+213pyWP1362/xmAMmesyVgxyTFOfAeKtwPah+f2znabdNdcqOPbyM7j/xWHbXAqhmg==", + "dev": true, + "dependencies": { + "class-proxy": "^1.1.1", + "whatwg-url": "^7.0.0" + } + }, + "node_modules/jsdom-url/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/jsdom-url/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsverify": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/jsverify/-/jsverify-0.8.4.tgz", + "integrity": "sha512-nUG73Sfi8L4eOkc7pv9sflgAm43v+z6XMuePGVdRoBUxBLJiVcMcf3Xgc4h19eHHF3JwsaagOkUu825UnPBLJw==", + "dev": true, + "dependencies": { + "lazy-seq": "^1.0.0", + "rc4": "~0.1.5", + "trampa": "^1.0.0", + "typify-parser": "^1.1.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lazy-seq": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazy-seq/-/lazy-seq-1.0.0.tgz", + "integrity": "sha512-AQ4vRcnULa7FX6R6YTAjKQAE1MuEThidVQm0TEtTpedaBpnOwid5k6go16E5NDkafel1xAsZL73WkwdG03IzhA==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nwmatcher": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", + "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha512-w2jx/0tJzvgKwZa58sj2vAYq/S/K1QJfIB3cWYea/Iu1scFPDQQ3IQiVZTHWtRBwAjv2Yd7S/xeZf3XqLDb3bA==", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", + "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/rc4": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/rc4/-/rc4-0.1.5.tgz", + "integrity": "sha512-xdDTNV90z5x5u25Oc871Xnvu7yAr4tV7Eluh0VSvrhUkry39q1k+zkz7xroqHbRq+8PiazySHJPArqifUvz9VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/trampa": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trampa/-/trampa-1.0.1.tgz", + "integrity": "sha512-93WeyHNuRggPEsfCe+yHxCgM2s6H3Q8Wmlt6b6ObJL8qc7eZlRaFjQxwTrB+zbvGtlDRnAkMoYYo3+2uH/fEwA==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typify-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typify-parser/-/typify-parser-1.1.0.tgz", + "integrity": "sha512-p5+L1sc6Al3bcStMwiZNxDh4ii4JxL+famEbSIUuOUMVoNn9Nz27AT1jL3x7poMHxqKK0UQIUAp5lGkKbyKkFA==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/webcrypto-core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.5.tgz", + "integrity": "sha512-gaExY2/3EHQlRNNNVSrbG2Cg94Rutl7fAaKILS1w8ZDhGxdFOaw6EbCfHIxPy9vt/xwp5o0VQAx9aySPF6hU1A==", + "dev": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-url": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-4.8.0.tgz", + "integrity": "sha512-nUvUPuenPFtPfy/X+dAYh/TfRbTBlnXTM5iIfLseJFkkQewmpG9pGR6i87E9qL+lZaJzv+99kkQWoGOtLfkZQQ==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/whatwg-url/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xml-name-validator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", + "integrity": "sha512-jRKe/iQYMyVJpzPH+3HL97Lgu5HrCfii+qSo+TfjKHtOnvbnvdVfMYrn9Q34YV81M2e5sviJlI6Ko9y+nByzvA==", + "dev": true + } + }, + "dependencies": { + "@peculiar/asn1-schema": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.2.0.tgz", + "integrity": "sha512-1ENEJNY7Lwlua/1wvzpYP194WtjQBfFxvde2FlzfBFh/ln6wvChrtxlORhbKEnYswzn6fOC4c7HdC5izLPMTJg==", + "dev": true, + "requires": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dev": true, + "requires": { + "tslib": "^2.0.0" + } + }, + "@peculiar/webcrypto": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.0.tgz", + "integrity": "sha512-U58N44b2m3OuTgpmKgf0LPDOmP3bhwNz01vAnj1mBwxBASRhptWYK+M3zG+HBkDqGQM+bFsoIihTW8MdmPXEqg==", + "dev": true, + "requires": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0", + "webcrypto-core": "^1.7.4" + } + }, + "abab": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", + "integrity": "sha512-I+Wi+qiE2kUXyrRhNsWv6XsjUTBJjSoVSctKNBfLG5zG/Xe7Rjbxf13+vqYHNTwHaFU+FtSlVxOCTiMEVtPv0A==", + "dev": true + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", + "dev": true + }, + "acorn-globals": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==", + "dev": true, + "requires": { + "acorn": "^4.0.4" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==", + "dev": true + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dev": true, + "requires": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "class-proxy": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/class-proxy/-/class-proxy-1.1.2.tgz", + "integrity": "sha512-kowpC1EGn0b5ZxOMbF8f7IO03gg6dtI1rwBIHMfG5dEAeOVpZpukN9cT4K9cxv+IG8JihVdsqPr0V5bitB+pqQ==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "content-type-parser": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.2.tgz", + "integrity": "sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "integrity": "sha512-FUpKc+1FNBsHUr9IsfSGCovr8VuGOiiuzlgCyppKBjJi2jYTOFLN3oiiNRMIvYqbFzF38mqKj4BgcevzU5/kIA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "jsdom": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.12.0.tgz", + "integrity": "sha512-Qw4oqNxo4LyzkSqVIyCnEltTc4xV3g1GBaI88AvYTesWzmWHUSoMNmhBjUBa+6ldXIBJS9xoeLNJPfUAykTyxw==", + "dev": true, + "requires": { + "abab": "^1.0.3", + "acorn": "^4.0.4", + "acorn-globals": "^3.1.0", + "array-equal": "^1.0.0", + "content-type-parser": "^1.0.1", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": ">= 0.2.37 < 0.3.0", + "escodegen": "^1.6.1", + "html-encoding-sniffer": "^1.0.1", + "nwmatcher": ">= 1.3.9 < 2.0.0", + "parse5": "^1.5.1", + "request": "^2.79.0", + "sax": "^1.2.1", + "symbol-tree": "^3.2.1", + "tough-cookie": "^2.3.2", + "webidl-conversions": "^4.0.0", + "whatwg-encoding": "^1.0.1", + "whatwg-url": "^4.3.0", + "xml-name-validator": "^2.0.1" + } + }, + "jsdom-global": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-2.1.1.tgz", + "integrity": "sha512-nVZiKQhXZzmkFSF+AfpvErIYuzPEuBV684gYpWagtwWTLiy0p5EgQbP7gmNNA6/qxFb8l1E5w1NjES5nSBCw5A==", + "dev": true + }, + "jsdom-url": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jsdom-url/-/jsdom-url-2.2.1.tgz", + "integrity": "sha512-+wha7QGq/vPR97R/wz5+213pyWP1362/xmAMmesyVgxyTFOfAeKtwPah+f2znabdNdcqOPbyM7j/xWHbXAqhmg==", + "dev": true, + "requires": { + "class-proxy": "^1.1.1", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "jsverify": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/jsverify/-/jsverify-0.8.4.tgz", + "integrity": "sha512-nUG73Sfi8L4eOkc7pv9sflgAm43v+z6XMuePGVdRoBUxBLJiVcMcf3Xgc4h19eHHF3JwsaagOkUu825UnPBLJw==", + "dev": true, + "requires": { + "lazy-seq": "^1.0.0", + "rc4": "~0.1.5", + "trampa": "^1.0.0", + "typify-parser": "^1.1.0" + } + }, + "lazy-seq": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazy-seq/-/lazy-seq-1.0.0.tgz", + "integrity": "sha512-AQ4vRcnULa7FX6R6YTAjKQAE1MuEThidVQm0TEtTpedaBpnOwid5k6go16E5NDkafel1xAsZL73WkwdG03IzhA==", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "nwmatcher": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", + "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha512-w2jx/0tJzvgKwZa58sj2vAYq/S/K1QJfIB3cWYea/Iu1scFPDQQ3IQiVZTHWtRBwAjv2Yd7S/xeZf3XqLDb3bA==", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "pvtsutils": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", + "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", + "dev": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "dev": true + }, + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true + }, + "rc4": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/rc4/-/rc4-0.1.5.tgz", + "integrity": "sha512-xdDTNV90z5x5u25Oc871Xnvu7yAr4tV7Eluh0VSvrhUkry39q1k+zkz7xroqHbRq+8PiazySHJPArqifUvz9VA==", + "dev": true + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "trampa": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trampa/-/trampa-1.0.1.tgz", + "integrity": "sha512-93WeyHNuRggPEsfCe+yHxCgM2s6H3Q8Wmlt6b6ObJL8qc7eZlRaFjQxwTrB+zbvGtlDRnAkMoYYo3+2uH/fEwA==", + "dev": true + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typify-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typify-parser/-/typify-parser-1.1.0.tgz", + "integrity": "sha512-p5+L1sc6Al3bcStMwiZNxDh4ii4JxL+famEbSIUuOUMVoNn9Nz27AT1jL3x7poMHxqKK0UQIUAp5lGkKbyKkFA==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "webcrypto-core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.5.tgz", + "integrity": "sha512-gaExY2/3EHQlRNNNVSrbG2Cg94Rutl7fAaKILS1w8ZDhGxdFOaw6EbCfHIxPy9vt/xwp5o0VQAx9aySPF6hU1A==", + "dev": true, + "requires": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-url": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-4.8.0.tgz", + "integrity": "sha512-nUvUPuenPFtPfy/X+dAYh/TfRbTBlnXTM5iIfLseJFkkQewmpG9pGR6i87E9qL+lZaJzv+99kkQWoGOtLfkZQQ==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "xml-name-validator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", + "integrity": "sha512-jRKe/iQYMyVJpzPH+3HL97Lgu5HrCfii+qSo+TfjKHtOnvbnvdVfMYrn9Q34YV81M2e5sviJlI6Ko9y+nByzvA==", + "dev": true + } + } +} From 08946d1cababe0a84545225e2054b3668f037128 Mon Sep 17 00:00:00 2001 From: rugk Date: Sat, 9 Jul 2022 16:48:21 +0200 Subject: [PATCH 023/506] Use npm ci instead of npm install for tests in CI So it uses the package-json.lock file actually. --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 55a51aaf..7bc1e120 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -112,7 +112,7 @@ jobs: run: npm install -g mocha - name: Setup Node modules - run: npm install + run: npm ci working-directory: js - name: Run unit tests From 79fd33d21ffb1bdb613bf5d03cc14f2addebf768 Mon Sep 17 00:00:00 2001 From: rugk Date: Sat, 9 Jul 2022 16:57:06 +0200 Subject: [PATCH 024/506] chore: run tests with NodeJS 14 I expect no stuff to break or so, so let's just try to use the current recommend LTS version. (v14 will also die at some time, but Fedora e.g. still seems to use it for now by default. Likely we may upgrade soon even more.) Ref https://nodejs.org/en/about/releases/ --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 55a51aaf..530be1cc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -104,7 +104,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v3 with: - node-version: '12' + node-version: '14' cache: 'npm' cache-dependency-path: 'js/package.json' From 9a476ac34d67dc61adfb8313d39077907b21b82a Mon Sep 17 00:00:00 2001 From: rugk Date: Sat, 9 Jul 2022 17:00:45 +0200 Subject: [PATCH 025/506] chore: switch to proper cache file now we have it, i.e. package-lock.json as per https://github.com/actions/setup-node#caching-global-packages-data --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7bc1e120..bc01735c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -106,7 +106,7 @@ jobs: with: node-version: '12' cache: 'npm' - cache-dependency-path: 'js/package.json' + cache-dependency-path: 'js/package-lock.json' - name: Setup Mocha run: npm install -g mocha From e536db9b7e9fb38229c19ec2b245592b676989d2 Mon Sep 17 00:00:00 2001 From: rugk Date: Sat, 9 Jul 2022 17:04:28 +0200 Subject: [PATCH 026/506] style: run tests via npm script insread of custom command I.e. not call mocha directly but let the script defined in package.json do it's job. --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 530be1cc..10e84b48 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -116,6 +116,6 @@ jobs: working-directory: js - name: Run unit tests - run: mocha + run: npm test working-directory: js From 48bb2fdf0f1e9d54101369fb8f4b9cc998bfaf07 Mon Sep 17 00:00:00 2001 From: rugk Date: Sun, 10 Jul 2022 00:13:47 +0200 Subject: [PATCH 027/506] Use NodeJs v16 for tests So 14 worked, let's try 16. (Actually noticed fedora uses v16 not 14 which makes sense if you see the support time.) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 319db88d..2b1194e1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -104,7 +104,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v3 with: - node-version: '14' + node-version: '16' cache: 'npm' cache-dependency-path: 'js/package-lock.json' From 9e499652bef8afbdcfce91f555be3f481f11b64a Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Thu, 14 Jul 2022 08:34:07 +0200 Subject: [PATCH 028/506] New translations en.json (Spanish) --- i18n/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/es.json b/i18n/es.json index 909b32cf..38cbd34b 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -186,5 +186,5 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite este enlace para ver la nota. Dar la URL a cualquier persona también les permite acceder a la nota.", "URL shortener may expose your decrypt key in URL.": "El acortador de URL puede exponer su clave de descifrado en el URL.", "Save paste": "Guardar \"paste\"", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Tu IP no está autorizada para crear contenido." } From 925f8cb338e5ef01fdec65e4f039e94dc00231fc Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Thu, 14 Jul 2022 09:41:47 +0200 Subject: [PATCH 029/506] New translations en.json (Spanish) --- i18n/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/es.json b/i18n/es.json index 38cbd34b..641ef3ba 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -2,7 +2,7 @@ "PrivateBin": "PrivateBin", "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s es un \"pastebin\" en línea minimalista de código abierto, donde el servidor no tiene ningún conocimiento de los datos guardados. Los datos son cifrados/descifrados %sen el navegador%s usando 256 bits AES.", "More information on the project page.": "Más información en la página del proyecto.", - "Because ignorance is bliss": "Porque la ignorancia es dicha", + "Because ignorance is bliss": "Porque la ignorancia es felicidad", "en": "es", "Paste does not exist, has expired or has been deleted.": "El \"paste\" no existe, ha caducado o ha sido eliminado.", "%s requires php %s or above to work. Sorry.": "%s requiere php %s o superior para funcionar. Lo siento.", From 5c20a424e1561b291a997153e871a7462c6afe36 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Fri, 22 Jul 2022 14:07:48 +0200 Subject: [PATCH 030/506] New translations en.json (Lithuanian) --- i18n/lt.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/lt.json b/i18n/lt.json index 195fab06..76b28163 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -186,5 +186,5 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.", "URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.", "Save paste": "Įrašyti įdėjimą", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Jūsų IP adresas neturi įgaliojimų kurti įdėjimų." } From 67365f8602de9bbc353f1f2efaeb0a7552c0b559 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 21 Aug 2022 17:21:27 +0200 Subject: [PATCH 031/506] New translations en.json (Ukrainian) --- i18n/uk.json | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/i18n/uk.json b/i18n/uk.json index 52e97233..7e3e6c46 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -8,10 +8,10 @@ "%s requires php %s or above to work. Sorry.": "Для роботи %s потрібен php %s и вище. Вибачте.", "%s requires configuration section [%s] to be present in configuration file.": "%s потрібна секція [%s] в конфігураційному файлі.", "Please wait %d seconds between each post.": [ - "Please wait %d second between each post. (singular)", - "Please wait %d seconds between each post. (1st plural)", - "Please wait %d seconds between each post. (2nd plural)", - "Please wait %d seconds between each post. (3rd plural)" + "Будь ласка, зачекайте %d секунду між створеннями.", + "Будь ласка, зачекайте %d секунди між створеннями.", + "Будь ласка, зачекайте %d секунд між створеннями.", + "Будь ласка, зачекайте %d секунд між створеннями." ], "Paste is limited to %s of encrypted data.": "Розмір допису обмежений %s зашифрованих даних.", "Invalid data.": "Неправильні дані.", @@ -170,21 +170,21 @@ "For more information see this FAQ entry.": "Для подробиць дивіться інформацію в FAQ.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Ваш переглядач вимагає підключення HTTPS для підтримки WebCrypto API. Спробуйте перемкнутися на HTTPS.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Ваш переглядач не підтримує WebAssembly, що використовується для стиснення zlib. Ви можете створювати нестиснені документи, але не зможете читати стиснені.", - "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", - "Retry": "Retry", - "Showing raw text…": "Showing raw text…", - "Notice:": "Notice:", - "This link will expire after %s.": "This link will expire after %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", - "Link:": "Link:", - "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", - "Use Current Timezone": "Use Current Timezone", - "Convert To UTC": "Convert To UTC", - "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", - "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "waiting on user to provide a password": "очікування користувача для вводу паролю", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Не вдалося розшифрувати дані. Може ви ввели неправильний пароль? Спробуйте знов з допомогою кнопки що зверху.", + "Retry": "Повторити", + "Showing raw text…": "Відображається сирий текст…", + "Notice:": "Примітка:", + "This link will expire after %s.": "Термін дії цього посилання сплине через %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Дане посилання доступна тільки один раз, не натискайте кнопку назад та не обновляйте сторінку браузера.", + "Link:": "Посилання:", + "Recipient may become aware of your timezone, convert time to UTC?": "Отримувач дізнається ваш часовий пояс, перетворити час в UTC?", + "Use Current Timezone": "Використовувати поточний часовий пояс", + "Convert To UTC": "Конвертувати в UTC", + "Close": "Закрити", + "Encrypted note on PrivateBin": "Зашифрована нотатка на PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Відвідайте посилання, щоб переглянути нотатку. Передача посилання будь-кому дозволить їм переглянути нотатку.", + "URL shortener may expose your decrypt key in URL.": "Сервіс скорочення посилань може викрити ваш ключ дешифрування з URL.", + "Save paste": "Зберегти вставку", + "Your IP is not authorized to create pastes.": "Вашому IP не дозволено створювати вставки." } From a105ba75665952c3eed5d60f9c41d614e70467fd Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 21 Aug 2022 17:21:28 +0200 Subject: [PATCH 032/506] New translations en.json (Turkish) --- i18n/tr.json | 228 +++++++++++++++++++++++++-------------------------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/i18n/tr.json b/i18n/tr.json index ad5d79af..c2c380e1 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -1,135 +1,135 @@ { "PrivateBin": "PrivateBin", - "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s sunucunun burada paylaştığınız veriyi görmediği, minimal, açık kaynak bir pastebindir. Veriler tarayıcıda 256 bit AES kullanılarak şifrelenir/çözülür.", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.", "More information on the project page.": "Daha fazla bilgi için proje sayfası'na göz atabilirsiniz.", "Because ignorance is bliss": "Çünkü, cehalet mutluluktur", "en": "tr", "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.", - "%s requires php %s or above to work. Sorry.": "%s PHP %s veya daha üstünü gerektirir.", - "%s requires configuration section [%s] to be present in configuration file.": "%s konfigürasyon bölümünün [%s] bulunmasını gerektir.", + "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.", + "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", "Please wait %d seconds between each post.": [ - "Lütfen paylaşımlar arasında %d saniye bekleyiniz.", - "Lütfen paylaşımlar arasında %d saniye bekleyiniz.", - "Lütfen paylaşımlar arasında %d saniye bekleyiniz.", - "Lütfen paylaşımlar arasında %d saniye bekleyiniz." + "Please wait %d second between each post. (singular)", + "Please wait %d seconds between each post. (1st plural)", + "Please wait %d seconds between each post. (2nd plural)", + "Please wait %d seconds between each post. (3rd plural)" ], - "Paste is limited to %s of encrypted data.": "Yazılar %s şifreli veriyle sınırlıdır.", + "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", "Invalid data.": "Geçersiz veri.", "You are unlucky. Try again.": "Lütfen tekrar deneyiniz.", - "Error saving comment. Sorry.": "Yorum kaydedilemedi.", - "Error saving paste. Sorry.": "Yazı kaydedilemedi. Üzgünüz.", - "Invalid paste ID.": "Geçersiz yazı ID'si.", - "Paste is not of burn-after-reading type.": "Yazı okunduğunda silinmeyecek şekilde ayarlanmış.", - "Wrong deletion token. Paste was not deleted.": "Yanlış silme anahtarı. Yazı silinemedi.", - "Paste was properly deleted.": "Yazı başarıyla silindi.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript %s 'in çalışması için gereklidir. Rahatsızlıktan dolayı özür dileriz.", - "%s requires a modern browser to work.": "%s çalışmak için çağdaş bir tarayıcı gerektirir.", + "Error saving comment. Sorry.": "Error saving comment. Sorry.", + "Error saving paste. Sorry.": "Error saving paste. Sorry.", + "Invalid paste ID.": "Invalid paste ID.", + "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", + "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", + "Paste was properly deleted.": "Paste was properly deleted.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", + "%s requires a modern browser to work.": "%s requires a modern browser to work.", "New": "Yeni", "Send": "Gönder", "Clone": "Kopyala", - "Raw text": "Açık yazı", + "Raw text": "Raw text", "Expires": "Süre Sonu", - "Burn after reading": "Okuduktan sonra sil", + "Burn after reading": "Burn after reading", "Open discussion": "Açık Tartışmalar", - "Password (recommended)": "Şifre (önerilir)", + "Password (recommended)": "Password (recommended)", "Discussion": "Tartışma", "Toggle navigation": "Gezinmeyi değiştir", "%d seconds": [ - "%d saniye", - "%d saniye", - "%d saniye", - "%d saniye" + "%d second (singular)", + "%d seconds (1st plural)", + "%d seconds (2nd plural)", + "%d seconds (3rd plural)" ], "%d minutes": [ - "%d dakika", - "%d dakika", - "%d dakika", - "%d dakika" + "%d minute (singular)", + "%d minutes (1st plural)", + "%d minutes (2nd plural)", + "%d minutes (3rd plural)" ], "%d hours": [ - "%d saat", - "%d saat", - "%d saat", - "%d saat" + "%d hour (singular)", + "%d hours (1st plural)", + "%d hours (2nd plural)", + "%d hours (3rd plural)" ], "%d days": [ - "%d gün", - "%d gün", - "%d gün", - "%d gün" + "%d day (singular)", + "%d days (1st plural)", + "%d days (2nd plural)", + "%d days (3rd plural)" ], "%d weeks": [ - "%d hafta", - "%d hafta", - "%d hafta", - "%d hafta" + "%d hafta (tekil)", + "%d haftalar (çoğul)", + "%d weeks (2nd plural)", + "%d weeks (3rd plural)" ], "%d months": [ - "%d ay", - "%d ay", - "%d ay", - "%d ay" + "%d month (singular)", + "%d months (1st plural)", + "%d months (2nd plural)", + "%d months (3rd plural)" ], "%d years": [ - "%d yıl", - "%d yıl", - "%d yıl", - "%d yıl" + "%d year (singular)", + "%d years (1st plural)", + "%d years (2nd plural)", + "%d years (3rd plural)" ], - "Never": "Asla", + "Never": "Never", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", "This document will expire in %d seconds.": [ - "Bu belge %s saniyede silinecektir.", - "Bu belge %s saniyede silinecektir.", - "Bu belge %s saniyede silinecektir.", - "Bu belge %s saniyede silinecektir." + "This document will expire in %d second. (singular)", + "This document will expire in %d seconds. (1st plural)", + "This document will expire in %d seconds. (2nd plural)", + "This document will expire in %d seconds. (3rd plural)" ], "This document will expire in %d minutes.": [ - "Bu belge %s dakikada silinecektir.", - "Bu belge %s dakikada silinecektir.", - "Bu belge %s dakikada silinecektir.", - "Bu belge %s dakikada silinecektir." + "This document will expire in %d minute. (singular)", + "This document will expire in %d minutes. (1st plural)", + "This document will expire in %d minutes. (2nd plural)", + "This document will expire in %d minutes. (3rd plural)" ], "This document will expire in %d hours.": [ - "Bu belge %s saatte silinecektir.", - "Bu belge %s saatte silinecektir.", - "Bu belge %s saatte silinecektir.", - "Bu belge %s saatte silinecektir.." + "This document will expire in %d hour. (singular)", + "This document will expire in %d hours. (1st plural)", + "This document will expire in %d hours. (2nd plural)", + "This document will expire in %d hours. (3rd plural)" ], "This document will expire in %d days.": [ - "Bu belge %s günde silinecektir.", - "Bu belge %s günde silinecektir.", - "Bu belge %s günde silinecektir.", - "Bu belge %s günde silinecektir.(3rd plural)" + "This document will expire in %d day. (singular)", + "This document will expire in %d days. (1st plural)", + "This document will expire in %d days. (2nd plural)", + "This document will expire in %d days. (3rd plural)" ], "This document will expire in %d months.": [ - "Bu belge %s ayda silinecektir.", - "Bu belge %s ayda silinecektir", - "Bu belge %s ayda silinecektir", - "Bu belge %s ayda silinecektir" + "This document will expire in %d month. (singular)", + "This document will expire in %d months. (1st plural)", + "This document will expire in %d months. (2nd plural)", + "This document will expire in %d months. (3rd plural)" ], - "Please enter the password for this paste:": "Lütfen bu yazı için şifrenizi girin:", - "Could not decrypt data (Wrong key?)": "Şifre çözülemedi (Yanlış anahtar mı kullandınız?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Yazı silinemedi, okunduktan sonra silinmek için ayarlanmadı.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "BU DOSYAYI SADECE SİZ GÖRÜNTÜLEYEBİLİRSİNİZ. Bu pencereyi kapatmayın, yazıyı tekrar görüntüleyemeyeceksiniz.", - "Could not decrypt comment; Wrong key?": "Dosya şifresi çözülemedi, doğru anahtarı girdiğinizden emin misiniz?", + "Please enter the password for this paste:": "Please enter the password for this paste:", + "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", + "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", "Reply": "Cevapla", "Anonymous": "Anonim", - "Avatar generated from IP address": "IP adresinden oluşturulmuş avatar", + "Avatar generated from IP address": "Avatar generated from IP address", "Add comment": "Yorum ekle", - "Optional nickname…": "İsteğe bağlı takma isim...", + "Optional nickname…": "Optional nickname…", "Post comment": "Yorumu gönder", - "Sending comment…": "Yorum gönderiliyor...", + "Sending comment…": "Sending comment…", "Comment posted.": "Yorum gönderildi.", - "Could not refresh display: %s": "Görüntü yenilenemedi: %s", - "unknown status": "bilinmeyen durum", - "server error or not responding": "sunucu hatası veya yanıt vermiyor", - "Could not post comment: %s": "Yorum paylaşılamadı: %s", - "Sending paste…": "Yazı gönderiliyor…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Yazınız: %s ([Ctrl]+[c] tuşlarına basarak kopyalayın.)", + "Could not refresh display: %s": "Could not refresh display: %s", + "unknown status": "unknown status", + "server error or not responding": "server error or not responding", + "Could not post comment: %s": "Could not post comment: %s", + "Sending paste…": "Sending paste…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", "Delete data": "Veriyi sil", - "Could not create paste: %s": "Yazı oluşturulamadı: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Yazı şifresi çözülemedi, çözme anahtarı URL'de bulunamadı. (Buraya bir yönlendirici veya URL kısaltıcı kullanarak gelmiş olabilirsiniz.)", + "Could not create paste: %s": "Could not create paste: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -140,51 +140,51 @@ "ZiB": "ZiB", "YiB": "YiB", "Format": "Format", - "Plain Text": "Düz Yazı", - "Source Code": "Kaynak Kodu", + "Plain Text": "Plain Text", + "Source Code": "Source Code", "Markdown": "Markdown", - "Download attachment": "Eki indir", - "Cloned: '%s'": "Klonlandı: '%s'", - "The cloned file '%s' was attached to this paste.": "Klonlanmış dosya '%s' bu yazıya eklendi.", - "Attach a file": "Dosya ekle", - "alternatively drag & drop a file or paste an image from the clipboard": "alternatif olarak dosyasyı yapıştırabilir veya sürükleyip bırakabilirsin.z", - "File too large, to display a preview. Please download the attachment.": "Dosya önizleme için çok büyük. Lütfen eki indirin.", - "Remove attachment": "Eki sil", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Tarayıcınız şifreli dosyaları desteklemiyor.", - "Invalid attachment.": "Geçersiz ek.", - "Options": "Seçenekler", - "Shorten URL": "URL kısaltma", - "Editor": "Düzenleyici", + "Download attachment": "Download attachment", + "Cloned: '%s'": "Cloned: '%s'", + "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", + "Attach a file": "Attach a file", + "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", + "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", + "Remove attachment": "Remove attachment", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", + "Invalid attachment.": "Invalid attachment.", + "Options": "Options", + "Shorten URL": "Shorten URL", + "Editor": "Editor", "Preview": "Ön izleme", "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", - "Decrypt": "Şifreyi çöz", + "Decrypt": "Decrypt", "Enter password": "Şifreyi girin", "Loading…": "Yükleniyor…", - "Decrypting paste…": "Yazı şifresi çözülüyor...", - "Preparing new paste…": "Yeni yazı hazırlanıyor...", + "Decrypting paste…": "Decrypting paste…", + "Preparing new paste…": "Preparing new paste…", "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", "+++ no paste text +++": "+++ no paste text +++", - "Could not get paste data: %s": "Yazı verisi alınamıyor: %s", + "Could not get paste data: %s": "Could not get paste data: %s", "QR code": "QR kodu", "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Dosya şifresi çözülemedi, doğru şifreyi kullandığınıza emin misiniz? Üstteki buton ile tekrar deneyin.", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", "Retry": "Yeniden Dene", - "Showing raw text…": "Açık yazı gösteriliyor...", + "Showing raw text…": "Showing raw text…", "Notice:": "Bildirim:", - "This link will expire after %s.": "Bu bağlantı şu kadar zaman sonra etkisiz kalacaktır: %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "Bu bağlantı sadece bir kere erişilebilir, lütfen sayfayı yenilemeyiniz.", + "This link will expire after %s.": "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", "Link:": "Bağlantı:", - "Recipient may become aware of your timezone, convert time to UTC?": "Alıcı zaman dilmini öğrenebilir, zaman dilimini UTC'ye çevirmek ister misin?", - "Use Current Timezone": "Şuanki zaman dilimini kullan", - "Convert To UTC": "UTC zaman dilimine çevir", + "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": "Use Current Timezone", + "Convert To UTC": "Convert To UTC", "Close": "Kapat", - "Encrypted note on PrivateBin": "PrivateBin üzerinde şifrelenmiş not", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Notu görmek için bu bağlantıyı ziyaret et. Bağlantıya sahip olan birisi notu görebilir.", - "URL shortener may expose your decrypt key in URL.": "URL kısaltıcı şifreleme anahtarınızı URL içerisinde gösterebilir.", - "Save paste": "Yazıyı kaydet", - "Your IP is not authorized to create pastes.": "IP adresinizin yazı oluşturmaya yetkisi yoktur." + "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", + "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } From 6e60efc2dd6ff320cae8f35e381857177084f00f Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 21 Aug 2022 17:21:33 +0200 Subject: [PATCH 033/506] New translations en.json (Dutch) --- i18n/nl.json | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/i18n/nl.json b/i18n/nl.json index 8294879f..b20416ae 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -26,7 +26,7 @@ "%s requires a modern browser to work.": "%s vereist een moderne browser om te kunnen werken ", "New": "Nieuw", "Send": "Verzenden", - "Clone": "Klonen", + "Clone": "Clonen", "Raw text": "Onbewerkte tekst", "Expires": "Verloopt", "Burn after reading": "Vernietig na lezen", @@ -35,7 +35,7 @@ "Discussion": "Discussie", "Toggle navigation": "Navigatie openen/sluiten", "%d seconds": [ - "%d seconde", + "%d second", "%d seconden", "%d seconds (2nd plural)", "%d seconds (3rd plural)" @@ -72,14 +72,14 @@ ], "%d years": [ "%d jaar", - "%d jaren", + "%d jaaren", "%d years (2nd plural)", "%d years (3rd plural)" ], "Never": "Nooit", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Opmerking: Dit is een testservice: Gegevens kunnen op elk gegeven moment verwijderd worden.", "This document will expire in %d seconds.": [ - "Dit document verloopt over %d seconde.", + "Dit document verloopt over %d second.", "Dit document verloopt over %d seconden.", "Dit document verloopt over %d seconden.", "Dit document verloopt over %d seconden." @@ -108,7 +108,7 @@ "Dit document verloopt over %d maanden.", "Dit document verloopt over %d maanden." ], - "Please enter the password for this paste:": "Voer het wachtwoord in voor deze geplakte tekst:", + "Please enter the password for this paste:": "Voer het wachtwoord in voor deze geplakte tekst:", "Could not decrypt data (Wrong key?)": "Kon de gegevens niet decoderen (verkeerde sleutel?)", "Could not delete the paste, it was not stored in burn after reading mode.": "Verwijderen van de geplakte tekst niet mogelijk, deze werd niet opgeslagen in 'vernietig na lezen' modus.", "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Sluit dit venster niet, dit bericht kan niet opnieuw worden weergegeven.", @@ -129,7 +129,7 @@ "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Uw geplakte tekst is %s (Druk [Ctrl]+[c] om te kopiëren)", "Delete data": "Gegevens wissen", "Could not create paste: %s": "Kon de geplakte tekst niet aanmaken: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Kon de geplakte tekst niet decoderen: Decoderingssleutel ontbreekt in URL (heeft u een redirector of een URL-verkorter gebruikt die een deel van de URL verwijdert?)", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Kon de geplakte tekst niet decoderen: Decoderingssleutel ontbreekt in URL (Hebt u een redirector of een URL-verkorter gebruikt die een deel van de URL verwijdert?)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -164,27 +164,27 @@ "Preparing new paste…": "Nieuwe geplakte tekst voorbereiden…", "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In het geval dat dit bericht nooit verdwijnt, kijkt u dan eens naar veelgestelde vragen voor informatie over het oplossen van problemen .", "+++ no paste text +++": "+++ geen geplakte tekst +++", - "Could not get paste data: %s": "Kon geen klembordgegevens verkrijgen: %s", - "QR code": "QR-code", - "This website is using an insecure HTTP connection! Please use it only for testing.": "Deze website gebruikt een onveilige HTTP-verbinding! Gelieve deze enkel te gebruiken om te testen.", - "For more information see this FAQ entry.": "Voor meer informatie zie dit FAQ-artikel.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Uw browser kan een HTTPS-verbinding nodig hebben om de WebCrypto API te ondersteunen. Probeer het met HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Uw browser ondersteunt WebAssembly niet, wat wordt gebruikt voor zlib compressie. U kunt niet-gecomprimeerde documenten maken, maar geen gecomprimeerde documenten lezen.", - "waiting on user to provide a password": "Wachtend op gebruiker om een wachtwoord te geven", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Kon de gegevens niet decoderen. Heeft u een verkeerd wachtwoord ingevoerd? Probeer het opnieuw met de knop bovenaan.", - "Retry": "Opnieuw proberen", - "Showing raw text…": "Platte tekst tonen…", - "Notice:": "Let op:", - "This link will expire after %s.": "Deze link vervalt na %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "Deze link kan slechts eenmaal worden geopend, gebruik niet de terug- of verversknop in uw browser.", + "Could not get paste data: %s": "Could not get paste data: %s", + "QR code": "QR code", + "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", + "For more information see this FAQ entry.": "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", + "waiting on user to provide a password": "waiting on user to provide a password", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Retry": "Retry", + "Showing raw text…": "Showing raw text…", + "Notice:": "Notice:", + "This link will expire after %s.": "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", "Link:": "Link:", - "Recipient may become aware of your timezone, convert time to UTC?": "Ontvanger kan zich bewust worden van uw tijdzone, tijd omzetten naar UTC?", - "Use Current Timezone": "Gebruik huidige tijdzone", - "Convert To UTC": "Omzetten naar UTC", - "Close": "Sluiten", - "Encrypted note on PrivateBin": "Versleutelde notitie op PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Bezoek deze link om de notitie te bekijken. Als je de URL aan iemand geeft, kan die de notitie ook bekijken.", - "URL shortener may expose your decrypt key in URL.": "URL-verkorter kan uw ontcijferingssleutel in URL blootleggen.", - "Save paste": "Notitie opslaan", - "Your IP is not authorized to create pastes.": "Uw IP-adres is niet gemachtigd om geplakte tekst te maken." + "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": "Use Current Timezone", + "Convert To UTC": "Convert To UTC", + "Close": "Close", + "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", + "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } From e740d0f761102209dc5bba92b5fe5f109bcd2c59 Mon Sep 17 00:00:00 2001 From: rugk Date: Mon, 22 Aug 2022 13:25:56 +0200 Subject: [PATCH 034/506] Remove COOP header for now Same as https://github.com/PrivateBin/docker-nginx-fpm-alpine/pull/108 Disable the header here as it breaks links to the own site. --- lib/Controller.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Controller.php b/lib/Controller.php index a6fd0a5b..62fa1e99 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -341,7 +341,10 @@ class Controller header('Content-Security-Policy: ' . $this->_conf->getKey('cspheader')); header('Cross-Origin-Resource-Policy: same-origin'); header('Cross-Origin-Embedder-Policy: require-corp'); - header('Cross-Origin-Opener-Policy: same-origin'); + // disabled, because it prevents links from a paste to the same site to + // be opened. Didn't work with `same-origin-allow-popups` either. + // See issue https://github.com/PrivateBin/PrivateBin/issues/970 for details. + // header('Cross-Origin-Opener-Policy: same-origin'); header('Permissions-Policy: browsing-topics=()'); header('Referrer-Policy: no-referrer'); header('X-Content-Type-Options: nosniff'); From d848ce2ed2ff99cce6fdd602b1c8eb7d38467945 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 30 Aug 2022 00:53:01 +0200 Subject: [PATCH 035/506] New translations en.json (Ukrainian) --- i18n/uk.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/uk.json b/i18n/uk.json index 7e3e6c46..2dbc6f40 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -171,10 +171,10 @@ "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Ваш переглядач вимагає підключення HTTPS для підтримки WebCrypto API. Спробуйте перемкнутися на HTTPS.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Ваш переглядач не підтримує WebAssembly, що використовується для стиснення zlib. Ви можете створювати нестиснені документи, але не зможете читати стиснені.", "waiting on user to provide a password": "очікування користувача для вводу паролю", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Не вдалося розшифрувати дані. Може ви ввели неправильний пароль? Спробуйте знов з допомогою кнопки що зверху.", - "Retry": "Повторити", - "Showing raw text…": "Відображається сирий текст…", - "Notice:": "Примітка:", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Не вдалося розшифрувати дані. Може, ви ввели неправильний пароль? Спробуйте знову за допомогою верхньої кнопки.", + "Retry": "Спробуйте ще раз", + "Showing raw text…": "Відображається неформатований текст…", + "Notice:": "Зверніть увагу:", "This link will expire after %s.": "Термін дії цього посилання сплине через %s.", "This link can only be accessed once, do not use back or refresh button in your browser.": "Дане посилання доступна тільки один раз, не натискайте кнопку назад та не обновляйте сторінку браузера.", "Link:": "Посилання:", From d065f4278516f74cd4c5780d015b71efa31d9c59 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 10 Sep 2022 14:08:53 +0200 Subject: [PATCH 036/506] New translations en.json (Czech) --- i18n/cs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/cs.json b/i18n/cs.json index 886e9c32..2b18566e 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -186,5 +186,5 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.", "URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.", "Save paste": "Uložit příspěvek", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať prilepenia." } From d57a849a401b4446ffb19094b901a851d72970e8 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 10 Sep 2022 21:32:32 +0200 Subject: [PATCH 037/506] New translations en.json (Dutch) --- i18n/nl.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/i18n/nl.json b/i18n/nl.json index b20416ae..da1f34ff 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -164,11 +164,11 @@ "Preparing new paste…": "Nieuwe geplakte tekst voorbereiden…", "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In het geval dat dit bericht nooit verdwijnt, kijkt u dan eens naar veelgestelde vragen voor informatie over het oplossen van problemen .", "+++ no paste text +++": "+++ geen geplakte tekst +++", - "Could not get paste data: %s": "Could not get paste data: %s", - "QR code": "QR code", - "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", - "For more information see this FAQ entry.": "For more information see this FAQ entry.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", + "Could not get paste data: %s": "Kon geen klembordgegevens verkrijgen: %s", + "QR code": "QR-code", + "This website is using an insecure HTTP connection! Please use it only for testing.": "Deze website gebruikt een onveilige HTTP-verbinding! Gelieve deze enkel te gebruiken om te testen.", + "For more information see this FAQ entry.": "Voor meer informatie zie dit FAQ-artikel.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Uw browser kan een HTTPS-verbinding nodig hebben om de WebCrypto API te ondersteunen. Probeer het met HTTPS.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", "waiting on user to provide a password": "waiting on user to provide a password", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", From fa1e4728dcd10d769428ad858ae27413630db0c1 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 10 Sep 2022 21:32:33 +0200 Subject: [PATCH 038/506] New translations en.json (Russian) --- i18n/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ru.json b/i18n/ru.json index 2d3edb9a..f1d237b2 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -186,5 +186,5 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Посетите эту ссылку чтобы просмотреть запись. Передача ссылки кому либо позволит им получить доступ к записи тоже.", "URL shortener may expose your decrypt key in URL.": "Сервис сокращения ссылок может получить ваш ключ расшифровки из ссылки.", "Save paste": "Сохранить запись", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Вашему IP адресу не разрешено создавать записи." } From 76fe7063caafbd18d0eb3c99a78e3addca6c689e Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 10 Sep 2022 22:29:14 +0200 Subject: [PATCH 039/506] New translations en.json (Dutch) --- i18n/nl.json | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/i18n/nl.json b/i18n/nl.json index da1f34ff..fc2ccc1f 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -169,22 +169,22 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "Deze website gebruikt een onveilige HTTP-verbinding! Gelieve deze enkel te gebruiken om te testen.", "For more information see this FAQ entry.": "Voor meer informatie zie dit FAQ-artikel.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Uw browser kan een HTTPS-verbinding nodig hebben om de WebCrypto API te ondersteunen. Probeer het met HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", - "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", - "Retry": "Retry", - "Showing raw text…": "Showing raw text…", - "Notice:": "Notice:", - "This link will expire after %s.": "This link will expire after %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Uw browser ondersteunt WebAssembly niet, wat wordt gebruikt voor zlib compressie. U kunt niet-gecomprimeerde documenten maken, maar geen gecomprimeerde documenten lezen.", + "waiting on user to provide a password": "wachtend op gebruiker om een wachtwoord te geven", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Kon de gegevens niet decoderen. Heeft u een verkeerd wachtwoord ingevoerd? Probeer het opnieuw met de knop bovenaan.", + "Retry": "Opnieuw proberen", + "Showing raw text…": "Platte tekst tonen…", + "Notice:": "Let op:", + "This link will expire after %s.": "Deze link vervalt na %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Deze link kan slechts eenmaal worden geopend, gebruik niet de terug- of verversknop in uw browser.", "Link:": "Link:", - "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", - "Use Current Timezone": "Use Current Timezone", - "Convert To UTC": "Convert To UTC", - "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", - "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Recipient may become aware of your timezone, convert time to UTC?": "Ontvanger kan zich bewust worden van uw tijdzone, tijd omzetten naar UTC?", + "Use Current Timezone": "Gebruik huidige tijdzone", + "Convert To UTC": "Omzetten naar UTC", + "Close": "Sluiten", + "Encrypted note on PrivateBin": "Versleutelde notitie op PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Bezoek deze link om de notitie te bekijken. Als je de URL aan iemand geeft, kan die de notitie ook bekijken.", + "URL shortener may expose your decrypt key in URL.": "URL-verkorter kan uw ontcijferingssleutel in URL blootleggen.", + "Save paste": "Notitie opslaan", + "Your IP is not authorized to create pastes.": "Uw IP-adres is niet gemachtigd om geplakte tekst te maken." } From e56b24fc3b4642c26426afe298d535b4446f821a Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 10 Sep 2022 22:29:16 +0200 Subject: [PATCH 040/506] New translations en.json (Turkish) --- i18n/tr.json | 224 +++++++++++++++++++++++++-------------------------- 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/i18n/tr.json b/i18n/tr.json index c2c380e1..c8eb670a 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -1,135 +1,135 @@ { "PrivateBin": "PrivateBin", - "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s sunucunun burada paylaştığınız veriyi görmediği, minimal, açık kaynak bir pastebindir. Veriler tarayıcıda 256 bit AES kullanılarak şifrelenir/çözülür.", "More information on the project page.": "Daha fazla bilgi için proje sayfası'na göz atabilirsiniz.", "Because ignorance is bliss": "Çünkü, cehalet mutluluktur", "en": "tr", "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.", - "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.", - "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", + "%s requires php %s or above to work. Sorry.": "%s PHP %s veya daha üstünü gerektirir.", + "%s requires configuration section [%s] to be present in configuration file.": "%s konfigürasyon bölümünün [%s] bulunmasını gerektir.", "Please wait %d seconds between each post.": [ - "Please wait %d second between each post. (singular)", - "Please wait %d seconds between each post. (1st plural)", - "Please wait %d seconds between each post. (2nd plural)", - "Please wait %d seconds between each post. (3rd plural)" + "Lütfen paylaşımlar arasında %d saniye bekleyiniz.", + "Lütfen paylaşımlar arasında %d saniye bekleyiniz.", + "Lütfen paylaşımlar arasında %d saniye bekleyiniz.", + "Lütfen paylaşımlar arasında %d saniye bekleyiniz." ], - "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", + "Paste is limited to %s of encrypted data.": "Yazılar %s şifreli veriyle sınırlıdır.", "Invalid data.": "Geçersiz veri.", "You are unlucky. Try again.": "Lütfen tekrar deneyiniz.", - "Error saving comment. Sorry.": "Error saving comment. Sorry.", - "Error saving paste. Sorry.": "Error saving paste. Sorry.", - "Invalid paste ID.": "Invalid paste ID.", - "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", - "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", - "Paste was properly deleted.": "Paste was properly deleted.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", - "%s requires a modern browser to work.": "%s requires a modern browser to work.", + "Error saving comment. Sorry.": "Yorum kaydedilemedi.", + "Error saving paste. Sorry.": "Yazı kaydedilemedi. Üzgünüz.", + "Invalid paste ID.": "Geçersiz yazı ID'si.", + "Paste is not of burn-after-reading type.": "Yazı okunduğunda silinmeyecek şekilde ayarlanmış.", + "Wrong deletion token. Paste was not deleted.": "Yanlış silme anahtarı. Yazı silinemedi.", + "Paste was properly deleted.": "Yazı başarıyla silindi.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript %s 'in çalışması için gereklidir. Rahatsızlıktan dolayı özür dileriz.", + "%s requires a modern browser to work.": "%s çalışmak için çağdaş bir tarayıcı gerektirir.", "New": "Yeni", "Send": "Gönder", "Clone": "Kopyala", - "Raw text": "Raw text", + "Raw text": "Açık yazı", "Expires": "Süre Sonu", - "Burn after reading": "Burn after reading", + "Burn after reading": "Okuduktan sonra sil", "Open discussion": "Açık Tartışmalar", - "Password (recommended)": "Password (recommended)", + "Password (recommended)": "Şifre (önerilir)", "Discussion": "Tartışma", "Toggle navigation": "Gezinmeyi değiştir", "%d seconds": [ - "%d second (singular)", - "%d seconds (1st plural)", - "%d seconds (2nd plural)", - "%d seconds (3rd plural)" + "%d saniye", + "%d saniye", + "%d saniye", + "%d saniye" ], "%d minutes": [ - "%d minute (singular)", - "%d minutes (1st plural)", - "%d minutes (2nd plural)", - "%d minutes (3rd plural)" + "%d dakika", + "%d dakika", + "%d dakika", + "%d dakika" ], "%d hours": [ - "%d hour (singular)", - "%d hours (1st plural)", - "%d hours (2nd plural)", - "%d hours (3rd plural)" + "%d saat", + "%d saat", + "%d saat", + "%d saat" ], "%d days": [ - "%d day (singular)", - "%d days (1st plural)", - "%d days (2nd plural)", - "%d days (3rd plural)" + "%d gün", + "%d gün", + "%d gün", + "%d gün" ], "%d weeks": [ "%d hafta (tekil)", "%d haftalar (çoğul)", - "%d weeks (2nd plural)", - "%d weeks (3rd plural)" + "%d hafta", + "%d hafta" ], "%d months": [ - "%d month (singular)", - "%d months (1st plural)", - "%d months (2nd plural)", - "%d months (3rd plural)" + "%d ay", + "%d ay", + "%d ay", + "%d ay" ], "%d years": [ - "%d year (singular)", - "%d years (1st plural)", - "%d years (2nd plural)", - "%d years (3rd plural)" + "%d yıl", + "%d yıl", + "%d yıl", + "%d yıl" ], - "Never": "Never", + "Never": "Asla", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", "This document will expire in %d seconds.": [ - "This document will expire in %d second. (singular)", - "This document will expire in %d seconds. (1st plural)", - "This document will expire in %d seconds. (2nd plural)", - "This document will expire in %d seconds. (3rd plural)" + "Bu belge %s saniyede silinecektir.", + "Bu belge %s saniyede silinecektir.", + "Bu belge %s saniyede silinecektir.", + "Bu belge %s saniyede silinecektir." ], "This document will expire in %d minutes.": [ - "This document will expire in %d minute. (singular)", - "This document will expire in %d minutes. (1st plural)", - "This document will expire in %d minutes. (2nd plural)", - "This document will expire in %d minutes. (3rd plural)" + "Bu belge %s dakikada silinecektir.", + "Bu belge %s dakikada silinecektir.", + "Bu belge %s dakikada silinecektir.", + "Bu belge %s dakikada silinecektir." ], "This document will expire in %d hours.": [ - "This document will expire in %d hour. (singular)", - "This document will expire in %d hours. (1st plural)", - "This document will expire in %d hours. (2nd plural)", - "This document will expire in %d hours. (3rd plural)" + "Bu belge %s saatte silinecektir.", + "Bu belge %s saatte silinecektir.", + "Bu belge %s saatte silinecektir.", + "Bu belge %s saatte silinecektir.." ], "This document will expire in %d days.": [ - "This document will expire in %d day. (singular)", - "This document will expire in %d days. (1st plural)", - "This document will expire in %d days. (2nd plural)", - "This document will expire in %d days. (3rd plural)" + "Bu belge %s günde silinecektir.", + "Bu belge %s günde silinecektir.", + "Bu belge %s günde silinecektir.", + "Bu belge %s günde silinecektir.(3rd plural)" ], "This document will expire in %d months.": [ - "This document will expire in %d month. (singular)", - "This document will expire in %d months. (1st plural)", - "This document will expire in %d months. (2nd plural)", - "This document will expire in %d months. (3rd plural)" + "Bu belge %s ayda silinecektir.", + "Bu belge %s ayda silinecektir", + "Bu belge %s ayda silinecektir", + "Bu belge %s ayda silinecektir" ], - "Please enter the password for this paste:": "Please enter the password for this paste:", - "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", - "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", + "Please enter the password for this paste:": "Lütfen bu yazı için şifrenizi girin:", + "Could not decrypt data (Wrong key?)": "Şifre çözülemedi (Yanlış anahtar mı kullandınız?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Yazı silinemedi, okunduktan sonra silinmek için ayarlanmadı.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "BU DOSYAYI SADECE SİZ GÖRÜNTÜLEYEBİLİRSİNİZ. Bu pencereyi kapatmayın, yazıyı tekrar görüntüleyemeyeceksiniz.", + "Could not decrypt comment; Wrong key?": "Dosya şifresi çözülemedi, doğru anahtarı girdiğinizden emin misiniz?", "Reply": "Cevapla", "Anonymous": "Anonim", - "Avatar generated from IP address": "Avatar generated from IP address", + "Avatar generated from IP address": "IP adresinden oluşturulmuş avatar", "Add comment": "Yorum ekle", - "Optional nickname…": "Optional nickname…", + "Optional nickname…": "İsteğe bağlı takma isim...", "Post comment": "Yorumu gönder", - "Sending comment…": "Sending comment…", + "Sending comment…": "Yorum gönderiliyor...", "Comment posted.": "Yorum gönderildi.", - "Could not refresh display: %s": "Could not refresh display: %s", - "unknown status": "unknown status", - "server error or not responding": "server error or not responding", - "Could not post comment: %s": "Could not post comment: %s", - "Sending paste…": "Sending paste…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", + "Could not refresh display: %s": "Görüntü yenilenemedi: %s", + "unknown status": "bilinmeyen durum", + "server error or not responding": "sunucu hatası veya yanıt vermiyor", + "Could not post comment: %s": "Yorum paylaşılamadı: %s", + "Sending paste…": "Yazı gönderiliyor…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Yazınız: %s ([Ctrl]+[c] tuşlarına basarak kopyalayın.)", "Delete data": "Veriyi sil", - "Could not create paste: %s": "Could not create paste: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "Could not create paste: %s": "Yazı oluşturulamadı: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Yazı şifresi çözülemedi, çözme anahtarı URL'de bulunamadı. (Buraya bir yönlendirici veya URL kısaltıcı kullanarak gelmiş olabilirsiniz.)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -140,51 +140,51 @@ "ZiB": "ZiB", "YiB": "YiB", "Format": "Format", - "Plain Text": "Plain Text", - "Source Code": "Source Code", + "Plain Text": "Düz Yazı", + "Source Code": "Kaynak Kodu", "Markdown": "Markdown", - "Download attachment": "Download attachment", - "Cloned: '%s'": "Cloned: '%s'", - "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", - "Attach a file": "Attach a file", - "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", - "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", - "Remove attachment": "Remove attachment", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", - "Invalid attachment.": "Invalid attachment.", - "Options": "Options", - "Shorten URL": "Shorten URL", - "Editor": "Editor", + "Download attachment": "Eki indir", + "Cloned: '%s'": "Klonlandı: '%s'", + "The cloned file '%s' was attached to this paste.": "Klonlanmış dosya '%s' bu yazıya eklendi.", + "Attach a file": "Dosya ekle", + "alternatively drag & drop a file or paste an image from the clipboard": "alternatif olarak dosyasyı yapıştırabilir veya sürükleyip bırakabilirsin.z", + "File too large, to display a preview. Please download the attachment.": "Dosya önizleme için çok büyük. Lütfen eki indirin.", + "Remove attachment": "Eki sil", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Tarayıcınız şifreli dosyaları desteklemiyor.", + "Invalid attachment.": "Geçersiz ek.", + "Options": "Seçenekler", + "Shorten URL": "URL kısaltma", + "Editor": "Düzenleyici", "Preview": "Ön izleme", "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", - "Decrypt": "Decrypt", + "Decrypt": "Şifreyi çöz", "Enter password": "Şifreyi girin", "Loading…": "Yükleniyor…", - "Decrypting paste…": "Decrypting paste…", - "Preparing new paste…": "Preparing new paste…", + "Decrypting paste…": "Yazı şifresi çözülüyor...", + "Preparing new paste…": "Yeni yazı hazırlanıyor...", "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", "+++ no paste text +++": "+++ no paste text +++", - "Could not get paste data: %s": "Could not get paste data: %s", + "Could not get paste data: %s": "Yazı verisi alınamıyor: %s", "QR code": "QR kodu", "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Dosya şifresi çözülemedi, doğru şifreyi kullandığınıza emin misiniz? Üstteki buton ile tekrar deneyin.", "Retry": "Yeniden Dene", - "Showing raw text…": "Showing raw text…", + "Showing raw text…": "Açık yazı gösteriliyor...", "Notice:": "Bildirim:", - "This link will expire after %s.": "This link will expire after %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", + "This link will expire after %s.": "Bu bağlantı şu kadar zaman sonra etkisiz kalacaktır: %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Bu bağlantı sadece bir kere erişilebilir, lütfen sayfayı yenilemeyiniz.", "Link:": "Bağlantı:", - "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", - "Use Current Timezone": "Use Current Timezone", - "Convert To UTC": "Convert To UTC", + "Recipient may become aware of your timezone, convert time to UTC?": "Alıcı zaman dilmini öğrenebilir, zaman dilimini UTC'ye çevirmek ister misin?", + "Use Current Timezone": "Şuanki zaman dilimini kullan", + "Convert To UTC": "UTC zaman dilimine çevir", "Close": "Kapat", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", - "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Encrypted note on PrivateBin": "PrivateBin üzerinde şifrelenmiş not", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Notu görmek için bu bağlantıyı ziyaret et. Bağlantıya sahip olan birisi notu görebilir.", + "URL shortener may expose your decrypt key in URL.": "URL kısaltıcı şifreleme anahtarınızı URL içerisinde gösterebilir.", + "Save paste": "Yazıyı kaydet", + "Your IP is not authorized to create pastes.": "IP adresinizin yazı oluşturmaya yetkisi yoktur." } From e11c89ab8556add4cac57f82ef224e427a267c5d Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Fri, 16 Sep 2022 23:59:49 +0200 Subject: [PATCH 041/506] New translations en.json (Czech) --- i18n/cs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/cs.json b/i18n/cs.json index 2b18566e..82cb1732 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -186,5 +186,5 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.", "URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.", "Save paste": "Uložit příspěvek", - "Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať prilepenia." + "Your IP is not authorized to create pastes.": "Vaše IP adresa nemá oprávnění k vytvoření vložení." } From 123210bb8f9a84d1ccb140f1ad442643e6bc53f2 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 18 Sep 2022 13:16:30 +0200 Subject: [PATCH 042/506] New translations en.json (Dutch) --- i18n/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/nl.json b/i18n/nl.json index fc2ccc1f..ab1381ee 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -129,7 +129,7 @@ "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Uw geplakte tekst is %s (Druk [Ctrl]+[c] om te kopiëren)", "Delete data": "Gegevens wissen", "Could not create paste: %s": "Kon de geplakte tekst niet aanmaken: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Kon de geplakte tekst niet decoderen: Decoderingssleutel ontbreekt in URL (Hebt u een redirector of een URL-verkorter gebruikt die een deel van de URL verwijdert?)", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Kon de geplakte tekst niet decoderen: Decoderingssleutel ontbreekt in URL (Hebt u een redirector of een URL-verkorter gebruikt die een deel van de URL verwijdert?)", "B": "B", "KiB": "KiB", "MiB": "MiB", From e35710ca30a556da864933b8673376fcc54eaffb Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 18 Sep 2022 13:16:31 +0200 Subject: [PATCH 043/506] New translations en.json (Turkish) --- i18n/tr.json | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/i18n/tr.json b/i18n/tr.json index c8eb670a..47d249cd 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -59,8 +59,8 @@ "%d gün" ], "%d weeks": [ - "%d hafta (tekil)", - "%d haftalar (çoğul)", + "%d hafta", + "%d haftalar", "%d hafta", "%d hafta" ], @@ -79,34 +79,34 @@ "Never": "Asla", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", "This document will expire in %d seconds.": [ - "Bu belge %s saniyede silinecektir.", - "Bu belge %s saniyede silinecektir.", - "Bu belge %s saniyede silinecektir.", - "Bu belge %s saniyede silinecektir." + "Bu belge %d saniyede silinecektir.", + "Bu belge %d saniyede silinecektir.", + "Bu belge %d saniyede silinecektir.", + "Bu belge %d saniyede silinecektir." ], "This document will expire in %d minutes.": [ - "Bu belge %s dakikada silinecektir.", - "Bu belge %s dakikada silinecektir.", - "Bu belge %s dakikada silinecektir.", - "Bu belge %s dakikada silinecektir." + "Bu belge %d dakikada silinecektir.", + "Bu belge %d dakikada silinecektir.", + "Bu belge %d dakikada silinecektir.", + "Bu belge %d dakikada silinecektir." ], "This document will expire in %d hours.": [ - "Bu belge %s saatte silinecektir.", - "Bu belge %s saatte silinecektir.", - "Bu belge %s saatte silinecektir.", - "Bu belge %s saatte silinecektir.." + "Bu belge %d saatte silinecektir.", + "Bu belge %d saatte silinecektir.", + "Bu belge %d saatte silinecektir.", + "Bu belge %d saatte silinecektir." ], "This document will expire in %d days.": [ - "Bu belge %s günde silinecektir.", - "Bu belge %s günde silinecektir.", - "Bu belge %s günde silinecektir.", - "Bu belge %s günde silinecektir.(3rd plural)" + "Bu belge %d günde silinecektir.", + "Bu belge %d günde silinecektir.", + "Bu belge %d günde silinecektir.", + "Bu belge %d günde silinecektir." ], "This document will expire in %d months.": [ - "Bu belge %s ayda silinecektir.", - "Bu belge %s ayda silinecektir", - "Bu belge %s ayda silinecektir", - "Bu belge %s ayda silinecektir" + "Bu belge %d ayda silinecektir.", + "Bu belge %d ayda silinecektir.", + "Bu belge %d ayda silinecektir.", + "Bu belge %d ayda silinecektir." ], "Please enter the password for this paste:": "Lütfen bu yazı için şifrenizi girin:", "Could not decrypt data (Wrong key?)": "Şifre çözülemedi (Yanlış anahtar mı kullandınız?)", @@ -117,9 +117,9 @@ "Anonymous": "Anonim", "Avatar generated from IP address": "IP adresinden oluşturulmuş avatar", "Add comment": "Yorum ekle", - "Optional nickname…": "İsteğe bağlı takma isim...", + "Optional nickname…": "İsteğe bağlı takma isim…", "Post comment": "Yorumu gönder", - "Sending comment…": "Yorum gönderiliyor...", + "Sending comment…": "Yorum gönderiliyor…", "Comment posted.": "Yorum gönderildi.", "Could not refresh display: %s": "Görüntü yenilenemedi: %s", "unknown status": "bilinmeyen durum", @@ -147,7 +147,7 @@ "Cloned: '%s'": "Klonlandı: '%s'", "The cloned file '%s' was attached to this paste.": "Klonlanmış dosya '%s' bu yazıya eklendi.", "Attach a file": "Dosya ekle", - "alternatively drag & drop a file or paste an image from the clipboard": "alternatif olarak dosyasyı yapıştırabilir veya sürükleyip bırakabilirsin.z", + "alternatively drag & drop a file or paste an image from the clipboard": "alternatif olarak dosyasyı yapıştırabilir veya sürükleyip bırakabilirsin", "File too large, to display a preview. Please download the attachment.": "Dosya önizleme için çok büyük. Lütfen eki indirin.", "Remove attachment": "Eki sil", "Your browser does not support uploading encrypted files. Please use a newer browser.": "Tarayıcınız şifreli dosyaları desteklemiyor.", @@ -160,8 +160,8 @@ "Decrypt": "Şifreyi çöz", "Enter password": "Şifreyi girin", "Loading…": "Yükleniyor…", - "Decrypting paste…": "Yazı şifresi çözülüyor...", - "Preparing new paste…": "Yeni yazı hazırlanıyor...", + "Decrypting paste…": "Yazı şifresi çözülüyor…", + "Preparing new paste…": "Yeni yazı hazırlanıyor…", "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", "+++ no paste text +++": "+++ no paste text +++", "Could not get paste data: %s": "Yazı verisi alınamıyor: %s", @@ -173,7 +173,7 @@ "waiting on user to provide a password": "waiting on user to provide a password", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Dosya şifresi çözülemedi, doğru şifreyi kullandığınıza emin misiniz? Üstteki buton ile tekrar deneyin.", "Retry": "Yeniden Dene", - "Showing raw text…": "Açık yazı gösteriliyor...", + "Showing raw text…": "Açık yazı gösteriliyor…", "Notice:": "Bildirim:", "This link will expire after %s.": "Bu bağlantı şu kadar zaman sonra etkisiz kalacaktır: %s.", "This link can only be accessed once, do not use back or refresh button in your browser.": "Bu bağlantı sadece bir kere erişilebilir, lütfen sayfayı yenilemeyiniz.", From d1b53360d5e2c7f255b25030a15696ce1f91c121 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 18 Sep 2022 13:16:32 +0200 Subject: [PATCH 044/506] New translations en.json (Slovak) --- i18n/sk.json | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 i18n/sk.json diff --git a/i18n/sk.json b/i18n/sk.json new file mode 100644 index 00000000..3663d3e4 --- /dev/null +++ b/i18n/sk.json @@ -0,0 +1,190 @@ +{ + "PrivateBin": "PrivateBin", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s je minimalistický, open source online pastebin, kde server nemá žiadne znalosti o vložených údajoch. Údaje sú šifrované/dešifrované %sv prehliadači%s pomocou 256-bitového AES.", + "More information on the project page.": "Viac informácií na stránke projektu.", + "Because ignorance is bliss": "Pretože nevedomosť je sladká", + "en": "sk", + "Paste does not exist, has expired or has been deleted.": "Vložený text neexistuje, jeho platnosť vypršala alebo bol vymazaný.", + "%s requires php %s or above to work. Sorry.": "%s vyžaduje php %s alebo vyššie. Prepáčte.", + "%s requires configuration section [%s] to be present in configuration file.": "%s vyžaduje, aby bola v konfiguračnom súbore prítomná sekcia [%s].", + "Please wait %d seconds between each post.": [ + "Počet sekúnd do ďalšieho príspevku: %d", + "Počet sekúnd do ďalšieho príspevku: %d", + "Počet sekúnd do ďalšieho príspevku: %d", + "Počet sekúnd do ďalšieho príspevku: %d" + ], + "Paste is limited to %s of encrypted data.": "Príspevok je obmedzený na %s zašifrovaných údajov.", + "Invalid data.": "Neplatné údaje.", + "You are unlucky. Try again.": "You are unlucky. Try again.", + "Error saving comment. Sorry.": "Error saving comment. Sorry.", + "Error saving paste. Sorry.": "Error saving paste. Sorry.", + "Invalid paste ID.": "Invalid paste ID.", + "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", + "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", + "Paste was properly deleted.": "Paste was properly deleted.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", + "%s requires a modern browser to work.": "%s requires a modern browser to work.", + "New": "Nový", + "Send": "Odoslať", + "Clone": "Klonovať", + "Raw text": "Surový text", + "Expires": "Expirácia", + "Burn after reading": "Po prečítaní zmazať", + "Open discussion": "Povoliť komentáre", + "Password (recommended)": "Heslo (doporučené)", + "Discussion": "Komentáre", + "Toggle navigation": "Toggle navigation", + "%d seconds": [ + "%d second (singular)", + "%d seconds (1st plural)", + "%d seconds (2nd plural)", + "%d seconds (3rd plural)" + ], + "%d minutes": [ + "%d minute (singular)", + "%d minutes (1st plural)", + "%d minutes (2nd plural)", + "%d minutes (3rd plural)" + ], + "%d hours": [ + "%d hour (singular)", + "%d hours (1st plural)", + "%d hours (2nd plural)", + "%d hours (3rd plural)" + ], + "%d days": [ + "%d day (singular)", + "%d days (1st plural)", + "%d days (2nd plural)", + "%d days (3rd plural)" + ], + "%d weeks": [ + "%d week (singular)", + "%d weeks (1st plural)", + "%d weeks (2nd plural)", + "%d weeks (3rd plural)" + ], + "%d months": [ + "%d month (singular)", + "%d months (1st plural)", + "%d months (2nd plural)", + "%d months (3rd plural)" + ], + "%d years": [ + "%d year (singular)", + "%d years (1st plural)", + "%d years (2nd plural)", + "%d years (3rd plural)" + ], + "Never": "Never", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "This document will expire in %d seconds.": [ + "This document will expire in %d second. (singular)", + "This document will expire in %d seconds. (1st plural)", + "This document will expire in %d seconds. (2nd plural)", + "This document will expire in %d seconds. (3rd plural)" + ], + "This document will expire in %d minutes.": [ + "This document will expire in %d minute. (singular)", + "This document will expire in %d minutes. (1st plural)", + "This document will expire in %d minutes. (2nd plural)", + "This document will expire in %d minutes. (3rd plural)" + ], + "This document will expire in %d hours.": [ + "This document will expire in %d hour. (singular)", + "This document will expire in %d hours. (1st plural)", + "This document will expire in %d hours. (2nd plural)", + "This document will expire in %d hours. (3rd plural)" + ], + "This document will expire in %d days.": [ + "This document will expire in %d day. (singular)", + "This document will expire in %d days. (1st plural)", + "This document will expire in %d days. (2nd plural)", + "This document will expire in %d days. (3rd plural)" + ], + "This document will expire in %d months.": [ + "This document will expire in %d month. (singular)", + "This document will expire in %d months. (1st plural)", + "This document will expire in %d months. (2nd plural)", + "This document will expire in %d months. (3rd plural)" + ], + "Please enter the password for this paste:": "Please enter the password for this paste:", + "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", + "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", + "Reply": "Reply", + "Anonymous": "Anonymous", + "Avatar generated from IP address": "Avatar generated from IP address", + "Add comment": "Add comment", + "Optional nickname…": "Optional nickname…", + "Post comment": "Post comment", + "Sending comment…": "Sending comment…", + "Comment posted.": "Comment posted.", + "Could not refresh display: %s": "Could not refresh display: %s", + "unknown status": "unknown status", + "server error or not responding": "server error or not responding", + "Could not post comment: %s": "Could not post comment: %s", + "Sending paste…": "Sending paste…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", + "Delete data": "Delete data", + "Could not create paste: %s": "Could not create paste: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "B": "B", + "KiB": "KiB", + "MiB": "MiB", + "GiB": "GiB", + "TiB": "TiB", + "PiB": "PiB", + "EiB": "EiB", + "ZiB": "ZiB", + "YiB": "YiB", + "Format": "Format", + "Plain Text": "Plain Text", + "Source Code": "Source Code", + "Markdown": "Markdown", + "Download attachment": "Download attachment", + "Cloned: '%s'": "Cloned: '%s'", + "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", + "Attach a file": "Attach a file", + "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", + "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", + "Remove attachment": "Remove attachment", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", + "Invalid attachment.": "Invalid attachment.", + "Options": "Options", + "Shorten URL": "Shorten URL", + "Editor": "Editor", + "Preview": "Preview", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", + "Decrypt": "Decrypt", + "Enter password": "Enter password", + "Loading…": "Loading…", + "Decrypting paste…": "Decrypting paste…", + "Preparing new paste…": "Preparing new paste…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", + "+++ no paste text +++": "+++ no paste text +++", + "Could not get paste data: %s": "Could not get paste data: %s", + "QR code": "QR code", + "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", + "For more information see this FAQ entry.": "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", + "waiting on user to provide a password": "waiting on user to provide a password", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Retry": "Retry", + "Showing raw text…": "Showing raw text…", + "Notice:": "Notice:", + "This link will expire after %s.": "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": "Use Current Timezone", + "Convert To UTC": "Convert To UTC", + "Close": "Close", + "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", + "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." +} From 49b83125058a1ca750ab8e943804ddd956510af3 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 18 Sep 2022 14:19:00 +0200 Subject: [PATCH 045/506] New translations en.json (Dutch) --- i18n/nl.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/nl.json b/i18n/nl.json index ab1381ee..6157bfa3 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -35,7 +35,7 @@ "Discussion": "Discussie", "Toggle navigation": "Navigatie openen/sluiten", "%d seconds": [ - "%d second", + "%d seconde", "%d seconden", "%d seconds (2nd plural)", "%d seconds (3rd plural)" @@ -72,14 +72,14 @@ ], "%d years": [ "%d jaar", - "%d jaaren", + "%d jaren", "%d years (2nd plural)", "%d years (3rd plural)" ], "Never": "Nooit", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Opmerking: Dit is een testservice: Gegevens kunnen op elk gegeven moment verwijderd worden.", "This document will expire in %d seconds.": [ - "Dit document verloopt over %d second.", + "Dit document verloopt over %d seconde.", "Dit document verloopt over %d seconden.", "Dit document verloopt over %d seconden.", "Dit document verloopt over %d seconden." @@ -108,7 +108,7 @@ "Dit document verloopt over %d maanden.", "Dit document verloopt over %d maanden." ], - "Please enter the password for this paste:": "Voer het wachtwoord in voor deze geplakte tekst:", + "Please enter the password for this paste:": "Voer het wachtwoord in voor deze geplakte tekst:", "Could not decrypt data (Wrong key?)": "Kon de gegevens niet decoderen (verkeerde sleutel?)", "Could not delete the paste, it was not stored in burn after reading mode.": "Verwijderen van de geplakte tekst niet mogelijk, deze werd niet opgeslagen in 'vernietig na lezen' modus.", "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Sluit dit venster niet, dit bericht kan niet opnieuw worden weergegeven.", From 7580155243a8a5fe0e226a1e6b6c6af859ea51a3 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 18 Sep 2022 14:19:01 +0200 Subject: [PATCH 046/506] New translations en.json (Slovak) --- i18n/sk.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/i18n/sk.json b/i18n/sk.json index 3663d3e4..0b5f8027 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -15,13 +15,13 @@ ], "Paste is limited to %s of encrypted data.": "Príspevok je obmedzený na %s zašifrovaných údajov.", "Invalid data.": "Neplatné údaje.", - "You are unlucky. Try again.": "You are unlucky. Try again.", - "Error saving comment. Sorry.": "Error saving comment. Sorry.", - "Error saving paste. Sorry.": "Error saving paste. Sorry.", - "Invalid paste ID.": "Invalid paste ID.", - "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", - "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", - "Paste was properly deleted.": "Paste was properly deleted.", + "You are unlucky. Try again.": "Ľutujem. Skúste to znova.", + "Error saving comment. Sorry.": "Pri ukladaní komentára sa vyskytla chyba.", + "Error saving paste. Sorry.": "Pri ukladaní príspevku sa vyskytla chyba.", + "Invalid paste ID.": "Chybne vložené ID.", + "Paste is not of burn-after-reading type.": "Príspevok nieje nastavený na zmazanie po prečítaní.", + "Wrong deletion token. Paste was not deleted.": "Nesprávny token odstránenia. Príspevok nebol odstránený.", + "Paste was properly deleted.": "Príspevok bol správne vymazaný.", "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", "%s requires a modern browser to work.": "%s requires a modern browser to work.", "New": "Nový", From 4025619236f626e1c9ee78f59cf33c3c36644eb1 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 20 Sep 2022 20:11:36 +0200 Subject: [PATCH 047/506] New translations en.json (Slovak) --- i18n/sk.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/i18n/sk.json b/i18n/sk.json index 0b5f8027..ba804583 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -35,38 +35,38 @@ "Discussion": "Komentáre", "Toggle navigation": "Toggle navigation", "%d seconds": [ - "%d second (singular)", - "%d seconds (1st plural)", - "%d seconds (2nd plural)", - "%d seconds (3rd plural)" + "%d sekunda", + "%d sekundy", + "%d sekúnd", + "%d sekúnd" ], "%d minutes": [ - "%d minute (singular)", - "%d minutes (1st plural)", - "%d minutes (2nd plural)", - "%d minutes (3rd plural)" + "%d minúta", + "%d minúty", + "%d minút", + "%d minút" ], "%d hours": [ - "%d hour (singular)", - "%d hours (1st plural)", - "%d hours (2nd plural)", - "%d hours (3rd plural)" + "%d hodina", + "%d hodiny", + "%d hodín", + "%d hodín" ], "%d days": [ - "%d day (singular)", - "%d days (1st plural)", - "%d days (2nd plural)", - "%d days (3rd plural)" + "%d deň", + "%d dni", + "%d dní", + "%d dní" ], "%d weeks": [ - "%d week (singular)", - "%d weeks (1st plural)", - "%d weeks (2nd plural)", - "%d weeks (3rd plural)" + "%d týždeň", + "%d týždne", + "%d týždňov", + "%d týždňov" ], "%d months": [ - "%d month (singular)", - "%d months (1st plural)", + "%d mesiac", + "%d mesiace", "%d months (2nd plural)", "%d months (3rd plural)" ], From 3255a4d95410fdd8c637c2eff9719e548264e543 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 20 Sep 2022 21:21:45 +0200 Subject: [PATCH 048/506] New translations en.json (Slovak) --- i18n/sk.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/i18n/sk.json b/i18n/sk.json index ba804583..d5e9756f 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -67,16 +67,16 @@ "%d months": [ "%d mesiac", "%d mesiace", - "%d months (2nd plural)", - "%d months (3rd plural)" + "%d mesiacov", + "%d mesiacov" ], "%d years": [ - "%d year (singular)", - "%d years (1st plural)", - "%d years (2nd plural)", - "%d years (3rd plural)" + "%d rok", + "%d roky", + "%d rokov", + "%d rokov" ], - "Never": "Never", + "Never": "Nikdy", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", "This document will expire in %d seconds.": [ "This document will expire in %d second. (singular)", From 1b727f7fa4f0fa83a1a732984d955f09d7d5b6ca Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 25 Sep 2022 16:12:48 +0200 Subject: [PATCH 049/506] New translations en.json (Slovak) --- i18n/sk.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/sk.json b/i18n/sk.json index d5e9756f..2c0d6930 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -22,8 +22,8 @@ "Paste is not of burn-after-reading type.": "Príspevok nieje nastavený na zmazanie po prečítaní.", "Wrong deletion token. Paste was not deleted.": "Nesprávny token odstránenia. Príspevok nebol odstránený.", "Paste was properly deleted.": "Príspevok bol správne vymazaný.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", - "%s requires a modern browser to work.": "%s requires a modern browser to work.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "Na fungovanie %s je potrebný JavaScript. Ospravedlňujeme sa za nepríjemnosti.", + "%s requires a modern browser to work.": "%s vyžaduje na fungovanie moderný prehliadač.", "New": "Nový", "Send": "Odoslať", "Clone": "Klonovať", @@ -33,7 +33,7 @@ "Open discussion": "Povoliť komentáre", "Password (recommended)": "Heslo (doporučené)", "Discussion": "Komentáre", - "Toggle navigation": "Toggle navigation", + "Toggle navigation": "Prepnúť navigáciu", "%d seconds": [ "%d sekunda", "%d sekundy", @@ -77,7 +77,7 @@ "%d rokov" ], "Never": "Nikdy", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Poznámka: Toto je testovacia služba: Údaje môžu byť kedykoľvek vymazané. Pri zneužití tejto služby zomrú mačiatka.", "This document will expire in %d seconds.": [ "This document will expire in %d second. (singular)", "This document will expire in %d seconds. (1st plural)", @@ -113,8 +113,8 @@ "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", - "Reply": "Reply", - "Anonymous": "Anonymous", + "Reply": "Odpovedať", + "Anonymous": "Anonymný", "Avatar generated from IP address": "Avatar generated from IP address", "Add comment": "Add comment", "Optional nickname…": "Optional nickname…", From 51f5082f39dc35cb966fba5f7756b1cc9f1684ac Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 25 Sep 2022 17:09:10 +0200 Subject: [PATCH 050/506] New translations en.json (Slovak) --- i18n/sk.json | 172 +++++++++++++++++++++++++-------------------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/i18n/sk.json b/i18n/sk.json index 2c0d6930..f1815da3 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -79,57 +79,57 @@ "Never": "Nikdy", "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Poznámka: Toto je testovacia služba: Údaje môžu byť kedykoľvek vymazané. Pri zneužití tejto služby zomrú mačiatka.", "This document will expire in %d seconds.": [ - "This document will expire in %d second. (singular)", - "This document will expire in %d seconds. (1st plural)", - "This document will expire in %d seconds. (2nd plural)", - "This document will expire in %d seconds. (3rd plural)" + "Platnosť tohto dokumentu vyprší o %d sekundu.", + "Platnosť tohto dokumentu vyprší o %d sekundy.", + "Platnosť tohto dokumentu vyprší o %d sekúnd.", + "Platnosť tohto dokumentu vyprší o %d sekúnd." ], "This document will expire in %d minutes.": [ - "This document will expire in %d minute. (singular)", - "This document will expire in %d minutes. (1st plural)", - "This document will expire in %d minutes. (2nd plural)", - "This document will expire in %d minutes. (3rd plural)" + "Platnosť tohto dokumentu vyprší o %d minútu.", + "Platnosť tohto dokumentu vyprší o %d minúty.", + "Platnosť tohto dokumentu vyprší o %d minút.", + "Platnosť tohto dokumentu vyprší o %d minút." ], "This document will expire in %d hours.": [ - "This document will expire in %d hour. (singular)", - "This document will expire in %d hours. (1st plural)", - "This document will expire in %d hours. (2nd plural)", - "This document will expire in %d hours. (3rd plural)" + "Platnosť tohto dokumentu vyprší o %d hodinu.", + "Platnosť tohto dokumentu vyprší o %d hodiny.", + "Platnosť tohto dokumentu vyprší o %d hodín.", + "Platnosť tohto dokumentu vyprší o %d hodín." ], "This document will expire in %d days.": [ - "This document will expire in %d day. (singular)", - "This document will expire in %d days. (1st plural)", - "This document will expire in %d days. (2nd plural)", - "This document will expire in %d days. (3rd plural)" + "Platnosť tohto dokumentu vyprší o %d deň.", + "Platnosť tohto dokumentu vyprší o %d dni.", + "Platnosť tohto dokumentu vyprší o %d dní.", + "Platnosť tohto dokumentu vyprší o %d dní." ], "This document will expire in %d months.": [ - "This document will expire in %d month. (singular)", - "This document will expire in %d months. (1st plural)", - "This document will expire in %d months. (2nd plural)", - "This document will expire in %d months. (3rd plural)" + "Platnosť tohto dokumentu vyprší o %d mesiac.", + "Platnosť tohto dokumentu vyprší o %d mesiace.", + "Platnosť tohto dokumentu vyprší o %d mesiacov.", + "Platnosť tohto dokumentu vyprší o %d mesiacov." ], - "Please enter the password for this paste:": "Please enter the password for this paste:", - "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", - "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", + "Please enter the password for this paste:": "Zadajte prosím heslo:", + "Could not decrypt data (Wrong key?)": "Nepodarilo sa dešifrovať údaje (nesprávny kľúč?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Nepodarilo sa odstrániť príspevok, nebol uložený v režime zmazania po prečítaní.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "IBA PRE VAŠE OČI. Toto okno nezatvárajte, táto správa sa nedá znova zobraziť.", + "Could not decrypt comment; Wrong key?": "Nepodarilo sa dešifrovať komentár. Nesprávny kľúč?", "Reply": "Odpovedať", "Anonymous": "Anonymný", - "Avatar generated from IP address": "Avatar generated from IP address", - "Add comment": "Add comment", - "Optional nickname…": "Optional nickname…", - "Post comment": "Post comment", - "Sending comment…": "Sending comment…", - "Comment posted.": "Comment posted.", - "Could not refresh display: %s": "Could not refresh display: %s", - "unknown status": "unknown status", - "server error or not responding": "server error or not responding", - "Could not post comment: %s": "Could not post comment: %s", - "Sending paste…": "Sending paste…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", - "Delete data": "Delete data", - "Could not create paste: %s": "Could not create paste: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "Avatar generated from IP address": "Avatar vygenerovaný z IP adresy", + "Add comment": "Pridať komentár", + "Optional nickname…": "Voliteľná prezývka…", + "Post comment": "Odoslať komentár", + "Sending comment…": "Odosielanie komentára…", + "Comment posted.": "Komentár odoslaný.", + "Could not refresh display: %s": "Nepodarilo sa obnoviť zobrazenie: %s", + "unknown status": "neznámy stav", + "server error or not responding": "chyba servera alebo server neodpovedá", + "Could not post comment: %s": "Nepodarilo sa pridať komentár: %s", + "Sending paste…": "Odosiela sa príspevok…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Váš príspevok je %s (skopírujte stlačením [Ctrl]+[c])", + "Delete data": "Odstrániť dáta", + "Could not create paste: %s": "Nepodarilo sa vytvoriť príspevok: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Nie je možné dešifrovať príspevok: V URL adrese chýba dešifrovací kľúč (Použili ste presmerovač alebo skracovač adresy, ktorý odstráni časť adresy URL?)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -139,52 +139,52 @@ "EiB": "EiB", "ZiB": "ZiB", "YiB": "YiB", - "Format": "Format", - "Plain Text": "Plain Text", - "Source Code": "Source Code", + "Format": "Formát", + "Plain Text": "Čistý text", + "Source Code": "Zdrojový kód", "Markdown": "Markdown", - "Download attachment": "Download attachment", - "Cloned: '%s'": "Cloned: '%s'", - "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", - "Attach a file": "Attach a file", - "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", - "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", - "Remove attachment": "Remove attachment", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", - "Invalid attachment.": "Invalid attachment.", - "Options": "Options", - "Shorten URL": "Shorten URL", + "Download attachment": "Stiahnuť prílohu", + "Cloned: '%s'": "Naklonované: '%s'", + "The cloned file '%s' was attached to this paste.": "K tomuto príspevku bol pripojený klonovaný súbor '%s'.", + "Attach a file": "Priložiť súbor", + "alternatively drag & drop a file or paste an image from the clipboard": "prípadne presuňte súbor myšou alebo vložte obrázok zo schránky", + "File too large, to display a preview. Please download the attachment.": "Súbor je príliš veľký na zobrazenie ukážky. Stiahnite si prosím prílohu.", + "Remove attachment": "Odstrániť prílohu", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Váš prehliadač nepodporuje nahrávanie šifrovaných súborov. Použite prosím novší prehliadač.", + "Invalid attachment.": "Neplatná príloha.", + "Options": "Možnosti", + "Shorten URL": "Skrátiť URL", "Editor": "Editor", - "Preview": "Preview", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", - "Decrypt": "Decrypt", - "Enter password": "Enter password", - "Loading…": "Loading…", - "Decrypting paste…": "Decrypting paste…", - "Preparing new paste…": "Preparing new paste…", - "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", - "+++ no paste text +++": "+++ no paste text +++", - "Could not get paste data: %s": "Could not get paste data: %s", - "QR code": "QR code", - "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", - "For more information see this FAQ entry.": "For more information see this FAQ entry.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", - "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", - "Retry": "Retry", - "Showing raw text…": "Showing raw text…", - "Notice:": "Notice:", - "This link will expire after %s.": "This link will expire after %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", - "Link:": "Link:", - "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", - "Use Current Timezone": "Use Current Timezone", - "Convert To UTC": "Convert To UTC", - "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", - "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Preview": "Náhľad", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH končila na \"%s\". Aktualizujte prosím PATH vo svojom index.php.", + "Decrypt": "Dešifrovať", + "Enter password": "Zadajte heslo", + "Loading…": "Načítava sa…", + "Decrypting paste…": "Dešifrovanie príspevku…", + "Preparing new paste…": "Príprava nového príspevku…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "V prípade, že táto správa nezmizne, pozrite si tieto často kladené otázky, kde nájdete informácie na riešenie problémov.", + "+++ no paste text +++": "+++ žiadny vložený text +++", + "Could not get paste data: %s": "Nepodarilo sa načítať údaje príspevku: %s", + "QR code": "QR kód", + "This website is using an insecure HTTP connection! Please use it only for testing.": "Táto webová stránka používa nezabezpečené pripojenie HTTP! Používajte ju len na testovanie.", + "For more information see this FAQ entry.": "Pre viac informácií si pozrite tento záznam FAQ.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Váš prehliadač môže na podporu rozhrania WebCrypto API vyžadovať pripojenie HTTPS. Skúste prepnúť na HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Váš prehliadač nepodporuje WebAssembly, ktorý sa používa na kompresiu zlib. Môžete vytvárať nekomprimované dokumenty, ale nemôžete čítať komprimované.", + "waiting on user to provide a password": "čakám na zadanie hesla", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Údaje sa nepodarilo dešifrovať. Zadali ste nesprávne heslo? Skúste to znova pomocou tlačidla v hornej časti.", + "Retry": "Opakovať", + "Showing raw text…": "Zobrazuje sa surový text…", + "Notice:": "Upozornenie:", + "This link will expire after %s.": "Platnosť odkazu vyprší za %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Tento odkaz je prístupný iba raz, nepoužívajte v prehliadači tlačidlo Späť ani Obnoviť.", + "Link:": "Odkaz:", + "Recipient may become aware of your timezone, convert time to UTC?": "Príjemca sa môže dozvedieť o vašom časovom pásme, previesť čas na UTC?", + "Use Current Timezone": "Použiť aktuálne časové pásmo", + "Convert To UTC": "Previesť na UTC", + "Close": "Zavrieť", + "Encrypted note on PrivateBin": "Zašifrovaná poznámka na PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Ak chcete zobraziť poznámku, navštívte tento odkaz. Poskytnutie adresy URL komukoľvek im umožní prístup aj k poznámke.", + "URL shortener may expose your decrypt key in URL.": "Skracovač adries URL môže odhaliť váš dešifrovací kľúč v adrese URL.", + "Save paste": "Uložiť príspevok", + "Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať príspevky." } From b61b4253a6f7332a36ec099e139f272252eb4bfd Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 29 Sep 2022 05:34:49 +0200 Subject: [PATCH 051/506] enabled use of Slovak translations --- CHANGELOG.md | 2 +- CREDITS.md | 1 + js/privatebin.js | 7 ++++--- lib/I18n.php | 11 ++++++----- tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1343024c..efdcfa31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # PrivateBin version history * **1.4.1 (not yet released)** - * ADDED: Translations for Turkish + * ADDED: Translations for Turkish and Slovak * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) * FIXED: Apply table prefix to indexes as well, to support multiple instances sharing a single database (#943) diff --git a/CREDITS.md b/CREDITS.md index 1badfb9b..0498fe4a 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -57,3 +57,4 @@ * Patriccollu di Santa Maria è Sichè - Corsican * Markus Mikkonen - Finnish * Emir Ensar Rahmanlar - Turkish +* Stevo984 - Slovak \ No newline at end of file diff --git a/js/privatebin.js b/js/privatebin.js index 9eec6e09..04798da0 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -627,7 +627,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @prop {string[]} * @readonly */ - const supportedLanguages = ['bg', 'ca', 'co', 'cs', 'de', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sl', 'tr', 'uk', 'zh']; + const supportedLanguages = ['bg', 'ca', 'co', 'cs', 'de', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sk', 'sl', 'tr', 'uk', 'zh']; /** * built in language @@ -803,7 +803,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { switch (language) { case 'cs': - return n === 1 ? 0 : (n >= 2 && n <=4 ? 1 : 2); + case 'sk': + return n === 1 ? 0 : (n >= 2 && n <= 4 ? 1 : 2); case 'co': case 'fr': case 'oc': @@ -818,7 +819,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { case 'lt': return n % 10 === 1 && n % 100 !== 11 ? 0 : ((n % 10 >= 2 && n % 100 < 10 || n % 100 >= 20) ? 1 : 2); case 'pl': - return n === 1 ? 0 : (n % 10 >= 2 && n %10 <=4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); + return n === 1 ? 0 : (n % 10 >= 2 && n %10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); case 'ru': case 'uk': return n % 10 === 1 && n % 100 !== 11 ? 0 : (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); diff --git a/lib/I18n.php b/lib/I18n.php index 0d4734a3..7248c255 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -316,7 +316,8 @@ class I18n { switch (self::$_language) { case 'cs': - return $n == 1 ? 0 : ($n >= 2 && $n <= 4 ? 1 : 2); + case 'sk': + return $n === 1 ? 0 : ($n >= 2 && $n <= 4 ? 1 : 2); case 'co': case 'fr': case 'oc': @@ -331,15 +332,15 @@ class I18n case 'lt': return $n % 10 === 1 && $n % 100 !== 11 ? 0 : (($n % 10 >= 2 && $n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); case 'pl': - return $n == 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); + return $n === 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); case 'ru': case 'uk': - return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); + return $n % 10 === 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); case 'sl': - return $n % 100 == 1 ? 1 : ($n % 100 == 2 ? 2 : ($n % 100 == 3 || $n % 100 == 4 ? 3 : 0)); + return $n % 100 === 1 ? 1 : ($n % 100 === 2 ? 2 : ($n % 100 === 3 || $n % 100 === 4 ? 3 : 0)); // bg, ca, de, en, es, et, fi, hu, it, nl, no, pt default: - return $n != 1 ? 1 : 0; + return $n !== 1 ? 1 : 0; } } diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 65f093ef..746a1671 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index 1e377609..82dc443c 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From 0f1c2fdb0479d70913e8447f824a7ad7a2d91dcb Mon Sep 17 00:00:00 2001 From: Christos Karamolegkos Date: Thu, 29 Sep 2022 15:29:23 +0300 Subject: [PATCH 052/506] Update strings in el.json and enable greek language --- i18n/el.json | 300 +++++++++++++++++++++++----------------------- js/privatebin.js | 2 +- tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 4 files changed, 153 insertions(+), 153 deletions(-) diff --git a/i18n/el.json b/i18n/el.json index acfca8f9..61eb3b17 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -1,135 +1,135 @@ { "PrivateBin": "PrivateBin", - "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.", - "More information on the project page.": "More information on the project page.", - "Because ignorance is bliss": "Because ignorance is bliss", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s είναι ένα λιτό, ανοικτού λογισμικού διαδικτυακής υπηρεσίας επικόλλησης όπου ο διακομιστής έχει πλήρη άγνια του περιεχομένου που επικολλήθηκαν. Τα Δεδομένα κρυπτογραφούνται και αποκρυπτογραφούνται %sστον φιλομετρητή (browser)%s χρησιμοποιόντας 256 bits AES.", + "More information on the project page.": "Περισσότερες πληροφορίες στον ιστότοπο του εργαλείου.", + "Because ignorance is bliss": "Επειδή η άγνοια είναι ευτυχία", "en": "el", - "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.", - "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.", - "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", + "Paste does not exist, has expired or has been deleted.": "Η επικόλληση δεν υπάρχει, έληξε ή διαγράφηκε", + "%s requires php %s or above to work. Sorry.": "%s απαιτεί php %s ή νεότερη για να λειτουργήσει. Συγγνώμη.", + "%s requires configuration section [%s] to be present in configuration file.": "%s απαιτεί οι ρυθμίσεις [%s] να υπάρχουν στο αρχείο ρυθμίσεων.", "Please wait %d seconds between each post.": [ - "Please wait %d second between each post. (singular)", - "Please wait %d seconds between each post. (1st plural)", - "Please wait %d seconds between each post. (2nd plural)", - "Please wait %d seconds between each post. (3rd plural)" + "Παρακαλώ περιμένετε %d δευτερόλεπτο μεταξύ κάθε επικόλλησης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης." ], - "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", - "Invalid data.": "Invalid data.", - "You are unlucky. Try again.": "You are unlucky. Try again.", - "Error saving comment. Sorry.": "Error saving comment. Sorry.", - "Error saving paste. Sorry.": "Error saving paste. Sorry.", - "Invalid paste ID.": "Invalid paste ID.", - "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", - "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", - "Paste was properly deleted.": "Paste was properly deleted.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", - "%s requires a modern browser to work.": "%s requires a modern browser to work.", - "New": "New", - "Send": "Send", - "Clone": "Clone", - "Raw text": "Raw text", - "Expires": "Expires", - "Burn after reading": "Burn after reading", - "Open discussion": "Open discussion", - "Password (recommended)": "Password (recommended)", - "Discussion": "Discussion", - "Toggle navigation": "Toggle navigation", + "Paste is limited to %s of encrypted data.": "Η επικόλληση είναι περιορισμένη σε %s κρυπτογραφημένων δεδομένων.", + "Invalid data.": "Λάθος δεδομένα.", + "You are unlucky. Try again.": "Ατυχήσατε. Προσπαθήστε πάλι.", + "Error saving comment. Sorry.": "Λάθος στην αποθήκευση του σχόλιου. Συγγνώμη.", + "Error saving paste. Sorry.": "Λάθος στην αποθήκευση της επικόλλησης. Συγγνώμη.", + "Invalid paste ID.": "Λάθος αναγνωριστικό επικόλλησης.", + "Paste is not of burn-after-reading type.": "Η επικόληση δεν είναι τύπου καταστροφή-μετά-το-διάβασμα.", + "Wrong deletion token. Paste was not deleted.": "Λάθος αναγνωριστικό διαγραφής. Η επικόλληση δεν διαγράφηκε.", + "Paste was properly deleted.": "Η επικόλληση διαγράφηκε επιτυχώς.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "Η JavaScript είναι απαραίτητη για να λειτουργήσει το %s. Συγγνώμη για την ταλαιπωρία.", + "%s requires a modern browser to work.": "%s απαιτεί σύγχρονο φυλλομετρητή (browser) για να λειτουργήσει.", + "New": "Νέο", + "Send": "Αποστολή", + "Clone": "Κλωνοποίηση", + "Raw text": "Κείμενο", + "Expires": "Λήγει", + "Burn after reading": "Διαγραφή μετά την ανάγνωση", + "Open discussion": "Ανοικτή συζήτηση", + "Password (recommended)": "Κωδικός (προτείνεται)", + "Discussion": "Συζήτηση", + "Toggle navigation": "Εναλλαγή πλοήγησης", "%d seconds": [ - "%d second (singular)", - "%d seconds (1st plural)", - "%d seconds (2nd plural)", - "%d seconds (3rd plural)" + "%d δευτερόλεπτο", + "%d δευτερόλεπτα", + "%d δευτερόλεπτα", + "%d δευτερόλεπτα" ], "%d minutes": [ - "%d minute (singular)", - "%d minutes (1st plural)", - "%d minutes (2nd plural)", - "%d minutes (3rd plural)" + "%d λεπτό", + "%d λεπτά", + "%d λεπτά", + "%d λεπτά" ], "%d hours": [ - "%d hour (singular)", - "%d hours (1st plural)", - "%d hours (2nd plural)", - "%d hours (3rd plural)" + "%d ώρα", + "%d ώρες", + "%d ώρες", + "%d ώρες" ], "%d days": [ - "%d day (singular)", - "%d days (1st plural)", - "%d days (2nd plural)", - "%d days (3rd plural)" + "%d ημέρα", + "%d ημέρες", + "%d ημέρες", + "%d ημέρες" ], "%d weeks": [ - "%d week (singular)", - "%d weeks (1st plural)", - "%d weeks (2nd plural)", - "%d weeks (3rd plural)" + "%d εβδομάδα", + "%d εβδομάδες", + "%d εβδομάδες", + "%d εβδομάδες" ], "%d months": [ - "%d month (singular)", - "%d months (1st plural)", - "%d months (2nd plural)", - "%d months (3rd plural)" + "%d μήνας", + "%d μήνες", + "%d μήνες", + "%d μήνες" ], "%d years": [ - "%d year (singular)", - "%d years (1st plural)", - "%d years (2nd plural)", - "%d years (3rd plural)" + "%d χρόνο", + "%d χρόνια", + "%d χρόνια", + "%d χρόνια" ], - "Never": "Never", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "Never": "Ποτέ", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Σημείωση: αυτή είναι μία δοκιμαστική υπηρεσία. Τα δεδομένα μπορεί να σβηστούν ανά πάσα στιγμή.", "This document will expire in %d seconds.": [ - "This document will expire in %d second. (singular)", - "This document will expire in %d seconds. (1st plural)", - "This document will expire in %d seconds. (2nd plural)", - "This document will expire in %d seconds. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτο.", + "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.", + "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.", + "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα." ], "This document will expire in %d minutes.": [ - "This document will expire in %d minute. (singular)", - "This document will expire in %d minutes. (1st plural)", - "This document will expire in %d minutes. (2nd plural)", - "This document will expire in %d minutes. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d λεπτό.", + "Αυτό το έγγραφο θα λήξει σε %d λεπτά.", + "Αυτό το έγγραφο θα λήξει σε %d λεπτά.", + "Αυτό το έγγραφο θα λήξει σε %d λεπτά." ], "This document will expire in %d hours.": [ - "This document will expire in %d hour. (singular)", - "This document will expire in %d hours. (1st plural)", - "This document will expire in %d hours. (2nd plural)", - "This document will expire in %d hours. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d ώρα.", + "Αυτό το έγγραφο θα λήξει σε %d ώρες.", + "Αυτό το έγγραφο θα λήξει σε %d ώρες.", + "Αυτό το έγγραφο θα λήξει σε %d ώρες." ], "This document will expire in %d days.": [ - "This document will expire in %d day. (singular)", - "This document will expire in %d days. (1st plural)", - "This document will expire in %d days. (2nd plural)", - "This document will expire in %d days. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d ημέρα.", + "Αυτό το έγγραφο θα λήξει σε %d ημέρες.", + "Αυτό το έγγραφο θα λήξει σε %d ημέρες.", + "Αυτό το έγγραφο θα λήξει σε %d ημέρες." ], "This document will expire in %d months.": [ - "This document will expire in %d month. (singular)", - "This document will expire in %d months. (1st plural)", - "This document will expire in %d months. (2nd plural)", - "This document will expire in %d months. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d μήνα.", + "Αυτό το έγγραφο θα λήξει σε %d μήνες.", + "Αυτό το έγγραφο θα λήξει σε %d μήνες.", + "Αυτό το έγγραφο θα λήξει σε %d μήνες." ], - "Please enter the password for this paste:": "Please enter the password for this paste:", - "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", - "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", - "Reply": "Reply", - "Anonymous": "Anonymous", - "Avatar generated from IP address": "Avatar generated from IP address", - "Add comment": "Add comment", - "Optional nickname…": "Optional nickname…", - "Post comment": "Post comment", - "Sending comment…": "Sending comment…", - "Comment posted.": "Comment posted.", - "Could not refresh display: %s": "Could not refresh display: %s", - "unknown status": "unknown status", - "server error or not responding": "server error or not responding", - "Could not post comment: %s": "Could not post comment: %s", - "Sending paste…": "Sending paste…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", - "Delete data": "Delete data", - "Could not create paste: %s": "Could not create paste: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "Please enter the password for this paste:": "Παρακαλώ εισάγετε τον κωδικό για αυτή την επικόληση:", + "Could not decrypt data (Wrong key?)": "Δεν ήταν δυνατή η αποκρυπτογράφηση των δεδομένων (πιθανώς λανθασμένο κλειδί;)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Δεν ήταν δυνατή η διαγραφή της επικόλλησης, δεν ήταν αποθηκευμένη σε μορφή διαγραφής μετά την ανάγνωση.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ΜΟΝΟ ΓΙΑ ΕΣΑΣ. Μην κλείσετε το αυτό το παράθυρο, αυτό το μήνυμα δεν μπορεί να εμφανιστεί ξανά.", + "Could not decrypt comment; Wrong key?": "Δεν ήταν δυνατή η αποκρυπτογράφηση του σχολίου. Λάθος κλειδί;", + "Reply": "Απάντηση", + "Anonymous": "Ανώνυμος", + "Avatar generated from IP address": "το avatar δημιουργήθηκε από τη διεύθυνση IP", + "Add comment": "Σχολιάστε", + "Optional nickname…": "Προαιρετικό ψευδώνυμο…", + "Post comment": "Αποστολή σχολίου", + "Sending comment…": "Το σχόλιο αποστέλλεται…", + "Comment posted.": "Το σχόλιο δημοσιεύτηκε.", + "Could not refresh display: %s": "Δεν ήταν δυνατή η ανανέωση της σελίδας: %s", + "unknown status": "άγνωστη κατάσταση", + "server error or not responding": "Πρόβλημα του διακομιστή ή δεν υπάρχει απάντηση", + "Could not post comment: %s": "Δεν ήταν δυνατή η δημοσίευση του σχολίου: %s", + "Sending paste…": "Η επικόλληση αποστέλλεται…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Η επικόλλησή σας είναι %s (Πληκτρολογήστε [Ctrl]+[c] για αντιγραφή)", + "Delete data": "Διαγραφή δεδομένων", + "Could not create paste: %s": "Δεν ήταν δυνατή η δημιουργία επικόλλησης: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Δεν ήταν δυνατή η αποκρυπτογράφηση της επικόλλησης: Το κλειδί αποκρυπτογράφησης λείπει από τον σύνδεσμο (Μήπως χρησιμοποιήσατε ανακατεύθυνση συνδέσμου ή υπηρεσία συντόμευσης συνδέσμου;)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -139,52 +139,52 @@ "EiB": "EiB", "ZiB": "ZiB", "YiB": "YiB", - "Format": "Format", - "Plain Text": "Plain Text", - "Source Code": "Source Code", + "Format": "Μορφοποίηση", + "Plain Text": "Απλό κείμενο", + "Source Code": "Πηγαίος Κώδικας", "Markdown": "Markdown", - "Download attachment": "Download attachment", - "Cloned: '%s'": "Cloned: '%s'", - "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", - "Attach a file": "Attach a file", - "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", - "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", - "Remove attachment": "Remove attachment", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", - "Invalid attachment.": "Invalid attachment.", - "Options": "Options", - "Shorten URL": "Shorten URL", - "Editor": "Editor", - "Preview": "Preview", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", - "Decrypt": "Decrypt", - "Enter password": "Enter password", - "Loading…": "Loading…", - "Decrypting paste…": "Decrypting paste…", - "Preparing new paste…": "Preparing new paste…", - "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", - "+++ no paste text +++": "+++ no paste text +++", - "Could not get paste data: %s": "Could not get paste data: %s", - "QR code": "QR code", - "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", - "For more information see this FAQ entry.": "For more information see this FAQ entry.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", - "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", - "Retry": "Retry", - "Showing raw text…": "Showing raw text…", - "Notice:": "Notice:", - "This link will expire after %s.": "This link will expire after %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", - "Link:": "Link:", - "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", - "Use Current Timezone": "Use Current Timezone", - "Convert To UTC": "Convert To UTC", - "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", - "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Download attachment": "Λήψη επισυναπτόμενου", + "Cloned: '%s'": "Κλώνος: '%s'", + "The cloned file '%s' was attached to this paste.": "Το κλωνοποιημένο αρχείο '%s' επισυνάφθηκε στ αυτή την επικόλληση.", + "Attach a file": "Επισύναψη αρχείου", + "alternatively drag & drop a file or paste an image from the clipboard": "εναλλακτικά σύρετε το αρχείο ή επικολλήστε μία εικόνα από το clipboard", + "File too large, to display a preview. Please download the attachment.": "Πολύ μεγάλο αρχείο για προεπισκόπηση. Παρακαλώ κατεβάστε το επισυναπτόμενο.", + "Remove attachment": "Αφαίρεση επισυναπτόμενου", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Ο φυλλομετρητής (browser) σας δεν υποστηρίζει κρυπτογραφημένα αρχεία. Παρακαλώ χρησιμοποιήστε νεότερο φιλομετρητή.", + "Invalid attachment.": "Λάθος επισυναπτόμενο.", + "Options": "Επιλογές", + "Shorten URL": "Συντόμευση σύνδεσμου", + "Editor": "Διορθωτής", + "Preview": "Προεπισκόπηση", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s απαιτεί το PATH να τελειώνει σε \"%s\". Παρακαλώ ενημερώστε το PATH στο index.php σας.", + "Decrypt": "Αποκρυπτογράφηση", + "Enter password": "Εισαγωγή κωδικού", + "Loading…": "Φόρτωση…", + "Decrypting paste…": "Η επικόλληση αποκρυπτογραφείται…", + "Preparing new paste…": "Προετοιμασία νέας επικόλλησης…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "Σε περίπτωση που αυτό το μήνυμα δεν εξαφανίζεται παρακαλώ κοιτάξτε στις Ερωταποκρίσεις για πληροφορίες στην αντιμετώπιση προβλημάτων.", + "+++ no paste text +++": "+++ Δεν υπάρχει επικόλληση +++", + "Could not get paste data: %s": "Δεν ήταν δυνατή η λήψη της επικόλλησης: %s", + "QR code": "QR εικονοστοιχειοσειρά", + "This website is using an insecure HTTP connection! Please use it only for testing.": "Αυτός ο ιστότοπος χρησιμοποιεί μη ασφαλή HTTP σύνδεση! Παρακαλώ χρησιμοποιήστε το μόνο δοκιμαστικά.", + "For more information see this FAQ entry.": "Για περισσότερες πληροφορίες δείτε τις ερωταπαντήσεις.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Ο φυλλομετρητής (browser) σας μπορεί να απαιτεί HTTPS σύνδεση για να υποστηρίξει το WebCrypto API. Δοκιμάστε το HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Ο φυλλομετρητής (browser) σας δεν υποστηρίζει WebAssembly, που χρησιμοποιήθηκε για zlib συμπίεση. Μπορείτε να δημιουργήσετε ασυμπίεστα αρχεία αλλά δεν μπορείτε να διαβάσετε συμπιεσμένα.", + "waiting on user to provide a password": "Αναμονή ο χρήστης να δώσει τον κωδικό", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Δεν ήταν δυνατή η αποκρυπτογράφηση των δεδομένων. Μήπως εισάγατε λάθος κωδικό; Προσπαθήστε με το κουμπί στο επάνω μέρος.", + "Retry": "Επαναπροσπάθεια", + "Showing raw text…": "Προβολή κειμένου…", + "Notice:": "Επισήμανση:", + "This link will expire after %s.": "Ο σύνδεσμος θα λήξει σε %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Αυτός ο σύνδεσμος μπορεί να προσπελαστεί μόνο μία φορά, μην χρησιμοποιήσετε το κουμπί επιστροφή (back) ή ανανέωση (refresh) στον φυλλομετρητή (browser) σας.", + "Link:": "Σύνδεσμος:", + "Recipient may become aware of your timezone, convert time to UTC?": "Ο παραλήπτης μπορεί να αναγνωρίσει τη ζώνη ώρας σας, θέλετε μετατροπή της ώρας σε UTC;", + "Use Current Timezone": "Χρήση τρέχουσας ζώνης ώρας", + "Convert To UTC": "Μετατροπή σε UTC", + "Close": "Κλείσιμο", + "Encrypted note on PrivateBin": "Κρυπτογραφημένο μήνυμα από το PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφτείτε αυτόν τον σύνδεσμο για να δείτε το μήνυμα. Δίνοντας τον σύνδεσμο σε οποιονδήποτε, του επιτρέπετε να επισκεφτεί το μήνυμα επίσης.", + "URL shortener may expose your decrypt key in URL.": "Συντομευτές συνδέσμων πιθανώς να δημοσιοποιήσουν το κλειδί αποκρυπτογράφισης στον σύνδεσμο.", + "Save paste": "Αποθήκευση επικόλλησης", + "Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις." } diff --git a/js/privatebin.js b/js/privatebin.js index 9eec6e09..1713c583 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -627,7 +627,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @prop {string[]} * @readonly */ - const supportedLanguages = ['bg', 'ca', 'co', 'cs', 'de', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sl', 'tr', 'uk', 'zh']; + const supportedLanguages = ['bg', 'ca', 'co', 'cs', 'de', 'el', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sl', 'tr', 'uk', 'zh']; /** * built in language diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 65f093ef..d00887f7 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index 1e377609..e46f4bd1 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From 77409e6065afd459e9911f4539f9f1af4ef3bb39 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 29 Sep 2022 21:15:00 +0200 Subject: [PATCH 053/506] crediting greek language as well, plus docs --- CHANGELOG.md | 2 +- CREDITS.md | 3 ++- js/privatebin.js | 2 +- lib/I18n.php | 2 +- tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efdcfa31..15bb1b1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # PrivateBin version history * **1.4.1 (not yet released)** - * ADDED: Translations for Turkish and Slovak + * ADDED: Translations for Turkish, Slovak and Greek * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) * FIXED: Apply table prefix to indexes as well, to support multiple instances sharing a single database (#943) diff --git a/CREDITS.md b/CREDITS.md index 0498fe4a..c0be0ad2 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -57,4 +57,5 @@ * Patriccollu di Santa Maria è Sichè - Corsican * Markus Mikkonen - Finnish * Emir Ensar Rahmanlar - Turkish -* Stevo984 - Slovak \ No newline at end of file +* Stevo984 - Slovak +* Christos Karamolegkos - Greek \ No newline at end of file diff --git a/js/privatebin.js b/js/privatebin.js index be0cfe21..fe326b49 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -825,7 +825,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { return n % 10 === 1 && n % 100 !== 11 ? 0 : (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); case 'sl': return n % 100 === 1 ? 1 : (n % 100 === 2 ? 2 : (n % 100 === 3 || n % 100 === 4 ? 3 : 0)); - // bg, ca, de, en, es, et, fi, hu, it, nl, no, pt + // bg, ca, de, el, en, es, et, fi, hu, it, nl, no, pt default: return n !== 1 ? 1 : 0; } diff --git a/lib/I18n.php b/lib/I18n.php index 7248c255..6394a584 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -338,7 +338,7 @@ class I18n return $n % 10 === 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); case 'sl': return $n % 100 === 1 ? 1 : ($n % 100 === 2 ? 2 : ($n % 100 === 3 || $n % 100 === 4 ? 3 : 0)); - // bg, ca, de, en, es, et, fi, hu, it, nl, no, pt + // bg, ca, de, el, en, es, et, fi, hu, it, nl, no, pt default: return $n !== 1 ? 1 : 0; } diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index dc123cb7..8eb5565d 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index a3754174..eddbb4b7 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From c6659747ae37a58b65cc40c553915e5804a3acb0 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Wed, 5 Oct 2022 09:01:55 +0200 Subject: [PATCH 054/506] New translations en.json (Greek) --- i18n/el.json | 300 +++++++++++++++++++++++++-------------------------- 1 file changed, 150 insertions(+), 150 deletions(-) diff --git a/i18n/el.json b/i18n/el.json index 61eb3b17..8c281e2f 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -1,135 +1,135 @@ { "PrivateBin": "PrivateBin", - "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s είναι ένα λιτό, ανοικτού λογισμικού διαδικτυακής υπηρεσίας επικόλλησης όπου ο διακομιστής έχει πλήρη άγνια του περιεχομένου που επικολλήθηκαν. Τα Δεδομένα κρυπτογραφούνται και αποκρυπτογραφούνται %sστον φιλομετρητή (browser)%s χρησιμοποιόντας 256 bits AES.", - "More information on the project page.": "Περισσότερες πληροφορίες στον ιστότοπο του εργαλείου.", - "Because ignorance is bliss": "Επειδή η άγνοια είναι ευτυχία", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s είναι ένα μινιμαλιστικό, ανοικτού κώδικα online pastebin όπου ο διακομιστής έχει μηδενική γνώση της επικόλλησης δεδομένων. Τα δεδομένα κρυπτογραφούνται/αποκρυπτογραφούνται %sστο πρόγραμμα περιήγησης%s χρησιμοποιώντας 256 bits AES.", + "More information on the project page.": "Περισσότερες πληροφορίες στη σελίδα του έργου.", + "Because ignorance is bliss": "Because ignorance is bliss", "en": "el", - "Paste does not exist, has expired or has been deleted.": "Η επικόλληση δεν υπάρχει, έληξε ή διαγράφηκε", - "%s requires php %s or above to work. Sorry.": "%s απαιτεί php %s ή νεότερη για να λειτουργήσει. Συγγνώμη.", - "%s requires configuration section [%s] to be present in configuration file.": "%s απαιτεί οι ρυθμίσεις [%s] να υπάρχουν στο αρχείο ρυθμίσεων.", + "Paste does not exist, has expired or has been deleted.": "Η επικόλληση δεν υπάρχει ή έχει διαγραφτεί.", + "%s requires php %s or above to work. Sorry.": "%s απαιτεί php %s ή παραπάνω για να λειτουργήσει. Συγνώμη.", + "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", "Please wait %d seconds between each post.": [ - "Παρακαλώ περιμένετε %d δευτερόλεπτο μεταξύ κάθε επικόλλησης.", - "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης.", - "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης.", - "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης." + "Παρακαλώ περιμένετε %d δευτερόλεπτο μεταξύ κάθε δημοσίευσης. (ενικό)", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε δημοσίευσης. (1ος πλουραλικός)", + "Please wait %d seconds between each post. (2nd plural)", + "Please wait %d seconds between each post. (3rd plural)" ], - "Paste is limited to %s of encrypted data.": "Η επικόλληση είναι περιορισμένη σε %s κρυπτογραφημένων δεδομένων.", - "Invalid data.": "Λάθος δεδομένα.", - "You are unlucky. Try again.": "Ατυχήσατε. Προσπαθήστε πάλι.", - "Error saving comment. Sorry.": "Λάθος στην αποθήκευση του σχόλιου. Συγγνώμη.", - "Error saving paste. Sorry.": "Λάθος στην αποθήκευση της επικόλλησης. Συγγνώμη.", - "Invalid paste ID.": "Λάθος αναγνωριστικό επικόλλησης.", - "Paste is not of burn-after-reading type.": "Η επικόληση δεν είναι τύπου καταστροφή-μετά-το-διάβασμα.", - "Wrong deletion token. Paste was not deleted.": "Λάθος αναγνωριστικό διαγραφής. Η επικόλληση δεν διαγράφηκε.", - "Paste was properly deleted.": "Η επικόλληση διαγράφηκε επιτυχώς.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "Η JavaScript είναι απαραίτητη για να λειτουργήσει το %s. Συγγνώμη για την ταλαιπωρία.", - "%s requires a modern browser to work.": "%s απαιτεί σύγχρονο φυλλομετρητή (browser) για να λειτουργήσει.", - "New": "Νέο", - "Send": "Αποστολή", - "Clone": "Κλωνοποίηση", - "Raw text": "Κείμενο", - "Expires": "Λήγει", - "Burn after reading": "Διαγραφή μετά την ανάγνωση", - "Open discussion": "Ανοικτή συζήτηση", - "Password (recommended)": "Κωδικός (προτείνεται)", - "Discussion": "Συζήτηση", - "Toggle navigation": "Εναλλαγή πλοήγησης", + "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", + "Invalid data.": "Invalid data.", + "You are unlucky. Try again.": "You are unlucky. Try again.", + "Error saving comment. Sorry.": "Error saving comment. Sorry.", + "Error saving paste. Sorry.": "Error saving paste. Sorry.", + "Invalid paste ID.": "Invalid paste ID.", + "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", + "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", + "Paste was properly deleted.": "Paste was properly deleted.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", + "%s requires a modern browser to work.": "%s requires a modern browser to work.", + "New": "New", + "Send": "Send", + "Clone": "Clone", + "Raw text": "Raw text", + "Expires": "Expires", + "Burn after reading": "Burn after reading", + "Open discussion": "Open discussion", + "Password (recommended)": "Password (recommended)", + "Discussion": "Discussion", + "Toggle navigation": "Toggle navigation", "%d seconds": [ - "%d δευτερόλεπτο", - "%d δευτερόλεπτα", - "%d δευτερόλεπτα", - "%d δευτερόλεπτα" + "%d second (singular)", + "%d seconds (1st plural)", + "%d seconds (2nd plural)", + "%d seconds (3rd plural)" ], "%d minutes": [ - "%d λεπτό", - "%d λεπτά", - "%d λεπτά", - "%d λεπτά" + "%d minute (singular)", + "%d minutes (1st plural)", + "%d minutes (2nd plural)", + "%d minutes (3rd plural)" ], "%d hours": [ - "%d ώρα", - "%d ώρες", - "%d ώρες", - "%d ώρες" + "%d hour (singular)", + "%d hours (1st plural)", + "%d hours (2nd plural)", + "%d hours (3rd plural)" ], "%d days": [ - "%d ημέρα", - "%d ημέρες", - "%d ημέρες", - "%d ημέρες" + "%d day (singular)", + "%d days (1st plural)", + "%d days (2nd plural)", + "%d days (3rd plural)" ], "%d weeks": [ - "%d εβδομάδα", - "%d εβδομάδες", - "%d εβδομάδες", - "%d εβδομάδες" + "%d week (singular)", + "%d weeks (1st plural)", + "%d weeks (2nd plural)", + "%d weeks (3rd plural)" ], "%d months": [ - "%d μήνας", - "%d μήνες", - "%d μήνες", - "%d μήνες" + "%d month (singular)", + "%d months (1st plural)", + "%d months (2nd plural)", + "%d months (3rd plural)" ], "%d years": [ - "%d χρόνο", - "%d χρόνια", - "%d χρόνια", - "%d χρόνια" + "%d year (singular)", + "%d years (1st plural)", + "%d years (2nd plural)", + "%d years (3rd plural)" ], - "Never": "Ποτέ", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Σημείωση: αυτή είναι μία δοκιμαστική υπηρεσία. Τα δεδομένα μπορεί να σβηστούν ανά πάσα στιγμή.", + "Never": "Never", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", "This document will expire in %d seconds.": [ - "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτο.", - "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.", - "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.", - "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα." + "This document will expire in %d second. (singular)", + "This document will expire in %d seconds. (1st plural)", + "This document will expire in %d seconds. (2nd plural)", + "This document will expire in %d seconds. (3rd plural)" ], "This document will expire in %d minutes.": [ - "Αυτό το έγγραφο θα λήξει σε %d λεπτό.", - "Αυτό το έγγραφο θα λήξει σε %d λεπτά.", - "Αυτό το έγγραφο θα λήξει σε %d λεπτά.", - "Αυτό το έγγραφο θα λήξει σε %d λεπτά." + "This document will expire in %d minute. (singular)", + "This document will expire in %d minutes. (1st plural)", + "This document will expire in %d minutes. (2nd plural)", + "This document will expire in %d minutes. (3rd plural)" ], "This document will expire in %d hours.": [ - "Αυτό το έγγραφο θα λήξει σε %d ώρα.", - "Αυτό το έγγραφο θα λήξει σε %d ώρες.", - "Αυτό το έγγραφο θα λήξει σε %d ώρες.", - "Αυτό το έγγραφο θα λήξει σε %d ώρες." + "This document will expire in %d hour. (singular)", + "This document will expire in %d hours. (1st plural)", + "This document will expire in %d hours. (2nd plural)", + "This document will expire in %d hours. (3rd plural)" ], "This document will expire in %d days.": [ - "Αυτό το έγγραφο θα λήξει σε %d ημέρα.", - "Αυτό το έγγραφο θα λήξει σε %d ημέρες.", - "Αυτό το έγγραφο θα λήξει σε %d ημέρες.", - "Αυτό το έγγραφο θα λήξει σε %d ημέρες." + "This document will expire in %d day. (singular)", + "This document will expire in %d days. (1st plural)", + "This document will expire in %d days. (2nd plural)", + "This document will expire in %d days. (3rd plural)" ], "This document will expire in %d months.": [ - "Αυτό το έγγραφο θα λήξει σε %d μήνα.", - "Αυτό το έγγραφο θα λήξει σε %d μήνες.", - "Αυτό το έγγραφο θα λήξει σε %d μήνες.", - "Αυτό το έγγραφο θα λήξει σε %d μήνες." + "This document will expire in %d month. (singular)", + "This document will expire in %d months. (1st plural)", + "This document will expire in %d months. (2nd plural)", + "This document will expire in %d months. (3rd plural)" ], - "Please enter the password for this paste:": "Παρακαλώ εισάγετε τον κωδικό για αυτή την επικόληση:", - "Could not decrypt data (Wrong key?)": "Δεν ήταν δυνατή η αποκρυπτογράφηση των δεδομένων (πιθανώς λανθασμένο κλειδί;)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Δεν ήταν δυνατή η διαγραφή της επικόλλησης, δεν ήταν αποθηκευμένη σε μορφή διαγραφής μετά την ανάγνωση.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ΜΟΝΟ ΓΙΑ ΕΣΑΣ. Μην κλείσετε το αυτό το παράθυρο, αυτό το μήνυμα δεν μπορεί να εμφανιστεί ξανά.", - "Could not decrypt comment; Wrong key?": "Δεν ήταν δυνατή η αποκρυπτογράφηση του σχολίου. Λάθος κλειδί;", - "Reply": "Απάντηση", - "Anonymous": "Ανώνυμος", - "Avatar generated from IP address": "το avatar δημιουργήθηκε από τη διεύθυνση IP", - "Add comment": "Σχολιάστε", - "Optional nickname…": "Προαιρετικό ψευδώνυμο…", - "Post comment": "Αποστολή σχολίου", - "Sending comment…": "Το σχόλιο αποστέλλεται…", - "Comment posted.": "Το σχόλιο δημοσιεύτηκε.", - "Could not refresh display: %s": "Δεν ήταν δυνατή η ανανέωση της σελίδας: %s", - "unknown status": "άγνωστη κατάσταση", - "server error or not responding": "Πρόβλημα του διακομιστή ή δεν υπάρχει απάντηση", - "Could not post comment: %s": "Δεν ήταν δυνατή η δημοσίευση του σχολίου: %s", - "Sending paste…": "Η επικόλληση αποστέλλεται…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Η επικόλλησή σας είναι %s (Πληκτρολογήστε [Ctrl]+[c] για αντιγραφή)", - "Delete data": "Διαγραφή δεδομένων", - "Could not create paste: %s": "Δεν ήταν δυνατή η δημιουργία επικόλλησης: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Δεν ήταν δυνατή η αποκρυπτογράφηση της επικόλλησης: Το κλειδί αποκρυπτογράφησης λείπει από τον σύνδεσμο (Μήπως χρησιμοποιήσατε ανακατεύθυνση συνδέσμου ή υπηρεσία συντόμευσης συνδέσμου;)", + "Please enter the password for this paste:": "Please enter the password for this paste:", + "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", + "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", + "Reply": "Reply", + "Anonymous": "Anonymous", + "Avatar generated from IP address": "Avatar generated from IP address", + "Add comment": "Add comment", + "Optional nickname…": "Optional nickname…", + "Post comment": "Post comment", + "Sending comment…": "Sending comment…", + "Comment posted.": "Comment posted.", + "Could not refresh display: %s": "Could not refresh display: %s", + "unknown status": "unknown status", + "server error or not responding": "server error or not responding", + "Could not post comment: %s": "Could not post comment: %s", + "Sending paste…": "Sending paste…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", + "Delete data": "Delete data", + "Could not create paste: %s": "Could not create paste: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -139,52 +139,52 @@ "EiB": "EiB", "ZiB": "ZiB", "YiB": "YiB", - "Format": "Μορφοποίηση", - "Plain Text": "Απλό κείμενο", - "Source Code": "Πηγαίος Κώδικας", + "Format": "Format", + "Plain Text": "Plain Text", + "Source Code": "Source Code", "Markdown": "Markdown", - "Download attachment": "Λήψη επισυναπτόμενου", - "Cloned: '%s'": "Κλώνος: '%s'", - "The cloned file '%s' was attached to this paste.": "Το κλωνοποιημένο αρχείο '%s' επισυνάφθηκε στ αυτή την επικόλληση.", - "Attach a file": "Επισύναψη αρχείου", - "alternatively drag & drop a file or paste an image from the clipboard": "εναλλακτικά σύρετε το αρχείο ή επικολλήστε μία εικόνα από το clipboard", - "File too large, to display a preview. Please download the attachment.": "Πολύ μεγάλο αρχείο για προεπισκόπηση. Παρακαλώ κατεβάστε το επισυναπτόμενο.", - "Remove attachment": "Αφαίρεση επισυναπτόμενου", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Ο φυλλομετρητής (browser) σας δεν υποστηρίζει κρυπτογραφημένα αρχεία. Παρακαλώ χρησιμοποιήστε νεότερο φιλομετρητή.", - "Invalid attachment.": "Λάθος επισυναπτόμενο.", - "Options": "Επιλογές", - "Shorten URL": "Συντόμευση σύνδεσμου", - "Editor": "Διορθωτής", - "Preview": "Προεπισκόπηση", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s απαιτεί το PATH να τελειώνει σε \"%s\". Παρακαλώ ενημερώστε το PATH στο index.php σας.", - "Decrypt": "Αποκρυπτογράφηση", - "Enter password": "Εισαγωγή κωδικού", - "Loading…": "Φόρτωση…", - "Decrypting paste…": "Η επικόλληση αποκρυπτογραφείται…", - "Preparing new paste…": "Προετοιμασία νέας επικόλλησης…", - "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "Σε περίπτωση που αυτό το μήνυμα δεν εξαφανίζεται παρακαλώ κοιτάξτε στις Ερωταποκρίσεις για πληροφορίες στην αντιμετώπιση προβλημάτων.", - "+++ no paste text +++": "+++ Δεν υπάρχει επικόλληση +++", - "Could not get paste data: %s": "Δεν ήταν δυνατή η λήψη της επικόλλησης: %s", - "QR code": "QR εικονοστοιχειοσειρά", - "This website is using an insecure HTTP connection! Please use it only for testing.": "Αυτός ο ιστότοπος χρησιμοποιεί μη ασφαλή HTTP σύνδεση! Παρακαλώ χρησιμοποιήστε το μόνο δοκιμαστικά.", - "For more information see this FAQ entry.": "Για περισσότερες πληροφορίες δείτε τις ερωταπαντήσεις.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Ο φυλλομετρητής (browser) σας μπορεί να απαιτεί HTTPS σύνδεση για να υποστηρίξει το WebCrypto API. Δοκιμάστε το HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Ο φυλλομετρητής (browser) σας δεν υποστηρίζει WebAssembly, που χρησιμοποιήθηκε για zlib συμπίεση. Μπορείτε να δημιουργήσετε ασυμπίεστα αρχεία αλλά δεν μπορείτε να διαβάσετε συμπιεσμένα.", - "waiting on user to provide a password": "Αναμονή ο χρήστης να δώσει τον κωδικό", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Δεν ήταν δυνατή η αποκρυπτογράφηση των δεδομένων. Μήπως εισάγατε λάθος κωδικό; Προσπαθήστε με το κουμπί στο επάνω μέρος.", - "Retry": "Επαναπροσπάθεια", - "Showing raw text…": "Προβολή κειμένου…", - "Notice:": "Επισήμανση:", - "This link will expire after %s.": "Ο σύνδεσμος θα λήξει σε %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "Αυτός ο σύνδεσμος μπορεί να προσπελαστεί μόνο μία φορά, μην χρησιμοποιήσετε το κουμπί επιστροφή (back) ή ανανέωση (refresh) στον φυλλομετρητή (browser) σας.", - "Link:": "Σύνδεσμος:", - "Recipient may become aware of your timezone, convert time to UTC?": "Ο παραλήπτης μπορεί να αναγνωρίσει τη ζώνη ώρας σας, θέλετε μετατροπή της ώρας σε UTC;", - "Use Current Timezone": "Χρήση τρέχουσας ζώνης ώρας", - "Convert To UTC": "Μετατροπή σε UTC", - "Close": "Κλείσιμο", - "Encrypted note on PrivateBin": "Κρυπτογραφημένο μήνυμα από το PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφτείτε αυτόν τον σύνδεσμο για να δείτε το μήνυμα. Δίνοντας τον σύνδεσμο σε οποιονδήποτε, του επιτρέπετε να επισκεφτεί το μήνυμα επίσης.", - "URL shortener may expose your decrypt key in URL.": "Συντομευτές συνδέσμων πιθανώς να δημοσιοποιήσουν το κλειδί αποκρυπτογράφισης στον σύνδεσμο.", - "Save paste": "Αποθήκευση επικόλλησης", - "Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις." + "Download attachment": "Download attachment", + "Cloned: '%s'": "Cloned: '%s'", + "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", + "Attach a file": "Attach a file", + "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", + "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", + "Remove attachment": "Remove attachment", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", + "Invalid attachment.": "Invalid attachment.", + "Options": "Options", + "Shorten URL": "Shorten URL", + "Editor": "Editor", + "Preview": "Preview", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", + "Decrypt": "Decrypt", + "Enter password": "Enter password", + "Loading…": "Loading…", + "Decrypting paste…": "Decrypting paste…", + "Preparing new paste…": "Preparing new paste…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", + "+++ no paste text +++": "+++ no paste text +++", + "Could not get paste data: %s": "Could not get paste data: %s", + "QR code": "QR code", + "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", + "For more information see this FAQ entry.": "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", + "waiting on user to provide a password": "waiting on user to provide a password", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Retry": "Retry", + "Showing raw text…": "Showing raw text…", + "Notice:": "Notice:", + "This link will expire after %s.": "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": "Use Current Timezone", + "Convert To UTC": "Convert To UTC", + "Close": "Close", + "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", + "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } From ad6e802e8ac46e45017e3a7df3c805293dd4c7f5 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:30:02 +0200 Subject: [PATCH 055/506] New translations en.json (Greek) --- i18n/el.json | 292 +++++++++++++++++++++++++-------------------------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/i18n/el.json b/i18n/el.json index 8c281e2f..4ad6e505 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -1,135 +1,135 @@ { "PrivateBin": "PrivateBin", - "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s είναι ένα μινιμαλιστικό, ανοικτού κώδικα online pastebin όπου ο διακομιστής έχει μηδενική γνώση της επικόλλησης δεδομένων. Τα δεδομένα κρυπτογραφούνται/αποκρυπτογραφούνται %sστο πρόγραμμα περιήγησης%s χρησιμοποιώντας 256 bits AES.", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s είναι ένα μινιμαλιστικό, ανοικτού κώδικα σύνδεση pastebin όπου ο διακομιστής έχει μηδενική γνώση της επικόλλησης δεδομένων. Τα δεδομένα κρυπτογραφούνται/αποκρυπτογραφούνται %sστο πρόγραμμα περιήγησης%s χρησιμοποιώντας 256 bits AES.", "More information on the project page.": "Περισσότερες πληροφορίες στη σελίδα του έργου.", "Because ignorance is bliss": "Because ignorance is bliss", "en": "el", "Paste does not exist, has expired or has been deleted.": "Η επικόλληση δεν υπάρχει ή έχει διαγραφτεί.", "%s requires php %s or above to work. Sorry.": "%s απαιτεί php %s ή παραπάνω για να λειτουργήσει. Συγνώμη.", - "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", + "%s requires configuration section [%s] to be present in configuration file.": "%s απαιτεί την ενότητα παραμέτρων [%s] για να είναι παρούσα στο αρχείο ρυθμίσεων.", "Please wait %d seconds between each post.": [ - "Παρακαλώ περιμένετε %d δευτερόλεπτο μεταξύ κάθε δημοσίευσης. (ενικό)", - "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε δημοσίευσης. (1ος πλουραλικός)", - "Please wait %d seconds between each post. (2nd plural)", - "Please wait %d seconds between each post. (3rd plural)" + "Παρακαλώ περιμένετε %d δευτερόλεπτο μεταξύ κάθε δημοσίευσης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε δημοσίευσης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε δημοσίευσης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε δημοσίευσης." ], - "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", - "Invalid data.": "Invalid data.", - "You are unlucky. Try again.": "You are unlucky. Try again.", - "Error saving comment. Sorry.": "Error saving comment. Sorry.", - "Error saving paste. Sorry.": "Error saving paste. Sorry.", - "Invalid paste ID.": "Invalid paste ID.", - "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", - "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", - "Paste was properly deleted.": "Paste was properly deleted.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", - "%s requires a modern browser to work.": "%s requires a modern browser to work.", - "New": "New", - "Send": "Send", - "Clone": "Clone", - "Raw text": "Raw text", - "Expires": "Expires", - "Burn after reading": "Burn after reading", - "Open discussion": "Open discussion", - "Password (recommended)": "Password (recommended)", - "Discussion": "Discussion", - "Toggle navigation": "Toggle navigation", + "Paste is limited to %s of encrypted data.": "Η επικόλληση περιορίζεται στο %s των κρυπτογραφημένων δεδομένων.", + "Invalid data.": "Μη έγκυρα δεδομένα.", + "You are unlucky. Try again.": "Είστε άτυχοι. Δοκιμάστε ξανά.", + "Error saving comment. Sorry.": "Σφάλμα κατά την αποθήκευση σχολίου. Λυπούμαστε.", + "Error saving paste. Sorry.": "Σφάλμα κατά την αποθήκευση επικόλλησης. Λυπούμαστε.", + "Invalid paste ID.": "Μη έγκυρη ID επικόλλησης.", + "Paste is not of burn-after-reading type.": "Η επικόλληση δεν είναι τύπου κάψτε-μετά-την-ανάγνωση.", + "Wrong deletion token. Paste was not deleted.": "Λάθος διακριτικό διαγραφής. Η επικόλληση δεν διαγράφηκε.", + "Paste was properly deleted.": "Η επικόλληση διαγράφηκε σωστά.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "Το JavaScript απαιτείται για να δουλέψει το %s. Λυπούμαστε για την ταλαιπωρία.", + "%s requires a modern browser to work.": "%s απαιτεί ένα σύγχρονο πρόγραμμα περιήγησης για να λειτουργήσει.", + "New": "Νέο", + "Send": "Αποστολή", + "Clone": "Αντιγραφή", + "Raw text": "Ακατέργαστο κείμενο", + "Expires": "Λήγει", + "Burn after reading": "Κάψτε μετά την ανάγνωση", + "Open discussion": "Άνοιγμα συζήτησης", + "Password (recommended)": "Κωδικός Πρόσβασης (Προτείνεται)", + "Discussion": "Συζήτηση", + "Toggle navigation": "Εναλλαγή πλοήγησης", "%d seconds": [ - "%d second (singular)", - "%d seconds (1st plural)", - "%d seconds (2nd plural)", - "%d seconds (3rd plural)" + "%d δευτερόλεπτο", + "%d δευτερόλεπτα", + "%d δευτερόλεπτα", + "%d δευτερόλεπτα" ], "%d minutes": [ - "%d minute (singular)", - "%d minutes (1st plural)", - "%d minutes (2nd plural)", - "%d minutes (3rd plural)" + "%d λεπτό", + "%d λεπτά", + "%d λεπτά", + "%d λεπτά" ], "%d hours": [ - "%d hour (singular)", - "%d hours (1st plural)", - "%d hours (2nd plural)", - "%d hours (3rd plural)" + "%d ώρα", + "%d ώρες", + "%d ώρες", + "%d ώρες" ], "%d days": [ - "%d day (singular)", - "%d days (1st plural)", - "%d days (2nd plural)", - "%d days (3rd plural)" + "%d ημέρα", + "%d ημέρες", + "%d ημέρες", + "%d ημέρες" ], "%d weeks": [ - "%d week (singular)", - "%d weeks (1st plural)", - "%d weeks (2nd plural)", - "%d weeks (3rd plural)" + "%d εβδομάδα", + "%d εβδομάδες", + "%d εβδομάδες", + "%d εβδομάδες" ], "%d months": [ - "%d month (singular)", - "%d months (1st plural)", - "%d months (2nd plural)", - "%d months (3rd plural)" + "%d μήνας", + "%d μήνες", + "%d μήνες", + "%d μήνες" ], "%d years": [ - "%d year (singular)", - "%d years (1st plural)", - "%d years (2nd plural)", - "%d years (3rd plural)" + "%d χρόνος", + "%d χρόνια", + "%d χρόνια", + "%d χρόνια" ], - "Never": "Never", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "Never": "Ποτέ", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Σημείωση: Αυτή είναι μια υπηρεσία δοκιμών: Τα δεδομένα μπορούν να διαγραφούν οποτεδήποτε. Γατάκια θα πεθάνουν εάν κάνετε κατάχρηση αυτής της υπηρεσίας.", "This document will expire in %d seconds.": [ - "This document will expire in %d second. (singular)", - "This document will expire in %d seconds. (1st plural)", - "This document will expire in %d seconds. (2nd plural)", - "This document will expire in %d seconds. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτο.", + "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.", + "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.", + "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα." ], "This document will expire in %d minutes.": [ - "This document will expire in %d minute. (singular)", - "This document will expire in %d minutes. (1st plural)", - "This document will expire in %d minutes. (2nd plural)", - "This document will expire in %d minutes. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d λεπτό.", + "Αυτό το έγγραφο θα λήξει σε %d λεπτά.", + "Αυτό το έγγραφο θα λήξει σε %d λεπτά.", + "Αυτό το έγγραφο θα λήξει σε %d λεπτά." ], "This document will expire in %d hours.": [ - "This document will expire in %d hour. (singular)", - "This document will expire in %d hours. (1st plural)", - "This document will expire in %d hours. (2nd plural)", - "This document will expire in %d hours. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d ώρα.", + "Αυτό το έγγραφο θα λήξει σε %d ώρες.", + "Αυτό το έγγραφο θα λήξει σε %d ώρες.", + "Αυτό το έγγραφο θα λήξει σε %d ώρες." ], "This document will expire in %d days.": [ - "This document will expire in %d day. (singular)", - "This document will expire in %d days. (1st plural)", - "This document will expire in %d days. (2nd plural)", - "This document will expire in %d days. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d ημέρα.", + "Αυτό το έγγραφο θα λήξει σε %d ημέρες.", + "Αυτό το έγγραφο θα λήξει σε %d ημέρες.", + "Αυτό το έγγραφο θα λήξει σε %d ημέρες." ], "This document will expire in %d months.": [ - "This document will expire in %d month. (singular)", - "This document will expire in %d months. (1st plural)", - "This document will expire in %d months. (2nd plural)", - "This document will expire in %d months. (3rd plural)" + "Αυτό το έγγραφο θα λήξει σε %d μήνα.", + "Αυτό το έγγραφο θα λήξει σε %d μήνες.", + "Αυτό το έγγραφο θα λήξει σε %d μήνες.", + "Αυτό το έγγραφο θα λήξει σε %d μήνες." ], - "Please enter the password for this paste:": "Please enter the password for this paste:", - "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", - "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", - "Reply": "Reply", - "Anonymous": "Anonymous", - "Avatar generated from IP address": "Avatar generated from IP address", - "Add comment": "Add comment", - "Optional nickname…": "Optional nickname…", - "Post comment": "Post comment", - "Sending comment…": "Sending comment…", - "Comment posted.": "Comment posted.", - "Could not refresh display: %s": "Could not refresh display: %s", - "unknown status": "unknown status", - "server error or not responding": "server error or not responding", - "Could not post comment: %s": "Could not post comment: %s", - "Sending paste…": "Sending paste…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", - "Delete data": "Delete data", - "Could not create paste: %s": "Could not create paste: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "Please enter the password for this paste:": "Παρακαλώ εισάγετε τον κωδικό πρόσβασης για αυτή την επικόλληση:", + "Could not decrypt data (Wrong key?)": "Αδυναμία αποκρυπτογράφησης δεδομένων (Λάθος κλειδί?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Δεν ήταν δυνατή η διαγραφή της επικόλλησης, δεν αποθηκεύτηκε σε λειτουργία καύσιμα μετά το διάβασμα.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ΜΌΝΟ ΓΙΑ ΤΑ ΜΑΤΙΑ ΣΑΣ. Μην κλείσετε αυτό το παράθυρο, αυτό το μήνυμα δεν μπορεί να εμφανιστεί ξανά.", + "Could not decrypt comment; Wrong key?": "Αδυναμία αποκρυπτογράφησης σχολίου. Λάθος κλειδί;", + "Reply": "Απάντηση", + "Anonymous": "Ανώνυμος", + "Avatar generated from IP address": "Το Avatar δημιουργήθηκε από τη διεύθυνση IP", + "Add comment": "Προσθήκη σχολίου", + "Optional nickname…": "Προαιρετικό ψευδώνυμο…", + "Post comment": "Δημοσίευση σχολίου", + "Sending comment…": "Αποστολή σχολίου…", + "Comment posted.": "Το σχόλιο δημοσιεύθηκε.", + "Could not refresh display: %s": "Αδυναμία ανανέωσης της οθόνης: %s", + "unknown status": "άγνωστη κατάσταση", + "server error or not responding": "σφάλμα διακομιστή ή δεν ανταποκρίνεται", + "Could not post comment: %s": "Δεν ήταν δυνατή η δημοσίευση σχολίου: %s", + "Sending paste…": "Αποστολή επικόλλησης…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Η επικόλληση σας είναι %s (Πατήστε [Ctrl]+[c] για αντιγραφή)", + "Delete data": "Διαγραφή δεδομένων", + "Could not create paste: %s": "Δεν ήταν δυνατή η δημιουργία επικόλλησης: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Δεν είναι δυνατή η αποκρυπτογράφηση της επικόλλησης: Το κλειδί αποκρυπτογράφησης λείπει στο URL (Χρησιμοποιείτε έναν αναδιευθυντή ή έναν συντομευτή URL που αφαιρεί μέρος του URL?)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -139,52 +139,52 @@ "EiB": "EiB", "ZiB": "ZiB", "YiB": "YiB", - "Format": "Format", - "Plain Text": "Plain Text", - "Source Code": "Source Code", + "Format": "Μορφή", + "Plain Text": "Απλό Κείμενο", + "Source Code": "Πηγαίος κώδικας", "Markdown": "Markdown", - "Download attachment": "Download attachment", - "Cloned: '%s'": "Cloned: '%s'", - "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", - "Attach a file": "Attach a file", - "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", - "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", - "Remove attachment": "Remove attachment", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", - "Invalid attachment.": "Invalid attachment.", - "Options": "Options", - "Shorten URL": "Shorten URL", - "Editor": "Editor", - "Preview": "Preview", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", - "Decrypt": "Decrypt", - "Enter password": "Enter password", - "Loading…": "Loading…", - "Decrypting paste…": "Decrypting paste…", - "Preparing new paste…": "Preparing new paste…", - "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", - "+++ no paste text +++": "+++ no paste text +++", - "Could not get paste data: %s": "Could not get paste data: %s", - "QR code": "QR code", - "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", - "For more information see this FAQ entry.": "For more information see this FAQ entry.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", - "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", - "Retry": "Retry", - "Showing raw text…": "Showing raw text…", - "Notice:": "Notice:", - "This link will expire after %s.": "This link will expire after %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", - "Link:": "Link:", - "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", - "Use Current Timezone": "Use Current Timezone", - "Convert To UTC": "Convert To UTC", - "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", - "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Download attachment": "Λήψη συννημένου", + "Cloned: '%s'": "Κλωνοποιήθηκε: '%s'", + "The cloned file '%s' was attached to this paste.": "Το κλωνοποιημένο αρχείο '%s' συνδέθηκε σε αυτήν την επικόλληση.", + "Attach a file": "Επισύναψη αρχείου", + "alternatively drag & drop a file or paste an image from the clipboard": "εναλλακτικά σύρετε & αφήστε ένα αρχείο ή επικολλήστε μια εικόνα από το πρόχειρο", + "File too large, to display a preview. Please download the attachment.": "Το αρχείο είναι πολύ μεγάλο, για προβολή. Παρακαλώ κατεβάστε το συνημμένο.", + "Remove attachment": "Αφαίρεση συνημμένου", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Το πρόγραμμα περιήγησής σας δεν υποστηρίζει τη μεταφόρτωση κρυπτογραφημένων αρχείων. Παρακαλούμε χρησιμοποιήστε ένα νεότερο πρόγραμμα περιήγησης.", + "Invalid attachment.": "Μη έγκυρο συνημμένο.", + "Options": "Ρυθμίσεις", + "Shorten URL": "Συντόμευση URL", + "Editor": "Επεξεργαστής", + "Preview": "Προεπισκόπηση", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s απαιτεί το PATH να τελειώσει σε \"%s\". Παρακαλούμε ενημερώστε το PATH στο index.php.", + "Decrypt": "Αποκρυπτογράφηση", + "Enter password": "Εισάγετε κωδικό πρόσβασης", + "Loading…": "Φόρτωση…", + "Decrypting paste…": "Αποκρυπτογράφηση επικόλλησης…", + "Preparing new paste…": "Προετοιμασία νέας επικόλλησης…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "Σε περίπτωση που αυτό το μήνυμα δεν εξαφανιστεί ποτέ παρακαλούμε ρίξτε μια ματιά στο FAQ για πληροφορίες για την αντιμετώπιση προβλημάτων.", + "+++ no paste text +++": "+++ κανένα κείμενο επικόλλησης +++", + "Could not get paste data: %s": "Δεν ήταν δυνατή η λήψη δεδομένων επικόλλησης: %s", + "QR code": "Κωδικός QR", + "This website is using an insecure HTTP connection! Please use it only for testing.": "Αυτή η ιστοσελίδα χρησιμοποιεί μια επισφαλή σύνδεση HTTP! Παρακαλούμε χρησιμοποιήστε την μόνο για δοκιμή.", + "For more information see this FAQ entry.": "Για περισσότερες πληροφορίες ανατρέξτε στην παρακάτω καταχώρηση FAQ.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Ο περιηγητής σας μπορεί να απαιτήσει μια σύνδεση HTTPS για την υποστήριξη του WebCrypto API. Δοκιμάστε να αλλάξετε σε HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Ο περιηγητής σας δεν υποστηρίζει WebAssembly, χρησιμοποιείται για τη συμπίεση zlib. Μπορείτε να δημιουργήσετε ασυμπίεστα έγγραφα, αλλά δεν μπορείτε να διαβάσετε συμπιεσμένα έγγραφα.", + "waiting on user to provide a password": "αναμονή για το χρήστη για να παρέχει έναν κωδικό πρόσβασης", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Δεν ήταν δυνατή η αποκρυπτογράφηση δεδομένων. Μήπως εισάγετε λάθος κωδικό? Δοκιμάστε ξανά με το κουμπί στην κορυφή.", + "Retry": "Επανάληψη", + "Showing raw text…": "Εμφάνιση ακατέργαστου κειμένου…", + "Notice:": "Προσοχή:", + "This link will expire after %s.": "Αυτός ο σύνδεσμος θα λήξει μετά από %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Αυτός ο σύνδεσμος μπορεί να προσπελαστεί μόνο μία φορά, μην χρησιμοποιήσετε το κουμπί επιστροφής ή ανανέωσης στον περιηγητή σας.", + "Link:": "Σύνδεσμος:", + "Recipient may become aware of your timezone, convert time to UTC?": "Ο Παραλήπτης μπορεί να ενημερωθεί για την ζώνη ώρας σας, μετατρέψετε την ώρα σε UTC;", + "Use Current Timezone": "Χρήση Τρέχουσας Ζώνης Ώρας", + "Convert To UTC": "Μετατροπή Σε UTC", + "Close": "Κλείσιμο", + "Encrypted note on PrivateBin": "Κρυπτογραφημένη σημείωση στο PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφθείτε αυτό το σύνδεσμο για να δείτε τη σημείωση. Αν δώσετε τη διεύθυνση URL σε οποιονδήποτε τους επιτρέπει να έχουν πρόσβαση και στη σημείωση.", + "URL shortener may expose your decrypt key in URL.": "Το URL shortener μπορεί να εκθέσει το κλειδί αποκρυπτογράφησης σας στο URL.", + "Save paste": "Αποθήκευση επικόλλησης", + "Your IP is not authorized to create pastes.": "Η IP σας δεν είναι εξουσιοδοτημένη να δημιουργεί επικολλήσεις." } From 8dded4e8e40ef7414d6bc467f91230f2fd87bca5 Mon Sep 17 00:00:00 2001 From: Ra'Jiska Date: Thu, 6 Oct 2022 12:19:06 +0800 Subject: [PATCH 056/506] GCS Support for Uniform ACL Buckets --- cfg/conf.sample.php | 1 + lib/Configuration.php | 5 +++-- lib/Data/GoogleCloudStorage.php | 37 ++++++++++++++++++++++----------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index 3c7f4625..ab37da7b 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -175,6 +175,7 @@ dir = PATH "data" ;[model_options] ;bucket = "my-private-bin" ;prefix = "pastes" +;uniformacl = false ;[model] ; example of DB configuration for MySQL diff --git a/lib/Configuration.php b/lib/Configuration.php index 56e55adb..9f4e35f7 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -153,8 +153,9 @@ class Configuration ) ) { $values = array( - 'bucket' => getenv('PRIVATEBIN_GCS_BUCKET') ? getenv('PRIVATEBIN_GCS_BUCKET') : null, - 'prefix' => 'pastes', + 'bucket' => getenv('PRIVATEBIN_GCS_BUCKET') ? getenv('PRIVATEBIN_GCS_BUCKET') : null, + 'prefix' => 'pastes', + 'uniformacl' => false, ); } diff --git a/lib/Data/GoogleCloudStorage.php b/lib/Data/GoogleCloudStorage.php index 2e8e2c5d..1f11a6ef 100644 --- a/lib/Data/GoogleCloudStorage.php +++ b/lib/Data/GoogleCloudStorage.php @@ -37,6 +37,15 @@ class GoogleCloudStorage extends AbstractData */ private static $_prefix = 'pastes'; + /** + * bucket acl type + * + * @access private + * @static + * @var bool + */ + private static $_uniformacl = false; + /** * returns a Google Cloud Storage data backend. * @@ -62,6 +71,9 @@ class GoogleCloudStorage extends AbstractData if (is_array($options) && array_key_exists('prefix', $options)) { self::$_prefix = $options['prefix']; } + if (is_array($options) && array_key_exists('uniformacl', $options)) { + self::$_uniformacl = $options['uniformacl']; + } if (empty(self::$_client)) { self::$_client = class_exists('StorageClientStub', false) ? @@ -100,21 +112,19 @@ class GoogleCloudStorage extends AbstractData */ private function _upload($key, $payload) { - $metadata = array_key_exists('meta', $payload) ? $payload['meta'] : array(); - unset($metadata['attachment'], $metadata['attachmentname'], $metadata['salt']); - foreach ($metadata as $k => $v) { - $metadata[$k] = strval($v); - } try { - self::$_bucket->upload(Json::encode($payload), array( + $data = array( 'name' => $key, 'chunkSize' => 262144, - 'predefinedAcl' => 'private', 'metadata' => array( 'content-type' => 'application/json', - 'metadata' => $metadata, + 'metadata' => $payload, ), - )); + ); + if (!self::$_uniformacl) { + $data['predefinedAcl'] = 'private'; + } + self::$_bucket->upload(Json::encode($payload), $data); } catch (Exception $e) { error_log('failed to upload ' . $key . ' to ' . self::$_bucket->name() . ', ' . trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); @@ -277,15 +287,18 @@ class GoogleCloudStorage extends AbstractData $metadata['value'] = strval($value); } try { - self::$_bucket->upload($value, array( + $data = array( 'name' => $key, 'chunkSize' => 262144, - 'predefinedAcl' => 'private', 'metadata' => array( 'content-type' => 'application/json', 'metadata' => $metadata, ), - )); + ); + if (!self::$_uniformacl) { + $data['predefinedAcl'] = 'private'; + } + self::$_bucket->upload($value, $data); } catch (Exception $e) { error_log('failed to set key ' . $key . ' to ' . self::$_bucket->name() . ', ' . trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); From 1aa93f7fb29edc3393f3e4b80e24c4d02397ecda Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Thu, 6 Oct 2022 08:30:58 +0200 Subject: [PATCH 057/506] New translations en.json (Slovak) --- i18n/sk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/sk.json b/i18n/sk.json index f1815da3..cdd0ea4c 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -156,7 +156,7 @@ "Shorten URL": "Skrátiť URL", "Editor": "Editor", "Preview": "Náhľad", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH končila na \"%s\". Aktualizujte prosím PATH vo svojom index.php.", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH končila na „%s\". Aktualizujte prosím PATH vo svojom index.php.", "Decrypt": "Dešifrovať", "Enter password": "Zadajte heslo", "Loading…": "Načítava sa…", From 23e0000101717f9cdc6ca56f93372cf25e514983 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Thu, 6 Oct 2022 08:30:59 +0200 Subject: [PATCH 058/506] New translations en.json (Greek) --- i18n/el.json | 166 +++++++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/i18n/el.json b/i18n/el.json index 4ad6e505..15df67be 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -1,37 +1,37 @@ { "PrivateBin": "PrivateBin", - "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s είναι ένα μινιμαλιστικό, ανοικτού κώδικα σύνδεση pastebin όπου ο διακομιστής έχει μηδενική γνώση της επικόλλησης δεδομένων. Τα δεδομένα κρυπτογραφούνται/αποκρυπτογραφούνται %sστο πρόγραμμα περιήγησης%s χρησιμοποιώντας 256 bits AES.", - "More information on the project page.": "Περισσότερες πληροφορίες στη σελίδα του έργου.", - "Because ignorance is bliss": "Because ignorance is bliss", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s είναι ένα λιτό, ανοικτού λογισμικού διαδικτυακής υπηρεσίας επικόλλησης όπου ο διακομιστής έχει πλήρη άγνια του περιεχομένου που επικολλήθηκαν. Τα Δεδομένα κρυπτογραφούνται και αποκρυπτογραφούνται %sστον φιλομετρητή (browser)%s χρησιμοποιόντας 256 bits AES.", + "More information on the project page.": "Περισσότερες πληροφορίες στον ιστότοπο του εργαλείου.", + "Because ignorance is bliss": "Επειδή η άγνοια είναι ευτυχία", "en": "el", - "Paste does not exist, has expired or has been deleted.": "Η επικόλληση δεν υπάρχει ή έχει διαγραφτεί.", - "%s requires php %s or above to work. Sorry.": "%s απαιτεί php %s ή παραπάνω για να λειτουργήσει. Συγνώμη.", - "%s requires configuration section [%s] to be present in configuration file.": "%s απαιτεί την ενότητα παραμέτρων [%s] για να είναι παρούσα στο αρχείο ρυθμίσεων.", + "Paste does not exist, has expired or has been deleted.": "Η επικόλληση δεν υπάρχει, έληξε ή διαγράφηκε", + "%s requires php %s or above to work. Sorry.": "%s απαιτεί php %s ή νεότερη για να λειτουργήσει. Συγγνώμη.", + "%s requires configuration section [%s] to be present in configuration file.": "%s απαιτεί οι ρυθμίσεις [%s] να υπάρχουν στο αρχείο ρυθμίσεων.", "Please wait %d seconds between each post.": [ - "Παρακαλώ περιμένετε %d δευτερόλεπτο μεταξύ κάθε δημοσίευσης.", - "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε δημοσίευσης.", - "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε δημοσίευσης.", - "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε δημοσίευσης." + "Παρακαλώ περιμένετε %d δευτερόλεπτο μεταξύ κάθε επικόλλησης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης.", + "Παρακαλώ περιμένετε %d δευτερόλεπτα μεταξύ κάθε επικόλλησης." ], - "Paste is limited to %s of encrypted data.": "Η επικόλληση περιορίζεται στο %s των κρυπτογραφημένων δεδομένων.", - "Invalid data.": "Μη έγκυρα δεδομένα.", - "You are unlucky. Try again.": "Είστε άτυχοι. Δοκιμάστε ξανά.", - "Error saving comment. Sorry.": "Σφάλμα κατά την αποθήκευση σχολίου. Λυπούμαστε.", - "Error saving paste. Sorry.": "Σφάλμα κατά την αποθήκευση επικόλλησης. Λυπούμαστε.", - "Invalid paste ID.": "Μη έγκυρη ID επικόλλησης.", - "Paste is not of burn-after-reading type.": "Η επικόλληση δεν είναι τύπου κάψτε-μετά-την-ανάγνωση.", - "Wrong deletion token. Paste was not deleted.": "Λάθος διακριτικό διαγραφής. Η επικόλληση δεν διαγράφηκε.", - "Paste was properly deleted.": "Η επικόλληση διαγράφηκε σωστά.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "Το JavaScript απαιτείται για να δουλέψει το %s. Λυπούμαστε για την ταλαιπωρία.", - "%s requires a modern browser to work.": "%s απαιτεί ένα σύγχρονο πρόγραμμα περιήγησης για να λειτουργήσει.", + "Paste is limited to %s of encrypted data.": "Η επικόλληση είναι περιορισμένη σε %s κρυπτογραφημένων δεδομένων.", + "Invalid data.": "Λάθος δεδομένα.", + "You are unlucky. Try again.": "Ατυχήσατε. Προσπαθήστε πάλι.", + "Error saving comment. Sorry.": "Λάθος στην αποθήκευση του σχόλιου. Συγγνώμη.", + "Error saving paste. Sorry.": "Λάθος στην αποθήκευση της επικόλλησης. Συγγνώμη.", + "Invalid paste ID.": "Λάθος αναγνωριστικό επικόλλησης.", + "Paste is not of burn-after-reading type.": "Η επικόληση δεν είναι τύπου καταστροφή-μετά-το-διάβασμα.", + "Wrong deletion token. Paste was not deleted.": "Λάθος αναγνωριστικό διαγραφής. Η επικόλληση δεν διαγράφηκε.", + "Paste was properly deleted.": "Η επικόλληση διαγράφηκε επιτυχώς.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "Η JavaScript είναι απαραίτητη για να λειτουργήσει το %s. Συγγνώμη για την ταλαιπωρία.", + "%s requires a modern browser to work.": "%s απαιτεί σύγχρονο φυλλομετρητή (browser) για να λειτουργήσει.", "New": "Νέο", "Send": "Αποστολή", - "Clone": "Αντιγραφή", - "Raw text": "Ακατέργαστο κείμενο", + "Clone": "Κλωνοποίηση", + "Raw text": "Κείμενο", "Expires": "Λήγει", - "Burn after reading": "Κάψτε μετά την ανάγνωση", - "Open discussion": "Άνοιγμα συζήτησης", - "Password (recommended)": "Κωδικός Πρόσβασης (Προτείνεται)", + "Burn after reading": "Διαγραφή μετά την ανάγνωση", + "Open discussion": "Ανοικτή συζήτηση", + "Password (recommended)": "Κωδικός (προτείνεται)", "Discussion": "Συζήτηση", "Toggle navigation": "Εναλλαγή πλοήγησης", "%d seconds": [ @@ -71,13 +71,13 @@ "%d μήνες" ], "%d years": [ - "%d χρόνος", + "%d χρόνο", "%d χρόνια", "%d χρόνια", "%d χρόνια" ], "Never": "Ποτέ", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Σημείωση: Αυτή είναι μια υπηρεσία δοκιμών: Τα δεδομένα μπορούν να διαγραφούν οποτεδήποτε. Γατάκια θα πεθάνουν εάν κάνετε κατάχρηση αυτής της υπηρεσίας.", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Σημείωση: αυτή είναι μία δοκιμαστική υπηρεσία. Τα δεδομένα μπορεί να σβηστούν ανά πάσα στιγμή.", "This document will expire in %d seconds.": [ "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτο.", "Αυτό το έγγραφο θα λήξει σε %d δευτερόλεπτα.", @@ -108,28 +108,28 @@ "Αυτό το έγγραφο θα λήξει σε %d μήνες.", "Αυτό το έγγραφο θα λήξει σε %d μήνες." ], - "Please enter the password for this paste:": "Παρακαλώ εισάγετε τον κωδικό πρόσβασης για αυτή την επικόλληση:", - "Could not decrypt data (Wrong key?)": "Αδυναμία αποκρυπτογράφησης δεδομένων (Λάθος κλειδί?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Δεν ήταν δυνατή η διαγραφή της επικόλλησης, δεν αποθηκεύτηκε σε λειτουργία καύσιμα μετά το διάβασμα.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ΜΌΝΟ ΓΙΑ ΤΑ ΜΑΤΙΑ ΣΑΣ. Μην κλείσετε αυτό το παράθυρο, αυτό το μήνυμα δεν μπορεί να εμφανιστεί ξανά.", - "Could not decrypt comment; Wrong key?": "Αδυναμία αποκρυπτογράφησης σχολίου. Λάθος κλειδί;", + "Please enter the password for this paste:": "Παρακαλώ εισάγετε τον κωδικό για αυτή την επικόληση:", + "Could not decrypt data (Wrong key?)": "Δεν ήταν δυνατή η αποκρυπτογράφηση των δεδομένων (πιθανώς λανθασμένο κλειδί;)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Δεν ήταν δυνατή η διαγραφή της επικόλλησης, δεν ήταν αποθηκευμένη σε μορφή διαγραφής μετά την ανάγνωση.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "ΜΟΝΟ ΓΙΑ ΕΣΑΣ. Μην κλείσετε το αυτό το παράθυρο, αυτό το μήνυμα δεν μπορεί να εμφανιστεί ξανά.", + "Could not decrypt comment; Wrong key?": "Δεν ήταν δυνατή η αποκρυπτογράφηση του σχολίου. Λάθος κλειδί;", "Reply": "Απάντηση", "Anonymous": "Ανώνυμος", - "Avatar generated from IP address": "Το Avatar δημιουργήθηκε από τη διεύθυνση IP", - "Add comment": "Προσθήκη σχολίου", + "Avatar generated from IP address": "το avatar δημιουργήθηκε από τη διεύθυνση IP", + "Add comment": "Σχολιάστε", "Optional nickname…": "Προαιρετικό ψευδώνυμο…", - "Post comment": "Δημοσίευση σχολίου", - "Sending comment…": "Αποστολή σχολίου…", - "Comment posted.": "Το σχόλιο δημοσιεύθηκε.", - "Could not refresh display: %s": "Αδυναμία ανανέωσης της οθόνης: %s", + "Post comment": "Αποστολή σχολίου", + "Sending comment…": "Το σχόλιο αποστέλλεται…", + "Comment posted.": "Το σχόλιο δημοσιεύτηκε.", + "Could not refresh display: %s": "Δεν ήταν δυνατή η ανανέωση της σελίδας: %s", "unknown status": "άγνωστη κατάσταση", - "server error or not responding": "σφάλμα διακομιστή ή δεν ανταποκρίνεται", - "Could not post comment: %s": "Δεν ήταν δυνατή η δημοσίευση σχολίου: %s", - "Sending paste…": "Αποστολή επικόλλησης…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Η επικόλληση σας είναι %s (Πατήστε [Ctrl]+[c] για αντιγραφή)", + "server error or not responding": "Πρόβλημα του διακομιστή ή δεν υπάρχει απάντηση", + "Could not post comment: %s": "Δεν ήταν δυνατή η δημοσίευση του σχολίου: %s", + "Sending paste…": "Η επικόλληση αποστέλλεται…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Η επικόλλησή σας είναι %s (Πληκτρολογήστε [Ctrl]+[c] για αντιγραφή)", "Delete data": "Διαγραφή δεδομένων", "Could not create paste: %s": "Δεν ήταν δυνατή η δημιουργία επικόλλησης: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Δεν είναι δυνατή η αποκρυπτογράφηση της επικόλλησης: Το κλειδί αποκρυπτογράφησης λείπει στο URL (Χρησιμοποιείτε έναν αναδιευθυντή ή έναν συντομευτή URL που αφαιρεί μέρος του URL?)", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Δεν ήταν δυνατή η αποκρυπτογράφηση της επικόλλησης: Το κλειδί αποκρυπτογράφησης λείπει από τον σύνδεσμο (Μήπως χρησιμοποιήσατε ανακατεύθυνση συνδέσμου ή υπηρεσία συντόμευσης συνδέσμου;)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -139,52 +139,52 @@ "EiB": "EiB", "ZiB": "ZiB", "YiB": "YiB", - "Format": "Μορφή", - "Plain Text": "Απλό Κείμενο", - "Source Code": "Πηγαίος κώδικας", + "Format": "Μορφοποίηση", + "Plain Text": "Απλό κείμενο", + "Source Code": "Πηγαίος Κώδικας", "Markdown": "Markdown", - "Download attachment": "Λήψη συννημένου", - "Cloned: '%s'": "Κλωνοποιήθηκε: '%s'", - "The cloned file '%s' was attached to this paste.": "Το κλωνοποιημένο αρχείο '%s' συνδέθηκε σε αυτήν την επικόλληση.", + "Download attachment": "Λήψη επισυναπτόμενου", + "Cloned: '%s'": "Κλώνος: '%s'", + "The cloned file '%s' was attached to this paste.": "Το κλωνοποιημένο αρχείο '%s' επισυνάφθηκε στ αυτή την επικόλληση.", "Attach a file": "Επισύναψη αρχείου", - "alternatively drag & drop a file or paste an image from the clipboard": "εναλλακτικά σύρετε & αφήστε ένα αρχείο ή επικολλήστε μια εικόνα από το πρόχειρο", - "File too large, to display a preview. Please download the attachment.": "Το αρχείο είναι πολύ μεγάλο, για προβολή. Παρακαλώ κατεβάστε το συνημμένο.", - "Remove attachment": "Αφαίρεση συνημμένου", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Το πρόγραμμα περιήγησής σας δεν υποστηρίζει τη μεταφόρτωση κρυπτογραφημένων αρχείων. Παρακαλούμε χρησιμοποιήστε ένα νεότερο πρόγραμμα περιήγησης.", - "Invalid attachment.": "Μη έγκυρο συνημμένο.", - "Options": "Ρυθμίσεις", - "Shorten URL": "Συντόμευση URL", - "Editor": "Επεξεργαστής", + "alternatively drag & drop a file or paste an image from the clipboard": "εναλλακτικά σύρετε το αρχείο ή επικολλήστε μία εικόνα από το clipboard", + "File too large, to display a preview. Please download the attachment.": "Πολύ μεγάλο αρχείο για προεπισκόπηση. Παρακαλώ κατεβάστε το επισυναπτόμενο.", + "Remove attachment": "Αφαίρεση επισυναπτόμενου", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Ο φυλλομετρητής (browser) σας δεν υποστηρίζει κρυπτογραφημένα αρχεία. Παρακαλώ χρησιμοποιήστε νεότερο φιλομετρητή.", + "Invalid attachment.": "Λάθος επισυναπτόμενο.", + "Options": "Επιλογές", + "Shorten URL": "Συντόμευση σύνδεσμου", + "Editor": "Διορθωτής", "Preview": "Προεπισκόπηση", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s απαιτεί το PATH να τελειώσει σε \"%s\". Παρακαλούμε ενημερώστε το PATH στο index.php.", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s απαιτεί το PATH να τελειώνει σε \"%s\". Παρακαλώ ενημερώστε το PATH στο index.php σας.", "Decrypt": "Αποκρυπτογράφηση", - "Enter password": "Εισάγετε κωδικό πρόσβασης", + "Enter password": "Εισαγωγή κωδικού", "Loading…": "Φόρτωση…", - "Decrypting paste…": "Αποκρυπτογράφηση επικόλλησης…", + "Decrypting paste…": "Η επικόλληση αποκρυπτογραφείται…", "Preparing new paste…": "Προετοιμασία νέας επικόλλησης…", - "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "Σε περίπτωση που αυτό το μήνυμα δεν εξαφανιστεί ποτέ παρακαλούμε ρίξτε μια ματιά στο FAQ για πληροφορίες για την αντιμετώπιση προβλημάτων.", - "+++ no paste text +++": "+++ κανένα κείμενο επικόλλησης +++", - "Could not get paste data: %s": "Δεν ήταν δυνατή η λήψη δεδομένων επικόλλησης: %s", - "QR code": "Κωδικός QR", - "This website is using an insecure HTTP connection! Please use it only for testing.": "Αυτή η ιστοσελίδα χρησιμοποιεί μια επισφαλή σύνδεση HTTP! Παρακαλούμε χρησιμοποιήστε την μόνο για δοκιμή.", - "For more information see this FAQ entry.": "Για περισσότερες πληροφορίες ανατρέξτε στην παρακάτω καταχώρηση FAQ.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Ο περιηγητής σας μπορεί να απαιτήσει μια σύνδεση HTTPS για την υποστήριξη του WebCrypto API. Δοκιμάστε να αλλάξετε σε HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Ο περιηγητής σας δεν υποστηρίζει WebAssembly, χρησιμοποιείται για τη συμπίεση zlib. Μπορείτε να δημιουργήσετε ασυμπίεστα έγγραφα, αλλά δεν μπορείτε να διαβάσετε συμπιεσμένα έγγραφα.", - "waiting on user to provide a password": "αναμονή για το χρήστη για να παρέχει έναν κωδικό πρόσβασης", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Δεν ήταν δυνατή η αποκρυπτογράφηση δεδομένων. Μήπως εισάγετε λάθος κωδικό? Δοκιμάστε ξανά με το κουμπί στην κορυφή.", - "Retry": "Επανάληψη", - "Showing raw text…": "Εμφάνιση ακατέργαστου κειμένου…", - "Notice:": "Προσοχή:", - "This link will expire after %s.": "Αυτός ο σύνδεσμος θα λήξει μετά από %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "Αυτός ο σύνδεσμος μπορεί να προσπελαστεί μόνο μία φορά, μην χρησιμοποιήσετε το κουμπί επιστροφής ή ανανέωσης στον περιηγητή σας.", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "Σε περίπτωση που αυτό το μήνυμα δεν εξαφανίζεται παρακαλώ κοιτάξτε στις Ερωταποκρίσεις για πληροφορίες στην αντιμετώπιση προβλημάτων.", + "+++ no paste text +++": "+++ Δεν υπάρχει επικόλληση +++", + "Could not get paste data: %s": "Δεν ήταν δυνατή η λήψη της επικόλλησης: %s", + "QR code": "QR εικονοστοιχειοσειρά", + "This website is using an insecure HTTP connection! Please use it only for testing.": "Αυτός ο ιστότοπος χρησιμοποιεί μη ασφαλή HTTP σύνδεση! Παρακαλώ χρησιμοποιήστε το μόνο δοκιμαστικά.", + "For more information see this FAQ entry.": "Για περισσότερες πληροφορίες δείτε τις ερωταπαντήσεις.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Ο φυλλομετρητής σας μπορεί να απαιτεί HTTPS σύνδεση για να υποστηρίξει το WebCrypto API. Δοκιμάστε το HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Ο φυλλομετρητής σας δεν υποστηρίζει WebAssembly, που χρησιμοποιήθηκε για zlib συμπίεση. Μπορείτε να δημιουργήσετε ασυμπίεστα αρχεία αλλά δεν μπορείτε να διαβάσετε συμπιεσμένα.", + "waiting on user to provide a password": "Αναμονή ο χρήστης να δώσει τον κωδικό", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Δεν ήταν δυνατή η αποκρυπτογράφηση των δεδομένων. Μήπως εισάγατε λάθος κωδικό; Προσπαθήστε με το κουμπί στο επάνω μέρος.", + "Retry": "Επαναπροσπάθεια", + "Showing raw text…": "Προβολή κειμένου…", + "Notice:": "Επισήμανση:", + "This link will expire after %s.": "Ο σύνδεσμος θα λήξει σε %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "Αυτός ο σύνδεσμος μπορεί να προσπελαστεί μόνο μία φορά, μην χρησιμοποιήσετε το κουμπί επιστροφή ή ανανέωση στον φυλλομετρητή σας.", "Link:": "Σύνδεσμος:", - "Recipient may become aware of your timezone, convert time to UTC?": "Ο Παραλήπτης μπορεί να ενημερωθεί για την ζώνη ώρας σας, μετατρέψετε την ώρα σε UTC;", - "Use Current Timezone": "Χρήση Τρέχουσας Ζώνης Ώρας", - "Convert To UTC": "Μετατροπή Σε UTC", + "Recipient may become aware of your timezone, convert time to UTC?": "Ο παραλήπτης μπορεί να αναγνωρίσει τη ζώνη ώρας σας, θέλετε μετατροπή της ώρας σε UTC;", + "Use Current Timezone": "Χρήση τρέχουσας ζώνης ώρας", + "Convert To UTC": "Μετατροπή σε UTC", "Close": "Κλείσιμο", - "Encrypted note on PrivateBin": "Κρυπτογραφημένη σημείωση στο PrivateBin", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφθείτε αυτό το σύνδεσμο για να δείτε τη σημείωση. Αν δώσετε τη διεύθυνση URL σε οποιονδήποτε τους επιτρέπει να έχουν πρόσβαση και στη σημείωση.", - "URL shortener may expose your decrypt key in URL.": "Το URL shortener μπορεί να εκθέσει το κλειδί αποκρυπτογράφησης σας στο URL.", + "Encrypted note on PrivateBin": "Κρυπτογραφημένο μήνυμα από το PrivateBin", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφτείτε αυτόν τον σύνδεσμο για να δείτε το μήνυμα. Δίνοντας τον σύνδεσμο σε οποιονδήποτε, του επιτρέπετε να επισκεφτεί το μήνυμα επίσης.", + "URL shortener may expose your decrypt key in URL.": "Συντομευτές συνδέσμων πιθανώς να δημοσιοποιήσουν το κλειδί αποκρυπτογράφισης στον σύνδεσμο.", "Save paste": "Αποθήκευση επικόλλησης", - "Your IP is not authorized to create pastes.": "Η IP σας δεν είναι εξουσιοδοτημένη να δημιουργεί επικολλήσεις." + "Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις." } From 8dbe60621de10d36befb3a3dda859dab31ede5f2 Mon Sep 17 00:00:00 2001 From: Ra'Jiska Date: Thu, 6 Oct 2022 14:41:37 +0800 Subject: [PATCH 059/506] Fix GCS Upload Metadata Mistake --- lib/Data/GoogleCloudStorage.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/Data/GoogleCloudStorage.php b/lib/Data/GoogleCloudStorage.php index 1f11a6ef..e8763258 100644 --- a/lib/Data/GoogleCloudStorage.php +++ b/lib/Data/GoogleCloudStorage.php @@ -112,13 +112,18 @@ class GoogleCloudStorage extends AbstractData */ private function _upload($key, $payload) { + $metadata = array_key_exists('meta', $payload) ? $payload['meta'] : array(); + unset($metadata['attachment'], $metadata['attachmentname'], $metadata['salt']); + foreach ($metadata as $k => $v) { + $metadata[$k] = strval($v); + } try { $data = array( 'name' => $key, 'chunkSize' => 262144, 'metadata' => array( 'content-type' => 'application/json', - 'metadata' => $payload, + 'metadata' => $metadata, ), ); if (!self::$_uniformacl) { From 38245287d03e7b2a91350a772166dc3a13c7960a Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Fri, 7 Oct 2022 07:11:45 +0200 Subject: [PATCH 060/506] New translations en.json (Slovak) --- i18n/sk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/sk.json b/i18n/sk.json index cdd0ea4c..f1815da3 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -156,7 +156,7 @@ "Shorten URL": "Skrátiť URL", "Editor": "Editor", "Preview": "Náhľad", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH končila na „%s\". Aktualizujte prosím PATH vo svojom index.php.", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s vyžaduje, aby PATH končila na \"%s\". Aktualizujte prosím PATH vo svojom index.php.", "Decrypt": "Dešifrovať", "Enter password": "Zadajte heslo", "Loading…": "Načítava sa…", From 08b60703599796385b714c955ca5e8ccad8f1b4b Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 15 Oct 2022 09:05:19 +0200 Subject: [PATCH 061/506] update zlib to 1.2.13 --- CHANGELOG.md | 1 + js/common.js | 2 +- js/{zlib-1.2.12.js => zlib-1.2.13.js} | 4 ++-- js/{zlib-1.2.12.wasm => zlib-1.2.13.wasm} | Bin 58814 -> 58828 bytes tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 6 files changed, 6 insertions(+), 5 deletions(-) rename js/{zlib-1.2.12.js => zlib-1.2.13.js} (97%) rename js/{zlib-1.2.12.wasm => zlib-1.2.13.wasm} (88%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15bb1b1f..c42e7960 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) * FIXED: Apply table prefix to indexes as well, to support multiple instances sharing a single database (#943) + * CHANGED: Upgrading libraries to: zlib 1.2.13 * **1.4 (2022-04-09)** * ADDED: Translations for Corsican, Estonian, Finnish and Lojban * ADDED: new HTTP headers improving security (#765) diff --git a/js/common.js b/js/common.js index 7a68c7ed..12e4c882 100644 --- a/js/common.js +++ b/js/common.js @@ -12,7 +12,7 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto; // application libraries to test global.$ = global.jQuery = require('./jquery-3.6.0'); global.RawDeflate = require('./rawinflate-0.3').RawDeflate; -global.zlib = require('./zlib-1.2.12').zlib; +global.zlib = require('./zlib-1.2.13').zlib; require('./prettify'); global.prettyPrint = window.PR.prettyPrint; global.prettyPrintOne = window.PR.prettyPrintOne; diff --git a/js/zlib-1.2.12.js b/js/zlib-1.2.13.js similarity index 97% rename from js/zlib-1.2.12.js rename to js/zlib-1.2.13.js index a245608f..809ce0cd 100644 --- a/js/zlib-1.2.12.js +++ b/js/zlib-1.2.13.js @@ -26,9 +26,9 @@ let buff; if (typeof fetch === 'undefined') { - buff = fs.readFileSync('zlib-1.2.12.wasm'); + buff = fs.readFileSync('zlib-1.2.13.wasm'); } else { - const resp = await fetch('js/zlib-1.2.12.wasm'); + const resp = await fetch('js/zlib-1.2.13.wasm'); buff = await resp.arrayBuffer(); } const module = await WebAssembly.compile(buff); diff --git a/js/zlib-1.2.12.wasm b/js/zlib-1.2.13.wasm similarity index 88% rename from js/zlib-1.2.12.wasm rename to js/zlib-1.2.13.wasm index 0b86cf5d88f5b2ea31337ec4f4c3274576b6e9f0..145060df799555df0311644a0e00801b00a803ed 100644 GIT binary patch delta 2340 zcma)8U2IfE6yBM;-M>3?d$-%(UE4~}T-&;Zh*AL?Frh=-La2qrgs6!L@SurzpEfod zgFsPH!JqOofDq%m8a0Lm6Muq+XktWTj88t{gBl-9jQU`FQNMGy6%)bu(9XFtbI$qB z-#2^lviI3#@2v$Pe(oF;$4cUqE31kdR~I!&+mo0cn=v`%x!=^QYch5D`YpDUSg#%T zP?neMoX!yT4-1>!qJ>XAChN;-IZdLWGwzbUIZwDclbv=)f>9ydo53zAeJAiC-FUFa zUF^Ndg}vL0asd|Ac3gbCx90ZuTK8yJ?)=pI*hAv$PP6?;R_M-^y>AFllXge=;4&`IIQ2JUover0V=0M43VFM`qZ_)P ze4B0YIz+l@5QZIQ%O-@>&r(D8QAj@QetX~xPiS}kiAh^UjBKeEN4)e?t{LYzBUQ>J zRHO(S(8-aXP&7Lf_6#nYGa5h<2tC?9oUShYDJ1a zq^c87&7^6VJM`q=+N0Oju3uNXv+b#pKvH);Jt~H^?QO-OEhHuf0QDrUvVXskorb$p z&wRGFiayX(#BpgU$9Y5B4NNAvCV2y%Xg=7;Z zP{Q}qPg6tREBC<*_fIP7v%ws+E3ij>^Q00M1-1(bl=wVM;I_gks`yabwiu5p3fedu zU=RWP14fX#$4pR=x>xSl;yRd1O%#$CkU66j6p398uq&h7cZ+p|9vrQ0Qp>8XI3Sb6 z6)MxpW~^oz9Vtk(h2^bi5*_+9%E6D4+My-Yfa}4d@qLQQCcr2LbO+4C&jz>(xGy-7 zB8ipG_^^9dLbo!q8ja5B0y|2Kp;1$&iBuo)Eh)1WU|u=8E>tjFhFQQHU zZJ=^OL6b}qZvGYB?rVm(GNG{qI{9*|j<2~>H529eG(nqzDV>-J&OAi; zP@Fa2jA2#{{#4qzoFKy$RPN02P33NuRK`d4)10^;j^7v|GlDa-)DxT(Rv0?5Rx3+j zMmflCm3!dCG@9h)6C3gW>l4pmZXR^&LXFNg5nPU>+^^khjyC9jPO*2{2S^>3bopW8nONgru3^&EB}Bx zjtdB#BF;j!3pp-Q5z_&s*k1-ee|o2=c0N5VnQlIRaaX^_(}1UHcF0d@mt)dy`b<>8 zfn9hc#u?>ihq&*xd-%*qj(IiKZt={4O3JH93A30FDg|4*k+ahS;LM`R`uxojiUz4O zfA-J~;#c?kxyc#NPMMNFugVsF7sgtF7kNtOd-V} z?ZP&gmp0qx9~}x(Z;K?B+qMqHQVV_>q-|~0lKa|bNH$|R28_J@Xv-G(#|JDI>T)U$ zIHCexF)n~~8_%!AZ;gk}zdwK(u?PIP$me3|+;fu`){EcW!xuiz11(&L&g!?n^u+Dw M-hFSCcPV540=TlJ@&Et; delta 2238 zcma)8-EUMy6yLdbyWQP8bGzGZ?=CISGeg0)1h7q8KE%*L+JZociA0GHnn(<}`@#m& zD1p`p$oE&Ld`0;KNH8%h7=woJpizXxj~6i^zG(Ep2ZJyAB>v7V2u3laY44et^YJ@p z&iPGm-te#9@ZX;h;)nX1;&@)1b46KlMqVq~l+KW68)DO-(xo4Vs8!2t&YUR0IO`DwGG^hSu(}CB-H}zM?wxxxv zf4k#7;Y*Tk-_AZE-IblQuz73eMbVGVE-yv%sHJLTJP5JDQfvxT;O*%hIjmYJu<06q z+u`NvINRSI|I&xE3vcx;i-v(dVw)DqR81zP94{(HVo3pID2Pd}Z7(#m!GB8(-&zJp zT)I0GksH{3t`|WNugjZh3M@6)Pg1cdL(xRMO&hRTrpSr}WPzf|y(39V>-Oya+qm<; zjk_LYTwk*{FObUfZ+D8B(l*sh!DeIJXoKyFO~lcI;q(wiZff7n{s@;XDTm{{26%sn z8aZjo)~vTZHXRF6!jv~CLBX&>nE+KwH?@Cbwp`VXl%=w}vww~#yVe8iR+h(122G)} z@R8%=jBTu0KbBrVW$OV$5+H{w&;{sZ*l(WXh%)y*)4{eTI33dg%^p@W_|)Azuy9`4 zHvW&feqcT`E2}!s!0M|G_M;B&jYB^PqqNV%&= zHuWiLw&8kMm*9_@x08xl6xhzjFyiw+zu)sD^r?qf#>V3w$6 zV*_Yhxe_jeUAD4IsQ!4g3##f^WrYI5kP+5QNIEtpDpF6?sI`oO6eJpDc{Q3r6$0wy zBs)oMP##qffAcZ(qN1V>QJ|0(!#(0GL#UANp9>~pqf{z@-&HX!Vq_KST(7bmDAt-f zb&qkWGlVKr*88ZIFrx!P;Cw zhEd_-t5M}AfMh;k-St=^(W;)ytE#ThGAhOtR!LWZ@A0zfiD~X=jBA|sn0_3O_7U}Q zJtumXt7In^jyrK#;-~`5(PmUaCzM66Dx|-b&;t6)lO>S zem*fPLS+P3=3WnQQP`kuvR^4nAT_Uz!z%aE|?YT}H@` zgsP=G?`WBPcsc`&(Civz#;6=WV1kH1gN^Iey|Hb3Fn4Wk)|4!iK{B5&jw!>W%d@+5 zs$+f>Ofw%i;Ow${5Rydp>p_8xg8I7>m^pf?j&pT}DZ+a>s1`V&GLj3q$YO8W@e zSje-tMm%0Ri?wejp2ga?=`s9cfG5Mp%R)XrPp)n^z7j|SPNhweUo}1g1~_}&)NB^5 z8rX64JKSWuyd@^&bh3Djxca_(`cjYZ-Ihxq7Xp*xBXRG@b4xD|ir?JU%b(VlfAF<0 P`s(48kLLTIrM~zJYmJ(* diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 8eb5565d..97e028a3 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -55,7 +55,7 @@ if ($ZEROBINCOMPATIBILITY) : - + diff --git a/tpl/page.php b/tpl/page.php index eddbb4b7..7636f31a 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY): - + Date: Thu, 20 Oct 2022 23:23:01 +0200 Subject: [PATCH 062/506] implemented S3 storage backend added sample configuration + aws php sdk version coding style cleanup --- CHANGELOG.md | 1 + CREDITS.md | 3 +- INSTALL.md | 39 ++++ cfg/conf.sample.php | 22 ++ composer.json | 3 +- lib/Configuration.php | 16 ++ lib/Data/S3Storage.php | 464 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 546 insertions(+), 2 deletions(-) create mode 100644 lib/Data/S3Storage.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 15bb1b1f..bda29706 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) * FIXED: Apply table prefix to indexes as well, to support multiple instances sharing a single database (#943) + * ADDED: S3 Storage backend (#994) * **1.4 (2022-04-09)** * ADDED: Translations for Corsican, Estonian, Finnish and Lojban * ADDED: new HTTP headers improving security (#765) diff --git a/CREDITS.md b/CREDITS.md index c0be0ad2..d0035077 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -29,6 +29,7 @@ * rodehoed - option to exempt ips from the rate-limiter * Mark van Holsteijn - Google Cloud Storage backend * Austin Huang - Oracle database support +* Felix J. Ogris - S3 Storage backend ## Translations * Hexalyse - French @@ -58,4 +59,4 @@ * Markus Mikkonen - Finnish * Emir Ensar Rahmanlar - Turkish * Stevo984 - Slovak -* Christos Karamolegkos - Greek \ No newline at end of file +* Christos Karamolegkos - Greek diff --git a/INSTALL.md b/INSTALL.md index 615ce56e..f35d68bf 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -232,3 +232,42 @@ Platform using Google Cloud Run is easy and cheap. To use the Google Cloud Storage backend you have to install the suggested library using the command `composer require google/cloud-storage`. + +#### Using S3 Storage +Similar to Google Cloud Storage, you can choose S3 as storage backend. It uses +the AWS SDK for PHP, but can also talk to a Rados gateway as part of a CEPH +cluster. To use this backend, you first have to install the SDK in the +document root of PrivateBin: `composer require aws/aws-sdk-php`. You have to +create the S3 bucket on the CEPH cluster before using the S3 backend. + +In the `[model]` section of cfg/conf.php, set `class` to `S3Storage`. + +You can set any combination of the following options in the `[model_options]` +section: + + * region + * version + * endpoint + * bucket + * prefix + * accesskey + * secretkey + * use_path_style_endpoint + +By default, prefix is empty. If set, the S3 backend will place all PrivateBin +data beneath this prefix. + +For AWS, you have to provide at least `region`, `bucket`, `accesskey`, and +`secretkey`. + +For CEPH, follow this example: + +``` +region = "" +version = "2006-03-01" +endpoint = "https://s3.my-ceph.invalid" +use_path_style_endpoint = true +bucket = "my-bucket" +accesskey = "my-rados-user" +secretkey = "my-rados-pass" +``` diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index ab37da7b..cf465980 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -205,3 +205,25 @@ dir = PATH "data" ;usr = "privatebin" ;pwd = "Z3r0P4ss" ;opt[12] = true ; PDO::ATTR_PERSISTENT + +;[model] +; example of S3 configuration for Rados gateway / CEPH +;class = S3Storage +;[model_options] +;region = "" +;version = "2006-03-01" +;endpoint = "https://s3.my-ceph.invalid" +;use_path_style_endpoint = true +;bucket = "my-bucket" +;accesskey = "my-rados-user" +;secretkey = "my-rados-pass" + +;[model] +; example of S3 configuration for AWS +;class = S3Storage +;[model_options] +;region = "eu-central-1" +;version = "latest" +;bucket = "my-bucket" +;accesskey = "access key id" +;secretkey = "secret access key" diff --git a/composer.json b/composer.json index 0fd34559..01d384f2 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,8 @@ "mlocati/ip-lib" : "1.18.0" }, "suggest" : { - "google/cloud-storage" : "1.26.1" + "google/cloud-storage" : "1.26.1", + "aws/aws-sdk-php" : "3.239.0" }, "require-dev" : { "phpunit/phpunit" : "^4.6 || ^5.0" diff --git a/lib/Configuration.php b/lib/Configuration.php index 9f4e35f7..fad44a27 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -157,6 +157,22 @@ class Configuration 'prefix' => 'pastes', 'uniformacl' => false, ); + } elseif ( + $section == 'model_options' && in_array( + $this->_configuration['model']['class'], + array('S3Storage') + ) + ) { + $values = array( + 'region' => null, + 'version' => null, + 'endpoint' => null, + 'accesskey' => null, + 'secretkey' => null, + 'use_path_style_endpoint' => null, + 'bucket' => null, + 'prefix' => '', + ); } // "*_options" sections don't require all defaults to be set diff --git a/lib/Data/S3Storage.php b/lib/Data/S3Storage.php new file mode 100644 index 00000000..d741e099 --- /dev/null +++ b/lib/Data/S3Storage.php @@ -0,0 +1,464 @@ + self::$_bucket, + 'Prefix' => $prefix, + ); + + do { + $objectsListResponse = self::$_client->listObjects($options); + $objects = $objectsListResponse['Contents'] ?? array(); + foreach ($objects as $object) { + $allObjects[] = $object; + $options['Marker'] = $object['Key']; + } + } while ($objectsListResponse['IsTruncated']); + + return $allObjects; + } + + /** + * returns the S3 storage object key for $pasteid in self::$_bucket. + * + * @access private + * @param $pasteid string to get the key for + * @return string + */ + private function _getKey($pasteid) + { + if (self::$_prefix != '') { + return self::$_prefix . '/' . $pasteid; + } + return $pasteid; + } + + /** + * Uploads the payload in the self::$_bucket under the specified key. + * The entire payload is stored as a JSON document. The metadata is replicated + * as the S3 object's metadata except for the fields attachment, attachmentname + * and salt. + * + * @param $key string to store the payload under + * @param $payload array to store + * @return bool true if successful, otherwise false. + */ + private function _upload($key, $payload) + { + $metadata = array_key_exists('meta', $payload) ? $payload['meta'] : array(); + unset($metadata['attachment'], $metadata['attachmentname'], $metadata['salt']); + foreach ($metadata as $k => $v) { + $metadata[$k] = strval($v); + } + try { + self::$_client->putObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $key, + 'Body' => Json::encode($payload), + 'ContentType' => 'application/json', + 'Metadata' => $metadata, + )); + } catch (S3Exception $e) { + error_log('failed to upload ' . $key . ' to ' . self::$_bucket . ', ' . + trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); + return false; + } + return true; + } + + /** + * @inheritDoc + */ + public function create($pasteid, array $paste) + { + if ($this->exists($pasteid)) { + return false; + } + + return $this->_upload($this->_getKey($pasteid), $paste); + } + + /** + * @inheritDoc + */ + public function read($pasteid) + { + try { + $object = self::$_client->getObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $this->_getKey($pasteid), + )); + $data = $object['Body']->getContents(); + return Json::decode($data); + } catch (S3Exception $e) { + error_log('failed to read ' . $pasteid . ' from ' . self::$_bucket . ', ' . + trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); + return false; + } + } + + /** + * @inheritDoc + */ + public function delete($pasteid) + { + $name = $this->_getKey($pasteid); + + try { + $comments = $this->_listAllObjects($name . '/discussion/'); + foreach ($comments as $comment) { + try { + self::$_client->deleteObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $comment['Key'], + )); + } catch (S3Exception $e) { + // ignore if already deleted. + } + } + } catch (S3Exception $e) { + // there are no discussions associated with the paste + } + + try { + self::$_client->deleteObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $name, + )); + } catch (S3Exception $e) { + // ignore if already deleted + } + } + + /** + * @inheritDoc + */ + public function exists($pasteid) + { + return self::$_client->doesObjectExistV2(self::$_bucket, $this->_getKey($pasteid)); + } + + /** + * @inheritDoc + */ + public function createComment($pasteid, $parentid, $commentid, array $comment) + { + if ($this->existsComment($pasteid, $parentid, $commentid)) { + return false; + } + $key = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid; + return $this->_upload($key, $comment); + } + + /** + * @inheritDoc + */ + public function readComments($pasteid) + { + $comments = array(); + $prefix = $this->_getKey($pasteid) . '/discussion/'; + try { + $entries = $this->_listAllObjects($prefix); + foreach ($entries as $entry) { + $object = self::$_client->getObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $entry['Key'], + )); + $body = JSON::decode($object['Body']->getContents()); + $items = explode('/', $entry['Key']); + $body['id'] = $items[3]; + $body['parentid'] = $items[2]; + $slot = $this->getOpenSlot($comments, (int) $object['Metadata']['created']); + $comments[$slot] = $body; + } + } catch (S3Exception $e) { + // no comments found + } + return $comments; + } + + /** + * @inheritDoc + */ + public function existsComment($pasteid, $parentid, $commentid) + { + $name = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid; + return self::$_client->doesObjectExistV2(self::$_bucket, $name); + } + + /** + * @inheritDoc + */ + public function purgeValues($namespace, $time) + { + $path = self::$_prefix; + if ($path != '') { + $path .= '/'; + } + $path .= 'config/' . $namespace; + + try { + foreach ($this->_listAllObjects($path) as $object) { + $name = $object['Key']; + if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') { + continue; + } + $head = self::$_client->headObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $name, + )); + if (array_key_exists('Metadata', $head) && array_key_exists('value', $head['Metadata'])) { + $value = $head['Metadata']['value']; + if (is_numeric($value) && intval($value) < $time) { + try { + self::$_client->deleteObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $name, + )); + } catch (S3Exception $e) { + // deleted by another instance. + } + } + } + } + } catch (S3Exception $e) { + // no objects in the bucket yet + } + } + + /** + * For S3, the value will also be stored in the metadata for the + * namespaces traffic_limiter and purge_limiter. + * @inheritDoc + */ + public function setValue($value, $namespace, $key = '') + { + $prefix = self::$_prefix; + if ($prefix != '') { + $prefix .= '/'; + } + + if ($key === '') { + $key = $prefix . 'config/' . $namespace; + } else { + $key = $prefix . 'config/' . $namespace . '/' . $key; + } + + $metadata = array('namespace' => $namespace); + if ($namespace != 'salt') { + $metadata['value'] = strval($value); + } + try { + self::$_client->putObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $key, + 'Body' => $value, + 'ContentType' => 'application/json', + 'Metadata' => $metadata, + )); + } catch (S3Exception $e) { + error_log('failed to set key ' . $key . ' to ' . self::$_bucket . ', ' . + trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); + return false; + } + return true; + } + + /** + * @inheritDoc + */ + public function getValue($namespace, $key = '') + { + $prefix = self::$_prefix; + if ($prefix != '') { + $prefix .= '/'; + } + + if ($key === '') { + $key = $prefix . 'config/' . $namespace; + } else { + $key = $prefix . 'config/' . $namespace . '/' . $key; + } + + try { + $object = self::$_client->getObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $key, + )); + return $object['Body']->getContents(); + } catch (S3Exception $e) { + return ''; + } + } + + /** + * @inheritDoc + */ + protected function _getExpiredPastes($batchsize) + { + $expired = array(); + $now = time(); + $prefix = self::$_prefix; + if ($prefix != '') { + $prefix .= '/'; + } + + try { + foreach ($this->_listAllObjects($prefix) as $object) { + $head = self::$_client->headObject(array( + 'Bucket' => self::$_bucket, + 'Key' => $object['Key'], + )); + if (array_key_exists('Metadata', $head) && array_key_exists('expire_date', $head['Metadata'])) { + $expire_at = intval($head['Metadata']['expire_date']); + if ($expire_at != 0 && $expire_at < $now) { + array_push($expired, $object['Key']); + } + } + + if (count($expired) > $batchsize) { + break; + } + } + } catch (S3Exception $e) { + // no objects in the bucket yet + } + return $expired; + } +} From b0f17f0a91cdebbfd6732781943f1e04ce3311f7 Mon Sep 17 00:00:00 2001 From: "Jens-U. Mozdzen" Date: Sun, 23 Oct 2022 00:18:56 +0200 Subject: [PATCH 063/506] added server-side YOURLS shortener call --- shortenviayourls.php | 85 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 shortenviayourls.php diff --git a/shortenviayourls.php b/shortenviayourls.php new file mode 100644 index 00000000..28022819 --- /dev/null +++ b/shortenviayourls.php @@ -0,0 +1,85 @@ +getKey( "basepath") . "/?")) { + + // Init the CURL session + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $conf->getKey( "apiurl", "yourls")); + curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result + curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request + curl_setopt($ch, CURLOPT_POSTFIELDS, array( // Data to POST + 'signature' => $conf->getKey( "signature", "yourls"), + 'format' => 'json', + 'action' => 'shorturl', + 'url' => $originalUrl + )); + // Fetch and return content + $data = curl_exec($ch); + curl_close($ch); + if (!($data === FALSE) && is_string($data)) + { + $data = json_decode( $data, true); + + if (!is_null($data) && array_key_exists('statusCode', $data) + && array_key_exists('shorturl', $data) && ($data['statusCode'] == 200)) + { + $shortenedUrl = $data['shorturl']; + $opSuccess = TRUE; + } else { + // error with contents of YOURLS response. + $errCode = 3; + } + } else { + // error when calling YOURLS - probably a PrivateBin configuration issue, like wrong/missing apiurl or signature + $errCode = 2; + } + } else { + // trying to shorten a URL not pointing to our PrivateBin instance. + $errCode = 1; + } +} + +if ($opSuccess) +{ + print("
Your shortened paste is $shortenedUrl"); +} +else +{ + print("
Error: An error occured while trying to shorten the given URL (error code $errCode)"); +} + +function getGetData() { + $data = http_build_query($_GET); + return $data; +} + +function startsWith($haystack, $needle) +{ + $length = strlen($needle); + return (substr($haystack, 0, $length) === $needle); +} +?> From 3115cb8883cae1d4c08f8df54cb3e521f29cd465 Mon Sep 17 00:00:00 2001 From: "Jens-U. Mozdzen" Date: Sun, 23 Oct 2022 00:19:43 +0200 Subject: [PATCH 064/506] added parameters for server-side YOURLS shortener call --- cfg/conf.sample.php | 12 ++++++++++++ lib/Configuration.php | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index cf465980..487a20ae 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -227,3 +227,15 @@ dir = PATH "data" ;bucket = "my-bucket" ;accesskey = "access key id" ;secretkey = "secret access key" + +[yourls] +; don't mix this up with "urlshortener" config item: +; - when using a standard configuration, "urlshortener" will point to the YOURLS API, including access credentials, and will be part of the PrivateBin public web page (insecure!) +; - when using the parameters in this section ("signature" and "apiurl"), "urlshortener" will point to a fixed PrivateBin page ("$basepath/shortenviayourls.php") and +; that PHP will in turn call YOURLS server-side, using the URL from "apiurl" and using the "access signature" from "signature" parameter. + +; (optional) the "signature" (access key) issued by YOURLS for the using account +; signature = "" + +; (optional) the URL of the YOURLS API, called to shorten a PrivateBin URL +; apiurl = "" diff --git a/lib/Configuration.php b/lib/Configuration.php index fad44a27..c2a5316b 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -93,6 +93,10 @@ class Configuration 'model_options' => array( 'dir' => 'data', ), + 'yourls' => array( + 'signature' => '', + 'apiurl' => '', + ), ); /** From dce8b8d3521811f2f34a6d5e31708cd759377fb4 Mon Sep 17 00:00:00 2001 From: "Jens-U. Mozdzen" Date: Sun, 23 Oct 2022 01:07:43 +0200 Subject: [PATCH 065/506] updated code formatting --- lib/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index c2a5316b..6f3a8225 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -95,7 +95,7 @@ class Configuration ), 'yourls' => array( 'signature' => '', - 'apiurl' => '', + 'apiurl' => '', ), ); From 0dc9ab7576d5a1296debeb788afb2ae9c72d137c Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 08:10:56 +0200 Subject: [PATCH 066/506] refactor shortenviayourls.php for our MVC framework --- lib/Controller.php | 28 +++++++++- lib/Request.php | 6 +++ lib/YourlsProxy.php | 120 +++++++++++++++++++++++++++++++++++++++++++ shortenviayourls.php | 85 ------------------------------ tpl/yourlsproxy.php | 25 +++++++++ 5 files changed, 177 insertions(+), 87 deletions(-) create mode 100644 lib/YourlsProxy.php delete mode 100644 shortenviayourls.php create mode 100644 tpl/yourlsproxy.php diff --git a/lib/Controller.php b/lib/Controller.php index 62fa1e99..8d7f0f13 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -136,6 +136,9 @@ class Controller case 'jsonld': $this->_jsonld($this->_request->getParam('jsonld')); return; + case 'yourlsproxy': + $this->_yourlsproxy($this->_request->getParam('link')); + break; } // output JSON or HTML @@ -378,9 +381,15 @@ class Controller ); $page = new View; + $page->assign('CSPHEADER', $metacspheader); + $page->assign('ERROR', I18n::_($this->_error)); + if ($this->_request->getOperation() === 'yourlsproxy') { + $page->assign('SHORTURL', $this->_status); + $page->draw('yourlsproxy'); + return; + } $page->assign('NAME', $this->_conf->getKey('name')); $page->assign('BASEPATH', I18n::_($this->_conf->getKey('basepath'))); - $page->assign('ERROR', I18n::_($this->_error)); $page->assign('STATUS', I18n::_($this->_status)); $page->assign('VERSION', self::VERSION); $page->assign('DISCUSSION', $this->_conf->getKey('discussion')); @@ -405,7 +414,6 @@ class Controller $page->assign('HTTPWARNING', $this->_conf->getKey('httpwarning')); $page->assign('HTTPSLINK', 'https://' . $this->_request->getHost() . $this->_request->getRequestUri()); $page->assign('COMPRESSION', $this->_conf->getKey('compression')); - $page->assign('CSPHEADER', $metacspheader); $page->draw($this->_conf->getKey('template')); } @@ -439,6 +447,22 @@ class Controller echo $content; } + /** + * proxies link to YOURLS, updates status or error with response + * + * @access private + * @param string $link + */ + private function _yourlsproxy($link) + { + $yourls = new YourlsProxy($this->_conf, $link); + if ($yourls->isError()) { + $this->_error = $yourls->getError(); + } else { + $this->_status = $yourls->getUrl(); + } + } + /** * prepares JSON encoded status message * diff --git a/lib/Request.php b/lib/Request.php index 2eff8a96..9ed73074 100644 --- a/lib/Request.php +++ b/lib/Request.php @@ -120,6 +120,7 @@ class Request if ( !array_key_exists('pasteid', $this->_params) && !array_key_exists('jsonld', $this->_params) && + !array_key_exists('link', $this->_params) && array_key_exists('QUERY_STRING', $_SERVER) && !empty($_SERVER['QUERY_STRING']) ) { @@ -135,6 +136,11 @@ class Request } } elseif (array_key_exists('jsonld', $this->_params) && !empty($this->_params['jsonld'])) { $this->_operation = 'jsonld'; + } elseif (array_key_exists('link', $this->_params) && !empty($this->_params['link'])) { + $request_url = filter_var($_SERVER['REQUEST_URI'], FILTER_SANITIZE_URL); + if (strpos($request_url, '/shortenviayourls?link=') !== false) { + $this->_operation = 'yourlsproxy'; + } } } diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php new file mode 100644 index 00000000..6cc0f24e --- /dev/null +++ b/lib/YourlsProxy.php @@ -0,0 +1,120 @@ +getKey('basepath') . '/?') !== false) { + // Init the CURL session + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $conf->getKey("apiurl", "yourls")); + curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result + curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request + curl_setopt($ch, CURLOPT_POSTFIELDS, array( // Data to POST + 'signature' => $conf->getKey("signature", "yourls"), + 'format' => 'json', + 'action' => 'shorturl', + 'url' => $link + )); + // Fetch and return content + $data = curl_exec($ch); + curl_close($ch); + + if (!($data === FALSE) && is_string($data)) + { + $data = json_decode( $data, true); + + if (!is_null($data) && array_key_exists('statusCode', $data) + && array_key_exists('shorturl', $data) && ($data['statusCode'] == 200)) + { + $this->_url = $data['shorturl']; + $opSuccess = TRUE; + } else { + $this->_error = 'Error parsing YOURLS response.'; + } + } else { + $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; + } + } else { + $this->_error = 'Trying to shorten a URL not pointing to our PrivateBin instance.'; + } + } + + /** + * Returns the (untranslated) error message + * + * @access public + * @return string + */ + public function getError() + { + return $this->_error; + } + + /** + * Returns the shortened URL + * + * @access public + * @return string + */ + public function getUrl() + { + return $this->_url; + } + + /** + * Returns true if any error has occurred + * + * @access public + * @return bool + */ + public function isError() + { + return !empty($this->_error); + } +} diff --git a/shortenviayourls.php b/shortenviayourls.php deleted file mode 100644 index 28022819..00000000 --- a/shortenviayourls.php +++ /dev/null @@ -1,85 +0,0 @@ -getKey( "basepath") . "/?")) { - - // Init the CURL session - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $conf->getKey( "apiurl", "yourls")); - curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result - curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request - curl_setopt($ch, CURLOPT_POSTFIELDS, array( // Data to POST - 'signature' => $conf->getKey( "signature", "yourls"), - 'format' => 'json', - 'action' => 'shorturl', - 'url' => $originalUrl - )); - // Fetch and return content - $data = curl_exec($ch); - curl_close($ch); - if (!($data === FALSE) && is_string($data)) - { - $data = json_decode( $data, true); - - if (!is_null($data) && array_key_exists('statusCode', $data) - && array_key_exists('shorturl', $data) && ($data['statusCode'] == 200)) - { - $shortenedUrl = $data['shorturl']; - $opSuccess = TRUE; - } else { - // error with contents of YOURLS response. - $errCode = 3; - } - } else { - // error when calling YOURLS - probably a PrivateBin configuration issue, like wrong/missing apiurl or signature - $errCode = 2; - } - } else { - // trying to shorten a URL not pointing to our PrivateBin instance. - $errCode = 1; - } -} - -if ($opSuccess) -{ - print("
Your shortened paste is $shortenedUrl"); -} -else -{ - print("
Error: An error occured while trying to shorten the given URL (error code $errCode)"); -} - -function getGetData() { - $data = http_build_query($_GET); - return $data; -} - -function startsWith($haystack, $needle) -{ - $length = strlen($needle); - return (substr($haystack, 0, $length) === $needle); -} -?> diff --git a/tpl/yourlsproxy.php b/tpl/yourlsproxy.php new file mode 100644 index 00000000..c451c5a2 --- /dev/null +++ b/tpl/yourlsproxy.php @@ -0,0 +1,25 @@ + + + + + + + + <?php echo I18n::_($NAME); ?> + + + +

%s (Hit [Ctrl]+[c] to copy)', $SHORTURL, $SHORTURL); ?>

+ +

+ + + From 0a2094f0698860fb0d7cc71c811fe8cbf7810ac9 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 08:16:05 +0200 Subject: [PATCH 067/506] code style --- lib/YourlsProxy.php | 68 +++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php index 6cc0f24e..9d4cee8c 100644 --- a/lib/YourlsProxy.php +++ b/lib/YourlsProxy.php @@ -48,40 +48,42 @@ class YourlsProxy */ public function __construct(Configuration $conf, $link) { - if (strpos($link, $conf->getKey('basepath') . '/?') !== false) { - // Init the CURL session - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $conf->getKey("apiurl", "yourls")); - curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result - curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request - curl_setopt($ch, CURLOPT_POSTFIELDS, array( // Data to POST - 'signature' => $conf->getKey("signature", "yourls"), - 'format' => 'json', - 'action' => 'shorturl', - 'url' => $link - )); - // Fetch and return content - $data = curl_exec($ch); - curl_close($ch); - - if (!($data === FALSE) && is_string($data)) - { - $data = json_decode( $data, true); - - if (!is_null($data) && array_key_exists('statusCode', $data) - && array_key_exists('shorturl', $data) && ($data['statusCode'] == 200)) - { - $this->_url = $data['shorturl']; - $opSuccess = TRUE; - } else { - $this->_error = 'Error parsing YOURLS response.'; - } - } else { - $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; - } - } else { + if (strpos($link, $conf->getKey('basepath') . '/?') === false) { $this->_error = 'Trying to shorten a URL not pointing to our PrivateBin instance.'; + return; + } + + // Init the CURL session + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $conf->getKey("apiurl", "yourls")); + curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result + curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request + curl_setopt($ch, CURLOPT_POSTFIELDS, array( // Data to POST + 'signature' => $conf->getKey("signature", "yourls"), + 'format' => 'json', + 'action' => 'shorturl', + 'url' => $link + )); + // Fetch and return content + $data = curl_exec($ch); + curl_close($ch); + + if ($data === false || !is_string($data)) { + $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; + return; + } + + $data = json_decode($data, true); + if ( + !is_null($data) && + array_key_exists('statusCode', $data) && + array_key_exists('shorturl', $data) && + $data['statusCode'] == 200 + ) { + $this->_url = $data['shorturl']; + } else { + $this->_error = 'Error parsing YOURLS response.'; } } From b768a2e8cb5e58497c21f1418d704112a70725d8 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 08:21:37 +0200 Subject: [PATCH 068/506] use JSON wrapper for decoding error catching --- lib/YourlsProxy.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php index 9d4cee8c..b5161103 100644 --- a/lib/YourlsProxy.php +++ b/lib/YourlsProxy.php @@ -12,7 +12,9 @@ namespace PrivateBin; +use Exception; use PrivateBin\Configuration; +use PrivateBin\Json; /** * YourlsProxy @@ -74,7 +76,13 @@ class YourlsProxy return; } - $data = json_decode($data, true); + try { + $data = Json::decode($data); + } catch (Exception $e) { + $this->_error = $e->getMessage(); + return; + } + if ( !is_null($data) && array_key_exists('statusCode', $data) && From f4000150faa1d410678be719f23d9547b9646798 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 09:05:17 +0200 Subject: [PATCH 069/506] avoid cURL dependency, native functions should suffice for such a simple call --- lib/YourlsProxy.php | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php index b5161103..dc19e24d 100644 --- a/lib/YourlsProxy.php +++ b/lib/YourlsProxy.php @@ -55,22 +55,24 @@ class YourlsProxy return; } - // Init the CURL session - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $conf->getKey("apiurl", "yourls")); - curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result - curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request - curl_setopt($ch, CURLOPT_POSTFIELDS, array( // Data to POST - 'signature' => $conf->getKey("signature", "yourls"), - 'format' => 'json', - 'action' => 'shorturl', - 'url' => $link - )); - // Fetch and return content - $data = curl_exec($ch); - curl_close($ch); - + $data = file_get_contents( + $conf->getKey('apiurl', 'yourls'), false, stream_context_create( + array( + 'http' => array( + 'method' => 'POST', + 'header' => "Content-Type: application/x-www-form-urlencoded\r\n", + 'content' => http_build_query( + array( + 'signature' => $conf->getKey('signature', 'yourls'), + 'format' => 'json', + 'action' => 'shorturl', + 'url' => $link + ) + ) + ) + ) + ) + ); if ($data === false || !is_string($data)) { $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; return; From 2a162d075c962ea212d253811b4e19cc8fac6474 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 09:12:31 +0200 Subject: [PATCH 070/506] allow unit tests to pass --- tpl/yourlsproxy.php | 4 +++- tst/ViewTest.php | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tpl/yourlsproxy.php b/tpl/yourlsproxy.php index c451c5a2..f642047d 100644 --- a/tpl/yourlsproxy.php +++ b/tpl/yourlsproxy.php @@ -17,7 +17,9 @@ if (empty($ERROR)) : -

+
+

+
diff --git a/tst/ViewTest.php b/tst/ViewTest.php index 1e4d9374..3e8a8aea 100644 --- a/tst/ViewTest.php +++ b/tst/ViewTest.php @@ -106,6 +106,10 @@ class ViewTest extends PHPUnit_Framework_TestCase $content, $template . ': outputs error correctly' ); + if ($template === 'yourlsproxy') { + // yourlsproxy template only displays error message + continue; + } $this->assertRegExp( '#<[^>]+id="password"[^>]*>#', $content, From 69034ef9d1e76be4968729ca52a215633cc74af7 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 09:16:55 +0200 Subject: [PATCH 071/506] apply StyleCI recommendations --- lib/YourlsProxy.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php index dc19e24d..4162a6fa 100644 --- a/lib/YourlsProxy.php +++ b/lib/YourlsProxy.php @@ -13,8 +13,6 @@ namespace PrivateBin; use Exception; -use PrivateBin\Configuration; -use PrivateBin\Json; /** * YourlsProxy @@ -66,10 +64,10 @@ class YourlsProxy 'signature' => $conf->getKey('signature', 'yourls'), 'format' => 'json', 'action' => 'shorturl', - 'url' => $link + 'url' => $link, ) - ) - ) + ), + ), ) ) ); From 4bd5ef9cda32c95b63c2468ba4a35a896167bcca Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 10:50:18 +0200 Subject: [PATCH 072/506] add new messages to translate --- i18n/ar.json | 5 ++++- i18n/bg.json | 5 ++++- i18n/ca.json | 5 ++++- i18n/co.json | 5 ++++- i18n/cs.json | 5 ++++- i18n/de.json | 5 ++++- i18n/el.json | 5 ++++- i18n/en.json | 5 ++++- i18n/es.json | 5 ++++- i18n/et.json | 5 ++++- i18n/fi.json | 5 ++++- i18n/fr.json | 5 ++++- i18n/he.json | 5 ++++- i18n/hi.json | 5 ++++- i18n/hu.json | 5 ++++- i18n/id.json | 5 ++++- i18n/it.json | 5 ++++- i18n/ja.json | 5 ++++- i18n/jbo.json | 5 ++++- i18n/ku.json | 5 ++++- i18n/la.json | 5 ++++- i18n/lt.json | 5 ++++- i18n/nl.json | 5 ++++- i18n/no.json | 5 ++++- i18n/oc.json | 5 ++++- i18n/pl.json | 5 ++++- i18n/pt.json | 5 ++++- i18n/ru.json | 5 ++++- i18n/sk.json | 5 ++++- i18n/sl.json | 5 ++++- i18n/sv.json | 5 ++++- i18n/tr.json | 5 ++++- i18n/uk.json | 5 ++++- i18n/zh.json | 5 ++++- lib/YourlsProxy.php | 2 +- 35 files changed, 137 insertions(+), 35 deletions(-) diff --git a/i18n/ar.json b/i18n/ar.json index 1827ddf2..dbc85bcf 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/bg.json b/i18n/bg.json index 717c5f18..ec8f540d 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/ca.json b/i18n/ca.json index 01651989..154110d4 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/co.json b/i18n/co.json index 21ca71ec..90b6811d 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitate stu liame per vede a nota. Date l’indirizzu à qualunque li permette d’accede à a nota dinù.", "URL shortener may expose your decrypt key in URL.": "Un ammuzzatore d’indirizzu pò palisà a vostra chjave di dicifratura in l’indirizzu.", "Save paste": "Arregistrà l’appiccicu", - "Your IP is not authorized to create pastes.": "U vostru indirizzu IP ùn hè micca auturizatu à creà l’appiccichi." + "Your IP is not authorized to create pastes.": "U vostru indirizzu IP ùn hè micca auturizatu à creà l’appiccichi.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/cs.json b/i18n/cs.json index 82cb1732..6996f9ad 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.", "URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.", "Save paste": "Uložit příspěvek", - "Your IP is not authorized to create pastes.": "Vaše IP adresa nemá oprávnění k vytvoření vložení." + "Your IP is not authorized to create pastes.": "Vaše IP adresa nemá oprávnění k vytvoření vložení.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/de.json b/i18n/de.json index 42752f2f..7ab57050 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besuche diesen Link um das Dokument zu sehen. Wird die URL an eine andere Person gegeben, so kann diese Person ebenfalls auf dieses Dokument zugreifen.", "URL shortener may expose your decrypt key in URL.": "Der URL-Verkürzer kann den Schlüssel in der URL enthüllen.", "Save paste": "Text speichern", - "Your IP is not authorized to create pastes.": "Deine IP ist nicht berechtigt, Texte zu erstellen." + "Your IP is not authorized to create pastes.": "Deine IP ist nicht berechtigt, Texte zu erstellen.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/el.json b/i18n/el.json index 15df67be..4f1a601c 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφτείτε αυτόν τον σύνδεσμο για να δείτε το μήνυμα. Δίνοντας τον σύνδεσμο σε οποιονδήποτε, του επιτρέπετε να επισκεφτεί το μήνυμα επίσης.", "URL shortener may expose your decrypt key in URL.": "Συντομευτές συνδέσμων πιθανώς να δημοσιοποιήσουν το κλειδί αποκρυπτογράφισης στον σύνδεσμο.", "Save paste": "Αποθήκευση επικόλλησης", - "Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις." + "Your IP is not authorized to create pastes.": "Η IP σας δεν επιτρέπεται να δημιουργεί επικολλήσεις.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/en.json b/i18n/en.json index 2ba6068f..ac71b5ae 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/es.json b/i18n/es.json index 641ef3ba..c3687023 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite este enlace para ver la nota. Dar la URL a cualquier persona también les permite acceder a la nota.", "URL shortener may expose your decrypt key in URL.": "El acortador de URL puede exponer su clave de descifrado en el URL.", "Save paste": "Guardar \"paste\"", - "Your IP is not authorized to create pastes.": "Tu IP no está autorizada para crear contenido." + "Your IP is not authorized to create pastes.": "Tu IP no está autorizada para crear contenido.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/et.json b/i18n/et.json index f02cefba..3a73b83f 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kirja nägemiseks külasta seda linki. Teistele URL-i andmine lubab ka neil ligi pääseda kirjale.", "URL shortener may expose your decrypt key in URL.": "URL-i lühendaja võib paljastada sinu dekrüpteerimisvõtme URL-is.", "Save paste": "Salvesta kleebe", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/fi.json b/i18n/fi.json index 90b56733..1956bf41 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Käy tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomeen viestiä. ", "URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.", "Save paste": "Tallenna paste", - "Your IP is not authorized to create pastes.": "IP:llesi ei ole annettu oikeutta luoda pasteja." + "Your IP is not authorized to create pastes.": "IP:llesi ei ole annettu oikeutta luoda pasteja.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/fr.json b/i18n/fr.json index 2f3d491e..19f99c0a 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visiter ce lien pour voir la note. Donner l'URL à une autre personne lui permet également d'accéder à la note.", "URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.", "Save paste": "Sauver le paste", - "Your IP is not authorized to create pastes.": "Votre adresse IP n'est pas autorisée à créer des pastes." + "Your IP is not authorized to create pastes.": "Votre adresse IP n'est pas autorisée à créer des pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/he.json b/i18n/he.json index 503dbc16..3d25ff33 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "נא לבקר בקישור כדי לצפות בהערה. מסירת הקישור לאנשים כלשהם תאפשר גם להם לגשת להערה.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/hi.json b/i18n/hi.json index 4df6aa71..4eee3825 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/hu.json b/i18n/hu.json index c9acb042..19f7f16d 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Látogasd meg ezt a hivatkozást a bejegyzés megtekintéséhez. Ha mások számára is megadod ezt a linket, azzal hozzáférnek ők is.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/id.json b/i18n/id.json index 1edeb997..b3171df8 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kunjungi tautan ini untuk melihat catatan. Memberikan alamat URL pada siapapun juga, akan mengizinkan mereka untuk mengakses catatan, so pasti gitu loh Kaka.", "URL shortener may expose your decrypt key in URL.": "Pemendek URL mungkin akan menampakkan kunci dekrip Anda dalam URL.", "Save paste": "Simpan paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/it.json b/i18n/it.json index e00ce310..c724e1fd 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visita questo collegamento per vedere la nota. Dare l'URL a chiunque consente anche a loro di accedere alla nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener può esporre la tua chiave decrittografata nell'URL.", "Save paste": "Salva il messagio", - "Your IP is not authorized to create pastes.": "Il tuo IP non è autorizzato a creare dei messaggi." + "Your IP is not authorized to create pastes.": "Il tuo IP non è autorizzato a creare dei messaggi.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/ja.json b/i18n/ja.json index 330032fd..6f6d9acd 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/jbo.json b/i18n/jbo.json index 82cea900..8bb399a3 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "rejgau fukpi", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/ku.json b/i18n/ku.json index bca43477..adb5cd5b 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/la.json b/i18n/la.json index fe6c4001..ef2bdf7f 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/lt.json b/i18n/lt.json index 76b28163..25684e4f 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.", "URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.", "Save paste": "Įrašyti įdėjimą", - "Your IP is not authorized to create pastes.": "Jūsų IP adresas neturi įgaliojimų kurti įdėjimų." + "Your IP is not authorized to create pastes.": "Jūsų IP adresas neturi įgaliojimų kurti įdėjimų.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/nl.json b/i18n/nl.json index 6157bfa3..8fbb8781 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Bezoek deze link om de notitie te bekijken. Als je de URL aan iemand geeft, kan die de notitie ook bekijken.", "URL shortener may expose your decrypt key in URL.": "URL-verkorter kan uw ontcijferingssleutel in URL blootleggen.", "Save paste": "Notitie opslaan", - "Your IP is not authorized to create pastes.": "Uw IP-adres is niet gemachtigd om geplakte tekst te maken." + "Your IP is not authorized to create pastes.": "Uw IP-adres is niet gemachtigd om geplakte tekst te maken.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/no.json b/i18n/no.json index eda1e4c5..a2215245 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besøk denne lenken for å se notatet. Hvis lenken deles med andre, vil de også kunne se notatet.", "URL shortener may expose your decrypt key in URL.": "URL forkorter kan avsløre dekrypteringsnøkkelen.", "Save paste": "Lagre utklipp", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/oc.json b/i18n/oc.json index f074d919..4890f4a4 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitatz aqueste ligam per veire la nòta. Fornir lo ligam a qualqu’un mai li permet tanben d’accedir a la nòta.", "URL shortener may expose your decrypt key in URL.": "Los espleches d’acorchiment d’URL pòdon expausar la clau de deschiframent dins l’URL.", "Save paste": "Enregistrar lo tèxt", - "Your IP is not authorized to create pastes.": "Vòstra adreça IP a pas l’autorizacion de crear de tèxtes." + "Your IP is not authorized to create pastes.": "Vòstra adreça IP a pas l’autorizacion de crear de tèxtes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/pl.json b/i18n/pl.json index b6127cad..09bfb25b 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/pt.json b/i18n/pt.json index 72d0250f..f7cc09bd 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite esse link para ver a nota. Dar a URL para qualquer um permite que eles também acessem a nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/ru.json b/i18n/ru.json index f1d237b2..677de762 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Посетите эту ссылку чтобы просмотреть запись. Передача ссылки кому либо позволит им получить доступ к записи тоже.", "URL shortener may expose your decrypt key in URL.": "Сервис сокращения ссылок может получить ваш ключ расшифровки из ссылки.", "Save paste": "Сохранить запись", - "Your IP is not authorized to create pastes.": "Вашему IP адресу не разрешено создавать записи." + "Your IP is not authorized to create pastes.": "Вашему IP адресу не разрешено создавать записи.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/sk.json b/i18n/sk.json index f1815da3..a1efd043 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Ak chcete zobraziť poznámku, navštívte tento odkaz. Poskytnutie adresy URL komukoľvek im umožní prístup aj k poznámke.", "URL shortener may expose your decrypt key in URL.": "Skracovač adries URL môže odhaliť váš dešifrovací kľúč v adrese URL.", "Save paste": "Uložiť príspevok", - "Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať príspevky." + "Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať príspevky.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/sl.json b/i18n/sl.json index 27c43611..b1628fc3 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/sv.json b/i18n/sv.json index bb613296..ac8a5843 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/tr.json b/i18n/tr.json index 47d249cd..3b3ad126 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Notu görmek için bu bağlantıyı ziyaret et. Bağlantıya sahip olan birisi notu görebilir.", "URL shortener may expose your decrypt key in URL.": "URL kısaltıcı şifreleme anahtarınızı URL içerisinde gösterebilir.", "Save paste": "Yazıyı kaydet", - "Your IP is not authorized to create pastes.": "IP adresinizin yazı oluşturmaya yetkisi yoktur." + "Your IP is not authorized to create pastes.": "IP adresinizin yazı oluşturmaya yetkisi yoktur.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/uk.json b/i18n/uk.json index 2dbc6f40..c2f2c5f4 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Відвідайте посилання, щоб переглянути нотатку. Передача посилання будь-кому дозволить їм переглянути нотатку.", "URL shortener may expose your decrypt key in URL.": "Сервіс скорочення посилань може викрити ваш ключ дешифрування з URL.", "Save paste": "Зберегти вставку", - "Your IP is not authorized to create pastes.": "Вашому IP не дозволено створювати вставки." + "Your IP is not authorized to create pastes.": "Вашому IP не дозволено створювати вставки.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/i18n/zh.json b/i18n/zh.json index 9bcad318..004f5926 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -186,5 +186,8 @@ "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "访问此链接来查看该笔记。将此 URL 发送给任何人即可允许其访问该笔记。", "URL shortener may expose your decrypt key in URL.": "短链接服务可能会暴露您在 URL 中的解密密钥。", "Save paste": "保存内容", - "Your IP is not authorized to create pastes.": "您的 IP 无权创建粘贴。" + "Your IP is not authorized to create pastes.": "您的 IP 无权创建粘贴。", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." } diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php index 4162a6fa..8a1a4d9e 100644 --- a/lib/YourlsProxy.php +++ b/lib/YourlsProxy.php @@ -49,7 +49,7 @@ class YourlsProxy public function __construct(Configuration $conf, $link) { if (strpos($link, $conf->getKey('basepath') . '/?') === false) { - $this->_error = 'Trying to shorten a URL not pointing to our PrivateBin instance.'; + $this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.'; return; } From 78e915e049e47dc3e2dfe2636062c8375d5301a0 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 13:09:54 +0200 Subject: [PATCH 073/506] adding tests for YOURLS functionality --- lib/Controller.php | 2 +- lib/Request.php | 3 +- lib/YourlsProxy.php | 20 ++++++----- tst/ControllerTest.php | 6 ++++ tst/JsonApiTest.php | 51 ++++++++++++++++++++++------ tst/YourlsProxyTest.php | 75 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 22 deletions(-) create mode 100644 tst/YourlsProxyTest.php diff --git a/lib/Controller.php b/lib/Controller.php index 8d7f0f13..1efd1145 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -383,12 +383,12 @@ class Controller $page = new View; $page->assign('CSPHEADER', $metacspheader); $page->assign('ERROR', I18n::_($this->_error)); + $page->assign('NAME', $this->_conf->getKey('name')); if ($this->_request->getOperation() === 'yourlsproxy') { $page->assign('SHORTURL', $this->_status); $page->draw('yourlsproxy'); return; } - $page->assign('NAME', $this->_conf->getKey('name')); $page->assign('BASEPATH', I18n::_($this->_conf->getKey('basepath'))); $page->assign('STATUS', I18n::_($this->_status)); $page->assign('VERSION', self::VERSION); diff --git a/lib/Request.php b/lib/Request.php index 9ed73074..ea566f5c 100644 --- a/lib/Request.php +++ b/lib/Request.php @@ -137,8 +137,7 @@ class Request } elseif (array_key_exists('jsonld', $this->_params) && !empty($this->_params['jsonld'])) { $this->_operation = 'jsonld'; } elseif (array_key_exists('link', $this->_params) && !empty($this->_params['link'])) { - $request_url = filter_var($_SERVER['REQUEST_URI'], FILTER_SANITIZE_URL); - if (strpos($request_url, '/shortenviayourls?link=') !== false) { + if (strpos($this->getRequestUri(), '/shortenviayourls') !== false) { $this->_operation = 'yourlsproxy'; } } diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php index 8a1a4d9e..858317a2 100644 --- a/lib/YourlsProxy.php +++ b/lib/YourlsProxy.php @@ -53,8 +53,14 @@ class YourlsProxy return; } + $yourls_api_url = $conf->getKey('apiurl', 'yourls'); + if (empty($yourls_api_url)) { + $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; + return; + } + $data = file_get_contents( - $conf->getKey('apiurl', 'yourls'), false, stream_context_create( + $yourls_api_url, false, stream_context_create( array( 'http' => array( 'method' => 'POST', @@ -71,23 +77,19 @@ class YourlsProxy ) ) ); - if ($data === false || !is_string($data)) { - $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; - return; - } - try { $data = Json::decode($data); } catch (Exception $e) { - $this->_error = $e->getMessage(); + $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; + error_log('Error calling YOURLS: ' . $e->getMessage()); return; } if ( !is_null($data) && array_key_exists('statusCode', $data) && - array_key_exists('shorturl', $data) && - $data['statusCode'] == 200 + $data['statusCode'] == 200 && + array_key_exists('shorturl', $data) ) { $this->_url = $data['shorturl']; } else { diff --git a/tst/ControllerTest.php b/tst/ControllerTest.php index 5c951273..e1637c11 100644 --- a/tst/ControllerTest.php +++ b/tst/ControllerTest.php @@ -48,6 +48,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase */ public function testView() { + $_SERVER['HTTP_HOST'] = 'example.com'; $_SERVER['QUERY_STRING'] = Helper::getPasteId(); $_GET[Helper::getPasteId()] = ''; ob_start(); @@ -64,6 +65,11 @@ class ControllerTest extends PHPUnit_Framework_TestCase $content, 'doesn\'t output shortener button' ); + $this->assertRegExp( + '# href="https://' . preg_quote($_SERVER['HTTP_HOST']) . '/">switching to HTTPS#', + $content, + 'outputs configured https URL correctly' + ); } /** diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index 6d9732a5..058bd320 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -15,6 +15,9 @@ class JsonApiTest extends PHPUnit_Framework_TestCase { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; + if (!is_dir($this->_path)) { + mkdir($this->_path); + } $this->_model = Filesystem::getInstance(array('dir' => $this->_path)); ServerSalt::setStore($this->_model); @@ -186,8 +189,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase */ public function testJsonLdPaste() { - $paste = Helper::getPaste(); - $this->_model->create(Helper::getPasteId(), $paste); $_GET['jsonld'] = 'paste'; ob_start(); new Controller; @@ -205,8 +206,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase */ public function testJsonLdComment() { - $paste = Helper::getPaste(); - $this->_model->create(Helper::getPasteId(), $paste); $_GET['jsonld'] = 'comment'; ob_start(); new Controller; @@ -224,8 +223,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase */ public function testJsonLdPasteMeta() { - $paste = Helper::getPaste(); - $this->_model->create(Helper::getPasteId(), $paste); $_GET['jsonld'] = 'pastemeta'; ob_start(); new Controller; @@ -243,8 +240,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase */ public function testJsonLdCommentMeta() { - $paste = Helper::getPaste(); - $this->_model->create(Helper::getPasteId(), $paste); $_GET['jsonld'] = 'commentmeta'; ob_start(); new Controller; @@ -262,8 +257,6 @@ class JsonApiTest extends PHPUnit_Framework_TestCase */ public function testJsonLdInvalid() { - $paste = Helper::getPaste(); - $this->_model->create(Helper::getPasteId(), $paste); $_GET['jsonld'] = CONF; ob_start(); new Controller; @@ -271,4 +264,42 @@ class JsonApiTest extends PHPUnit_Framework_TestCase ob_end_clean(); $this->assertEquals('{}', $content, 'does not output nasty data'); } + + /** + * @runInSeparateProcess + */ + public function testShortenViaYourls() + { + $mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json'; + $options = parse_ini_file(CONF, true); + $options['main']['basepath'] = 'https://example.com/path'; + $options['main']['urlshortener'] = 'https://example.com/path/shortenviayourls?link='; + $options['yourls']['apiurl'] = $mock_yourls_service; + Helper::createIniFile(CONF, $options); + + // the real service answer is more complex, but we only look for the shorturl & statusCode + file_put_contents($mock_yourls_service, '{"shorturl":"https:\/\/example.com\/1","statusCode":200}'); + + $_SERVER['REQUEST_URI'] = '/path/shortenviayourls?link=https%3A%2F%2Fexample.com%2Fpath%2F%3Ffoo%23bar'; + $_GET['link'] = 'https://example.com/path/?foo#bar'; + ob_start(); + new Controller; + $content = ob_get_contents(); + ob_end_clean(); + $this->assertContains('id="pasteurl" href="https://example.com/1"', $content, 'outputs shortened URL correctly'); + } + + /** + * @runInSeparateProcess + */ + public function testShortenViaYourlsFailure() + { + $_SERVER['REQUEST_URI'] = '/path/shortenviayourls?link=https%3A%2F%2Fexample.com%2Fpath%2F%3Ffoo%23bar'; + $_GET['link'] = 'https://example.com/path/?foo#bar'; + ob_start(); + new Controller; + $content = ob_get_contents(); + ob_end_clean(); + $this->assertContains('Error calling YOURLS.', $content, 'outputs error correctly'); + } } diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php new file mode 100644 index 00000000..8c90112c --- /dev/null +++ b/tst/YourlsProxyTest.php @@ -0,0 +1,75 @@ +_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; + if (!is_dir($this->_path)) { + mkdir($this->_path); + } + $this->_mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json'; + $options = parse_ini_file(CONF_SAMPLE, true); + $options['main']['basepath'] = 'https://example.com'; + $options['main']['urlshortener'] = 'https://example.com/shortenviayourls?link='; + $options['yourls']['apiurl'] = $this->_mock_yourls_service; + Helper::confBackup(); + Helper::createIniFile(CONF, $options); + $this->_conf = new Configuration; + } + + public function tearDown() + { + /* Tear Down Routine */ + unlink(CONF); + Helper::confRestore(); + Helper::rmDir($this->_path); + } + + public function testYourlsProxy() + { + // the real service answer is more complex, but we only look for the shorturl & statusCode + file_put_contents($this->_mock_yourls_service, '{"shorturl":"https:\/\/example.com\/1","statusCode":200}'); + + $yourls = new YourlsProxy($this->_conf, 'https://example.com/?foo#bar'); + $this->assertFalse($yourls->isError()); + $this->assertEquals($yourls->getUrl(), 'https://example.com/1'); + } + + public function testForeignUrl() + { + $yourls = new YourlsProxy($this->_conf, 'https://other.example.com/?foo#bar'); + $this->assertTrue($yourls->isError()); + $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); + } + + public function testYourlsError() + { + // when statusCode is not 200, shorturl may not have been set + file_put_contents($this->_mock_yourls_service, '{"statusCode":403}'); + + $yourls = new YourlsProxy($this->_conf, 'https://example.com/?foo#bar'); + $this->assertTrue($yourls->isError()); + $this->assertEquals($yourls->getError(), 'Error parsing YOURLS response.'); + } + + public function testServerError() + { + // simulate some other server error that results in a non-JSON reply + file_put_contents($this->_mock_yourls_service, ''); + + $yourls = new YourlsProxy($this->_conf, 'https://example.com/?foo#bar'); + $this->assertTrue($yourls->isError()); + $this->assertEquals($yourls->getError(), 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'); + } +} \ No newline at end of file From 0a949d39032e940fe131995eb23aa9ef24bc84a3 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 13:10:55 +0200 Subject: [PATCH 074/506] credit change, document it and improve wording --- CHANGELOG.md | 1 + CREDITS.md | 1 + cfg/conf.sample.php | 11 ++++++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6431e67f..b897b676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * CHANGED: Upgrading libraries to: zlib 1.2.13 * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) * FIXED: Apply table prefix to indexes as well, to support multiple instances sharing a single database (#943) + * FIXED: YOURLS integration via new proxy, storing signature in configuration (#725) * **1.4 (2022-04-09)** * ADDED: Translations for Corsican, Estonian, Finnish and Lojban * ADDED: new HTTP headers improving security (#765) diff --git a/CREDITS.md b/CREDITS.md index d0035077..97c11251 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -30,6 +30,7 @@ * Mark van Holsteijn - Google Cloud Storage backend * Austin Huang - Oracle database support * Felix J. Ogris - S3 Storage backend +* Mounir Idrassi & J. Mozdzen - secure YOURLS integration ## Translations * Hexalyse - French diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index 487a20ae..7afe7aae 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -230,9 +230,14 @@ dir = PATH "data" [yourls] ; don't mix this up with "urlshortener" config item: -; - when using a standard configuration, "urlshortener" will point to the YOURLS API, including access credentials, and will be part of the PrivateBin public web page (insecure!) -; - when using the parameters in this section ("signature" and "apiurl"), "urlshortener" will point to a fixed PrivateBin page ("$basepath/shortenviayourls.php") and -; that PHP will in turn call YOURLS server-side, using the URL from "apiurl" and using the "access signature" from "signature" parameter. +; - when using a standard configuration, "urlshortener" will point to the YOURLS +; API, including access credentials, and will be part of the PrivateBin public +; web page (insecure!) +; - when using the parameters in this section ("signature" and "apiurl"), +; "urlshortener" will point to a fixed PrivateBin page +; ("$basepath/shortenviayourls?link=") and that URL will in turn call YOURLS +; server-side, using the URL from "apiurl" and the "access signature" from the +; "signature" parameters below. ; (optional) the "signature" (access key) issued by YOURLS for the using account ; signature = "" From 2776033997c5b7d18a6c929bf983653ccc9aa124 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 13:13:12 +0200 Subject: [PATCH 075/506] apply StyleCI recommendations --- tst/JsonApiTest.php | 2 +- tst/YourlsProxyTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index 058bd320..6f48b1b4 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -295,7 +295,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase public function testShortenViaYourlsFailure() { $_SERVER['REQUEST_URI'] = '/path/shortenviayourls?link=https%3A%2F%2Fexample.com%2Fpath%2F%3Ffoo%23bar'; - $_GET['link'] = 'https://example.com/path/?foo#bar'; + $_GET['link'] = 'https://example.com/path/?foo#bar'; ob_start(); new Controller; $content = ob_get_contents(); diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 8c90112c..6e4df607 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -72,4 +72,4 @@ class YourlsProxyTest extends PHPUnit_Framework_TestCase $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'); } -} \ No newline at end of file +} From 44f78ffcdf6d59ca370d51608f5d0724bd5686e4 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 13:14:27 +0200 Subject: [PATCH 076/506] apply StyleCI recommendations --- tst/JsonApiTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index 6f48b1b4..4ad629ee 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -281,7 +281,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase file_put_contents($mock_yourls_service, '{"shorturl":"https:\/\/example.com\/1","statusCode":200}'); $_SERVER['REQUEST_URI'] = '/path/shortenviayourls?link=https%3A%2F%2Fexample.com%2Fpath%2F%3Ffoo%23bar'; - $_GET['link'] = 'https://example.com/path/?foo#bar'; + $_GET['link'] = 'https://example.com/path/?foo#bar'; ob_start(); new Controller; $content = ob_get_contents(); From a66f170c5e9812bf4564db9909b459086e165d29 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Oct 2022 13:21:22 +0200 Subject: [PATCH 077/506] PHP 5.6 seems to tolerate an empty string as valid JSON --- tst/YourlsProxyTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 6e4df607..2e372995 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -66,7 +66,7 @@ class YourlsProxyTest extends PHPUnit_Framework_TestCase public function testServerError() { // simulate some other server error that results in a non-JSON reply - file_put_contents($this->_mock_yourls_service, ''); + file_put_contents($this->_mock_yourls_service, '500 Internal Server Error'); $yourls = new YourlsProxy($this->_conf, 'https://example.com/?foo#bar'); $this->assertTrue($yourls->isError()); From fef83a37efd92df29da195599bb0c791c762df4e Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 23 Oct 2022 22:46:25 +0200 Subject: [PATCH 078/506] New translations en.json (Slovak) --- i18n/sk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/sk.json b/i18n/sk.json index a1efd043..f8926cbb 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -187,7 +187,7 @@ "URL shortener may expose your decrypt key in URL.": "Skracovač adries URL môže odhaliť váš dešifrovací kľúč v adrese URL.", "Save paste": "Uložiť príspevok", "Your IP is not authorized to create pastes.": "Vaša IP adresa nie je oprávnená vytvárať príspevky.", - "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Trying to shorten a URL that isn't pointing at our instance.": "Pokúšate sa skrátiť adresu URL, ktorá neukazuje na túto inštanciu.", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", "Error parsing YOURLS response.": "Error parsing YOURLS response." } From 5e513588db20792e2758e4ee99d7b38380c73bbf Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 06:08:09 +0200 Subject: [PATCH 079/506] New translations en.json (German) --- i18n/de.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/de.json b/i18n/de.json index 7ab57050..813cab9e 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -187,7 +187,7 @@ "URL shortener may expose your decrypt key in URL.": "Der URL-Verkürzer kann den Schlüssel in der URL enthüllen.", "Save paste": "Text speichern", "Your IP is not authorized to create pastes.": "Deine IP ist nicht berechtigt, Texte zu erstellen.", - "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", - "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Trying to shorten a URL that isn't pointing at our instance.": "Versuch eine URL zu verkürzen, die nicht auf unsere Instanz zeigt.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Fehler beim Aufruf von YOURLS. Wahrscheinlich ein Konfigurationsproblem, wie eine falsche oder fehlende \"apiurl\" oder \"signature\".", + "Error parsing YOURLS response.": "Fehler beim Verarbeiten der YOURLS-Antwort." } From 849c1c7cd16dafcc36670cfad137cdf8f2ee80ee Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 25 Oct 2022 06:34:40 +0200 Subject: [PATCH 080/506] fix display of configured name in twitter title --- i18n/ar.json | 2 +- i18n/bg.json | 2 +- i18n/ca.json | 2 +- i18n/co.json | 2 +- i18n/cs.json | 2 +- i18n/de.json | 2 +- i18n/el.json | 2 +- i18n/en.json | 2 +- i18n/es.json | 2 +- i18n/et.json | 2 +- i18n/fi.json | 2 +- i18n/fr.json | 2 +- i18n/he.json | 2 +- i18n/hi.json | 2 +- i18n/hu.json | 2 +- i18n/id.json | 2 +- i18n/it.json | 2 +- i18n/ja.json | 2 +- i18n/jbo.json | 2 +- i18n/ku.json | 2 +- i18n/la.json | 2 +- i18n/lt.json | 2 +- i18n/nl.json | 2 +- i18n/no.json | 2 +- i18n/oc.json | 2 +- i18n/pl.json | 2 +- i18n/pt.json | 2 +- i18n/ru.json | 2 +- i18n/sk.json | 2 +- i18n/sl.json | 2 +- i18n/sv.json | 2 +- i18n/tr.json | 2 +- i18n/uk.json | 2 +- i18n/zh.json | 2 +- tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 36 files changed, 36 insertions(+), 36 deletions(-) diff --git a/i18n/ar.json b/i18n/ar.json index dbc85bcf..204b61bb 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/bg.json b/i18n/bg.json index ec8f540d..244763bb 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/ca.json b/i18n/ca.json index 154110d4..b1e09367 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/co.json b/i18n/co.json index 90b6811d..c0659b31 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Impiegà u fusu orariu attuale", "Convert To UTC": "Cunvertisce in UTC", "Close": "Chjode", - "Encrypted note on PrivateBin": "Nota cifrata nant’à PrivateBin", + "Encrypted note on %s": "Nota cifrata nant’à %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitate stu liame per vede a nota. Date l’indirizzu à qualunque li permette d’accede à a nota dinù.", "URL shortener may expose your decrypt key in URL.": "Un ammuzzatore d’indirizzu pò palisà a vostra chjave di dicifratura in l’indirizzu.", "Save paste": "Arregistrà l’appiccicu", diff --git a/i18n/cs.json b/i18n/cs.json index 6996f9ad..a0121e9f 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Použít aktuální časové pásmo", "Convert To UTC": "Převést na UTC", "Close": "Zavřít", - "Encrypted note on PrivateBin": "Šifrovaná poznámka ve službě PrivateBin", + "Encrypted note on %s": "Šifrovaná poznámka ve službě %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.", "URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.", "Save paste": "Uložit příspěvek", diff --git a/i18n/de.json b/i18n/de.json index 7ab57050..fc2065bb 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Aktuelle Zeitzone verwenden", "Convert To UTC": "In UTC umwandeln", "Close": "Schliessen", - "Encrypted note on PrivateBin": "Verschlüsselte Notiz auf PrivateBin", + "Encrypted note on %s": "Verschlüsselte Notiz auf %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besuche diesen Link um das Dokument zu sehen. Wird die URL an eine andere Person gegeben, so kann diese Person ebenfalls auf dieses Dokument zugreifen.", "URL shortener may expose your decrypt key in URL.": "Der URL-Verkürzer kann den Schlüssel in der URL enthüllen.", "Save paste": "Text speichern", diff --git a/i18n/el.json b/i18n/el.json index 4f1a601c..fbb14805 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Χρήση τρέχουσας ζώνης ώρας", "Convert To UTC": "Μετατροπή σε UTC", "Close": "Κλείσιμο", - "Encrypted note on PrivateBin": "Κρυπτογραφημένο μήνυμα από το PrivateBin", + "Encrypted note on %s": "Κρυπτογραφημένο μήνυμα από το %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφτείτε αυτόν τον σύνδεσμο για να δείτε το μήνυμα. Δίνοντας τον σύνδεσμο σε οποιονδήποτε, του επιτρέπετε να επισκεφτεί το μήνυμα επίσης.", "URL shortener may expose your decrypt key in URL.": "Συντομευτές συνδέσμων πιθανώς να δημοσιοποιήσουν το κλειδί αποκρυπτογράφισης στον σύνδεσμο.", "Save paste": "Αποθήκευση επικόλλησης", diff --git a/i18n/en.json b/i18n/en.json index ac71b5ae..a4d6d350 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/es.json b/i18n/es.json index c3687023..45e8ecbc 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Usar Zona Horaria Actual", "Convert To UTC": "Convertir A UTC", "Close": "Cerrar", - "Encrypted note on PrivateBin": "Nota cifrada en PrivateBin", + "Encrypted note on %s": "Nota cifrada en %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite este enlace para ver la nota. Dar la URL a cualquier persona también les permite acceder a la nota.", "URL shortener may expose your decrypt key in URL.": "El acortador de URL puede exponer su clave de descifrado en el URL.", "Save paste": "Guardar \"paste\"", diff --git a/i18n/et.json b/i18n/et.json index 3a73b83f..4c8e48b8 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Kasuta praegust ajavööndit", "Convert To UTC": "Teisenda UTC-ks", "Close": "Sulge", - "Encrypted note on PrivateBin": "Krüpteeritud kiri PrivateBin-is", + "Encrypted note on %s": "Krüpteeritud kiri %s-is", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kirja nägemiseks külasta seda linki. Teistele URL-i andmine lubab ka neil ligi pääseda kirjale.", "URL shortener may expose your decrypt key in URL.": "URL-i lühendaja võib paljastada sinu dekrüpteerimisvõtme URL-is.", "Save paste": "Salvesta kleebe", diff --git a/i18n/fi.json b/i18n/fi.json index 1956bf41..665ea278 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Käytä nykyistä aikavyöhykettä", "Convert To UTC": "Muuta UTC:ksi", "Close": "Sulje", - "Encrypted note on PrivateBin": "Salattu viesti PrivateBinissä", + "Encrypted note on %s": "Salattu viesti %sissä", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Käy tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomeen viestiä. ", "URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.", "Save paste": "Tallenna paste", diff --git a/i18n/fr.json b/i18n/fr.json index 19f99c0a..788bd5d5 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Conserver l'actuel", "Convert To UTC": "Convertir en UTC", "Close": "Fermer", - "Encrypted note on PrivateBin": "Message chiffré sur PrivateBin", + "Encrypted note on %s": "Message chiffré sur %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visiter ce lien pour voir la note. Donner l'URL à une autre personne lui permet également d'accéder à la note.", "URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.", "Save paste": "Sauver le paste", diff --git a/i18n/he.json b/i18n/he.json index 3d25ff33..0a1bae6c 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -182,7 +182,7 @@ "Use Current Timezone": "להשתמש באזור הזמן הנוכחי", "Convert To UTC": "המרה ל־UTC", "Close": "סגירה", - "Encrypted note on PrivateBin": "הערה מוצפנת ב־PrivateBin", + "Encrypted note on %s": "הערה מוצפנת ב־%s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "נא לבקר בקישור כדי לצפות בהערה. מסירת הקישור לאנשים כלשהם תאפשר גם להם לגשת להערה.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/hi.json b/i18n/hi.json index 4eee3825..7e8d8c07 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/hu.json b/i18n/hu.json index 19f7f16d..ffe15514 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Az aktuális időzóna használata", "Convert To UTC": "Átalakítás UTC időzónára", "Close": "Bezárás", - "Encrypted note on PrivateBin": "Titkosított jegyzet a PrivateBinen", + "Encrypted note on %s": "Titkosított jegyzet a %sen", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Látogasd meg ezt a hivatkozást a bejegyzés megtekintéséhez. Ha mások számára is megadod ezt a linket, azzal hozzáférnek ők is.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/id.json b/i18n/id.json index b3171df8..4c5af357 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Gunakan Zonawaktu Saat Ini", "Convert To UTC": "Konversi Ke UTC", "Close": "Tutup", - "Encrypted note on PrivateBin": "Catatan ter-ekrip di PrivateBin", + "Encrypted note on %s": "Catatan ter-ekrip di %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kunjungi tautan ini untuk melihat catatan. Memberikan alamat URL pada siapapun juga, akan mengizinkan mereka untuk mengakses catatan, so pasti gitu loh Kaka.", "URL shortener may expose your decrypt key in URL.": "Pemendek URL mungkin akan menampakkan kunci dekrip Anda dalam URL.", "Save paste": "Simpan paste", diff --git a/i18n/it.json b/i18n/it.json index c724e1fd..49112b31 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Usa Fuso Orario Corrente", "Convert To UTC": "Converti a UTC", "Close": "Chiudi", - "Encrypted note on PrivateBin": "Nota crittografata su PrivateBin", + "Encrypted note on %s": "Nota crittografata su %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visita questo collegamento per vedere la nota. Dare l'URL a chiunque consente anche a loro di accedere alla nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener può esporre la tua chiave decrittografata nell'URL.", "Save paste": "Salva il messagio", diff --git a/i18n/ja.json b/i18n/ja.json index 6f6d9acd..6f243f92 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/jbo.json b/i18n/jbo.json index 8bb399a3..307e0303 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "galfi lo cabni la utc", "Close": "ganlo", - "Encrypted note on PrivateBin": ".i lo lo notci ku mifra cu zvati sivlolnitvanku'a", + "Encrypted note on %s": ".i lo lo notci ku mifra cu zvati %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "rejgau fukpi", diff --git a/i18n/ku.json b/i18n/ku.json index adb5cd5b..8a0bbaac 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/la.json b/i18n/la.json index ef2bdf7f..54d9b3f8 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/lt.json b/i18n/lt.json index 25684e4f..74f36d82 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Naudoti esamą laiko juostą", "Convert To UTC": "Konvertuoti į UTC", "Close": "Užverti", - "Encrypted note on PrivateBin": "Šifruoti užrašai ties PrivateBin", + "Encrypted note on %s": "Šifruoti užrašai ties %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.", "URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.", "Save paste": "Įrašyti įdėjimą", diff --git a/i18n/nl.json b/i18n/nl.json index 8fbb8781..600d41ed 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Gebruik huidige tijdzone", "Convert To UTC": "Omzetten naar UTC", "Close": "Sluiten", - "Encrypted note on PrivateBin": "Versleutelde notitie op PrivateBin", + "Encrypted note on %s": "Versleutelde notitie op %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Bezoek deze link om de notitie te bekijken. Als je de URL aan iemand geeft, kan die de notitie ook bekijken.", "URL shortener may expose your decrypt key in URL.": "URL-verkorter kan uw ontcijferingssleutel in URL blootleggen.", "Save paste": "Notitie opslaan", diff --git a/i18n/no.json b/i18n/no.json index a2215245..251487e0 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Bruk gjeldende tidssone", "Convert To UTC": "Konverter til UTC", "Close": "Steng", - "Encrypted note on PrivateBin": "Kryptert notat på PrivateBin", + "Encrypted note on %s": "Kryptert notat på %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besøk denne lenken for å se notatet. Hvis lenken deles med andre, vil de også kunne se notatet.", "URL shortener may expose your decrypt key in URL.": "URL forkorter kan avsløre dekrypteringsnøkkelen.", "Save paste": "Lagre utklipp", diff --git a/i18n/oc.json b/i18n/oc.json index 4890f4a4..d277368d 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Utilizar l’actual", "Convert To UTC": "Convertir en UTC", "Close": "Tampar", - "Encrypted note on PrivateBin": "Nòtas chifradas sus PrivateBin", + "Encrypted note on %s": "Nòtas chifradas sus %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitatz aqueste ligam per veire la nòta. Fornir lo ligam a qualqu’un mai li permet tanben d’accedir a la nòta.", "URL shortener may expose your decrypt key in URL.": "Los espleches d’acorchiment d’URL pòdon expausar la clau de deschiframent dins l’URL.", "Save paste": "Enregistrar lo tèxt", diff --git a/i18n/pl.json b/i18n/pl.json index 09bfb25b..933e67c7 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/pt.json b/i18n/pt.json index f7cc09bd..6d890a13 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Usar Fuso Horário Atual", "Convert To UTC": "Converter para UTC", "Close": "Fechar", - "Encrypted note on PrivateBin": "Nota criptografada no PrivateBin", + "Encrypted note on %s": "Nota criptografada no %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite esse link para ver a nota. Dar a URL para qualquer um permite que eles também acessem a nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/ru.json b/i18n/ru.json index 677de762..1c708196 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Использовать текущий часовой пояс", "Convert To UTC": "Конвертировать в UTC", "Close": "Закрыть", - "Encrypted note on PrivateBin": "Зашифрованная запись на PrivateBin", + "Encrypted note on %s": "Зашифрованная запись на %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Посетите эту ссылку чтобы просмотреть запись. Передача ссылки кому либо позволит им получить доступ к записи тоже.", "URL shortener may expose your decrypt key in URL.": "Сервис сокращения ссылок может получить ваш ключ расшифровки из ссылки.", "Save paste": "Сохранить запись", diff --git a/i18n/sk.json b/i18n/sk.json index a1efd043..62af7241 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Použiť aktuálne časové pásmo", "Convert To UTC": "Previesť na UTC", "Close": "Zavrieť", - "Encrypted note on PrivateBin": "Zašifrovaná poznámka na PrivateBin", + "Encrypted note on %s": "Zašifrovaná poznámka na %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Ak chcete zobraziť poznámku, navštívte tento odkaz. Poskytnutie adresy URL komukoľvek im umožní prístup aj k poznámke.", "URL shortener may expose your decrypt key in URL.": "Skracovač adries URL môže odhaliť váš dešifrovací kľúč v adrese URL.", "Save paste": "Uložiť príspevok", diff --git a/i18n/sl.json b/i18n/sl.json index b1628fc3..099f98d5 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/sv.json b/i18n/sv.json index ac8a5843..87ee2a02 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", diff --git a/i18n/tr.json b/i18n/tr.json index 3b3ad126..79a52da3 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Şuanki zaman dilimini kullan", "Convert To UTC": "UTC zaman dilimine çevir", "Close": "Kapat", - "Encrypted note on PrivateBin": "PrivateBin üzerinde şifrelenmiş not", + "Encrypted note on %s": "%s üzerinde şifrelenmiş not", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Notu görmek için bu bağlantıyı ziyaret et. Bağlantıya sahip olan birisi notu görebilir.", "URL shortener may expose your decrypt key in URL.": "URL kısaltıcı şifreleme anahtarınızı URL içerisinde gösterebilir.", "Save paste": "Yazıyı kaydet", diff --git a/i18n/uk.json b/i18n/uk.json index c2f2c5f4..946dea4a 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Використовувати поточний часовий пояс", "Convert To UTC": "Конвертувати в UTC", "Close": "Закрити", - "Encrypted note on PrivateBin": "Зашифрована нотатка на PrivateBin", + "Encrypted note on %s": "Зашифрована нотатка на %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Відвідайте посилання, щоб переглянути нотатку. Передача посилання будь-кому дозволить їм переглянути нотатку.", "URL shortener may expose your decrypt key in URL.": "Сервіс скорочення посилань може викрити ваш ключ дешифрування з URL.", "Save paste": "Зберегти вставку", diff --git a/i18n/zh.json b/i18n/zh.json index 004f5926..e5e60a52 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -182,7 +182,7 @@ "Use Current Timezone": "使用当前时区", "Convert To UTC": "转换为 UTC", "Close": "关闭", - "Encrypted note on PrivateBin": "PrivateBin 上的加密笔记", + "Encrypted note on %s": "%s 上的加密笔记", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "访问此链接来查看该笔记。将此 URL 发送给任何人即可允许其访问该笔记。", "URL shortener may expose your decrypt key in URL.": "短链接服务可能会暴露您在 URL 中的解密密钥。", "Save paste": "保存内容", diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 97e028a3..3dd49135 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -85,7 +85,7 @@ endif; - + diff --git a/tpl/page.php b/tpl/page.php index 7636f31a..f91cb7dd 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -63,7 +63,7 @@ endif; - + From 17d7a6967e0b92474d865624e5e49ddfd48d7079 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 25 Oct 2022 06:39:50 +0200 Subject: [PATCH 081/506] make YourlsProxyTest compatible with newer phpunit --- tst/YourlsProxyTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 2e372995..1895503b 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -3,7 +3,7 @@ use PrivateBin\Configuration; use PrivateBin\YourlsProxy; -class YourlsProxyTest extends PHPUnit_Framework_TestCase +class YourlsProxyTest extends TestCase { private $_conf; From 522c2721a286f3367c3ce038e1a574d7a5120295 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 25 Oct 2022 06:41:42 +0200 Subject: [PATCH 082/506] make YourlsProxyTest compatible with newer phpunit --- tst/YourlsProxyTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 1895503b..fb12137d 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -1,5 +1,6 @@ Date: Tue, 25 Oct 2022 06:43:17 +0200 Subject: [PATCH 083/506] make YourlsProxyTest compatible with newer phpunit --- tst/YourlsProxyTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index fb12137d..389f1b35 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -12,7 +12,7 @@ class YourlsProxyTest extends TestCase private $_mock_yourls_service; - public function setUp() + public function setUp(): void { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; @@ -29,7 +29,7 @@ class YourlsProxyTest extends TestCase $this->_conf = new Configuration; } - public function tearDown() + public function tearDown(): void { /* Tear Down Routine */ unlink(CONF); From 27965d0287c31516be1170cf26b39e07dff14676 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 25 Oct 2022 06:53:07 +0200 Subject: [PATCH 084/506] make tests compatible with newer phpunit --- tst/ControllerTest.php | 2 +- tst/I18nTest.php | 2 +- tst/JsonApiTest.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tst/ControllerTest.php b/tst/ControllerTest.php index 5e3b924b..6656cf66 100644 --- a/tst/ControllerTest.php +++ b/tst/ControllerTest.php @@ -66,7 +66,7 @@ class ControllerTest extends TestCase $content, 'doesn\'t output shortener button' ); - $this->assertRegExp( + $this->assertMatchesRegularExpression( '# href="https://' . preg_quote($_SERVER['HTTP_HOST']) . '/">switching to HTTPS#', $content, 'outputs configured https URL correctly' diff --git a/tst/I18nTest.php b/tst/I18nTest.php index ac4cfcb0..98eaa32f 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -189,7 +189,7 @@ class I18nTest extends TestCase foreach (array_keys($languages) as $language) { // most languages don't translate the data size units, ignore those if ($messageId !== 'B' && strlen($messageId) !== 3 && strpos($messageId, 'B', 2) !== 2) { - $this->assertContains( + $this->assertStringContains( $messageId, $languages[$language], "message ID '$messageId' exists in translation file $language.json" diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index a9f73b38..328d66be 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -287,7 +287,7 @@ class JsonApiTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertContains('id="pasteurl" href="https://example.com/1"', $content, 'outputs shortened URL correctly'); + $this->assertStringContains('id="pasteurl" href="https://example.com/1"', $content, 'outputs shortened URL correctly'); } /** @@ -301,6 +301,6 @@ class JsonApiTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertContains('Error calling YOURLS.', $content, 'outputs error correctly'); + $this->assertStringContains('Error calling YOURLS.', $content, 'outputs error correctly'); } } From b890d768d150e441ca0ecd304fed15066b9aec7b Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 25 Oct 2022 06:53:26 +0200 Subject: [PATCH 085/506] enable use of PHP 8.2 --- .github/workflows/tests.yml | 43 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 367bd839..9d96ac88 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,23 +12,23 @@ jobs: run: composer validate - name: Install dependencies run: composer install --prefer-dist --no-dev - + PHPunit: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['7.3', '7.4', '8.0', '8.1'] + php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2'] name: PHP ${{ matrix.php-versions }} unit tests on ${{ matrix.operating-system }} env: extensions: gd, sqlite3 extensions-cache-key-name: phpextensions - + steps: - + # let's get started! - name: Checkout uses: actions/checkout@v3 - + # cache PHP extensions - name: Setup cache environment id: extcache @@ -44,29 +44,29 @@ jobs: path: ${{ steps.extcache.outputs.dir }} key: ${{ steps.extcache.outputs.key }} restore-keys: ${{ runner.os }}-${{ env.extensions-cache-key }} - + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} extensions: ${{ env.extensions }} - + # Setup GitHub CI PHP problem matchers # https://github.com/shivammathur/setup-php#problem-matchers - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + - name: Setup problem matchers for PHPUnit run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - + # composer cache - name: Remove composer lock run: rm composer.lock - + - name: Get composer cache directory id: composer-cache run: echo "::set-output name=dir::$(composer config cache-files-dir)" - + # http://man7.org/linux/man-pages/man1/date.1.html # https://github.com/actions/cache#creating-a-cache-key - name: Get Date @@ -74,48 +74,47 @@ jobs: run: | echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" shell: bash - + - name: Cache dependencies uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}- - + # composer installation - name: Setup PHPunit run: composer install -n - name: Install Google Cloud Storage run: composer require google/cloud-storage - + # testing - name: Run unit tests run: ../vendor/bin/phpunit --no-coverage working-directory: tst - + Mocha: runs-on: ubuntu-latest steps: - + - name: Checkout uses: actions/checkout@v3 - + - name: Setup Node uses: actions/setup-node@v3 with: node-version: '16' cache: 'npm' cache-dependency-path: 'js/package-lock.json' - + - name: Setup Mocha run: npm install -g mocha - + - name: Setup Node modules run: npm ci working-directory: js - + - name: Run unit tests run: npm test working-directory: js - From 510103fd9f5fa144d0f998a71603630d43a7c32e Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 25 Oct 2022 06:55:24 +0200 Subject: [PATCH 086/506] make tests compatible with newer phpunit --- tst/I18nTest.php | 2 +- tst/JsonApiTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tst/I18nTest.php b/tst/I18nTest.php index 98eaa32f..09597032 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -189,7 +189,7 @@ class I18nTest extends TestCase foreach (array_keys($languages) as $language) { // most languages don't translate the data size units, ignore those if ($messageId !== 'B' && strlen($messageId) !== 3 && strpos($messageId, 'B', 2) !== 2) { - $this->assertStringContains( + $this->assertStringContainsString( $messageId, $languages[$language], "message ID '$messageId' exists in translation file $language.json" diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index 328d66be..96024fed 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -287,7 +287,7 @@ class JsonApiTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertStringContains('id="pasteurl" href="https://example.com/1"', $content, 'outputs shortened URL correctly'); + $this->assertStringContainsString('id="pasteurl" href="https://example.com/1"', $content, 'outputs shortened URL correctly'); } /** @@ -301,6 +301,6 @@ class JsonApiTest extends TestCase new Controller; $content = ob_get_contents(); ob_end_clean(); - $this->assertStringContains('Error calling YOURLS.', $content, 'outputs error correctly'); + $this->assertStringContainsString('Error calling YOURLS.', $content, 'outputs error correctly'); } } From 5b3d61cedccd80eb1582a5e62cb26c201d14ae08 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 25 Oct 2022 06:58:42 +0200 Subject: [PATCH 087/506] revert, this one actually was correct --- tst/I18nTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/I18nTest.php b/tst/I18nTest.php index 09597032..ac4cfcb0 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -189,7 +189,7 @@ class I18nTest extends TestCase foreach (array_keys($languages) as $language) { // most languages don't translate the data size units, ignore those if ($messageId !== 'B' && strlen($messageId) !== 3 && strpos($messageId, 'B', 2) !== 2) { - $this->assertStringContainsString( + $this->assertContains( $messageId, $languages[$language], "message ID '$messageId' exists in translation file $language.json" From 930063442ac7630273221b604b450889151d75b8 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:35 +0200 Subject: [PATCH 088/506] New translations en.json (French) --- i18n/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fr.json b/i18n/fr.json index 19f99c0a..84d6197c 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Conserver l'actuel", "Convert To UTC": "Convertir en UTC", "Close": "Fermer", - "Encrypted note on PrivateBin": "Message chiffré sur PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visiter ce lien pour voir la note. Donner l'URL à une autre personne lui permet également d'accéder à la note.", "URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.", "Save paste": "Sauver le paste", From f8bb6efcf9aa215a041f854e0e6f6ff1f27fc6f8 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:37 +0200 Subject: [PATCH 089/506] New translations en.json (Polish) --- i18n/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/pl.json b/i18n/pl.json index 09bfb25b..933e67c7 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 09902b9d67c94341aac075d143a226acfe943a73 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:38 +0200 Subject: [PATCH 090/506] New translations en.json (Occitan) --- i18n/oc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/oc.json b/i18n/oc.json index 4890f4a4..2bbfcc44 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Utilizar l’actual", "Convert To UTC": "Convertir en UTC", "Close": "Tampar", - "Encrypted note on PrivateBin": "Nòtas chifradas sus PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitatz aqueste ligam per veire la nòta. Fornir lo ligam a qualqu’un mai li permet tanben d’accedir a la nòta.", "URL shortener may expose your decrypt key in URL.": "Los espleches d’acorchiment d’URL pòdon expausar la clau de deschiframent dins l’URL.", "Save paste": "Enregistrar lo tèxt", From a1b4fcdefbc657f01651c8bd9a0c5af94b660710 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:39 +0200 Subject: [PATCH 091/506] New translations en.json (Latin) --- i18n/la.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/la.json b/i18n/la.json index ef2bdf7f..54d9b3f8 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From f31e3849808cacde3a816c466c4eccfa2995e9ec Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:39 +0200 Subject: [PATCH 092/506] New translations en.json (Lojban) --- i18n/jbo.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/jbo.json b/i18n/jbo.json index 8bb399a3..1c7a7860 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "galfi lo cabni la utc", "Close": "ganlo", - "Encrypted note on PrivateBin": ".i lo lo notci ku mifra cu zvati sivlolnitvanku'a", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "rejgau fukpi", From c2ec38e0a3b2d5f41eca57898bd83758f5ecef08 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:41 +0200 Subject: [PATCH 093/506] New translations en.json (Hindi) --- i18n/hi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/hi.json b/i18n/hi.json index 4eee3825..7e8d8c07 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 08ac373b127b0abdbd0a6f4f6c19edf68b66a6a9 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:42 +0200 Subject: [PATCH 094/506] New translations en.json (Estonian) --- i18n/et.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/et.json b/i18n/et.json index 3a73b83f..71c4e01c 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Kasuta praegust ajavööndit", "Convert To UTC": "Teisenda UTC-ks", "Close": "Sulge", - "Encrypted note on PrivateBin": "Krüpteeritud kiri PrivateBin-is", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kirja nägemiseks külasta seda linki. Teistele URL-i andmine lubab ka neil ligi pääseda kirjale.", "URL shortener may expose your decrypt key in URL.": "URL-i lühendaja võib paljastada sinu dekrüpteerimisvõtme URL-is.", "Save paste": "Salvesta kleebe", From 989fe6cc3a85815977f666474693a164d98164b2 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:44 +0200 Subject: [PATCH 095/506] New translations en.json (Indonesian) --- i18n/id.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/id.json b/i18n/id.json index b3171df8..5b21a65e 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Gunakan Zonawaktu Saat Ini", "Convert To UTC": "Konversi Ke UTC", "Close": "Tutup", - "Encrypted note on PrivateBin": "Catatan ter-ekrip di PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kunjungi tautan ini untuk melihat catatan. Memberikan alamat URL pada siapapun juga, akan mengizinkan mereka untuk mengakses catatan, so pasti gitu loh Kaka.", "URL shortener may expose your decrypt key in URL.": "Pemendek URL mungkin akan menampakkan kunci dekrip Anda dalam URL.", "Save paste": "Simpan paste", From c9144def9f107de2c9c7dc01c791a859ce500d9f Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:45 +0200 Subject: [PATCH 096/506] New translations en.json (Chinese Simplified) --- i18n/zh.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/zh.json b/i18n/zh.json index 004f5926..358b52fb 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -182,7 +182,7 @@ "Use Current Timezone": "使用当前时区", "Convert To UTC": "转换为 UTC", "Close": "关闭", - "Encrypted note on PrivateBin": "PrivateBin 上的加密笔记", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "访问此链接来查看该笔记。将此 URL 发送给任何人即可允许其访问该笔记。", "URL shortener may expose your decrypt key in URL.": "短链接服务可能会暴露您在 URL 中的解密密钥。", "Save paste": "保存内容", From 5cb40e1f9e41bbaf67022f0fc71d42777eb3766a Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:46 +0200 Subject: [PATCH 097/506] New translations en.json (Ukrainian) --- i18n/uk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/uk.json b/i18n/uk.json index c2f2c5f4..512221f9 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Використовувати поточний часовий пояс", "Convert To UTC": "Конвертувати в UTC", "Close": "Закрити", - "Encrypted note on PrivateBin": "Зашифрована нотатка на PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Відвідайте посилання, щоб переглянути нотатку. Передача посилання будь-кому дозволить їм переглянути нотатку.", "URL shortener may expose your decrypt key in URL.": "Сервіс скорочення посилань може викрити ваш ключ дешифрування з URL.", "Save paste": "Зберегти вставку", From 40a037b6252c01993c428af9950b831329d19c9b Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:47 +0200 Subject: [PATCH 098/506] New translations en.json (Turkish) --- i18n/tr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/tr.json b/i18n/tr.json index 3b3ad126..62243cbc 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Şuanki zaman dilimini kullan", "Convert To UTC": "UTC zaman dilimine çevir", "Close": "Kapat", - "Encrypted note on PrivateBin": "PrivateBin üzerinde şifrelenmiş not", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Notu görmek için bu bağlantıyı ziyaret et. Bağlantıya sahip olan birisi notu görebilir.", "URL shortener may expose your decrypt key in URL.": "URL kısaltıcı şifreleme anahtarınızı URL içerisinde gösterebilir.", "Save paste": "Yazıyı kaydet", From 534d014254f474c50caf8fa07c5acb5ba1990a73 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:48 +0200 Subject: [PATCH 099/506] New translations en.json (Swedish) --- i18n/sv.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/sv.json b/i18n/sv.json index ac8a5843..87ee2a02 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 79c4ace626749fd71958d1ba65a5306bad424e4e Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:49 +0200 Subject: [PATCH 100/506] New translations en.json (Slovenian) --- i18n/sl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/sl.json b/i18n/sl.json index b1628fc3..099f98d5 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 8a9761b430265de7ce656e401bce7e888a5edc5a Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:50 +0200 Subject: [PATCH 101/506] New translations en.json (Slovak) --- i18n/sk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/sk.json b/i18n/sk.json index f8926cbb..d746ca1b 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Použiť aktuálne časové pásmo", "Convert To UTC": "Previesť na UTC", "Close": "Zavrieť", - "Encrypted note on PrivateBin": "Zašifrovaná poznámka na PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Ak chcete zobraziť poznámku, navštívte tento odkaz. Poskytnutie adresy URL komukoľvek im umožní prístup aj k poznámke.", "URL shortener may expose your decrypt key in URL.": "Skracovač adries URL môže odhaliť váš dešifrovací kľúč v adrese URL.", "Save paste": "Uložiť príspevok", From b756da5839ab6adf89a8401af2b6682b85e3f9c2 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:51 +0200 Subject: [PATCH 102/506] New translations en.json (Russian) --- i18n/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ru.json b/i18n/ru.json index 677de762..2da31743 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Использовать текущий часовой пояс", "Convert To UTC": "Конвертировать в UTC", "Close": "Закрыть", - "Encrypted note on PrivateBin": "Зашифрованная запись на PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Посетите эту ссылку чтобы просмотреть запись. Передача ссылки кому либо позволит им получить доступ к записи тоже.", "URL shortener may expose your decrypt key in URL.": "Сервис сокращения ссылок может получить ваш ключ расшифровки из ссылки.", "Save paste": "Сохранить запись", From 06b01c57ac87ae6dee03700d2630c191ac5fd20b Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:52 +0200 Subject: [PATCH 103/506] New translations en.json (Portuguese) --- i18n/pt.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/pt.json b/i18n/pt.json index f7cc09bd..f09f15cc 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Usar Fuso Horário Atual", "Convert To UTC": "Converter para UTC", "Close": "Fechar", - "Encrypted note on PrivateBin": "Nota criptografada no PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite esse link para ver a nota. Dar a URL para qualquer um permite que eles também acessem a nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 019c8b64b80da9f7fe86b9df80e3be4178fcc923 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:53 +0200 Subject: [PATCH 104/506] New translations en.json (Norwegian) --- i18n/no.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/no.json b/i18n/no.json index a2215245..070e01aa 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Bruk gjeldende tidssone", "Convert To UTC": "Konverter til UTC", "Close": "Steng", - "Encrypted note on PrivateBin": "Kryptert notat på PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besøk denne lenken for å se notatet. Hvis lenken deles med andre, vil de også kunne se notatet.", "URL shortener may expose your decrypt key in URL.": "URL forkorter kan avsløre dekrypteringsnøkkelen.", "Save paste": "Lagre utklipp", From 7ab3f3f2716ef4b7735e2e4794656f698efe40ca Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:54 +0200 Subject: [PATCH 105/506] New translations en.json (Spanish) --- i18n/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/es.json b/i18n/es.json index c3687023..efbb9204 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Usar Zona Horaria Actual", "Convert To UTC": "Convertir A UTC", "Close": "Cerrar", - "Encrypted note on PrivateBin": "Nota cifrada en PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite este enlace para ver la nota. Dar la URL a cualquier persona también les permite acceder a la nota.", "URL shortener may expose your decrypt key in URL.": "El acortador de URL puede exponer su clave de descifrado en el URL.", "Save paste": "Guardar \"paste\"", From d288f2ab738d7880dd0510f8d1115265538ce823 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:56 +0200 Subject: [PATCH 106/506] New translations en.json (Dutch) --- i18n/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/nl.json b/i18n/nl.json index 8fbb8781..c838f860 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Gebruik huidige tijdzone", "Convert To UTC": "Omzetten naar UTC", "Close": "Sluiten", - "Encrypted note on PrivateBin": "Versleutelde notitie op PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Bezoek deze link om de notitie te bekijken. Als je de URL aan iemand geeft, kan die de notitie ook bekijken.", "URL shortener may expose your decrypt key in URL.": "URL-verkorter kan uw ontcijferingssleutel in URL blootleggen.", "Save paste": "Notitie opslaan", From 945435e133cbdb6f1419d06ed930854f25cc7ab9 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:57 +0200 Subject: [PATCH 107/506] New translations en.json (Lithuanian) --- i18n/lt.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/lt.json b/i18n/lt.json index 25684e4f..6b6d2770 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Naudoti esamą laiko juostą", "Convert To UTC": "Konvertuoti į UTC", "Close": "Užverti", - "Encrypted note on PrivateBin": "Šifruoti užrašai ties PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.", "URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.", "Save paste": "Įrašyti įdėjimą", From 3d4f9cc1b3d89f46be1fb318f9dcd192fa969fdb Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:58 +0200 Subject: [PATCH 108/506] New translations en.json (Kurdish) --- i18n/ku.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ku.json b/i18n/ku.json index adb5cd5b..8a0bbaac 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From c2d5c6fc43ea48d63ecc975283c86c3f7e57ee28 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:04:59 +0200 Subject: [PATCH 109/506] New translations en.json (Japanese) --- i18n/ja.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ja.json b/i18n/ja.json index 6f6d9acd..6f243f92 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From f254285b01c7d4e4fbe3a81a512f756b5e68d6b7 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:00 +0200 Subject: [PATCH 110/506] New translations en.json (Italian) --- i18n/it.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/it.json b/i18n/it.json index c724e1fd..e7a28160 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Usa Fuso Orario Corrente", "Convert To UTC": "Converti a UTC", "Close": "Chiudi", - "Encrypted note on PrivateBin": "Nota crittografata su PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visita questo collegamento per vedere la nota. Dare l'URL a chiunque consente anche a loro di accedere alla nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener può esporre la tua chiave decrittografata nell'URL.", "Save paste": "Salva il messagio", From f713b92893261a65fcbc4565b3e44d63afa35f4d Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:01 +0200 Subject: [PATCH 111/506] New translations en.json (Hungarian) --- i18n/hu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/hu.json b/i18n/hu.json index 19f7f16d..1d792dc0 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Az aktuális időzóna használata", "Convert To UTC": "Átalakítás UTC időzónára", "Close": "Bezárás", - "Encrypted note on PrivateBin": "Titkosított jegyzet a PrivateBinen", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Látogasd meg ezt a hivatkozást a bejegyzés megtekintéséhez. Ha mások számára is megadod ezt a linket, azzal hozzáférnek ők is.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From d6c5f97d5891965c0eaf221862011daea2279f3e Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:03 +0200 Subject: [PATCH 112/506] New translations en.json (Hebrew) --- i18n/he.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/he.json b/i18n/he.json index 3d25ff33..227d6787 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -182,7 +182,7 @@ "Use Current Timezone": "להשתמש באזור הזמן הנוכחי", "Convert To UTC": "המרה ל־UTC", "Close": "סגירה", - "Encrypted note on PrivateBin": "הערה מוצפנת ב־PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "נא לבקר בקישור כדי לצפות בהערה. מסירת הקישור לאנשים כלשהם תאפשר גם להם לגשת להערה.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 3845298804c9a221297f6a8e07859f575c486ad2 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:04 +0200 Subject: [PATCH 113/506] New translations en.json (Finnish) --- i18n/fi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fi.json b/i18n/fi.json index 1956bf41..01e01daa 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Käytä nykyistä aikavyöhykettä", "Convert To UTC": "Muuta UTC:ksi", "Close": "Sulje", - "Encrypted note on PrivateBin": "Salattu viesti PrivateBinissä", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Käy tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomeen viestiä. ", "URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.", "Save paste": "Tallenna paste", From d0d0621bac6ef3d87b48c048c3322fa163b87616 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:05 +0200 Subject: [PATCH 114/506] New translations en.json (Greek) --- i18n/el.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/el.json b/i18n/el.json index 4f1a601c..15291a22 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Χρήση τρέχουσας ζώνης ώρας", "Convert To UTC": "Μετατροπή σε UTC", "Close": "Κλείσιμο", - "Encrypted note on PrivateBin": "Κρυπτογραφημένο μήνυμα από το PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Επισκεφτείτε αυτόν τον σύνδεσμο για να δείτε το μήνυμα. Δίνοντας τον σύνδεσμο σε οποιονδήποτε, του επιτρέπετε να επισκεφτεί το μήνυμα επίσης.", "URL shortener may expose your decrypt key in URL.": "Συντομευτές συνδέσμων πιθανώς να δημοσιοποιήσουν το κλειδί αποκρυπτογράφισης στον σύνδεσμο.", "Save paste": "Αποθήκευση επικόλλησης", From 3de21004c4e0263d66c91a9b1b949303572df524 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:07 +0200 Subject: [PATCH 115/506] New translations en.json (German) --- i18n/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/de.json b/i18n/de.json index 813cab9e..fca3b988 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Aktuelle Zeitzone verwenden", "Convert To UTC": "In UTC umwandeln", "Close": "Schliessen", - "Encrypted note on PrivateBin": "Verschlüsselte Notiz auf PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besuche diesen Link um das Dokument zu sehen. Wird die URL an eine andere Person gegeben, so kann diese Person ebenfalls auf dieses Dokument zugreifen.", "URL shortener may expose your decrypt key in URL.": "Der URL-Verkürzer kann den Schlüssel in der URL enthüllen.", "Save paste": "Text speichern", From 0a1fccea11af2017d90d4378addc860b10243549 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:09 +0200 Subject: [PATCH 116/506] New translations en.json (Czech) --- i18n/cs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/cs.json b/i18n/cs.json index 6996f9ad..e97bf541 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Použít aktuální časové pásmo", "Convert To UTC": "Převést na UTC", "Close": "Zavřít", - "Encrypted note on PrivateBin": "Šifrovaná poznámka ve službě PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.", "URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.", "Save paste": "Uložit příspěvek", From 7b40893497979c52aa730045c9ff05afcc645070 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:10 +0200 Subject: [PATCH 117/506] New translations en.json (Catalan) --- i18n/ca.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ca.json b/i18n/ca.json index 154110d4..b1e09367 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From da48f8a9a1863b8f23d081fadd6fecaaf9691f5f Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:11 +0200 Subject: [PATCH 118/506] New translations en.json (Bulgarian) --- i18n/bg.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/bg.json b/i18n/bg.json index ec8f540d..244763bb 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 92c42afdc7bfc703f8d3d93d16ff5d3aefdc317c Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:12 +0200 Subject: [PATCH 119/506] New translations en.json (Arabic) --- i18n/ar.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ar.json b/i18n/ar.json index dbc85bcf..204b61bb 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Use Current Timezone", "Convert To UTC": "Convert To UTC", "Close": "Close", - "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 2eab8adcd1d8836ee381d6fa60837e3add5d415f Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 07:05:13 +0200 Subject: [PATCH 120/506] New translations en.json (Corsican) --- i18n/co.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/co.json b/i18n/co.json index 90b6811d..1e43c10f 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Impiegà u fusu orariu attuale", "Convert To UTC": "Cunvertisce in UTC", "Close": "Chjode", - "Encrypted note on PrivateBin": "Nota cifrata nant’à PrivateBin", + "Encrypted note on %s": "Encrypted note on %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitate stu liame per vede a nota. Date l’indirizzu à qualunque li permette d’accede à a nota dinù.", "URL shortener may expose your decrypt key in URL.": "Un ammuzzatore d’indirizzu pò palisà a vostra chjave di dicifratura in l’indirizzu.", "Save paste": "Arregistrà l’appiccicu", From bff4d3a016349c4e628b9ee12eda51938b2225f0 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 25 Oct 2022 07:15:09 +0200 Subject: [PATCH 121/506] PHP 8.2 compatibility: Use of "self" in callables is deprecated --- lib/Data/Database.php | 4 ++-- lib/Data/Filesystem.php | 4 ++-- lib/I18n.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index c34ee131..3ca7b756 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -584,7 +584,7 @@ class Database extends AbstractData // workaround for https://bugs.php.net/bug.php?id=46728 $result = array(); while ($row = $statement->fetch(PDO::FETCH_ASSOC)) { - $result[] = array_map('self::_sanitizeClob', $row); + $result[] = array_map('PrivateBin\Data\Database::_sanitizeClob', $row); } } else { $result = $statement->fetchAll(PDO::FETCH_ASSOC); @@ -593,7 +593,7 @@ class Database extends AbstractData if (self::$_type === 'oci' && is_array($result)) { // returned CLOB values are streams, convert these into strings $result = $firstOnly ? - array_map('self::_sanitizeClob', $result) : + array_map('PrivateBin\Data\Database::_sanitizeClob', $result) : $result; } return $result; diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index b2bc1eed..9674513c 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -351,7 +351,7 @@ class Filesystem extends AbstractData $pastes = array(); $firstLevel = array_filter( scandir(self::$_path), - 'self::_isFirstLevelDir' + 'PrivateBin\Data\Filesystem::_isFirstLevelDir' ); if (count($firstLevel) > 0) { // try at most 10 times the $batchsize pastes before giving up @@ -359,7 +359,7 @@ class Filesystem extends AbstractData $firstKey = array_rand($firstLevel); $secondLevel = array_filter( scandir(self::$_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]), - 'self::_isSecondLevelDir' + 'PrivateBin\Data\Filesystem::_isSecondLevelDir' ); // skip this folder in the next checks if it is empty diff --git a/lib/I18n.php b/lib/I18n.php index 6394a584..c3c635f7 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -84,7 +84,7 @@ class I18n */ public static function _($messageId) { - return forward_static_call_array('self::translate', func_get_args()); + return forward_static_call_array('PrivateBin\I18n::translate', func_get_args()); } /** From 5e48a927f279cfeead4a3736fe217a8a98f8de04 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:22 +0200 Subject: [PATCH 122/506] New translations en.json (Lithuanian) --- i18n/lt.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/lt.json b/i18n/lt.json index 6b6d2770..74f36d82 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Naudoti esamą laiko juostą", "Convert To UTC": "Konvertuoti į UTC", "Close": "Užverti", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "Šifruoti užrašai ties %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.", "URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.", "Save paste": "Įrašyti įdėjimą", From 7269755bc289fc4ad7feb40853e406a5e042268c Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:23 +0200 Subject: [PATCH 123/506] New translations en.json (Dutch) --- i18n/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/nl.json b/i18n/nl.json index c838f860..600d41ed 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Gebruik huidige tijdzone", "Convert To UTC": "Omzetten naar UTC", "Close": "Sluiten", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "Versleutelde notitie op %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Bezoek deze link om de notitie te bekijken. Als je de URL aan iemand geeft, kan die de notitie ook bekijken.", "URL shortener may expose your decrypt key in URL.": "URL-verkorter kan uw ontcijferingssleutel in URL blootleggen.", "Save paste": "Notitie opslaan", From ab3e8ffd49c2ae154536b85bedc947d2eb2e3e1c Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:24 +0200 Subject: [PATCH 124/506] New translations en.json (Norwegian) --- i18n/no.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/no.json b/i18n/no.json index 070e01aa..251487e0 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Bruk gjeldende tidssone", "Convert To UTC": "Konverter til UTC", "Close": "Steng", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "Kryptert notat på %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besøk denne lenken for å se notatet. Hvis lenken deles med andre, vil de også kunne se notatet.", "URL shortener may expose your decrypt key in URL.": "URL forkorter kan avsløre dekrypteringsnøkkelen.", "Save paste": "Lagre utklipp", From cd0a7effa0032ad3981755303167162a7125e058 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:25 +0200 Subject: [PATCH 125/506] New translations en.json (Portuguese) --- i18n/pt.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/pt.json b/i18n/pt.json index f09f15cc..6d890a13 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Usar Fuso Horário Atual", "Convert To UTC": "Converter para UTC", "Close": "Fechar", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "Nota criptografada no %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite esse link para ver a nota. Dar a URL para qualquer um permite que eles também acessem a nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From ed5859c6b642c7780605bfebca1eebf5d4c22a07 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:27 +0200 Subject: [PATCH 126/506] New translations en.json (Russian) --- i18n/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ru.json b/i18n/ru.json index 2da31743..1c708196 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Использовать текущий часовой пояс", "Convert To UTC": "Конвертировать в UTC", "Close": "Закрыть", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "Зашифрованная запись на %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Посетите эту ссылку чтобы просмотреть запись. Передача ссылки кому либо позволит им получить доступ к записи тоже.", "URL shortener may expose your decrypt key in URL.": "Сервис сокращения ссылок может получить ваш ключ расшифровки из ссылки.", "Save paste": "Сохранить запись", From 60b091d0e1d7a76e433c2b141cdb7e6455054663 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:28 +0200 Subject: [PATCH 127/506] New translations en.json (Slovak) --- i18n/sk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/sk.json b/i18n/sk.json index d746ca1b..e23d2957 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Použiť aktuálne časové pásmo", "Convert To UTC": "Previesť na UTC", "Close": "Zavrieť", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "Zašifrovaná poznámka na %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Ak chcete zobraziť poznámku, navštívte tento odkaz. Poskytnutie adresy URL komukoľvek im umožní prístup aj k poznámke.", "URL shortener may expose your decrypt key in URL.": "Skracovač adries URL môže odhaliť váš dešifrovací kľúč v adrese URL.", "Save paste": "Uložiť príspevok", From b1f24a51c8b99655e55f0b949944239ac1b3b44e Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:29 +0200 Subject: [PATCH 128/506] New translations en.json (Turkish) --- i18n/tr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/tr.json b/i18n/tr.json index 62243cbc..79a52da3 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Şuanki zaman dilimini kullan", "Convert To UTC": "UTC zaman dilimine çevir", "Close": "Kapat", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "%s üzerinde şifrelenmiş not", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Notu görmek için bu bağlantıyı ziyaret et. Bağlantıya sahip olan birisi notu görebilir.", "URL shortener may expose your decrypt key in URL.": "URL kısaltıcı şifreleme anahtarınızı URL içerisinde gösterebilir.", "Save paste": "Yazıyı kaydet", From ec75ef6e364920dcb8930f3fbb1539ef8c4c816c Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:30 +0200 Subject: [PATCH 129/506] New translations en.json (Ukrainian) --- i18n/uk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/uk.json b/i18n/uk.json index 512221f9..946dea4a 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Використовувати поточний часовий пояс", "Convert To UTC": "Конвертувати в UTC", "Close": "Закрити", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "Зашифрована нотатка на %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Відвідайте посилання, щоб переглянути нотатку. Передача посилання будь-кому дозволить їм переглянути нотатку.", "URL shortener may expose your decrypt key in URL.": "Сервіс скорочення посилань може викрити ваш ключ дешифрування з URL.", "Save paste": "Зберегти вставку", From 5584fdb347321131530830287e8a65ce36153eba Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:31 +0200 Subject: [PATCH 130/506] New translations en.json (Chinese Simplified) --- i18n/zh.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/zh.json b/i18n/zh.json index 358b52fb..e5e60a52 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -182,7 +182,7 @@ "Use Current Timezone": "使用当前时区", "Convert To UTC": "转换为 UTC", "Close": "关闭", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "%s 上的加密笔记", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "访问此链接来查看该笔记。将此 URL 发送给任何人即可允许其访问该笔记。", "URL shortener may expose your decrypt key in URL.": "短链接服务可能会暴露您在 URL 中的解密密钥。", "Save paste": "保存内容", From c3041924b68798c592441764d86a8776d6d5370d Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:03:32 +0200 Subject: [PATCH 131/506] New translations en.json (Occitan) --- i18n/oc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/oc.json b/i18n/oc.json index 2bbfcc44..d277368d 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Utilizar l’actual", "Convert To UTC": "Convertir en UTC", "Close": "Tampar", - "Encrypted note on %s": "Encrypted note on %s", + "Encrypted note on %s": "Nòtas chifradas sus %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitatz aqueste ligam per veire la nòta. Fornir lo ligam a qualqu’un mai li permet tanben d’accedir a la nòta.", "URL shortener may expose your decrypt key in URL.": "Los espleches d’acorchiment d’URL pòdon expausar la clau de deschiframent dins l’URL.", "Save paste": "Enregistrar lo tèxt", From 18a957ee5418cd41fb4a19d09ed5850aa521451f Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 21:01:17 +0200 Subject: [PATCH 132/506] New translations en.json (Hebrew) --- i18n/he.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/he.json b/i18n/he.json index 0a1bae6c..6bd54fcc 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -182,7 +182,7 @@ "Use Current Timezone": "להשתמש באזור הזמן הנוכחי", "Convert To UTC": "המרה ל־UTC", "Close": "סגירה", - "Encrypted note on %s": "הערה מוצפנת ב־%s", + "Encrypted note on %s": "%sהערה מוצפנת ב־", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "נא לבקר בקישור כדי לצפות בהערה. מסירת הקישור לאנשים כלשהם תאפשר גם להם לגשת להערה.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 1a828884d14220cba8bbbc1003f772bf40ff4fc6 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Tue, 25 Oct 2022 21:01:18 +0200 Subject: [PATCH 133/506] New translations en.json (Hungarian) --- i18n/hu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/hu.json b/i18n/hu.json index ffe15514..5f760df3 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -182,7 +182,7 @@ "Use Current Timezone": "Az aktuális időzóna használata", "Convert To UTC": "Átalakítás UTC időzónára", "Close": "Bezárás", - "Encrypted note on %s": "Titkosított jegyzet a %sen", + "Encrypted note on %s": "Titkosított jegyzet a %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Látogasd meg ezt a hivatkozást a bejegyzés megtekintéséhez. Ha mások számára is megadod ezt a linket, azzal hozzáférnek ők is.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", "Save paste": "Save paste", From 7b98d7381f6b7d3b18fd8b183a8c7ba334200610 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 05:30:37 +0200 Subject: [PATCH 134/506] allow tests to be manually triggered --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9d96ac88..74c74352 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,5 +1,7 @@ name: Tests -on: [push] +on: + push: + workflow_dispatch: jobs: From ae6248e27ef784a7a967f9aa09d022d8e1d294f3 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 05:48:39 +0200 Subject: [PATCH 135/506] handle github actions deprecation warnings see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ --- .github/workflows/tests.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2b1194e1..721c729f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -65,14 +65,13 @@ jobs: - name: Get composer cache directory id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" + run: echo "{dir}={$(composer config cache-files-dir)}" >> $GITHUB_OUTPUT # http://man7.org/linux/man-pages/man1/date.1.html # https://github.com/actions/cache#creating-a-cache-key - name: Get Date id: get-date - run: | - echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" + run: echo "{date}={$(/bin/date -u "+%Y%m%d")}" >> $GITHUB_OUTPUT shell: bash - name: Cache dependencies From ba4878056b7e3df7c7d0e9e11389d30b81060b87 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 05:51:36 +0200 Subject: [PATCH 136/506] misleading documentation --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 721c729f..e13e5364 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -65,13 +65,13 @@ jobs: - name: Get composer cache directory id: composer-cache - run: echo "{dir}={$(composer config cache-files-dir)}" >> $GITHUB_OUTPUT + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT # http://man7.org/linux/man-pages/man1/date.1.html # https://github.com/actions/cache#creating-a-cache-key - name: Get Date id: get-date - run: echo "{date}={$(/bin/date -u "+%Y%m%d")}" >> $GITHUB_OUTPUT + run: echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT shell: bash - name: Cache dependencies From 8ac69590cf9c81826a891979b60150f72970b06c Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 06:53:56 +0200 Subject: [PATCH 137/506] add new Jdenticon comment icon library, set it as default, fixes #793 --- cfg/conf.sample.php | 5 +- composer.json | 3 +- composer.lock | 695 ++++++++---------- lib/Configuration.php | 2 +- lib/Model/Comment.php | 13 +- tst/ModelTest.php | 13 +- vendor/composer/ClassLoader.php | 157 +++- vendor/composer/InstalledVersions.php | 350 +++++++++ vendor/composer/autoload_classmap.php | 39 + vendor/composer/autoload_psr4.php | 1 + vendor/composer/autoload_real.php | 15 +- vendor/composer/autoload_static.php | 47 ++ vendor/composer/installed.php | 59 ++ vendor/composer/platform_check.php | 26 + .../jdenticon/jdenticon/src/Canvas/Canvas.php | 130 ++++ .../jdenticon/src/Canvas/CanvasContext.php | 408 ++++++++++ .../jdenticon/src/Canvas/ColorUtils.php | 228 ++++++ .../jdenticon/jdenticon/src/Canvas/Matrix.php | 141 ++++ .../jdenticon/src/Canvas/Png/PngBuffer.php | 92 +++ .../jdenticon/src/Canvas/Png/PngEncoder.php | 238 ++++++ .../jdenticon/src/Canvas/Png/PngPalette.php | 92 +++ .../jdenticon/jdenticon/src/Canvas/Point.php | 41 ++ .../src/Canvas/Rasterization/Edge.php | 44 ++ .../Canvas/Rasterization/EdgeIntersection.php | 27 + .../EdgeSuperSampleIntersection.php | 24 + .../src/Canvas/Rasterization/EdgeTable.php | 158 ++++ .../src/Canvas/Rasterization/Layer.php | 30 + .../src/Canvas/Rasterization/LayerManager.php | 150 ++++ .../src/Canvas/Rasterization/Rasterizer.php | 379 ++++++++++ .../Rasterization/SuperSampleBuffer.php | 198 +++++ .../Canvas/Rasterization/SuperSampleRange.php | 27 + vendor/jdenticon/jdenticon/src/Color.php | 605 +++++++++++++++ vendor/jdenticon/jdenticon/src/Identicon.php | 492 +++++++++++++ .../jdenticon/src/IdenticonStyle.php | 460 ++++++++++++ .../src/Rendering/AbstractRenderer.php | 209 ++++++ .../jdenticon/src/Rendering/ColorTheme.php | 84 +++ .../jdenticon/src/Rendering/IconGenerator.php | 290 ++++++++ .../src/Rendering/ImagickRenderer.php | 296 ++++++++ .../src/Rendering/InternalPngRenderer.php | 123 ++++ .../jdenticon/src/Rendering/Point.php | 54 ++ .../jdenticon/src/Rendering/Rectangle.php | 60 ++ .../src/Rendering/RendererInterface.php | 141 ++++ .../jdenticon/src/Rendering/SvgPath.php | 83 +++ .../jdenticon/src/Rendering/SvgRenderer.php | 133 ++++ .../jdenticon/src/Rendering/Transform.php | 79 ++ .../src/Rendering/TriangleDirection.php | 35 + .../jdenticon/jdenticon/src/Shapes/Shape.php | 62 ++ .../jdenticon/src/Shapes/ShapeCategory.php | 71 ++ .../jdenticon/src/Shapes/ShapeDefinitions.php | 243 ++++++ .../jdenticon/src/Shapes/ShapePosition.php | 45 ++ 50 files changed, 6996 insertions(+), 401 deletions(-) create mode 100644 vendor/composer/InstalledVersions.php create mode 100644 vendor/composer/installed.php create mode 100644 vendor/composer/platform_check.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Canvas.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/CanvasContext.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/ColorUtils.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Matrix.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Png/PngBuffer.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Png/PngEncoder.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Png/PngPalette.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Point.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Edge.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeIntersection.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeSuperSampleIntersection.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeTable.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Layer.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/LayerManager.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Rasterizer.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php create mode 100644 vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleRange.php create mode 100644 vendor/jdenticon/jdenticon/src/Color.php create mode 100644 vendor/jdenticon/jdenticon/src/Identicon.php create mode 100644 vendor/jdenticon/jdenticon/src/IdenticonStyle.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/AbstractRenderer.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/ColorTheme.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/IconGenerator.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/Point.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/Rectangle.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/RendererInterface.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/SvgPath.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/SvgRenderer.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/Transform.php create mode 100644 vendor/jdenticon/jdenticon/src/Rendering/TriangleDirection.php create mode 100644 vendor/jdenticon/jdenticon/src/Shapes/Shape.php create mode 100644 vendor/jdenticon/jdenticon/src/Shapes/ShapeCategory.php create mode 100644 vendor/jdenticon/jdenticon/src/Shapes/ShapeDefinitions.php create mode 100644 vendor/jdenticon/jdenticon/src/Shapes/ShapePosition.php diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index 7afe7aae..ba6fff55 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -67,8 +67,9 @@ languageselection = false ; (optional) IP based icons are a weak mechanism to detect if a comment was from ; a different user when the same username was used in a comment. It might be ; used to get the IP of a non anonymous comment poster if the server salt is -; leaked and a SHA256 HMAC rainbow table is generated for all (relevant) IPs. -; Can be set to one these values: "none" / "vizhash" / "identicon" (default). +; leaked and a SHA512 HMAC rainbow table is generated for all (relevant) IPs. +; Can be set to one these values: +; "none" / "vizhash" / "identicon" / "jdenticon" (default). ; icon = "none" ; Content Security Policy headers allow a website to restrict what sources are diff --git a/composer.json b/composer.json index 01d384f2..6e99d5de 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "php" : "^5.6.0 || ^7.0 || ^8.0", "paragonie/random_compat" : "2.0.21", "yzalis/identicon" : "2.0.0", - "mlocati/ip-lib" : "1.18.0" + "mlocati/ip-lib" : "1.18.0", + "jdenticon/jdenticon": "^1.0" }, "suggest" : { "google/cloud-storage" : "1.26.1", diff --git a/composer.lock b/composer.lock index a159dd80..17948976 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,57 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fa52d4988bfe17d4b27e3a4789a1ec49", + "content-hash": "17bceced29627163f7aa330a0697f68b", "packages": [ + { + "name": "jdenticon/jdenticon", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dmester/jdenticon-php.git", + "reference": "994ee07293fb978f983393ffcb2c0250592a6ac4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dmester/jdenticon-php/zipball/994ee07293fb978f983393ffcb2c0250592a6ac4", + "reference": "994ee07293fb978f983393ffcb2c0250592a6ac4", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Jdenticon\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Mester Pirttijärvi" + } + ], + "description": "Render PNG and SVG identicons.", + "homepage": "https://jdenticon.com/", + "keywords": [ + "avatar", + "identicon", + "jdenticon" + ], + "support": { + "docs": "https://jdenticon.com/php-api.html", + "issues": "https://github.com/dmester/jdenticon-php/issues", + "source": "https://github.com/dmester/jdenticon-php" + }, + "time": "2022-07-02T11:03:15+00:00" + }, { "name": "mlocati/ip-lib", "version": "1.18.0", @@ -61,6 +110,10 @@ "range", "subnet" ], + "support": { + "issues": "https://github.com/mlocati/ip-lib/issues", + "source": "https://github.com/mlocati/ip-lib/tree/1.18.0" + }, "funding": [ { "url": "https://github.com/sponsors/mlocati", @@ -120,6 +173,11 @@ "pseudorandom", "random" ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, "time": "2022-02-16T17:07:03+00:00" }, { @@ -172,6 +230,10 @@ "identicon", "image" ], + "support": { + "issues": "https://github.com/yzalis/Identicon/issues", + "source": "https://github.com/yzalis/Identicon/tree/master" + }, "abandoned": true, "time": "2019-10-14T09:30:57+00:00" } @@ -179,29 +241,30 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.0", + "doctrine/coding-standard": "^9", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" }, "type": "library", "autoload": { @@ -226,6 +289,10 @@ "constructor", "instantiate" ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -240,32 +307,33 @@ "type": "tidelift" } ], - "time": "2020-11-10T18:47:58+00:00" + "time": "2022-03-03T08:28:38+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.10.2", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, - "replace": { - "myclabs/deep-copy": "self.version" + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { @@ -288,97 +356,53 @@ "object", "object graph" ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], - "time": "2020-11-13T09:40:50+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2020-06-27T09:03:43+00:00" + "time": "2022-03-03T13:19:32+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e6a969a640b00d8daa3c66518b0405fb41ae0c4b", + "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b", "shasum": "" }, "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" + "php": ">=5.3.3" }, "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" + "psr-0": { + "phpDocumentor": [ + "src/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -388,96 +412,46 @@ "authors": [ { "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "email": "mike.vanriel@naenius.com" } ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706" + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/2.x" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706", - "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2022-01-04T19:58:01+00:00" + "time": "2016-01-25T08:17:30+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.10.3", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "451c3cd1418cf640de218914901e51b064abb093" + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", - "reference": "451c3cd1418cf640de218914901e51b064abb093", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", - "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1" }, "require-dev": { - "phpspec/phpspec": "^2.5 || ^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + "phpspec/phpspec": "~2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.10.x-dev" + "dev-master": "1.4.x-dev" } }, "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" + "psr-0": { + "Prophecy\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -505,44 +479,48 @@ "spy", "stub" ], - "time": "2020-03-05T15:02:03+00:00" + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/master" + }, + "time": "2015-08-13T10:07:40+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.8", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + "reference": "85f5db2d0a0da79ad6a256eb54148ba383059ad9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85f5db2d0a0da79ad6a256eb54148ba383059ad9", + "reference": "85f5db2d0a0da79ad6a256eb54148ba383059ad9", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" + "php": ">=5.6", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/code-unit-reverse-lookup": "~1.0", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0|~2.0" }, "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~5" }, "suggest": { - "ext-xdebug": "^2.5.1" + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "3.2.x-dev" } }, "autoload": { @@ -568,7 +546,12 @@ "testing", "xunit" ], - "time": "2017-04-02T07:44:40+00:00" + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/3.2.0" + }, + "time": "2016-02-13T06:47:56+00:00" }, { "name": "phpunit/php-file-iterator", @@ -615,6 +598,11 @@ "filesystem", "iterator" ], + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" + }, "time": "2017-11-27T13:52:08+00:00" }, { @@ -656,32 +644,36 @@ "keywords": [ "template" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + }, "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "1.0.9", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -696,7 +688,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -705,33 +697,43 @@ "keywords": [ "timer" ], - "time": "2017-02-26T11:10:40+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/php-token-stream", - "version": "2.0.2", + "version": "1.4.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": "^7.0" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "~4.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -754,55 +756,51 @@ "keywords": [ "tokenizer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4" + }, "abandoned": true, - "time": "2017-11-27T05:48:46+00:00" + "time": "2017-12-04T08:55:13+00:00" }, { "name": "phpunit/phpunit", - "version": "5.7.27", + "version": "5.2.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" + "reference": "073701643835376cb2f15dc005ea8933f8d4edbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/073701643835376cb2f15dc005ea8933f8d4edbd", + "reference": "073701643835376cb2f15dc005ea8933f8d4edbd", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.4", + "php": ">=5.6", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~3.2", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "^1.2.4", - "sebastian/diff": "^1.4.3", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "~2.0", + "phpunit/php-timer": ">=1.0.6", + "phpunit/phpunit-mock-objects": ">=3.0.5", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", "sebastian/resource-operations": "~1.0", - "sebastian/version": "^1.0.6|^2.0.1", - "symfony/yaml": "~2.1|~3.0|~4.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" - }, - "require-dev": { - "ext-pdo": "*" + "sebastian/version": "~1.0|~2.0", + "symfony/yaml": "~2.1|~3.0" }, "suggest": { - "ext-xdebug": "*", "phpunit/php-invoker": "~1.1" }, "bin": [ @@ -811,7 +809,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7.x-dev" + "dev-master": "5.2.x-dev" } }, "autoload": { @@ -837,33 +835,35 @@ "testing", "xunit" ], - "time": "2018-02-01T05:50:59+00:00" + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/5.2.7" + }, + "time": "2016-02-18T06:39:51+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.4", + "version": "3.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" + "reference": "151c96874bff6fe61a25039df60e776613a61489" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", - "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/151c96874bff6fe61a25039df60e776613a61489", + "reference": "151c96874bff6fe61a25039df60e776613a61489", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" + "php": ">=5.6", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" }, "require-dev": { - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "~5" }, "suggest": { "ext-soap": "*" @@ -871,7 +871,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -896,8 +896,13 @@ "mock", "xunit" ], + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", + "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/3.1" + }, "abandoned": true, - "time": "2017-06-30T09:13:00+00:00" + "time": "2016-04-20T14:39:26+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -942,6 +947,10 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1012,27 +1021,31 @@ "compare", "equality" ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/1.2" + }, "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", - "version": "1.4.3", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "~4.8" }, "type": "library", "extra": { @@ -1064,32 +1077,36 @@ "keywords": [ "diff" ], - "time": "2017-05-22T07:24:03+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/master" + }, + "time": "2015-12-08T07:14:41+00:00" }, { "name": "sebastian/environment", - "version": "2.0.0", + "version": "1.3.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -1114,25 +1131,29 @@ "environment", "hhvm" ], - "time": "2016-11-26T07:53:53+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/1.3.7" + }, + "time": "2016-05-17T03:18:57+00:00" }, { "name": "sebastian/exporter", - "version": "2.0.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", "shasum": "" }, "require": { "php": ">=5.3.3", - "sebastian/recursion-context": "~2.0" + "sebastian/recursion-context": "~1.0" }, "require-dev": { "ext-mbstring": "*", @@ -1141,7 +1162,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -1181,7 +1202,11 @@ "export", "exporter" ], - "time": "2016-11-19T08:54:04+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/master" + }, + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", @@ -1232,66 +1257,24 @@ "keywords": [ "global state" ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/1.1.1" + }, "time": "2015-10-12T03:26:01+00:00" }, - { - "name": "sebastian/object-enumerator", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", - "shasum": "" - }, - "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-02-18T15:18:39+00:00" - }, { "name": "sebastian/recursion-context", - "version": "2.0.0", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", "shasum": "" }, "require": { @@ -1303,7 +1286,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -1331,7 +1314,11 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-19T07:33:16+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/master" + }, + "time": "2016-10-03T07:41:43+00:00" }, { "name": "sebastian/resource-operations", @@ -1373,6 +1360,10 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/master" + }, "time": "2015-07-28T20:34:47+00:00" }, { @@ -1416,20 +1407,24 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/master" + }, "time": "2016-10-03T07:35:21+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.24.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "30885182c981ab175d4d034db0f6f469898070ab" + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", - "reference": "30885182c981ab175d4d034db0f6f469898070ab", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", "shasum": "" }, "require": { @@ -1444,7 +1439,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.26-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1452,12 +1447,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1481,6 +1476,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1495,31 +1493,31 @@ "type": "tidelift" } ], - "time": "2021-10-20T20:35:02+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/yaml", - "version": "v4.4.37", + "version": "v3.4.47", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "d7f637cc0f0cc14beb0984f2bb50da560b271311" + "reference": "88289caa3c166321883f67fe5130188ebbb47094" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/d7f637cc0f0cc14beb0984f2bb50da560b271311", - "reference": "d7f637cc0f0cc14beb0984f2bb50da560b271311", + "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094", + "reference": "88289caa3c166321883f67fe5130188ebbb47094", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/console": "<3.4" }, "require-dev": { - "symfony/console": "^3.4|^4.0|^5.0" + "symfony/console": "~3.4|~4.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" @@ -1547,8 +1545,11 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Loads and dumps YAML files", + "description": "Symfony Yaml Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v3.4.47" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1563,61 +1564,7 @@ "type": "tidelift" } ], - "time": "2022-01-24T20:11:01+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2021-03-09T10:59:23+00:00" + "time": "2020-10-24T10:57:07+00:00" } ], "aliases": [], @@ -1629,5 +1576,5 @@ "php": "^5.6.0 || ^7.0 || ^8.0" }, "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.2.0" } diff --git a/lib/Configuration.php b/lib/Configuration.php index 6f3a8225..f4e537ef 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -53,7 +53,7 @@ class Configuration 'languagedefault' => '', 'urlshortener' => '', 'qrcode' => true, - 'icon' => 'identicon', + 'icon' => 'jdenticon', 'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\'; style-src \'self\'; font-src \'self\'; frame-ancestors \'none\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads', 'zerobincompatibility' => false, 'httpwarning' => true, diff --git a/lib/Model/Comment.php b/lib/Model/Comment.php index f9f45507..8e4142ee 100644 --- a/lib/Model/Comment.php +++ b/lib/Model/Comment.php @@ -14,6 +14,7 @@ namespace PrivateBin\Model; use Exception; use Identicon\Identicon; +use Jdenticon\Identicon as Jdenticon; use PrivateBin\Persistence\TrafficLimiter; use PrivateBin\Vizhash16x16; @@ -164,7 +165,17 @@ class Comment extends AbstractModel if ($icon != 'none') { $pngdata = ''; $hmac = TrafficLimiter::getHash(); - if ($icon == 'identicon') { + if ($icon == 'jdenticon') { + $jdenticon = new Jdenticon(array( + 'hash' => $hmac, + 'size' => 16, + 'style' => array( + 'backgroundColor' => '#fff0', // fully transparent, for dark mode + 'padding' => 0, + ), + )); + $pngdata = $jdenticon->getImageDataUri('png'); + } elseif ($icon == 'identicon') { $identicon = new Identicon(); $pngdata = $identicon->getImageDataUri($hmac, 16); } elseif ($icon == 'vizhash') { diff --git a/tst/ModelTest.php b/tst/ModelTest.php index a88e0296..49a2ae6b 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -1,6 +1,6 @@ get(); $comment->store(); - $identicon = new Identicon(); - $pngdata = $identicon->getImageDataUri(TrafficLimiter::getHash(), 16); + $identicon = new Identicon(array( + 'hash' => TrafficLimiter::getHash(), + 'size' => 16, + 'style' => array( + 'backgroundColor' => '#fff0', // fully transparent, for dark mode + 'padding' => 0, + ), + )); + $pngdata = $identicon->getImageDataUri('png'); $comment = current($this->_model->getPaste(Helper::getPasteId())->get()['comments']); $this->assertEquals($pngdata, $comment['meta']['icon'], 'icon gets set'); } diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index fce8549f..afef3fa2 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -37,57 +37,130 @@ namespace Composer\Autoload; * * @author Fabien Potencier * @author Jordi Boggiano - * @see http://www.php-fig.org/psr/psr-0/ - * @see http://www.php-fig.org/psr/psr-4/ + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ */ class ClassLoader { + /** @var ?string */ + private $vendorDir; + // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr4 = array(); // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr0 = array(); + /** @var bool */ private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ private $classMap = array(); + + /** @var bool */ private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ private $missingClasses = array(); + + /** @var ?string */ private $apcuPrefix; + /** + * @var self[] + */ + private static $registeredLoaders = array(); + + /** + * @param ?string $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + } + + /** + * @return string[] + */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); } + /** + * @return array[] + * @psalm-return array> + */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } + /** + * @return string[] Array of classname => path + * @psalm-return array + */ public function getClassMap() { return $this->classMap; } /** - * @param array $classMap Class to filename map + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void */ public function addClassMap(array $classMap) { @@ -102,9 +175,11 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { @@ -147,11 +222,13 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -195,8 +272,10 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -211,10 +290,12 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -234,6 +315,8 @@ class ClassLoader * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -256,6 +339,8 @@ class ClassLoader * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -276,6 +361,8 @@ class ClassLoader * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix + * + * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -296,25 +383,44 @@ class ClassLoader * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } } /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } } /** * Loads the given class or interface. * * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise + * @return true|null True if loaded, null otherwise */ public function loadClass($class) { @@ -323,6 +429,8 @@ class ClassLoader return true; } + + return null; } /** @@ -367,6 +475,21 @@ class ClassLoader return $file; } + /** + * Returns the currently registered loaders indexed by their corresponding vendor directories. + * + * @return self[] + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -438,6 +561,10 @@ class ClassLoader * Scope isolated include. * * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + * @private */ function includeFile($file) { diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php new file mode 100644 index 00000000..d50e0c9f --- /dev/null +++ b/vendor/composer/InstalledVersions.php @@ -0,0 +1,350 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints($constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } +} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 3f795c8a..ef2b6e97 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'IPLib\\Address\\AddressInterface' => $vendorDir . '/mlocati/ip-lib/src/Address/AddressInterface.php', 'IPLib\\Address\\AssignedRange' => $vendorDir . '/mlocati/ip-lib/src/Address/AssignedRange.php', 'IPLib\\Address\\IPv4' => $vendorDir . '/mlocati/ip-lib/src/Address/IPv4.php', @@ -28,12 +29,49 @@ return array( 'Identicon\\Generator\\ImageMagickGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php', 'Identicon\\Generator\\SvgGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/SvgGenerator.php', 'Identicon\\Identicon' => $vendorDir . '/yzalis/identicon/src/Identicon/Identicon.php', + 'Jdenticon\\Canvas\\Canvas' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Canvas.php', + 'Jdenticon\\Canvas\\CanvasContext' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/CanvasContext.php', + 'Jdenticon\\Canvas\\ColorUtils' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/ColorUtils.php', + 'Jdenticon\\Canvas\\Matrix' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Matrix.php', + 'Jdenticon\\Canvas\\Png\\PngBuffer' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Png/PngBuffer.php', + 'Jdenticon\\Canvas\\Png\\PngEncoder' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Png/PngEncoder.php', + 'Jdenticon\\Canvas\\Png\\PngPalette' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Png/PngPalette.php', + 'Jdenticon\\Canvas\\Point' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Point.php', + 'Jdenticon\\Canvas\\Rasterization\\Edge' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/Edge.php', + 'Jdenticon\\Canvas\\Rasterization\\EdgeIntersection' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeIntersection.php', + 'Jdenticon\\Canvas\\Rasterization\\EdgeSuperSampleIntersection' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeSuperSampleIntersection.php', + 'Jdenticon\\Canvas\\Rasterization\\EdgeTable' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeTable.php', + 'Jdenticon\\Canvas\\Rasterization\\Layer' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/Layer.php', + 'Jdenticon\\Canvas\\Rasterization\\LayerManager' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/LayerManager.php', + 'Jdenticon\\Canvas\\Rasterization\\Rasterizer' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/Rasterizer.php', + 'Jdenticon\\Canvas\\Rasterization\\SuperSampleBuffer' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php', + 'Jdenticon\\Canvas\\Rasterization\\SuperSampleRange' => $vendorDir . '/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleRange.php', + 'Jdenticon\\Color' => $vendorDir . '/jdenticon/jdenticon/src/Color.php', + 'Jdenticon\\Identicon' => $vendorDir . '/jdenticon/jdenticon/src/Identicon.php', + 'Jdenticon\\IdenticonStyle' => $vendorDir . '/jdenticon/jdenticon/src/IdenticonStyle.php', + 'Jdenticon\\Rendering\\AbstractRenderer' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/AbstractRenderer.php', + 'Jdenticon\\Rendering\\ColorTheme' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/ColorTheme.php', + 'Jdenticon\\Rendering\\IconGenerator' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/IconGenerator.php', + 'Jdenticon\\Rendering\\ImagickRenderer' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php', + 'Jdenticon\\Rendering\\InternalPngRenderer' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php', + 'Jdenticon\\Rendering\\Point' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Point.php', + 'Jdenticon\\Rendering\\Rectangle' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Rectangle.php', + 'Jdenticon\\Rendering\\RendererInterface' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/RendererInterface.php', + 'Jdenticon\\Rendering\\SvgPath' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/SvgPath.php', + 'Jdenticon\\Rendering\\SvgRenderer' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/SvgRenderer.php', + 'Jdenticon\\Rendering\\Transform' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Transform.php', + 'Jdenticon\\Rendering\\TriangleDirection' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/TriangleDirection.php', + 'Jdenticon\\Shapes\\Shape' => $vendorDir . '/jdenticon/jdenticon/src/Shapes/Shape.php', + 'Jdenticon\\Shapes\\ShapeCategory' => $vendorDir . '/jdenticon/jdenticon/src/Shapes/ShapeCategory.php', + 'Jdenticon\\Shapes\\ShapeDefinitions' => $vendorDir . '/jdenticon/jdenticon/src/Shapes/ShapeDefinitions.php', + 'Jdenticon\\Shapes\\ShapePosition' => $vendorDir . '/jdenticon/jdenticon/src/Shapes/ShapePosition.php', 'PrivateBin\\Configuration' => $baseDir . '/lib/Configuration.php', 'PrivateBin\\Controller' => $baseDir . '/lib/Controller.php', 'PrivateBin\\Data\\AbstractData' => $baseDir . '/lib/Data/AbstractData.php', 'PrivateBin\\Data\\Database' => $baseDir . '/lib/Data/Database.php', 'PrivateBin\\Data\\Filesystem' => $baseDir . '/lib/Data/Filesystem.php', 'PrivateBin\\Data\\GoogleCloudStorage' => $baseDir . '/lib/Data/GoogleCloudStorage.php', + 'PrivateBin\\Data\\S3Storage' => $baseDir . '/lib/Data/S3Storage.php', 'PrivateBin\\Filter' => $baseDir . '/lib/Filter.php', 'PrivateBin\\FormatV2' => $baseDir . '/lib/FormatV2.php', 'PrivateBin\\I18n' => $baseDir . '/lib/I18n.php', @@ -49,4 +87,5 @@ return array( 'PrivateBin\\Request' => $baseDir . '/lib/Request.php', 'PrivateBin\\View' => $baseDir . '/lib/View.php', 'PrivateBin\\Vizhash16x16' => $baseDir . '/lib/Vizhash16x16.php', + 'PrivateBin\\YourlsProxy' => $baseDir . '/lib/YourlsProxy.php', ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 9bd3702d..cf4579fa 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -7,6 +7,7 @@ $baseDir = dirname($vendorDir); return array( 'PrivateBin\\' => array($baseDir . '/lib'), + 'Jdenticon\\' => array($vendorDir . '/jdenticon/jdenticon/src'), 'Identicon\\' => array($vendorDir . '/yzalis/identicon/src/Identicon'), 'IPLib\\' => array($vendorDir . '/mlocati/ip-lib/src'), ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 7a6fd4c0..5b03524d 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -22,13 +22,15 @@ class ComposerAutoloaderInitDontChange return self::$loader; } + require __DIR__ . '/platform_check.php'; + spl_autoload_register(array('ComposerAutoloaderInitDontChange', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); spl_autoload_unregister(array('ComposerAutoloaderInitDontChange', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { - require_once __DIR__ . '/autoload_static.php'; + require __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInitDontChange::getInitializer($loader)); } else { @@ -63,11 +65,16 @@ class ComposerAutoloaderInitDontChange } } +/** + * @param string $fileIdentifier + * @param string $file + * @return void + */ function composerRequireDontChange($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; } } diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index ab1f7d33..b03812eb 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -15,6 +15,10 @@ class ComposerStaticInitDontChange array ( 'PrivateBin\\' => 11, ), + 'J' => + array ( + 'Jdenticon\\' => 10, + ), 'I' => array ( 'Identicon\\' => 10, @@ -27,6 +31,10 @@ class ComposerStaticInitDontChange array ( 0 => __DIR__ . '/../..' . '/lib', ), + 'Jdenticon\\' => + array ( + 0 => __DIR__ . '/..' . '/jdenticon/jdenticon/src', + ), 'Identicon\\' => array ( 0 => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon', @@ -38,6 +46,7 @@ class ComposerStaticInitDontChange ); public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'IPLib\\Address\\AddressInterface' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AddressInterface.php', 'IPLib\\Address\\AssignedRange' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AssignedRange.php', 'IPLib\\Address\\IPv4' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/IPv4.php', @@ -60,12 +69,49 @@ class ComposerStaticInitDontChange 'Identicon\\Generator\\ImageMagickGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php', 'Identicon\\Generator\\SvgGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/SvgGenerator.php', 'Identicon\\Identicon' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Identicon.php', + 'Jdenticon\\Canvas\\Canvas' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Canvas.php', + 'Jdenticon\\Canvas\\CanvasContext' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/CanvasContext.php', + 'Jdenticon\\Canvas\\ColorUtils' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/ColorUtils.php', + 'Jdenticon\\Canvas\\Matrix' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Matrix.php', + 'Jdenticon\\Canvas\\Png\\PngBuffer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Png/PngBuffer.php', + 'Jdenticon\\Canvas\\Png\\PngEncoder' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Png/PngEncoder.php', + 'Jdenticon\\Canvas\\Png\\PngPalette' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Png/PngPalette.php', + 'Jdenticon\\Canvas\\Point' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Point.php', + 'Jdenticon\\Canvas\\Rasterization\\Edge' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/Edge.php', + 'Jdenticon\\Canvas\\Rasterization\\EdgeIntersection' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeIntersection.php', + 'Jdenticon\\Canvas\\Rasterization\\EdgeSuperSampleIntersection' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeSuperSampleIntersection.php', + 'Jdenticon\\Canvas\\Rasterization\\EdgeTable' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeTable.php', + 'Jdenticon\\Canvas\\Rasterization\\Layer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/Layer.php', + 'Jdenticon\\Canvas\\Rasterization\\LayerManager' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/LayerManager.php', + 'Jdenticon\\Canvas\\Rasterization\\Rasterizer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/Rasterizer.php', + 'Jdenticon\\Canvas\\Rasterization\\SuperSampleBuffer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php', + 'Jdenticon\\Canvas\\Rasterization\\SuperSampleRange' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleRange.php', + 'Jdenticon\\Color' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Color.php', + 'Jdenticon\\Identicon' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Identicon.php', + 'Jdenticon\\IdenticonStyle' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/IdenticonStyle.php', + 'Jdenticon\\Rendering\\AbstractRenderer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/AbstractRenderer.php', + 'Jdenticon\\Rendering\\ColorTheme' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/ColorTheme.php', + 'Jdenticon\\Rendering\\IconGenerator' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/IconGenerator.php', + 'Jdenticon\\Rendering\\ImagickRenderer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php', + 'Jdenticon\\Rendering\\InternalPngRenderer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php', + 'Jdenticon\\Rendering\\Point' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Point.php', + 'Jdenticon\\Rendering\\Rectangle' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Rectangle.php', + 'Jdenticon\\Rendering\\RendererInterface' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/RendererInterface.php', + 'Jdenticon\\Rendering\\SvgPath' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/SvgPath.php', + 'Jdenticon\\Rendering\\SvgRenderer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/SvgRenderer.php', + 'Jdenticon\\Rendering\\Transform' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Transform.php', + 'Jdenticon\\Rendering\\TriangleDirection' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/TriangleDirection.php', + 'Jdenticon\\Shapes\\Shape' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Shapes/Shape.php', + 'Jdenticon\\Shapes\\ShapeCategory' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Shapes/ShapeCategory.php', + 'Jdenticon\\Shapes\\ShapeDefinitions' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Shapes/ShapeDefinitions.php', + 'Jdenticon\\Shapes\\ShapePosition' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Shapes/ShapePosition.php', 'PrivateBin\\Configuration' => __DIR__ . '/../..' . '/lib/Configuration.php', 'PrivateBin\\Controller' => __DIR__ . '/../..' . '/lib/Controller.php', 'PrivateBin\\Data\\AbstractData' => __DIR__ . '/../..' . '/lib/Data/AbstractData.php', 'PrivateBin\\Data\\Database' => __DIR__ . '/../..' . '/lib/Data/Database.php', 'PrivateBin\\Data\\Filesystem' => __DIR__ . '/../..' . '/lib/Data/Filesystem.php', 'PrivateBin\\Data\\GoogleCloudStorage' => __DIR__ . '/../..' . '/lib/Data/GoogleCloudStorage.php', + 'PrivateBin\\Data\\S3Storage' => __DIR__ . '/../..' . '/lib/Data/S3Storage.php', 'PrivateBin\\Filter' => __DIR__ . '/../..' . '/lib/Filter.php', 'PrivateBin\\FormatV2' => __DIR__ . '/../..' . '/lib/FormatV2.php', 'PrivateBin\\I18n' => __DIR__ . '/../..' . '/lib/I18n.php', @@ -81,6 +127,7 @@ class ComposerStaticInitDontChange 'PrivateBin\\Request' => __DIR__ . '/../..' . '/lib/Request.php', 'PrivateBin\\View' => __DIR__ . '/../..' . '/lib/View.php', 'PrivateBin\\Vizhash16x16' => __DIR__ . '/../..' . '/lib/Vizhash16x16.php', + 'PrivateBin\\YourlsProxy' => __DIR__ . '/../..' . '/lib/YourlsProxy.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php new file mode 100644 index 00000000..9756660e --- /dev/null +++ b/vendor/composer/installed.php @@ -0,0 +1,59 @@ + array( + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'type' => 'project', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => '78aa70e3ab9277172489f9d88f8fd08cc1d03c97', + 'name' => 'privatebin/privatebin', + 'dev' => false, + ), + 'versions' => array( + 'jdenticon/jdenticon' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../jdenticon/jdenticon', + 'aliases' => array(), + 'reference' => '994ee07293fb978f983393ffcb2c0250592a6ac4', + 'dev_requirement' => false, + ), + 'mlocati/ip-lib' => array( + 'pretty_version' => '1.18.0', + 'version' => '1.18.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../mlocati/ip-lib', + 'aliases' => array(), + 'reference' => 'c77bd0b1f3e3956c7e9661e75cb1f54ed67d95d2', + 'dev_requirement' => false, + ), + 'paragonie/random_compat' => array( + 'pretty_version' => 'v2.0.21', + 'version' => '2.0.21.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../paragonie/random_compat', + 'aliases' => array(), + 'reference' => '96c132c7f2f7bc3230723b66e89f8f150b29d5ae', + 'dev_requirement' => false, + ), + 'privatebin/privatebin' => array( + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'type' => 'project', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => '78aa70e3ab9277172489f9d88f8fd08cc1d03c97', + 'dev_requirement' => false, + ), + 'yzalis/identicon' => array( + 'pretty_version' => '2.0.0', + 'version' => '2.0.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../yzalis/identicon', + 'aliases' => array(), + 'reference' => 'ff5ed090129cab9bfa2a322857d4a01d107aa0ae', + 'dev_requirement' => false, + ), + ), +); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php new file mode 100644 index 00000000..8b379f44 --- /dev/null +++ b/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 50600)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Canvas.php b/vendor/jdenticon/jdenticon/src/Canvas/Canvas.php new file mode 100644 index 00000000..6c5222f2 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Canvas.php @@ -0,0 +1,130 @@ +width = $width; + $this->height = $height; + $this->edges = new EdgeTable($width, $height); + } + + /** + * The width of the canvas in pixels. + * + * @var integer + */ + public $width = 0; + + /** + * The height of the canvas in pixels. + * + * @var integer + */ + public $height = 0; + + /** + * Specifies the background color. Allowed values are: + * - 32 bit integers on the format 0xRRGGBBAA + * - strings on the format #RGB + * - strings on the format #RRGGBB + * - strings on the format #RRGGBBAA + * + * @var integer|string + */ + public $backColor = 0x00000000; + + /** + * Gets a context used to draw polygons on this canvas. + * + * @returns \Jdenticon\Canvas\CanvasContext + */ + public function getContext() + { + return new CanvasContext($this, $this->edges); + } + + /** + * Renders the canvas as a PNG data stream. + * + * @param array $keywords Keywords to be written to the PNG stream. + * See https://www.w3.org/TR/PNG/#11keywords. + * @returns string + */ + public function toPng($keywords = array()) + { + $colorRanges = array(); + + Rasterizer::rasterize( + $colorRanges, $this->edges, + $this->width, $this->height); + + $backColor = ColorUtils::parse($this->backColor); + if (ColorUtils::alpha($backColor) > 0) { + $isColor = false; + + foreach ($colorRanges as & $value) { + if ($isColor) { + $value = ColorUtils::over($value, $backColor); + $isColor = false; + } else { + $isColor = true; + } + } + + unset($value); + } + + $palette = new PngPalette($colorRanges); + $png = new PngEncoder(); + + $png->writeImageHeader($this->width, $this->height, $palette->isValid ? + PngEncoder::INDEXED_COLOR : PngEncoder::TRUE_COLOR_WITH_ALPHA); + + $png->writeImageGamma(); + + foreach ($keywords as $key => $value) { + $png->writeTextualData($key, $value); + } + + if ($palette && $palette->isValid) { + $png->writePalette($palette); + $png->writeTransparency($palette); + $png->writeIndexed($colorRanges, $palette, + $this->width, $this->height); + } else { + $png->writeTrueColorWithAlpha($colorRanges, + $this->width, $this->height); + } + + $png->writeImageEnd(); + return $png->getBuffer(); + } +} \ No newline at end of file diff --git a/vendor/jdenticon/jdenticon/src/Canvas/CanvasContext.php b/vendor/jdenticon/jdenticon/src/Canvas/CanvasContext.php new file mode 100644 index 00000000..9acfe5b1 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/CanvasContext.php @@ -0,0 +1,408 @@ +edges = $edges; + $this->canvas = $canvas; + $this->beginPath(); + $this->resetTransform(); + } + + /** + * Specifies the fill color that is used when the fill method is called. Allowed values are: + * - 32 bit integers on the format 0xRRGGBBAA + * - strings on the format #RGB + * - strings on the format #RRGGBB + * - strings on the format #RRGGBBAA + * + * @var integer|string + */ + public $fillStyle = 0x000000ff; + + /** + * Saves the current state to the state stack. + */ + public function save() + { + array_push($this->savedStates, array( + 'transform' => $this->transform, + 'fillStyle' => $this->fillStyle + )); + } + + /** + * Restores the last saved state of the CanvasContext. + */ + public function restore() + { + $state = array_pop($this->savedStates); + if ($state != NULL) { + $this->transform = $state['transform']; + $this->fillStyle = $state['fillStyle']; + } + } + + /** + * Resets the internal path buffer and begins a new path. + */ + public function resetTransform() + { + $this->transform = new Matrix(1, 0, 0, 1, 0, 0); + } + + /** + * Multiplies the current transformation matrix with the specified values. + */ + public function transform($a, $b, $c, $d, $e, $f) + { + if (gettype($a) != 'integer' || + gettype($b) != 'integer' || + gettype($c) != 'integer' || + gettype($d) != 'integer' || + gettype($e) != 'integer' || + gettype($f) != 'integer' + ) { + return; + } + + $this->transform = $this->transform->multiply($a, $b, $c, $d, $e, $f); + } + + /** + * Sets the transformation matrix to the specified matrix. + */ + public function setTransform($a, $b, $c, $d, $e, $f) + { + if (gettype($a) != 'integer' || + gettype($b) != 'integer' || + gettype($c) != 'integer' || + gettype($d) != 'integer' || + gettype($e) != 'integer' || + gettype($f) != 'integer' + ) { + return; + } + + $this->transform = new Matrix($a, $b, $c, $d, $e, $f); + } + + /** + * Applies a translation transformation to the CanvasContext. + * + * @param float $x Distance to move in the horizontal direction in pixels. + * @param float $y Distance to move in the vertical direction in pixels. + */ + public function translate($x, $y) + { + $this->transform = $this->transform->translate($x, $y); + } + + /** + * Applies a scale transformation to the CanvasContext. + * + * @param float $x Scale in the horizontal direction. 1 means no scale. + * @param float $y Scale in the vertical direction. 1 means no scale. + */ + public function scale($x, $y) + { + $this->transform = $this->transform->scale($x, $y); + } + + /** + * Applies a rotation transformation to the canvas around its current origo. + * + * @param float $angle Angle in radians measured clockwise from the + * positive x axis. + */ + public function rotate($angle) + { + $this->transform = $this->transform->rotate($angle); + } + + /** + * Removes all existing subpaths and begins a new path. + */ + public function beginPath() + { + $this->paths = array(); + } + + /** + * Starts a new subpath that begins in the same point as the start and end + * point of the previous one. + */ + public function closePath() + { + $pathsCount = count($this->paths); + if ($pathsCount > 0) { + $path = $this->paths[$pathsCount - 1]; + $pathCount = count($path); + + if ($pathCount > 2) { + // Close path + if ($path[0] != $path[$pathCount - 2] || + $path[1] != $path[$pathCount - 1] + ) { + $path[] = $path[0]; + $path[] = $path[1]; + } + + // Begin a new path + $this->paths[] = array($path[0], $path[1]); + } + } + } + + /** + * Begins a new subpath by moving the cursor to the specified position. + * + * @param float $x X coordinate. + * @param float $y Y coordinate. + */ + public function moveTo($x, $y) + { + $p = $this->transform->multiplyPoint($x, $y); + $this->paths[] = array($p->x, $p->y); + } + + /** + * Inserts an edge between the last and specified position. + * + * @param float $x Target X coordinate. + * @param float $y Target Y coordinate. + * @public + */ + public function lineTo($x, $y) + { + $pathsCount = count($this->paths); + if ($pathsCount == 0) { + $this->paths[] = array(); + $pathsCount++; + } + + $p = $this->transform->multiplyPoint($x, $y); + $path = &$this->paths[$pathsCount - 1]; + $path[] = $p->x; + $path[] = $p->y; + } + + /** + * Adds an arc to the current path. + * + * @param float $x X coordinate of the center of the arc. + * @param float $y Y coordinate of the center of the arc. + * @param float $radius Radius of the arc. + * @param float $startAngle The angle in radians at which the arc starts, + * measured clockwise from the positive x axis. + * @param float $endAngle The angle in radians at which the arc end, + * measured clockwise from the positive x axis. + * @param boolean $anticlockwise Specifies whether the arc will be drawn + * counter clockwise. Default is clockwise. + */ + public function arc($x, $y, $radius, $startAngle, $endAngle, $anticlockwise) + { + $TARGET_CHORD_LENGTH_PIXELS = 3; + + $sectors = floor((M_PI * $radius * 2) / $TARGET_CHORD_LENGTH_PIXELS); + if ($sectors < 9) { + $sectors = 9; + } + + $sectorAngle = M_PI * 2 / $sectors; + + if ($startAngle == $endAngle) { + return; + } + + if ($anticlockwise) { + $sectorAngle = -$sectorAngle; + + if ($startAngle - $endAngle >= M_PI * 2) { + $endAngle = $startAngle - M_PI * 2; + } else { + // Normalize end angle so that the sweep angle is in the range + // (0, -2PI] + $endAngle += + M_PI * 2 * ceil(($startAngle - $endAngle) / + (M_PI * 2) - 1); + } + } else { + if ($endAngle - $startAngle >= M_PI * 2) { + $endAngle = $startAngle + M_PI * 2; + } else { + // Normalize end angle so that the sweep angle is in the range + // (0, 2PI] + $endAngle -= + M_PI * 2 * ceil(($endAngle - $startAngle) / + (M_PI * 2) - 1); + } + } + + $dx; + $dy; + $sectors = ($endAngle - $startAngle) / $sectorAngle; + + $angle = $startAngle; + + for ($i = 0; $i < $sectors; $i++) { + $dx = cos($angle) * $radius; + $dy = sin($angle) * $radius; + $this->lineTo($x + $dx, $y + $dy); + $angle += $sectorAngle; + } + + $dx = cos($endAngle) * $radius; + $dy = sin($endAngle) * $radius; + $this->lineTo($x + $dx, $y + $dy); + } + + /** + * Fills the specified rectangle with fully transparent black without + * affecting the current paths. + * + * @param float $x X coordinate of the left side of the rectangle. + * @param float $y Y coordinate of the top of the rectangle. + * @param float $width Width of the rectangle. + * @param float $height Height of the rectangle. + */ + public function clearRect($x, $y, $width, $height) + { + $fullCanvas = false; + + if (!$this->transform->hasSkewing()) { + // Check if the whole canvas is cleared + $topLeft = $this->transform->multiplyPoint($x, $y); + if ($topLeft->x <= 0 && $topLeft->y <= 0) { + $bottomRight = $this->transform->multiplyPoint( + $x + $width, $y + $height); + if ($bottomRight->x >= $this->canvas->width && + $bottomRight->y >= $this->canvas->height + ) { + $fullCanvas = true; + } + } + } + + if ($fullCanvas) { + $this->edges->clear(); + } else { + $this->_fillRect(ColorUtils::FORCE_TRANSPARENT, + $x, $y, $width, $height); + } + } + + /** + * Fills the specified rectangle without affecting the current paths. + * + * @param float $x X coordinate of the left side of the rectangle. + * @param float $y Y coordinate of the top of the rectangle. + * @param float $width Width of the rectangle. + * @param float $height Height of the rectangle. + */ + public function fillRect($x, $y, $width, $height) + { + $fillColor = ColorUtils::parse($this->fillStyle); + $this->_fillRect($fillColor, $x, $y, $width, $height); + } + + private function _fillRect($fillColor, $x, $y, $width, $height) + { + $polygonId = $this->edges->getNextPolygonId(); + + $points = array( + $this->transform->multiplyPoint($x, $y), + $this->transform->multiplyPoint($x + $width, $y), + $this->transform->multiplyPoint($x + $width, $y + $height), + $this->transform->multiplyPoint($x, $y + $height), + $this->transform->multiplyPoint($x, $y) + ); + + $pointsCount = count($points); + for ($i = 1; $i < $pointsCount; $i++) { + $this->edges->add(new Edge( + $polygonId, + $points[$i - 1]->x, + $points[$i - 1]->y, + $points[$i]->x, + $points[$i]->y, + $fillColor)); + } + } + + /** + * Fills the defined paths. + * + * @param string $windingRule The winding rule to be used for determining + * which areas are covered by the current path. Valid values are + * "evenodd" and "nonzero". Default is "nonzero". + */ + public function fill($windingRule = "nonzero") + { + $polygonId = $this->edges->getNextPolygonId(); + $fillColor = ColorUtils::parse($this->fillStyle); + + foreach ($this->paths as $points) { + $pointsCount = count($points); + if ($pointsCount <= 2) { + // Nothing to fill + continue; + } + + for ($i = 2; $i < $pointsCount; $i += 2) { + $this->edges->add(new Edge( + $polygonId, + $points[$i - 2], + $points[$i - 1], + $points[$i], + $points[$i + 1], + $fillColor, + $windingRule)); + } + + // Close path + if ($points[0] != $points[$pointsCount - 2] || + $points[1] != $points[$pointsCount - 1] + ) { + $this->edges->add(new Edge( + $polygonId, + $points[$pointsCount - 2], + $points[$pointsCount - 1], + $points[0], + $points[1], + $fillColor, + $windingRule)); + } + } + } +} diff --git a/vendor/jdenticon/jdenticon/src/Canvas/ColorUtils.php b/vendor/jdenticon/jdenticon/src/Canvas/ColorUtils.php new file mode 100644 index 00000000..7709027d --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/ColorUtils.php @@ -0,0 +1,228 @@ +> 24) & 0xff; + } + + /** + * Gets the green component of a color. + * + * @param integer $color 32-bit color value on the format 0xRRGGBBAA. + * @return integer Green component in the range [0, 255]. + */ + public static function green($color) + { + return ($color >> 16) & 0xff; + } + + /** + * Gets the blue component of a color. + * + * @param integer $color 32-bit color value on the format 0xRRGGBBAA. + * @return integer Blue component in the range [0, 255]. + */ + public static function blue($color) + { + return ($color >> 8) & 0xff; + } + + /** + * Formats a color as a string. + * + * @param integer $color Color to format. + * @return string + */ + public static function format($color) + { + return bin2hex(pack('N', $color)); + } + + /** + * Computes a mix of the two specified colors, with the proportion given + * by the specified weight. + * + * @param integer $color1 First color to mix. + * @param integer $color2 Second color to mix. + * @param float $weight Weight in the range [0,1]. + * 0 gives $color1, 1 gives $color2. + * @return integer Mixed color. + */ + public static function mix($color1, $color2, $weight) + { + if ($weight < 0) { + $weight = 0; + } elseif ($weight > 1) { + $weight = 1; + } + + $a = ($color1 & 0xff) * (1 - $weight) + ($color2 & 0xff) * $weight; + if ($a <= 0.1) { + return 0; + } + + $r = ( + ($color1 >> 24) * ($color1 & 0xff) * (1 - $weight) + + ($color2 >> 24) * ($color2 & 0xff) * $weight + ) / $a; + + $g = ( + (($color1 >> 16) & 0xff) * ($color1 & 0xff) * (1 - $weight) + + (($color2 >> 16) & 0xff) * ($color2 & 0xff) * $weight + ) / $a; + + $b = ( + (($color1 >> 8) & 0xff) * ($color1 & 0xff) * (1 - $weight) + + (($color2 >> 8) & 0xff) * ($color2 & 0xff) * $weight + ) / $a; + + if ($a > 255) $a = 255; + if ($r > 255) $r = 255; + if ($g > 255) $g = 255; + if ($b > 255) $b = 255; + + return ((int)$r << 24) | ((int)$g << 16) | ((int)$b << 8) | (int)$a; + } + + /** + * Parses a value to a 32-bit color on the format 0xRRGGBBAA. + * + * @param integer|string $color The value to parse. + * @return integer + */ + public static function parse($color) + { + if (gettype($color) == "integer") { + return $color & 0xffffffff; + } + + $color = "$color"; + + if (preg_match('/^#?[0-9a-fA-F]+$/', $color)) { + $hexColor = $color; + if ($hexColor[0] == '#') { + $hexColor = substr($hexColor, 1); + } + + switch (strlen($hexColor)) { + case 3: + $numeric = intval($hexColor, 16); + return ( + (($numeric & 0xf00) << 20) | + (($numeric & 0xf00) << 16) | + (($numeric & 0x0f0) << 16) | + (($numeric & 0x0f0) << 12) | + (($numeric & 0x00f) << 12) | + (($numeric & 0x00f) << 8) | + 0xff); + case 6: + return (intval($hexColor, 16) << 8) | 0xff; + case 8: + // Workaround to cope with PHP limitation of intval + $numeric = + (intval(substr($hexColor, 0, 4), 16) << 16) | + (intval(substr($hexColor, 4, 4), 16)); + return $numeric; + } + } + + throw new \InvalidArgumentException("Invalid color '$color'."); + } + + /** + * Blends this color with another color using the over blending operation. + * + * @param integer $fore The foreground color. + * @param integer $back The background color. + * @return integer + */ + public static function over($fore, $back) + { + $foreA = ($fore & 0xff); + $backA = ($back & 0xff); + + if ($foreA < 1) { + return $back; + } elseif ($foreA > 254 || $backA < 1) { + return $fore; + } + + // Source: + // https://en.wikipedia.org/wiki/Alpha_compositing#Description + $forePA = $foreA * 255; + $backPA = $backA * (255 - $foreA); + $pa = ($forePA + $backPA); + + $b = (int) ( + ($forePA * (($fore >> 8) & 0xff) + $backPA * (($back >> 8) & 0xff)) / + $pa); + + $g = (int) ( + ($forePA * (($fore >> 16) & 0xff) + $backPA * (($back >> 16) & 0xff)) / + $pa); + + $r = (int) ( + ($forePA * (($fore >> 24) & 0xff) + $backPA * (($back >> 24) & 0xff)) / + $pa); + + $a = (int) ($pa / 255); + + return ($r << 24) | ($g << 16) | ($b << 8) | $a; + } +}; + diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Matrix.php b/vendor/jdenticon/jdenticon/src/Canvas/Matrix.php new file mode 100644 index 00000000..9ce00dcb --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Matrix.php @@ -0,0 +1,141 @@ +a = $a; + $this->b = $b; + $this->c = $c; + $this->d = $d; + $this->e = $e; + $this->f = $f; + } + + /** + * Gets a value determining if this matrix has skewing values. + * + * @return boolean + */ + public function hasSkewing() + { + return $this->b || $this->c; + } + + /** + * Gets a value determining if this matrix has translation values. + * + * @return boolean + */ + public function hasTranslation() + { + return $this->e || $this->f; + } + + /** + * Gets a value determining if this matrix has scaling values. + * + * @return boolean + */ + public function hasScaling() + { + return $this->a != 1 || $this->d != 1; + } + + /** + * Returns a new matrix based on the current matrix multiplied with the + * specified matrix values. + * + * @return \Jdenticon\Canvas\Matrix + */ + public function multiply($a, $b, $c, $d, $e, $f) + { + return new Matrix( + $this->a * $a + $this->c * $b, + $this->b * $a + $this->d * $b, + $this->a * $c + $this->c * $d, + $this->b * $c + $this->d * $d, + $this->a * $e + $this->c * $f + $this->e, + $this->b * $e + $this->d * $f + $this->f + ); + } + + /** + * Multiplies the specified point with the current matrix and returns the + * resulting point. + * + * @param float $x X coordinate. + * @param float $y Y coordinate. + * @return \Jdenticon\Canvas\Point + */ + public function multiplyPoint($x, $y) + { + return new Point( + $this->a * $x + $this->c * $y + $this->e, + $this->b * $x + $this->d * $y + $this->f + ); + } + + /** + * Returns a new matrix based on the current matrix with a rotation + * transformation applied. + * + * @param float $angle Rotation angle in radians. + * @return \Jdenticon\Canvas\Matrix + */ + public function rotate($angle) + { + $sin = sin($angle); + $cos = cos($angle); + return $this->multiply($cos, $sin, -$sin, $cos, 0, 0); + } + + /** + * Returns a new matrix based on the current matrix with a translation + * transformation applied. + * + * @param float $x Horizontal move distance. + * @param float $y Vertical move distance. + * @return \Jdenticon\Canvas\Matrix + */ + public function translate($x, $y) + { + return $this->multiply(1, 0, 0, 1, $x, $y); + } + + /** + * Returns a new matrix based on the current matrix with a scaling + * transformation applied. + * + * @param float $x Horizontal scale. + * @param float $y Vertical scale. + * @return \Jdenticon\Canvas\Matrix + */ + public function scale($x, $y) + { + return $this->multiply($x, 0, 0, $y, 0, 0); + } +} \ No newline at end of file diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Png/PngBuffer.php b/vendor/jdenticon/jdenticon/src/Canvas/Png/PngBuffer.php new file mode 100644 index 00000000..78a90ba5 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Png/PngBuffer.php @@ -0,0 +1,92 @@ +buffer .= $str; + } + + /** + * Writes a 32 bit unsigned int to the buffer in Big Endian format. + * + * @param integer $value Value to write. + */ + public function writeUInt32BE($value) + { + $this->buffer .= pack('N', $value); + } + + /** + * Writes an 8 bit unsigned int to the buffer. + * + * @param integer $value Value to write. + */ + public function writeUInt8($value) + { + $this->buffer .= pack('C', $value); + } + + /** + * Starts a new PNG chunk. + * + * @param string $type Name of the chunk. Must contain exactly 4 + * ASCII characters. + */ + public function startChunk($type) + { + $this->chunkPreviousBuffer = $this->buffer; + $this->buffer = $type; + } + + /** + * Closes the current PNG chunk. + */ + public function endChunk() + { + // Compute Crc32 for type + data + $data = $this->buffer; + $crc = crc32($data); + + $this->buffer = + $this->chunkPreviousBuffer . + + // Length + pack('N', strlen($data) - 4) . + + // Content + $data . + + // Crc32 + pack('N', $crc); + } + + /** + * Gets a string containing the PNG encoded data. + * + * @return string + */ + public function getBuffer() + { + return $this->buffer; + } +} diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Png/PngEncoder.php b/vendor/jdenticon/jdenticon/src/Canvas/Png/PngEncoder.php new file mode 100644 index 00000000..5927e704 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Png/PngEncoder.php @@ -0,0 +1,238 @@ +buffer = new PngBuffer(); + $this->buffer->writeString("\x89\x50\x4e\x47\xd\xa\x1a\xa"); + } + + /** + * Writes an IHDR chunk to the png data stream. + * + * @param int $width Image width in pixels. + * @param int $height Image height in pixels. + * @param int $colorType Color depth, speocfy one of the constants in + * PngEncoder. + */ + public function writeImageHeader($width, $height, $colorType) + { + $this->buffer->startChunk("IHDR"); + $this->buffer->writeUInt32BE($width); + $this->buffer->writeUInt32BE($height); + $this->buffer->writeUInt8(8); // Bit depth + $this->buffer->writeUInt8($colorType); + $this->buffer->writeUInt8(0); // Compression + $this->buffer->writeUInt8(0); // Filter + $this->buffer->writeUInt8(0); // Interlace + $this->buffer->endChunk(); + } + + /** + * Writes a gAMA chunk to the png data stream. + * + * @param int $gamma Gamma value. + */ + public function writeImageGamma($gamma = 45455) + { + $this->buffer->startChunk("gAMA"); + $this->buffer->writeUInt32BE($gamma); + $this->buffer->endChunk(); + } + + /** + * Writes an IDAT chunk of truecolor encoded image data. + * + * @param array $colorRanges Image data on the format + * array(count0, color0, count1, color1, ...) + * @param int $width Image width in pixels. + * @param int $height Image height in pixels. + */ + public function writeTrueColorWithAlpha( + array & $colorRanges, $width, $height) + { + $this->buffer->startChunk("IDAT"); + + $uncompressed = ''; + $count = -1; + $x = 0; + + foreach ($colorRanges as $value) { + if ($count === -1) { + $count = $value; + } else { + if ($count !== 0) { + if ($x === $width) { + $x = 0; + } + if ($x === 0) { + $uncompressed .= pack('C', 0); // No filtering + } + + $uncompressed .= str_repeat(pack('N', $value), $count); + $x += $count; + } + + $count = -1; + } + } + + $compressed = gzcompress($uncompressed, 2); + $this->buffer->writeString($compressed); + + $this->buffer->endChunk(); + } + + /** + * Writes an IDAT chunk of indexed image data. + * + * @param array $colorRanges Image data on the format + * array(count0, color0, count1, color1, ...) + * @param \Jdenticon\Canvas\Png\PngPalette $palette Palette containing the + * indexed colors. + * @param int $width Image width in pixels. + * @param int $height Image height in pixels. + */ + public function writeIndexed( + array & $colorRanges, + PngPalette $palette, + $width, $height) + { + $this->buffer->startChunk("IDAT"); + + $uncompressed = ''; + + $count = -1; + $x = 0; + + foreach ($colorRanges as $value) { + if ($count === -1) { + $count = $value; + } else { + if ($count !== 0) { + if ($x === $width) { + $x = 0; + } + if ($x === 0) { + $uncompressed .= pack('C', 0); // No filtering + } + + $colorIndex = $palette->lookup[$value]; + $uncompressed .= str_repeat(pack('C', $colorIndex), $count); + $x += $count; + } + + $count = -1; + } + } + + $compressed = gzcompress($uncompressed, 2); + $this->buffer->writeString($compressed); + + $this->buffer->endChunk(); + } + + /** + * Writes a PLTE chunk containing the indexed colors. + * + * @param \Jdenticon\Canvas\Png\PngPalette $palette Palette containing the + * indexed colors. + */ + public function writePalette(PngPalette $palette) + { + if ($palette && $palette->isValid) { + $this->buffer->startChunk("PLTE"); + + foreach ($palette->colors as $color) { + $this->buffer->writeString( + pack('C', ($color >> 24) & 0xff) . + pack('C', ($color >> 16) & 0xff) . + pack('C', ($color >> 8) & 0xff)); + } + + $this->buffer->endChunk(); + } + } + + /** + * Writes a tRNS chunk containing the alpha values of indexed colors. + * + * @param \Jdenticon\Canvas\Png\PngPalette $palette Palette containing the + * indexed colors. + */ + public function writeTransparency(PngPalette $palette) + { + if ($palette && $palette->isValid && $palette->hasAlphaChannel) { + $this->buffer->startChunk("tRNS"); + + $alpha = ''; + + foreach ($palette->colors as $color) { + $alpha .= pack('C', $color & 0xff); + } + + $this->buffer->writeString($alpha); + + $this->buffer->endChunk(); + } + } + + /** + * Writes a tEXt chunk containing the specified strings. + * + * @param string $key Key, one of + * {@link https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords} + * @param string $value Value. + */ + public function writeTextualData($key, $value) + { + $this->buffer->startChunk("tEXt"); + $this->buffer->writeString($key); + $this->buffer->writeUInt8(0); + $this->buffer->writeString($value); + $this->buffer->endChunk(); + } + + /** + * Writes an IEND chunk to the png data stream. + */ + public function writeImageEnd() + { + $this->buffer->startChunk("IEND"); + $this->buffer->endChunk(); + } + + /** + * Gets a binary string containing the PNG data. + * + * @return string + */ + public function getBuffer() + { + return $this->buffer->getBuffer(); + } +} diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Png/PngPalette.php b/vendor/jdenticon/jdenticon/src/Canvas/Png/PngPalette.php new file mode 100644 index 00000000..37887b65 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Png/PngPalette.php @@ -0,0 +1,92 @@ + 0 && !isset($lookup[$value])) { + if (!$hasAlphaChannel && ($value & 0xff) < 255) { + $hasAlphaChannel = true; + } + + $lookup[$value] = $colorsCount++; + $colors[] = $value; + + if ($colorsCount > 256) { + break; + } + } + + $count = -1; + } + } + + $this->hasAlphaChannel = $hasAlphaChannel; + $this->colors = & $colors; + $this->lookup = & $lookup; + $this->isValid = $colorsCount <= 256; + } + + /** + * Specifies if the palette is valid to be used for encoding a PNG image. + * + * @var boolean + */ + public $isValid; + + /** + * Specifies if the palette has any partial or fully transparent + * colors. + * + * @var boolean + */ + public $hasAlphaChannel; + + /** + * Array of colors in the palette. + * + * @var array + */ + public $colors; + + /** + * Lookup table from 32-bit color value to color index. + * + * @var array + */ + public $lookup; +} diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Point.php b/vendor/jdenticon/jdenticon/src/Canvas/Point.php new file mode 100644 index 00000000..0c73133f --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Point.php @@ -0,0 +1,41 @@ +x = $x; + $this->y = $y; + } +} \ No newline at end of file diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Edge.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Edge.php new file mode 100644 index 00000000..d554b91d --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Edge.php @@ -0,0 +1,44 @@ +polygonId = $polygonId; + $this->x0 = $x0; + $this->x1 = $x1; + $this->y0 = $y0; + $this->y1 = $y1; + $this->color = $color; + $this->windingRule = $windingRule; + } + + public function intersection($y) + { + $dx = + ($this->x1 - $this->x0) * ($this->y0 - $y) / + ($this->y0 - $this->y1); + return $this->x0 + $dx; + } +} + diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeIntersection.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeIntersection.php new file mode 100644 index 00000000..59f0ef37 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeIntersection.php @@ -0,0 +1,27 @@ +fromX = $fromX; + $this->width = $width; + $this->edge = $edge; + } +} + diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeSuperSampleIntersection.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeSuperSampleIntersection.php new file mode 100644 index 00000000..b88a2711 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeSuperSampleIntersection.php @@ -0,0 +1,24 @@ +x = $x; + $this->edge = $edge; + } +} \ No newline at end of file diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeTable.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeTable.php new file mode 100644 index 00000000..6a67f505 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeTable.php @@ -0,0 +1,158 @@ +width = $width; + $this->height = $height; + $this->clear(); + } + + /** + * Sorts the edges of each scanline in ascending x coordinates. + */ + public function clear() + { + $this->scanlines = array(); + $this->nextPolygonId = 1; + } + + /** + * Gets an id for the next polygon. + * + * @return int + */ + public function getNextPolygonId() + { + return $this->nextPolygonId++; + } + + /** + * Gets the scaline for the specified Y coordinate, or NULL if there are + * no edges for the specified Y coordinate. + * + * @return array|null. + */ + public function getScanline($y) + { + return isset($this->scanlines[$y]) ? $this->scanlines[$y] : null; + } + + /** + * Adds an edge to the table. + * + * @param \Jdenticon\Canvas\Rasterization\Edge $edge + */ + public function add(\Jdenticon\Canvas\Rasterization\Edge $edge) + { + $minY = 0; + $maxY = 0; + + if ($edge->y0 == $edge->y1) { + // Skip horizontal lines + return; + } elseif ($edge->y0 < $edge->y1) { + $minY = (int)($edge->y0); + $maxY = (int)($edge->y1 + 0.996 /* 1/255 */); + } else { + $minY = (int)($edge->y1); + $maxY = (int)($edge->y0 + 0.996 /* 1/255 */); + } + + if ($maxY < 0 || $minY >= $this->height) { + return; + } + + if ($minY < 0) { + $minY = 0; + } + if ($maxY > $this->height) { + $maxY = $this->height; + } + + if ($minY < $maxY) { + $y = $minY; + $x1 = $edge->intersection($y); + + while ($y < $maxY) { + $x2 = $edge->intersection($y + 1); + + $fromX; + $width; + if ($x1 < $x2) { + $fromX = (int)($x1); + $width = (int)($x2 + 0.9999) - $fromX; + } else { + $fromX = (int)($x2); + $width = (int)($x1 + 0.9999) - $fromX; + } + + if ($fromX < 0) { + $width += $fromX; + $fromX = 0; + + if ($width < 0) { + $width = 0; + } + } + + if ($fromX < $this->width) { + if (!isset($this->scanlines[$y])) { + $this->scanlines[$y] = array(); + } + + $this->scanlines[$y][] = new EdgeIntersection( + $fromX, $width, $edge); + } + + $x1 = $x2; + $y++; + } + } + } + + private static function edge_cmp($x, $y) + { + if ($x->fromX < $y->fromX) { + return -1; + } + if ($x->fromX > $y->fromX) { + return 1; + } + return 0; + } + + /** + * Sorts the edges of each scanline in ascending x coordinates. + */ + public function sort() + { + foreach ($this->scanlines as $i => &$scanline) { + usort($scanline, array( + 'Jdenticon\\Canvas\\Rasterization\\EdgeTable', 'edge_cmp')); + } + } +} \ No newline at end of file diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Layer.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Layer.php new file mode 100644 index 00000000..f3d83bf0 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Layer.php @@ -0,0 +1,30 @@ +polygonId = $polygonId; + $this->color = $color; + $this->winding = $winding; + $this->windingRule = $windingRule; + } +} diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/LayerManager.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/LayerManager.php new file mode 100644 index 00000000..98592729 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/LayerManager.php @@ -0,0 +1,150 @@ +color = ColorUtils::TRANSPARENT; + } + + /** + * Copies all layers in this manager to another LayerManager. + * + * @param \Jdenticon\Canvas\Rasterization\LayerManager $other The + * LayerManager to copy all layers to. + */ + public function copyTo(LayerManager $other) + { + $other->color = $this->color; + + $layer = $this->topLayer; + $previousCopy = null; + + while ($layer !== null) { + $copy = new Layer( + $layer->polygonId, + $layer->color, + $layer->winding, + $layer->windingRule + ); + + if ($previousCopy === null) { + $other->topLayer = $copy; + } + else { + $previousCopy->nextLayer = $copy; + } + + $previousCopy = $copy; + $layer = $layer->nextLayer; + } + } + + /** + * Adds a layer for the specified edge. The z-order is defined by its id. + * + * @param \Jdenticon\Canvas\Rasterization\Edge edge + */ + public function add(Edge $edge) + { + $dwinding = $edge->y0 < $edge->y1 ? 1 : -1; + + $layer = $this->topLayer; + $previousLayer = null; + + while ($layer !== null) { + if ($layer->polygonId === $edge->polygonId) { + $layer->winding += $dwinding; + + $inPath = $layer->windingRule == 'evenodd' ? + ($layer->winding % 2 === 1) : ($layer->winding !== 0); + + if (!$inPath) { + // Remove layer + if ($previousLayer === null) { + $this->topLayer = $layer->nextLayer; + } + else { + $previousLayer->nextLayer = $layer->nextLayer; + } + } + break; + } elseif ($layer->polygonId < $edge->polygonId) { + // Insert here + $newLayer = new Layer( + $edge->polygonId, + $edge->color, + $dwinding, + $edge->windingRule + ); + $newLayer->nextLayer = $layer; + + if ($previousLayer === null) { + $this->topLayer = $newLayer; + } else { + $previousLayer->nextLayer = $newLayer; + } + break; + } + + $previousLayer = $layer; + $layer = $layer->nextLayer; + } + + if ($layer === null) { + $newLayer = new Layer( + $edge->polygonId, + $edge->color, + $dwinding, + $edge->windingRule + ); + + if ($previousLayer === null) { + $this->topLayer = $newLayer; + } else { + $previousLayer->nextLayer = $newLayer; + } + } + + // Update current color + $color = ColorUtils::TRANSPARENT; + $layer = $this->topLayer; + + while ($layer !== null && ($color & 0xff) < 255) { + if ($layer->color === ColorUtils::FORCE_TRANSPARENT) { + break; + } + + $color = ColorUtils::over($layer->color, $color); + } + + $this->color = $color; + } +} diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Rasterizer.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Rasterizer.php new file mode 100644 index 00000000..0a5269af --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Rasterizer.php @@ -0,0 +1,379 @@ +sort(); + + $superSampleBuffer = new SuperSampleBuffer( + $width, self::SAMPLES_PER_PIXEL_X); + + $layers = array(); + $color = 0; + + // Keeps track of how many of the subpixellayers that are used for + // the currently rendered scanline. Until a range requiring + // supersampling is encountered only a single layer is needed. + $usedLayers = 0; + + for ($i = 0; $i < self::SAMPLES_PER_PIXEL_Y; $i++) { + $layers[] = new LayerManager(); + } + + for ($ey = 0; $ey < $height; $ey++) { + $scanline = $edgeTable->getScanline($ey); + if ($scanline === null) { + $colorData[] = $width; + $colorData[] = 0; + continue; + } + + $superSampleRanges = self::getSuperSampleRanges($scanline, $width); + $superSampleRangeCount = count($superSampleRanges); + + foreach ($layers as $layer) { + $layer->topLayer = null; + $layer->color = ColorUtils::TRANSPARENT; + } + + $usedLayers = 1; + + if ($superSampleRanges[0]->fromX) { + $colorData[] = $superSampleRanges[0]->fromX; + $colorData[] = 0; + } + + for ( + $rangeIndex = 0; + $rangeIndex < $superSampleRangeCount; + $rangeIndex++ + ) { + $superSampleRange = $superSampleRanges[$rangeIndex]; + $edge = $superSampleRange->edges[0]; + + // If there is exactly one edge in the supersample range, and it + // is crossing the entire scanline, we can perform the + // antialiasing by integrating the edge function. + if (!isset($superSampleRange->edges[1]) && ( + $edge->y0 <= $ey && $edge->y1 >= $ey + 1 || + $edge->y0 >= $ey + 1 && $edge->y1 <= $ey + )) { + // Determine the lower and upper x value where the edge + // intersects the scanline. + $xey = $edge->intersection($ey); + $xey1 = $edge->intersection($ey + 1); + + if ($xey < $xey1) { + $x0 = $xey; + $x1 = $xey1; + } else { + $x0 = $xey1; + $x1 = $xey; + } + + $rangeWidth = $x1 - $x0; + + if ($usedLayers === 1) { + $subScanlineLayers = $layers[0]; + $fromColor = $subScanlineLayers->color; + $subScanlineLayers->add($edge); + $toColor = $subScanlineLayers->color; + } else { + $fromColorR = 0; + $fromColorG = 0; + $fromColorB = 0; + $fromColorA = 0; + $toColorR = 0; + $toColorG = 0; + $toColorB = 0; + $toColorA = 0; + + // Compute the average color of all subpixel layers + // before and after the edge intersection. + // The calculation is inlined for increased performance. + for ($i = 0; $i < $usedLayers; $i++) { + $subScanlineLayers = $layers[$i]; + + // Add to average from-color + $color = $subScanlineLayers->color; + $alpha = $color & 0xff; + if ($alpha > 0) { + $fromColorA += $alpha; + $fromColorR += (($color >> 24) & 0xff) * $alpha; + $fromColorG += (($color >> 16) & 0xff) * $alpha; + $fromColorB += (($color >> 8) & 0xff) * $alpha; + } + + // Add the new layer + $subScanlineLayers->add($edge); + + // Add to average to-color + $color = $subScanlineLayers->color; + $alpha = $color & 0xff; + if ($alpha > 0) { + $toColorA += $alpha; + $toColorR += (($color >> 24) & 0xff) * $alpha; + $toColorG += (($color >> 16) & 0xff) * $alpha; + $toColorB += (($color >> 8) & 0xff) * $alpha; + } + } + + $fromColor = $fromColorA === 0 ? 0 : ColorUtils::from( + (int)($fromColorA / $usedLayers), + (int)($fromColorR / $fromColorA), + (int)($fromColorG / $fromColorA), + (int)($fromColorB / $fromColorA)); + + $toColor = $toColorA === 0 ? 0 : ColorUtils::from( + (int)($toColorA / $usedLayers), + (int)($toColorR / $toColorA), + (int)($toColorG / $toColorA), + (int)($toColorB / $toColorA)); + } + + // Render pixels + for ( + $x = $superSampleRange->fromX; + $x < $superSampleRange->toXExcl; + $x++ + ) { + if ($x0 >= $x + 1) { + // Pixel not covered + $colorData[] = 1; + $colorData[] = $fromColor; + continue; + } + + if ($x1 <= $x) { + // Pixel fully covered + $colorData[] = 1; + $colorData[] = $toColor; + continue; + } + + // toColor coverage in the range [0.0, 1.0] + // Initialize to the fully covered range of the pixel. + $coverage = $x1 < $x + 1 ? $x + 1 - $x1 : 0; + + // Compute integral for non-vertical edges + if ($rangeWidth > 0.001) { + // Range to integrate + $integralFrom = $x0 > $x ? $x0 : $x;; + $integralTo = $x1 < $x + 1 ? $x1 : $x + 1; + + $coverage += + ( + ( + $integralTo * $integralTo - + $integralFrom * $integralFrom + ) / 2 + + $x0 * ($integralFrom - $integralTo) + ) / $rangeWidth; + } + + $colorData[] = 1; + $colorData[] = ColorUtils::mix( + $fromColor, $toColor, $coverage); + } + + $color = $toColor; + + } // /simplified antialiasing + else { + // Super sampling + $y = $ey + self::SAMPLE_HEIGHT / 2; + + // Ensure all subpixel layers are initialized + while ($usedLayers < self::SAMPLES_PER_PIXEL_Y) { + $layers[0]->copyTo($layers[$usedLayers]); + $usedLayers++; + } + + foreach ($layers as $subScanlineLayers) { + $color = $subScanlineLayers->color; + + $intersections = self::getIntersections( + $superSampleRange->edges, $y); + + foreach ($intersections as $intersection) { + $superSampleBuffer->add($color, + $intersection->x - $superSampleRange->fromX); + $subScanlineLayers->add($intersection->edge); + $color = $subScanlineLayers->color; + } + + $superSampleBuffer->add( + $color, $superSampleRange->width + 1); + $superSampleBuffer->rewind(); + + $y += self::SAMPLE_HEIGHT; + } // /subpixel + + // Blend subpixels + $color = $superSampleBuffer->colorAt( + $superSampleRange->width); + $superSampleBuffer->emptyTo( + $colorData, $superSampleRange->width); + + //$color = end($colorData); + } // /super sampling + + // Forward last color + if ($rangeIndex + 1 < $superSampleRangeCount) { + $count = + $superSampleRanges[$rangeIndex + 1]->fromX - + $superSampleRange->toXExcl; + + if ($count > 0) { + $colorData[] = $count; + $colorData[] = $color; + } + } else { + $count = $width - $superSampleRange->toXExcl; + if ($count > 0) { + $colorData[] = $count; + $colorData[] = $color; + } + } + } // /range + } + + return $colorData; + } + + private static function intersection_cmp($a, $b) + { + if ($a->x < $b->x) { + return -1; + } + + if ($a->x > $b->x) { + return 1; + } + + return 0; + } + + /** + * Determines what edges that intersect a horizontal line with the specified + * y coordinate. For each intersecting edge the intersecting x coordinate is + * returned. + * + * @param array $edges Array of edges in the current scanline. + * @param int $y Y coordinate of the current scanline. + * @return array Array containing EdgeSuperSampleIntersection. Objects + * are sorted ascending by x coordinate. + */ + private static function getIntersections($edges, $y) + { + $intersections = array(); + + foreach ($edges as $edge) { + if ($edge->y0 < $y && $edge->y1 >= $y || + $edge->y0 >= $y && $edge->y1 < $y + ) { + $x = $edge->x0 + + ($edge->x1 - $edge->x0) * ($y - $edge->y0) / + ($edge->y1 - $edge->y0); + + $intersections[] = new EdgeSuperSampleIntersection($x, $edge); + } + } + + usort($intersections, array( + 'Jdenticon\\Canvas\\Rasterization\\Rasterizer', + 'intersection_cmp')); + + return $intersections; + } + + /** + * Determines what ranges of a scanline that needs to be supersampled. + * + * @param array $scanline Array of edges in the current scanline. + * @return array Array of SuperSampleRange. + */ + private static function getSuperSampleRanges(&$scanline, $width) + { + $superSampleRanges = array(); + + $rangeIndex = 0; + $scanlineCount = count($scanline); + + while ($rangeIndex < $scanlineCount) { + $range = $scanline[$rangeIndex]; + + if ($range->fromX >= $width) { + break; + } + + $superSampleRange = new SuperSampleRange( + $range->fromX, + $range->fromX + $range->width + ); + $superSampleRange->edges[] = $range->edge; + + $rangeIndex++; + + for ($i = $rangeIndex; $i < $scanlineCount; $i++) { + $range = $scanline[$i]; + + if ($range->fromX < $superSampleRange->toXExcl) { + $superSampleRange->toXExcl = max( + $superSampleRange->toXExcl, + $range->fromX + $range->width); + $superSampleRange->edges[] = $range->edge; + $rangeIndex++; + } else { + break; + } + } + + $superSampleRange->toXExcl = min($superSampleRange->toXExcl, $width); + $superSampleRange->width = + $superSampleRange->toXExcl - $superSampleRange->fromX; + + $superSampleRanges[] = $superSampleRange; + } + + return $superSampleRanges; + } +} + diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php new file mode 100644 index 00000000..82860e2e --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php @@ -0,0 +1,198 @@ +samples = array(); + $this->samplesPerPixel = $samplesPerPixel; + + $this->pixelOffset = 0; + $this->subPixelOffset = 0; + + $this->width = $width; + $this->used = -1; + } + + /** + * Rewinds the cursor to the beginning of the buffer. + */ + public function rewind() + { + $this->pixelOffset = 0; + $this->subPixelOffset = 0; + } + + /** + * Clears the samples in this buffer. + */ + public function clear() + { + $this->pixelOffset = 0; + $this->subPixelOffset = 0; + $this->used = -1; + } + + /** + * Writes the average color of each pixel to a specified color array. + * + * @param array $colorData The average colors will be written to this + * color array. + * @param integer $count Number of pixels to write. + */ + public function emptyTo(& $colorData, $count) + { + for ($i = 0; $i < $count; $i++) { + $sampleCount = $this->samples[$i * 5 + self::IDX_COUNT]; + $a = $this->samples[$i * 5 + self::IDX_A]; + $color = $sampleCount == 0 || $a == 0 ? 0 : + ColorUtils::from( + (int)($a / $sampleCount), + (int)($this->samples[$i * 5 + self::IDX_R] / $a), + (int)($this->samples[$i * 5 + self::IDX_G] / $a), + (int)($this->samples[$i * 5 + self::IDX_B] / $a) + ); + + $colorData[] = 1; + $colorData[] = $color; + } + + $this->pixelOffset = 0; + $this->subPixelOffset = 0; + $this->used = -1; + } + + /** + * Gets the average color of the pixel at a specified index. + * + * @param integer $index The index of the pixel. + * @return integer + */ + public function colorAt($index) + { + $sampleCount = $this->samples[$index * 5 + self::IDX_COUNT]; + $alphaSum = $this->samples[$index * 5 + self::IDX_A]; + return $sampleCount == 0 || $alphaSum == 0 ? 0 : + ColorUtils::from( + (int)($alphaSum / $sampleCount), + (int)($this->samples[$index * 5 + self::IDX_R] / $alphaSum), + (int)($this->samples[$index * 5 + self::IDX_G] / $alphaSum), + (int)($this->samples[$index * 5 + self::IDX_B] / $alphaSum) + ); + } + + /** + * Adds a color to the current pixel in the buffer. + * + * @param integer $count Number of samples of the color to be added to + * the buffer. + */ + private function _add($count, $a, $r, $g, $b) + { + if ($this->used < $this->pixelOffset) { + $this->used = $this->pixelOffset; + + $this->samples[$this->pixelOffset * 5 + self::IDX_COUNT] = $count; + $this->samples[$this->pixelOffset * 5 + self::IDX_A] = $a * $count; + $this->samples[$this->pixelOffset * 5 + self::IDX_R] = $a * $r * $count; + $this->samples[$this->pixelOffset * 5 + self::IDX_G] = $a * $g * $count; + $this->samples[$this->pixelOffset * 5 + self::IDX_B] = $a * $b * $count; + } else { + $this->samples[$this->pixelOffset * 5 + self::IDX_COUNT] += $count; + + if ($a > 0) { + $this->samples[$this->pixelOffset * 5 + self::IDX_A] += $a * $count; + $this->samples[$this->pixelOffset * 5 + self::IDX_R] += $a * $r * $count; + $this->samples[$this->pixelOffset * 5 + self::IDX_G] += $a * $g * $count; + $this->samples[$this->pixelOffset * 5 + self::IDX_B] += $a * $b * $count; + } + } + } + + /** + * Adds a color to the buffer up until the specified x index. + * + * @param integer $color Color to write. + * @param float $untilX Samples of the color will be added the buffer until + * the cursor reaches this coordinate. + */ + public function add($color, $untilX) + { + $samplesLeft = + (int)($untilX * $this->samplesPerPixel) - + $this->subPixelOffset - + $this->pixelOffset * $this->samplesPerPixel; + + // ColorUtils methods inlined for performance reasons + $a = ($color) & 0xff; + $r = ($color >> 24) & 0xff; + $g = ($color >> 16) & 0xff; + $b = ($color >> 8) & 0xff; + + // First partial pixel + if ($this->subPixelOffset > 0) { + $samples = $this->samplesPerPixel - $this->subPixelOffset; + if ($samples > $samplesLeft) { + $samples = $samplesLeft; + } + $samplesLeft -= $samples; + + $this->_add($samples, $a, $r, $g, $b); + + $this->subPixelOffset += $samples; + if ($this->subPixelOffset == $this->samplesPerPixel) { + $this->subPixelOffset = 0; + $this->pixelOffset++; + } + } + + // Full pixels + $fullPixels = (int)($samplesLeft / $this->samplesPerPixel); + if ($fullPixels > 0) { + for ($i = 0; $i < $fullPixels; $i++) { + $this->_add($this->samplesPerPixel, $a, $r, $g, $b); + $this->pixelOffset++; + } + + $samplesLeft -= $fullPixels * $this->samplesPerPixel; + } + + // Last partial pixel + if ($samplesLeft > 0) { + $this->_add($samplesLeft, $a, $r, $g, $b); + + $this->subPixelOffset += $samplesLeft; + + if ($this->subPixelOffset == $this->samplesPerPixel) { + $this->subPixelOffset = 0; + $this->pixelOffset++; + } + } + } +} \ No newline at end of file diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleRange.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleRange.php new file mode 100644 index 00000000..d65b1768 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleRange.php @@ -0,0 +1,27 @@ +fromX = $fromX; + $this->toXExcl = $toXExcl; + $this->edges = array(); + } +} \ No newline at end of file diff --git a/vendor/jdenticon/jdenticon/src/Color.php b/vendor/jdenticon/jdenticon/src/Color.php new file mode 100644 index 00000000..c07c9054 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Color.php @@ -0,0 +1,605 @@ +r = $red; + $color->g = $green; + $color->b = $blue; + $color->a = $alpha; + return $color; + } + + /** + * Creates a Color instance from HSL color parameters. + * + * @param float $hue Hue in the range [0, 1] + * @param float $saturation Saturation in the range [0, 1] + * @param float $lightness Lightness in the range [0, 1] + * @param float $alpha Alpha channel value in the range [0, 1]. + */ + public static function fromHsl($hue, $saturation, $lightness, $alpha = 1.0) + { + if ($hue < 0) $hue = 0; + if ($hue > 1) $hue = 1; + + if ($saturation < 0) $saturation = 0; + if ($saturation > 1) $saturation = 1; + + if ($lightness < 0) $lightness = 0; + if ($lightness > 1) $lightness = 1; + + if ($alpha < 0) $alpha = 0; + if ($alpha > 1) $alpha = 1; + + // Based on http://www.w3.org/TR/2011/REC-css3-color-20110607/#hsl-color + if ($saturation == 0) { + $value = (int)($lightness * 255); + return self::fromRgb($value, $value, $value, (int)($alpha * 255)); + } else { + if ($lightness <= 0.5) { + $m2 = $lightness * ($saturation + 1); + } else { + $m2 = $lightness + $saturation - $lightness * $saturation; + } + + $m1 = $lightness * 2 - $m2; + + return self::fromRgb( + self::hueToRgb($m1, $m2, $hue * 6 + 2), + self::hueToRgb($m1, $m2, $hue * 6), + self::hueToRgb($m1, $m2, $hue * 6 - 2), + (int)($alpha * 255)); + } + } + + /** + * Creates a Color> instance from HSL color parameters and will compensate + * the lightness for hues that appear to be darker than others. + * + * @param float $hue Hue in the range [0, 1]. + * @param float $saturation Saturation in the range [0, 1]. + * @param float $lightness Lightness in the range [0, 1]. + * @param float $alpha Alpha channel value in the range [0, 1]. + */ + public static function fromHslCompensated($hue, $saturation, $lightness, $alpha = 1.0) + { + if ($hue < 0) $hue = 0; + if ($hue > 1) $hue = 1; + + $lightnessCompensation = self::$lightnessCompensations[(int)($hue * 6 + 0.5)]; + + // Adjust the input lightness relative to the compensation + $lightness = $lightness < 0.5 ? + $lightness * $lightnessCompensation * 2 : + $lightnessCompensation + ($lightness - 0.5) * (1 - $lightnessCompensation) * 2; + + return self::fromHsl($hue, $saturation, $lightness, $alpha); + } + + // Helper method for FromHsl + private static function hueToRgb($m1, $m2, $h) + { + if ($h < 0) { + $h = $h + 6; + } elseif ($h > 6) { + $h = $h - 6; + } + + if ($h < 1) { + $r = $m1 + ($m2 - $m1) * $h; + } elseif ($h < 3) { + $r = $m2; + } elseif ($h < 4) { + $r = $m1 + ($m2 - $m1) * (4 - $h); + } else { + $r = $m1; + } + + return (int)(255 * $r); + } + + /** + * Gets the argb value of this color. + * + * @return int + */ + public function toRgba() + { + return + ($this->r << 24) | + ($this->g << 16) | + ($this->b << 8) | + ($this->a); + } + + /** + * Gets a hexadecimal representation of this color on the format #rrggbbaa. + * + * @return string + */ + public function __toString() + { + return '#' . bin2hex(pack('N', $this->toRgba())); + } + + /** + * Gets a hexadecimal representation of this color on the format #rrggbbaa. + * + * @return string + */ + public function toHexString($length = 8) + { + if ($length === 8) { + return $this->__toString(); + } + return '#' . substr(bin2hex(pack('N', $this->toRgba())), 0, 6); + } + + /** + * Tries to parse a value as a Color. + * + * @param mixed $value Value to parse. + * @throws InvalidArgumentException + * @return \Jdenticon\Color + */ + public static function parse($value) { + if ($value instanceof Color) { + return $value; + } + + $value = strtolower("$value"); + + if (preg_match('/^#?[0-9a-f]{3,8}$/', $value) && + self::parseHexColor($value, $result) + ) { + return $result; + } + + if (preg_match( + '/^rgba?\\(([^,]+),([^,]+),([^,]+)(?:,([^,]+))?\\)$/', + $value, $matches) && + self::parseRgbComponent($matches[1], $r) && + self::parseRgbComponent($matches[2], $g) && + self::parseRgbComponent($matches[3], $b) && + self::parseAlpha(isset($matches[4]) ? $matches[4] : null, $a) + ) { + return self::fromRgb($r, $g, $b, (int)(255 * $a)); + } + + if (preg_match( + '/^hsla?\\(([^,]+),([^,]+),([^,]+)(?:,([^,]+))?\\)$/', + $value, $matches) && + self::parseHue($matches[1], $h) && + self::parsePercent($matches[2], $s) && + self::parsePercent($matches[3], $l) && + self::parseAlpha(isset($matches[4]) ? $matches[4] : null, $a) + ) { + return self::fromHsl($h, $s, $l, $a); + } + + $result = self::parseNamedColor($value); + if ($result !== null) { + return $result; + } + + throw new \InvalidArgumentException( + "Cannot parse '$value' as a color."); + } + + /** + * Parses a percent value. + * + * @param string $input Input string. + * @param float $result Resulting value in range [0, 1]. + * + * @return boolean + */ + private static function parsePercent($input, &$result) + { + // Detect and remove percent sign + if (preg_match('/^\\s*(\\d*(?:\\.\\d*)?)%\\s*$/', $input, $matches)) { + $result = floatval($matches[1]) / 100; + + if ($result < 0) $result = 0; + if ($result > 1) $result = 1; + + return true; + } + return false; + } + + /** + * Parses an alpha value. + * + * @param string $input Input string. + * @param float $result Resulting alpha in range [0, 1]. + * + * @return boolean + */ + private static function parseAlpha($input, &$result) + { + if ($input === null || + $input === '' + ) { + $result = 1; + return true; + } + + if (preg_match('/^\\s*(\\d*(?:\\.\\d*)?)(%?)\\s*$/', $input, $matches)) { + $result = floatval($matches[1]); + + // Percentage + if ($matches[2] !== '') { + $result = $result / 100; + } + + if ($result < 0) $result = 0; + if ($result > 1) $result = 1; + + return true; + } + + return false; + } + + /** + * Parses an RGB component. + * + * @param string $input Input string. + * @param float $result Hue in range [0, 255]. + * + * @return boolean + */ + private static function parseRgbComponent($input, &$result) + { + if (preg_match('/^\\s*(\\d*(?:\\.\\d*)?)(%?)\\s*$/', $input, $matches)) { + $result = floatval($matches[1]); + + if ($matches[2] === '%') { + $result = 255 * $result / 100; + } + + $result = (int)$result; + + if ($result < 0) $result = 0; + if ($result > 255) $result = 255; + + return true; + } + return false; + } + + /** + * Parses a hue component. + * + * @param string $input Input string. + * @param float $result Hue in range [0, 1]. + * + * @return boolean + */ + private static function parseHue($input, &$result) + { + if (preg_match( + '/^\s*(\d*(?:\.\d*)?)(deg|grad|rad|turn|)\s*$/', + $input, $matches) + ) { + $result = floatval($matches[1]); + + // Percentage + switch ($matches[2]) { + case "grad": + // Gradians: range 0 - 400 + $result = $result / 400; + break; + case "rad": + // Radians: range 0 - 2pi + $result = $result / M_PI / 2; + break; + case "turn": + // Turns: range 0 - 1 + $result = $result; + break; + default: + // Degree: range 0 - 360 + $result = $result / 360; + break; + } + + $result = fmod($result, 1); + + if ($result < 0) { + $result += 1; + } + + return true; + } + return false; + } + + /** + * Parses a hex color string. + * + * @param string $input Input string. + * @param float $result Hue in range [0, 1]. + * + * @return boolean + */ + private static function parseHexColor($input, &$result) + { + if ($input[0] === '#') { + $input = substr($input, 1); + } + + // intval does not support unsigned 32-bit integers + // so we need to parse large numbers stepwise + $numeric24bit = intval(substr($input, 0, 6), 16); + $alpha8bit = intval(substr($input, 6, 2), 16); + + switch (strlen($input)) { + case 3: + $result = self::fromRgb( + (($numeric24bit & 0xf00) >> 8) | + (($numeric24bit & 0xf00) >> 4), + (($numeric24bit & 0x0f0) >> 4) | + (($numeric24bit & 0x0f0)), + (($numeric24bit & 0x00f) << 4) | + (($numeric24bit & 0x00f)) + ); + return true; + + case 4: + $result = self::fromRgb( + (($numeric24bit & 0xf000) >> 12) | + (($numeric24bit & 0xf000) >> 8), + (($numeric24bit & 0x0f00) >> 8) | + (($numeric24bit & 0x0f00) >> 4), + (($numeric24bit & 0x00f0) >> 4) | + (($numeric24bit & 0x00f0)), + (($numeric24bit & 0x000f) << 4) | + (($numeric24bit & 0x000f)) + ); + return true; + + case 6: + $result = self::fromRgb( + 0xff & ($numeric24bit >> 16), + 0xff & ($numeric24bit >> 8), + 0xff & ($numeric24bit) + ); + return true; + + case 8: + $result = self::fromRgb( + 0xff & ($numeric24bit >> 16), + 0xff & ($numeric24bit >> 8), + 0xff & ($numeric24bit), + 0xff & ($alpha8bit) + ); + return true; + } + + return false; + } + + /** + * Looks up a named color to a Color instance. + * + * @param string $input Input string. + * + * @return \Jdenticon\Color + */ + private static function parseNamedColor($input) + { + // Source: https://www.w3.org/TR/css-color-4/#named-colors + switch ($input) { + case 'aliceblue': return self::fromRgb(240,248,255); + case 'antiquewhite': return self::fromRgb(250,235,215); + case 'aqua': return self::fromRgb(0,255,255); + case 'aquamarine': return self::fromRgb(127,255,212); + case 'azure': return self::fromRgb(240,255,255); + case 'beige': return self::fromRgb(245,245,220); + case 'bisque': return self::fromRgb(255,228,196); + case 'black': return self::fromRgb(0,0,0); + case 'blanchedalmond': return self::fromRgb(255,235,205); + case 'blue': return self::fromRgb(0,0,255); + case 'blueviolet': return self::fromRgb(138,43,226); + case 'brown': return self::fromRgb(165,42,42); + case 'burlywood': return self::fromRgb(222,184,135); + case 'cadetblue': return self::fromRgb(95,158,160); + case 'chartreuse': return self::fromRgb(127,255,0); + case 'chocolate': return self::fromRgb(210,105,30); + case 'coral': return self::fromRgb(255,127,80); + case 'cornflowerblue': return self::fromRgb(100,149,237); + case 'cornsilk': return self::fromRgb(255,248,220); + case 'crimson': return self::fromRgb(220,20,60); + case 'cyan': return self::fromRgb(0,255,255); + case 'darkblue': return self::fromRgb(0,0,139); + case 'darkcyan': return self::fromRgb(0,139,139); + case 'darkgoldenrod': return self::fromRgb(184,134,11); + case 'darkgray': return self::fromRgb(169,169,169); + case 'darkgreen': return self::fromRgb(0,100,0); + case 'darkgrey': return self::fromRgb(169,169,169); + case 'darkkhaki': return self::fromRgb(189,183,107); + case 'darkmagenta': return self::fromRgb(139,0,139); + case 'darkolivegreen': return self::fromRgb(85,107,47); + case 'darkorange': return self::fromRgb(255,140,0); + case 'darkorchid': return self::fromRgb(153,50,204); + case 'darkred': return self::fromRgb(139,0,0); + case 'darksalmon': return self::fromRgb(233,150,122); + case 'darkseagreen': return self::fromRgb(143,188,143); + case 'darkslateblue': return self::fromRgb(72,61,139); + case 'darkslategray': return self::fromRgb(47,79,79); + case 'darkslategrey': return self::fromRgb(47,79,79); + case 'darkturquoise': return self::fromRgb(0,206,209); + case 'darkviolet': return self::fromRgb(148,0,211); + case 'deeppink': return self::fromRgb(255,20,147); + case 'deepskyblue': return self::fromRgb(0,191,255); + case 'dimgray': return self::fromRgb(105,105,105); + case 'dimgrey': return self::fromRgb(105,105,105); + case 'dodgerblue': return self::fromRgb(30,144,255); + case 'firebrick': return self::fromRgb(178,34,34); + case 'floralwhite': return self::fromRgb(255,250,240); + case 'forestgreen': return self::fromRgb(34,139,34); + case 'fuchsia': return self::fromRgb(255,0,255); + case 'gainsboro': return self::fromRgb(220,220,220); + case 'ghostwhite': return self::fromRgb(248,248,255); + case 'gold': return self::fromRgb(255,215,0); + case 'goldenrod': return self::fromRgb(218,165,32); + case 'gray': return self::fromRgb(128,128,128); + case 'green': return self::fromRgb(0,128,0); + case 'greenyellow': return self::fromRgb(173,255,47); + case 'grey': return self::fromRgb(128,128,128); + case 'honeydew': return self::fromRgb(240,255,240); + case 'hotpink': return self::fromRgb(255,105,180); + case 'indianred': return self::fromRgb(205,92,92); + case 'indigo': return self::fromRgb(75,0,130); + case 'ivory': return self::fromRgb(255,255,240); + case 'khaki': return self::fromRgb(240,230,140); + case 'lavender': return self::fromRgb(230,230,250); + case 'lavenderblush': return self::fromRgb(255,240,245); + case 'lawngreen': return self::fromRgb(124,252,0); + case 'lemonchiffon': return self::fromRgb(255,250,205); + case 'lightblue': return self::fromRgb(173,216,230); + case 'lightcoral': return self::fromRgb(240,128,128); + case 'lightcyan': return self::fromRgb(224,255,255); + case 'lightgoldenrodyellow': return self::fromRgb(250,250,210); + case 'lightgray': return self::fromRgb(211,211,211); + case 'lightgreen': return self::fromRgb(144,238,144); + case 'lightgrey': return self::fromRgb(211,211,211); + case 'lightpink': return self::fromRgb(255,182,193); + case 'lightsalmon': return self::fromRgb(255,160,122); + case 'lightseagreen': return self::fromRgb(32,178,170); + case 'lightskyblue': return self::fromRgb(135,206,250); + case 'lightslategray': return self::fromRgb(119,136,153); + case 'lightslategrey': return self::fromRgb(119,136,153); + case 'lightsteelblue': return self::fromRgb(176,196,222); + case 'lightyellow': return self::fromRgb(255,255,224); + case 'lime': return self::fromRgb(0,255,0); + case 'limegreen': return self::fromRgb(50,205,50); + case 'linen': return self::fromRgb(250,240,230); + case 'magenta': return self::fromRgb(255,0,255); + case 'maroon': return self::fromRgb(128,0,0); + case 'mediumaquamarine': return self::fromRgb(102,205,170); + case 'mediumblue': return self::fromRgb(0,0,205); + case 'mediumorchid': return self::fromRgb(186,85,211); + case 'mediumpurple': return self::fromRgb(147,112,219); + case 'mediumseagreen': return self::fromRgb(60,179,113); + case 'mediumslateblue': return self::fromRgb(123,104,238); + case 'mediumspringgreen': return self::fromRgb(0,250,154); + case 'mediumturquoise': return self::fromRgb(72,209,204); + case 'mediumvioletred': return self::fromRgb(199,21,133); + case 'midnightblue': return self::fromRgb(25,25,112); + case 'mintcream': return self::fromRgb(245,255,250); + case 'mistyrose': return self::fromRgb(255,228,225); + case 'moccasin': return self::fromRgb(255,228,181); + case 'navajowhite': return self::fromRgb(255,222,173); + case 'navy': return self::fromRgb(0,0,128); + case 'oldlace': return self::fromRgb(253,245,230); + case 'olive': return self::fromRgb(128,128,0); + case 'olivedrab': return self::fromRgb(107,142,35); + case 'orange': return self::fromRgb(255,165,0); + case 'orangered': return self::fromRgb(255,69,0); + case 'orchid': return self::fromRgb(218,112,214); + case 'palegoldenrod': return self::fromRgb(238,232,170); + case 'palegreen': return self::fromRgb(152,251,152); + case 'paleturquoise': return self::fromRgb(175,238,238); + case 'palevioletred': return self::fromRgb(219,112,147); + case 'papayawhip': return self::fromRgb(255,239,213); + case 'peachpuff': return self::fromRgb(255,218,185); + case 'peru': return self::fromRgb(205,133,63); + case 'pink': return self::fromRgb(255,192,203); + case 'plum': return self::fromRgb(221,160,221); + case 'powderblue': return self::fromRgb(176,224,230); + case 'purple': return self::fromRgb(128,0,128); + case 'rebeccapurple': return self::fromRgb(102,51,153); + case 'red': return self::fromRgb(255,0,0); + case 'rosybrown': return self::fromRgb(188,143,143); + case 'royalblue': return self::fromRgb(65,105,225); + case 'saddlebrown': return self::fromRgb(139,69,19); + case 'salmon': return self::fromRgb(250,128,114); + case 'sandybrown': return self::fromRgb(244,164,96); + case 'seagreen': return self::fromRgb(46,139,87); + case 'seashell': return self::fromRgb(255,245,238); + case 'sienna': return self::fromRgb(160,82,45); + case 'silver': return self::fromRgb(192,192,192); + case 'skyblue': return self::fromRgb(135,206,235); + case 'slateblue': return self::fromRgb(106,90,205); + case 'slategray': return self::fromRgb(112,128,144); + case 'slategrey': return self::fromRgb(112,128,144); + case 'snow': return self::fromRgb(255,250,250); + case 'springgreen': return self::fromRgb(0,255,127); + case 'steelblue': return self::fromRgb(70,130,180); + case 'tan': return self::fromRgb(210,180,140); + case 'teal': return self::fromRgb(0,128,128); + case 'thistle': return self::fromRgb(216,191,216); + case 'tomato': return self::fromRgb(255,99,71); + case 'transparent': return self::fromRgb(0,0,0,0); + case 'turquoise': return self::fromRgb(64,224,208); + case 'violet': return self::fromRgb(238,130,238); + case 'wheat': return self::fromRgb(245,222,179); + case 'white': return self::fromRgb(255,255,255); + case 'whitesmoke': return self::fromRgb(245,245,245); + case 'yellow': return self::fromRgb(255,255,0); + case 'yellowgreen': return self::fromRgb(154,205,50); + default: return null; + } + } +} diff --git a/vendor/jdenticon/jdenticon/src/Identicon.php b/vendor/jdenticon/jdenticon/src/Identicon.php new file mode 100644 index 00000000..48183b86 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Identicon.php @@ -0,0 +1,492 @@ +iconGenerator = IconGenerator::getDefaultGenerator(); + + if ($options !== null) { + $this->setOptions($options); + } + + if ($this->style === null) { + $this->style = new IdenticonStyle(); + } + } + + /** + * Creates an Identicon instance from a specified hash. + * + * @param string $hash A binary string containing the hash that will be used + * as base for this icon. The hash must contain at least 6 bytes. + * @param int $size The size of the icon in pixels (the icon is quadratic). + * @return \Jdenticon\Identicon + */ + public static function fromHash($hash, $size) + { + return new Identicon(array('hash' => $hash, 'size' => $size)); + } + + /** + * Creates an Identicon instance from a specified value. + * + * @param mixed $value The value that will be used as base for this icon. + * The value will be converted to a UTF8 encoded string and then hashed + * using SHA1. + * @param int $size The size of the icon in pixels (the icon is quadratic). + * @return \Jdenticon\Identicon + */ + public static function fromValue($value, $size) + { + return new Identicon(array('value' => $value, 'size' => $size)); + } + + /** + * Gets an associative array of all options of this identicon. + * + * @return array + */ + public function getOptions() + { + $options = array(); + + if ($this->valueSet) { + $options['value'] = $this->getValue(); + } elseif ($this->hash !== null) { + $options['hash'] = $this->getHash(); + } + + $options['size'] = $this->getSize(); + $options['style'] = $this->getStyle()->getOptions(); + + if ($this->enableImageMagick !== null) { + $options['enableImageMagick'] = $this->getEnableImageMagick(); + } + + if ($this->iconGenerator !== IconGenerator::getDefaultGenerator()) { + $options['iconGenerator'] = $this->getIconGenerator(); + } + + return $options; + } + + /** + * Sets options in this identicon by specifying an associative array of + * option values. + * + * @param array $options Options to set. + * @return self + */ + public function setOptions(array $options) + { + foreach ($options as $key => $value) { + $this->__set($key, $value); + } + return $this; + } + + public function __get($name) + { + switch (strtolower($name)) { + case 'size': + return $this->getSize(); + case 'hash': + return $this->getHash(); + case 'value': + return $this->getValue(); + case 'style': + return $this->getStyle(); + case 'icongenerator': + return $this->getIconGenerator(); + case 'enableimagemagick': + return $this->getEnableImageMagick(); + default: + throw new \InvalidArgumentException( + "Unknown Identicon option '$name'."); + } + } + + public function __set($name, $value) + { + switch (strtolower($name)) { + case 'size': + $this->setSize($value); + break; + case 'hash': + $this->setHash($value); + break; + case 'value': + $this->setValue($value); + break; + case 'style': + $this->setStyle($value); + break; + case 'icongenerator': + $this->setIconGenerator($value); + break; + case 'enableimagemagick': + $this->setEnableImageMagick($value); + break; + default: + throw new \InvalidArgumentException( + "Unknown Identicon option '$name'."); + } + } + + /** + * Gets the size of the icon in pixels. + */ + public function getSize() + { + return $this->size; + } + + /** + * Sets the size of this icon in pixels. + * + * @param int|float|double $size The width and height of the icon. + */ + public function setSize($size) + { + if (!is_numeric($size) || $size < 1) { + throw new \InvalidArgumentException( + "An invalid identicon size was specified. ". + "A numeric value >= 1 was expected. Specified value: $size."); + } + + $this->size = (int)$size; + } + + /** + * Gets the size of the icon in pixels. + */ + public function getEnableImageMagick() + { + // Enable ImageMagick on PHP < 7. On PHP 7 the performance increase + // is not as obvious as on PHP 5. Since the ImageMagick renderer has a + // lot of quirks, we don't want to use it unless really needed. + if ($this->enableImageMagick === null) { + return PHP_MAJOR_VERSION < 7 && extension_loaded('imagick'); + } + + return $this->enableImageMagick; + } + + /** + * Sets whether ImageMagick should be used to generate PNG icons. + * + * @param bool $enable true to enable ImageMagick. + */ + public function setEnableImageMagick($enable) + { + if (!is_bool($enable)) { + throw new \InvalidArgumentException( + "enableImageMagick can only assume boolean values. Specified value: $enable."); + } + + // Verify that the Imagick extension is installed + if ($enable && !extension_loaded('imagick')) { + throw new \Exception( + 'Failed to enable ImageMagick. '. + 'The Imagick PHP extension was not found on this system.'); + } + + $this->enableImageMagick = $enable; + } + + /** + * Gets the {@see IconGenerator} used to generate icons. + * + * @return \Jdenticon\Rendering\IconGenerator + */ + public function getIconGenerator() + { + return $this->iconGenerator; + } + + /** + * Sets the {@see IconGenerator} used to generate icons. + * + * @param \Jdenticon\Rendering\IconGenerator $iconGenerator Icon generator + * that will render the shapes of the identicon. + * @return \Jdenticon\Identicon + */ + public function setIconGenerator(IconGenerator $iconGenerator) + { + if ($iconGenerator === null) { + $iconGenerator = IconGenerator::getDefaultGenerator(); + } + $this->iconGenerator = $iconGenerator; + return $this; + } + + /** + * Gets or sets the style of the icon. + * + * @return \Jdenticon\IdenticonStyle + */ + public function getStyle() + { + return $this->style; + } + + /** + * Gets or sets the style of the icon. + * + * @param array|\Jdenticon\IdenticonStyle $style The new style of the icon. + * NULL will revert the identicon to use the default style. + * @return self + */ + public function setStyle($style) + { + if ($style == null) { + $this->style = new IdenticonStyle(); + } elseif ($style instanceof IdenticonStyle) { + $this->style = $style; + } elseif (is_array($style)) { + $this->style = new IdenticonStyle($style); + } else { + throw new \InvalidArgumentException( + "Invalid indenticon style was specified. ". + "Allowed values are IdenticonStyle instances and associative ". + "arrays containing IdenticonStyle options."); + } + + return $this; + } + + /** + * Gets a binary string containing the hash that is used as base for this + * icon. + */ + public function getHash() + { + return $this->hash; + } + + /** + * Sets a binary string containing the hash that is used as base for this + * icon. The string should contain at least 6 bytes. + * + * @param string $hash Binary string containing the hash. + */ + public function setHash($hash) + { + if (!is_string($hash)) { + throw new \InvalidArgumentException( + 'An invalid $hash was passed to Identicon. ' . + 'A binary string was expected.'); + } + if (strlen($hash) < 6) { + throw new \InvalidArgumentException( + 'An invalid $hash was passed to Identicon. ' . + 'The hash was expected to contain at least 6 bytes.'); + } + + $this->hash = $hash; + $this->value = null; + $this->valueSet = false; + return $this; + } + + /** + * Gets a binary string containing the hash that is used as base for this + * icon. + */ + public function getValue() + { + return $this->value; + } + + /** + * Sets a value that will be used as base for this icon. The value will + * be converted to a string and then hashed using SHA1. + * + * @param mixed $value Value that will be hashed. + */ + public function setValue($value) + { + $this->hash = sha1("$value"); + $this->value = $value; + $this->valueSet = true; + return $this; + } + + /** + * Gets the bounds of the icon excluding its padding. + * + * @return \Jdenticon\Rendering\Rectangle + */ + public function getIconBounds() + { + // Round padding to nearest integer + $padding = (int)($this->style->getPadding() * $this->size + 0.5); + + return new Rectangle( + $padding, $padding, + $this->size - $padding * 2, + $this->size - $padding * 2); + } + + private function getRenderer($imageFormat) + { + switch (strtolower($imageFormat)) { + case 'svg': + return new SvgRenderer($this->size, $this->size); + + default: + return $this->getEnableImageMagick() ? + new ImagickRenderer($this->size, $this->size) : + new InternalPngRenderer($this->size, $this->size); + } + } + + /** + * Draws this icon using a specified renderer. + * + * This method is only intended for usage with custom renderers. A custom + * renderer could as an example render an Identicon in a file format not + * natively supported by Jdenticon. To implement a new file format, + * implement {@see \Jdenticon\Rendering\RendererInterface}. + * + * @param \Jdenticon\Rendering\RendererInterface $renderer The renderer used + * to render this icon. + * @param \Jdenticon\Rendering\Rectangle $rect The bounds of the rendered + * icon. No padding will be applied to the rectangle. If the parameter + * is omitted, the rectangle is calculated from the current icon + * size and padding. + */ + public function draw( + \Jdenticon\Rendering\RendererInterface $renderer, + \Jdenticon\Rendering\Rectangle $rect = null) + { + if ($rect === null) { + $rect = $this->getIconBounds(); + } + $this->iconGenerator->generate( + $renderer, $rect, $this->style, $this->hash); + } + + /** + * Renders the icon directly to the page output. + * + * The method will set the 'Content-Type' HTTP header. You are recommended + * to set an appropriate 'Cache-Control' header before calling this method + * to ensure the icon is cached client side. + * + * @param string $imageFormat The image format of the output. + * Supported values are 'png' and 'svg'. + */ + public function displayImage($imageFormat = 'png') + { + $renderer = $this->getRenderer($imageFormat); + $this->draw($renderer, $this->getIconBounds()); + $mimeType = $renderer->getMimeType(); + $data = $renderer->getData(); + header("Content-Type: $mimeType"); + echo $data; + } + + /** + * Renders the icon to a binary string. + * + * @param string $imageFormat The image format of the output string. + * Supported values are 'png' and 'svg'. + * @return string + */ + public function getImageData($imageFormat = 'png') + { + $renderer = $this->getRenderer($imageFormat); + $this->draw($renderer, $this->getIconBounds()); + return $renderer->getData(); + } + + /** + * Renders the icon as a data URI. It is recommended to avoid using this + * method unless really necessary, since it will effectively disable client + * caching of generated icons, and will also cause the same icon to be + * rendered multiple times, when used multiple times on a single page. + * + * @param string $imageFormat The image format of the data URI. + * Supported values are 'png' and 'svg'. + * @return string + */ + public function getImageDataUri($imageFormat = 'png') + { + $renderer = $this->getRenderer($imageFormat); + $this->draw($renderer, $this->getIconBounds()); + $mimeType = $renderer->getMimeType(); + $base64 = base64_encode($renderer->getData()); + return "data:$mimeType;base64,$base64"; + } +} + + diff --git a/vendor/jdenticon/jdenticon/src/IdenticonStyle.php b/vendor/jdenticon/jdenticon/src/IdenticonStyle.php new file mode 100644 index 00000000..ad388c5e --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/IdenticonStyle.php @@ -0,0 +1,460 @@ +backgroundColor = self::getDefaultBackgroundColor(); + $this->padding = self::getDefaultPadding(); + $this->colorSaturation = self::getDefaultColorSaturation(); + $this->grayscaleSaturation = self::getDefaultGrayscaleSaturation(); + $this->colorLightness = self::getDefaultColorLightness(); + $this->grayscaleLightness = self::getDefaultGrayscaleLightness(); + + if ($options !== null) { + $this->setOptions($options); + } + } + + /** + * Gets an associative array of all options of this style. + * + * @return array + */ + public function getOptions() + { + $options = array(); + + $options['backgroundColor'] = $this->getBackgroundColor()->__toString(); + $options['padding'] = $this->getPadding(); + $options['colorSaturation'] = $this->getColorSaturation(); + $options['grayscaleSaturation'] = $this->getGrayscaleSaturation(); + $options['colorLightness'] = $this->getColorLightness(); + $options['grayscaleLightness'] = $this->getGrayscaleLightness(); + + if ($this->hues !== null) { + $options['hues'] = $this->getHues(); + } + + return $options; + } + + /** + * Sets options in this style by specifying an associative array of option + * values. + * + * @param array $options Options to set. + * @return self + */ + public function setOptions(array $options) + { + foreach ($options as $key => $value) { + $this->__set($key, $value); + } + return $this; + } + + public function __get($name) + { + switch (strtolower($name)) { + case 'backgroundcolor': + return $this->getBackgroundColor(); + case 'padding': + return $this->getPadding(); + case 'colorsaturation': + return $this->getColorSaturation(); + case 'grayscalesaturation': + return $this->getGrayscaleSaturation(); + case 'colorlightness': + return $this->getColorLightness(); + case 'grayscalelightness': + return $this->getGrayscaleLightness(); + case 'hues': + return $this->getHues(); + default: + throw new \InvalidArgumentException( + "Unknown IdenticonStyle option '$name'."); + } + } + + public function __set($name, $value) + { + switch (strtolower($name)) { + case 'backgroundcolor': + $this->setBackgroundColor($value); + break; + case 'padding': + $this->setPadding($value); + break; + case 'colorsaturation': + $this->setColorSaturation($value); + break; + case 'grayscalesaturation': + $this->setGrayscaleSaturation($value); + break; + case 'colorlightness': + $this->setColorLightness($value); + break; + case 'grayscalelightness': + $this->setGrayscaleLightness($value); + break; + case 'hues': + $this->setHues($value); + break; + default: + throw new \InvalidArgumentException( + "Unknown IdenticonStyle option '$name'."); + } + } + + /** + * Normalizes a hue to the first turn [0, 360). + * + * @param mixed $hue + * @return integer + */ + private static function normalizeHue($hue) + { + if (!is_numeric($hue)) { + throw new \InvalidArgumentException( + "'$hue' is not a valid hue."); + } + + $hue = $hue % 360; + if ($hue < 0) { + $hue += 360; + } + + return $hue; + } + + /** + * Gets an array of allowed hues, or null if there are no restrictions. + * + * @return array(int)|null + */ + public function getHues() + { + return $this->hues; + } + + /** + * Sets the allowed hues of generated icons. + * + * @param array(integer)|integer|null $value A hue specified in degrees, + * or an array of hues specified in degrees. If set to null, the hue + * list is cleared. + * @return self + */ + public function setHues($value) + { + $hues = array(); + + if ($value !== null) { + if (is_array($value)) { + foreach ($value as $hue) { + $hues[] = self::normalizeHue($hue); + } + } else { + $hues[] = self::normalizeHue($value); + } + } + + $this->hues = empty($hues) ? null : $hues; + return $this; + } + + /** + * Gets the padding of an icon in percents in the range [0.0, 0.4]. + * + * @return float + */ + public function getPadding() + { + return $this->padding; + } + + /** + * Sets the padding of an icon in percents. + * + * @param float $value New padding in the range [0.0, 0.4]. + * @return self + */ + public function setPadding($value) + { + if (!is_numeric($value) || $value < 0 || $value > 0.4) { + throw new \InvalidArgumentException( + "Padding '$value' out of range. ". + "Values in the range [0.0, 0.4] are allowed."); + } + $this->padding = (float)$value; + return $this; + } + + /** + * Gets the color of the identicon background. + * + * @return \Jdenticon\Color + */ + public function getBackgroundColor() + { + return $this->backgroundColor; + } + + /** + * Sets the color of the identicon background. + * + * @param \Jdenticon\Color|string $value New background color. + * @return \Jdenticon\IdenticonStyle + */ + public function setBackgroundColor($value) + { + if ($value instanceof Color) { + $this->backgroundColor = $value; + } else { + $this->backgroundColor = Color::parse($value); + } + + return $this; + } + + /** + * Gets the saturation of the originally grayscale identicon shapes. + * + * @return float Saturation in the range [0.0, 1.0]. + */ + public function getGrayscaleSaturation() + { + return $this->grayscaleSaturation; + } + + /** + * Sets the saturation of the originally grayscale identicon shapes. + * + * @param $value float Saturation in the range [0.0, 1.0]. + * @return self + */ + public function setGrayscaleSaturation($value) + { + if (!is_numeric($value) || + $value < 0 || $value > 1 + ) { + throw new \InvalidArgumentException( + "The grayscale saturation was invalid. ". + "Only values in the range [0.0, 1.0] are allowed."); + } + $this->grayscaleSaturation = (float)$value; + return $this; + } + + /** + * Gets the saturation of the colored identicon shapes. + * + * @return float Saturation in the range [0.0, 1.0]. + */ + public function getColorSaturation() + { + return $this->colorSaturation; + } + + /** + * Sets the saturation of the colored identicon shapes. + * + * @param $value float Saturation in the range [0.0, 1.0]. + * @return self + */ + public function setColorSaturation($value) + { + if (!is_numeric($value) || + $value < 0 || $value > 1 + ) { + throw new \InvalidArgumentException( + "The color saturation was invalid. ". + "Only values in the range [0.0, 1.0] are allowed."); + } + $this->colorSaturation = (float)$value; + return $this; + } + + /** + * Gets the value of the ColorLightness property. + * + * @return array(float, float) + */ + public function getColorLightness() + { + return $this->colorLightness; + } + + /** + * Sets the value of the ColorLightness property. + * + * @param $value array(float, float) Lightness range. + * @return self + */ + public function setColorLightness($value) + { + if (!is_array($value) || + !array_key_exists(0, $value) || + !array_key_exists(1, $value) || + !is_numeric($value[0]) || + !is_numeric($value[1]) || + $value[0] < 0 || $value[0] > 1 || + $value[1] < 0 || $value[1] > 1 + ) { + throw new \InvalidArgumentException( + "The value passed to setColorLightness was invalid. ". + "Please check the documentation."); + } + + $this->colorLightness = array((float)$value[0], (float)$value[1]); + return $this; + } + + /** + * Gets the value of the GrayscaleLightness property. + * + * @return array(float, float) + */ + public function getGrayscaleLightness() + { + return $this->grayscaleLightness; + } + + /** + * Sets the value of the GrayscaleLightness property. + * + * @param $value array(float, float) Lightness range. + * @return self + */ + public function setGrayscaleLightness($value) + { + if (!is_array($value) || + !array_key_exists(0, $value) || + !array_key_exists(1, $value) || + !is_numeric($value[0]) || + !is_numeric($value[1]) || + $value[0] < 0 || $value[0] > 1 || + $value[1] < 0 || $value[1] > 1 + ) { + throw new \InvalidArgumentException( + "The value passed to setGrayscaleLightness was invalid. ". + "Please check the documentation."); + } + $this->grayscaleLightness = array((float)$value[0], (float)$value[1]); + return $this; + } + + + + /** + * Gets the default value of the BackgroundColor property. Resolves to transparent. + * + * @return \Jdenticon\Color + */ + public static function getDefaultBackgroundColor() + { + return Color::fromRgb(255, 255, 255, 255); + } + + /** + * Gets the default value of the Padding property. Resolves to 0.08. + * + * @return float + */ + public static function getDefaultPadding() + { + return 0.08; + } + + /** + * Gets the default value of the ColorSaturation property. Resolves to 0.5. + * + * @return float + */ + public static function getDefaultColorSaturation() + { + return 0.5; + } + + /** + * Gets the default value of the GrayscaleSaturation property. Resolves to 0. + * + * @return float + */ + public static function getDefaultGrayscaleSaturation() + { + return 0; + } + + /** + * Gets the default value of the ColorLightness property. Resolves to [0.4, 0.8]. + * + * @return array + */ + public static function getDefaultColorLightness() + { + return array(0.4, 0.8); + } + + /** + * Gets the default value of the GrayscaleLightness property. Resolves to [0.3, 0.9]. + * + * @return array + */ + public static function getDefaultGrayscaleLightness() + { + return array(0.3, 0.9); + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/AbstractRenderer.php b/vendor/jdenticon/jdenticon/src/Rendering/AbstractRenderer.php new file mode 100644 index 00000000..0aeac805 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/AbstractRenderer.php @@ -0,0 +1,209 @@ +transform = Transform::getEmpty(); + } + + /** + * Sets the current transform that will be applied on all coordinates before + * being rendered to the target image. + * + * @param \Jdenticon\Rendering\Transform $transform The transform to set. + * If NULL is specified any existing transform is removed. + */ + public function setTransform(\Jdenticon\Rendering\Transform $transform) + { + $this->transform = $transform === null ? + Transform::getEmpty() : $transform; + } + + /** + * Gets the current transform that will be applied on all coordinates before + * being rendered to the target image. + * + * @return \Jdenticon\Rendering\Transform + */ + public function getTransform() + { + return $this->transform; + } + + /** + * Adds a polygon without translating its coordinates. + * + * @param array $points An array of the points that the polygon consists of. + */ + abstract protected function addPolygonNoTransform($points); + + /** + * Adds a circle without translating its coordinates. + * + * @param float $x The x-coordinate of the bounding rectangle + * upper-left corner. + * @param float $y The y-coordinate of the bounding rectangle + * upper-left corner. + * @param float $size The size of the bounding rectangle. + * @param bool $counterClockwise If true the circle will be drawn + * counter clockwise. + */ + abstract protected function addCircleNoTransform($x, $y, $size, $counterClockwise); + + /** + * Sets the background color of the image. + * + * @param \Jdenticon\Color $color The image background color. + */ + public function setBackgroundColor(\Jdenticon\Color $color) + { + $this->backgroundColor = $color; + } + + /** + * Gets the background color of the image. + * + * @return \Jdenticon\Color + */ + public function getBackgroundColor() + { + return $this->backgroundColor; + } + + private function addPolygonCore(array $points, $invert) + { + $transformedPoints = array(); + foreach ($points as $point) { + $transformedPoints[] = + $this->transform->transformPoint($point->x, $point->y); + } + + if ($invert) { + $transformedPoints = array_reverse($transformedPoints); + } + + //var_dump($transformedPoints); + + $this->addPolygonNoTransform($transformedPoints); + } + + /** + * Adds a rectangle to the image. + * + * @param float $x The x-coordinate of the rectangle upper-left corner. + * @param float $y The y-coordinate of the rectangle upper-left corner. + * @param float $width The width of the rectangle. + * @param float $height The height of the rectangle. + * @param bool $invert If true the area of the rectangle will be removed + * from the filled area. + */ + public function addRectangle($x, $y, $width, $height, $invert = false) + { + $this->addPolygonCore(array( + new Point($x, $y), + new Point($x + $width, $y), + new Point($x + $width, $y + $height), + new Point($x, $y + $height), + ), $invert); + } + + /** + * Adds a circle to the image. + * + * @param float $x The x-coordinate of the bounding rectangle + * upper-left corner. + * @param float $y The y-coordinate of the bounding rectangle + * upper-left corner. + * @param float $size The size of the bounding rectangle. + * @param bool $invert If true the area of the circle will be removed + * from the filled area. + */ + public function addCircle($x, $y, $size, $invert = false) + { + $northWest = $this->transform->transformPoint($x, $y, $size, $size); + $this->addCircleNoTransform($northWest->x, $northWest->y, $size, $invert); + } + + /** + * Adds a polygon to the image. + * + * @param array $points Array of points that the polygon consists of. + * @param bool $invert If true the area of the polygon will be removed + * from the filled area. + */ + public function addPolygon($points, $invert = false) + { + $this->addPolygonCore($points, $invert); + } + + /** + * Adds a triangle to the image. + * + * @param float $x The x-coordinate of the bounding rectangle + * upper-left corner. + * @param float $y The y-coordinate of the bounding rectangle + * upper-left corner. + * @param float $width The width of the bounding rectangle. + * @param float $height The height of the bounding rectangle. + * @param float $direction The direction of the 90 degree corner of the + * triangle. + * @param bool $invert If true the area of the triangle will be removed + * from the filled area. + */ + public function addTriangle($x, $y, $width, $height, $direction, $invert = false) + { + $points = array( + new Point($x + $width, $y), + new Point($x + $width, $y + $height), + new Point($x, $y + $height), + new Point($x, $y) + ); + + array_splice($points, $direction, 1); + + $this->addPolygonCore($points, $invert); + } + + /** + * Adds a rhombus to the image. + * + * @param float $x The x-coordinate of the bounding rectangle + * upper-left corner. + * @param float $y The y-coordinate of the bounding rectangle + * upper-left corner. + * @param float $width The width of the bounding rectangle. + * @param float $height The height of the bounding rectangle. + * @param bool $invert If true the area of the rhombus will be removed + * from the filled area. + */ + public function addRhombus($x, $y, $width, $height, $invert = false) + { + $this->addPolygonCore(array( + new Point($x + $width / 2, $y), + new Point($x + $width, $y + $height / 2), + new Point($x + $width / 2, $y + $height), + new Point($x, $y + $height / 2), + ), $invert); + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/ColorTheme.php b/vendor/jdenticon/jdenticon/src/Rendering/ColorTheme.php new file mode 100644 index 00000000..24af0f97 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/ColorTheme.php @@ -0,0 +1,84 @@ +getGrayscaleLightness(); + $colorLightness = $style->getColorLightness(); + $hues = $style->getHues(); + + if ($hues !== null) { + // $hue is in the range [0, 1] + // Multiply with 0.999 to change the range to [0, 1) + $hueIndex = (int)($hue * 0.999 * count($hues)); + $hue = (float)$hues[$hueIndex] / 360; + } + + $this->darkGray = Color::fromHslCompensated( + $hue, $style->getGrayscaleSaturation(), $grayscaleLightness[0]); + $this->midColor = Color::fromHslCompensated( + $hue, $style->getColorSaturation(), ($colorLightness[0] + $colorLightness[1]) / 2); + $this->lightGray = Color::fromHslCompensated( + $hue, $style->getGrayscaleSaturation(), $grayscaleLightness[1]); + $this->lightColor = Color::fromHslCompensated( + $hue, $style->getColorSaturation(), $colorLightness[1]); + $this->darkColor = Color::fromHslCompensated( + $hue, $style->getColorSaturation(), $colorLightness[0]); + } + + /** + * Gets a color from this color theme by index. + * + * @param int $index Color index in the range [0, getCount()). + * @return Jdenticon\Color + */ + public function getByIndex($index) + { + if ($index === 0) return $this->darkGray; + if ($index === 1) return $this->midColor; + if ($index === 2) return $this->lightGray; + if ($index === 3) return $this->lightColor; + if ($index === 4) return $this->darkColor; + return null; + } + + /** + * Gets the number of available colors in this theme. + * + * @return int + */ + public function getCount() + { + return 5; + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/IconGenerator.php b/vendor/jdenticon/jdenticon/src/Rendering/IconGenerator.php new file mode 100644 index 00000000..d31fdf3b --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/IconGenerator.php @@ -0,0 +1,290 @@ +defaultShapes = array( + // Sides + new ShapeCategory( + /*$colorIndex=*/ 8, + /*$shapes=*/ ShapeDefinitions::getOuterShapes(), + /*$shapeIndex=*/ 2, + /*$rotationIndex=*/ 3, + /*$positions=*/ array(1,0, 2,0, 2,3, 1,3, 0,1, 3,1, 3,2, 0,2) + ), + + // Corners + new ShapeCategory( + /*$colorIndex=*/ 9, + /*$shapes=*/ ShapeDefinitions::getOuterShapes(), + /*$shapeIndex=*/ 4, + /*$rotationIndex=*/ 5, + /*$positions=*/ array(0,0, 3,0, 3,3, 0,3) + ), + + // Center + new ShapeCategory( + /*$colorIndex=*/ 10, + /*$shapes=*/ ShapeDefinitions::getCenterShapes(), + /*$shapeIndex=*/ 1, + /*$rotationIndex=*/ null, + /*$positions=*/ array(1,1, 2,1, 2,2, 1,2) + ) + ); + } + + public static function getDefaultGenerator() + { + if (self::$instance === null) { + self::$instance = new IconGenerator(); + } + return self::$instance; + } + + /** + * Gets the number of cells in each direction of the icons generated by + * this IconGenerator. + * + * @return int + */ + public function getCellCount() + { + return 4; + } + + /** + * Determines the hue to be used in an icon for the specified hash. + * + * @return float Hue in the range [0, 1]. + */ + protected static function getHue($hash) + { + $value = hexdec(substr($hash, -7)); + return $value / 0xfffffff; + } + + /** + * Determines whether $newValue is duplicated in $source if all values + * in $duplicateValues are determined to be equal. + * + * @return bool + */ + private static function isDuplicate( + array $source, $newValue, + array $duplicateValues) + { + if (in_array($newValue, $duplicateValues, true)) { + foreach ($duplicateValues as $value) { + if (in_array($value, $source, true)) { + return true; + } + } + } + return false; + } + + /** + * Gets the specified octet from a byte array. + * + * @param string $hash The hexstring from which the octet will be retrieved. + * @param int $index The zero-based index of the octet to be returned. + * @return int + */ + protected static function getOctet($hash, $index) + { + return hexdec($hash[$index]); + } + + /** + * Gets an array of the shape categories to be rendered in icons generated + * by this IconGenerator. + * + * @return array + */ + protected function getCategories() + { + return $this->defaultShapes; + } + + /** + * Gets an enumeration of individual shapes to be rendered in an icon for a + * specific hash. + * + * @param \Jdenticon\Rendering\ColorTheme $colorTheme A color theme + * specifying the colors to be used in the icon. + * @param string $hash The hash for which the shapes will be returned. + * @return array(Jdenticon\Shapes\Shape) + */ + protected function getShapes($colorTheme, $hash) + { + $usedColorThemeIndexes = array(); + $categories = self::getCategories(); + $shapes = array(); + $colorCount = $colorTheme->getCount(); + + foreach ($categories as $category) { + $colorThemeIndex = + self::getOctet($hash, $category->colorIndex) % $colorCount; + + if (self::isDuplicate( + // Disallow dark gray and dark color combo + $usedColorThemeIndexes, $colorThemeIndex, array(0, 4)) || + self::isDuplicate( + // Disallow light gray and light color combo + $usedColorThemeIndexes, $colorThemeIndex, array(2, 3)) + ) { + $colorThemeIndex = 1; + } + + $usedColorThemeIndexes[] = $colorThemeIndex; + + $startRotationIndex = $category->rotationIndex === null ? + 0 : self::getOctet($hash, $category->rotationIndex); + $shapeIndex = + self::getOctet($hash, $category->shapeIndex) % + count($category->shapes); + $shape = $category->shapes[$shapeIndex]; + + $shapes[] = new Shape( + /*$definition=*/ $shape, + /*$color=*/ $colorTheme->getByIndex($colorThemeIndex), + /*$positions=*/ $category->positions, + /*$startRotationIndex=*/ $startRotationIndex + ); + } + + return $shapes; + } + + /** + * Creates a quadratic copy of the specified + * {@link \Jdenticon\Rendering\Rectangle} with a multiple of the cell count + * as size. + * + * @param \Jdenticon\Rendering\Rectangle $rect The rectangle to be + * normalized. + */ + protected function normalizeRectangle(\Jdenticon\Rendering\Rectangle $rect) + { + $size = (int)min($rect->width, $rect->height); + + // Make size a multiple of the cell count + $size -= $size % $this->getCellCount(); + + return new Rectangle( + (int)($rect->x + ($rect->width - $size) / 2), + (int)($rect->y + ($rect->height - $size) / 2), + $size, + $size); + } + + /** + * Renders the background of an icon. + * + * @param \Jdenticon\Rendering\RendererInterface $renderer The renderer to + * be used for rendering the icon on the target surface. + * @param \Jdenticon\Rendering\Rectangle $rect The outer bounds of the icon. + * @param \Jdenticon\IdenticonStyle $style The style of the icon. + * @param \Jdenticon\Rendering\ColorTheme $colorTheme A color theme + * specifying the colors to be used in the icon. + * @param string $hash The hash to be used as basis for the generated icon. + */ + protected function renderBackground( + \Jdenticon\Rendering\RendererInterface $renderer, + \Jdenticon\Rendering\Rectangle $rect, + \Jdenticon\IdenticonStyle $style, + \Jdenticon\Rendering\ColorTheme $colorTheme, + $hash) + { + $renderer->setBackgroundColor($style->getBackgroundColor()); + } + + /** + * Renders the foreground of an icon. + * + * @param \Jdenticon\Rendering\RendererInterface $renderer The renderer to + * be used for rendering the icon on the target surface. + * @param \Jdenticon\Rendering\Rectangle $rect The outer bounds of the icon. + * @param \Jdenticon\IdenticonStyle $style The style of the icon. + * @param \Jdenticon\Rendering\ColorTheme $colorTheme A color theme + * specifying the colors to be used in the icon. + * @param string $hash The hash to be used as basis for the generated icon. + */ + protected function renderForeground( + \Jdenticon\Rendering\RendererInterface $renderer, + \Jdenticon\Rendering\Rectangle $rect, + \Jdenticon\IdenticonStyle $style, + \Jdenticon\Rendering\ColorTheme $colorTheme, + $hash) + { + // Ensure rect is quadratic and a multiple of the cell count + $normalizedRect = $this->normalizeRectangle($rect); + $cellSize = $normalizedRect->width / $this->getCellCount(); + + foreach ($this->getShapes($colorTheme, $hash) as $shape) { + $rotation = $shape->startRotationIndex; + + $renderer->beginShape($shape->color); + + $positionCount = count($shape->positions); + for ($i = 0; $i + 1 < $positionCount; $i += 2) { + $renderer->setTransform(new Transform( + $normalizedRect->x + $shape->positions[$i + 0] * $cellSize, + $normalizedRect->y + $shape->positions[$i + 1] * $cellSize, + $cellSize, $rotation++ % 4)); + + $shape->definition->__invoke($renderer, $cellSize, $i / 2); + } + + $renderer->endShape(); + } + } + + /** + * Generates an identicon for the specified hash. + * + * @param \Jdenticon\Rendering\RendererInterface $renderer The renderer to + * be used for rendering the icon on the target surface. + * @param \Jdenticon\Rendering\Rectangle $rect The outer bounds of the icon. + * @param \Jdenticon\IdenticonStyle $style The style of the icon. + * @param string $hash The hash to be used as basis for the generated icon. + */ + public function generate( + \Jdenticon\Rendering\RendererInterface $renderer, + \Jdenticon\Rendering\Rectangle $rect, + \Jdenticon\IdenticonStyle $style, + $hash) + { + $hue = self::getHue($hash); + $colorTheme = new ColorTheme($hue, $style); + + $this->renderBackground($renderer, $rect, $style, $colorTheme, $hash); + $this->renderForeground($renderer, $rect, $style, $colorTheme, $hash); + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php b/vendor/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php new file mode 100644 index 00000000..dbd6cf36 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php @@ -0,0 +1,296 @@ +Px = $x0; + $line->Py = $y0; + + $line->rx = $x1 - $x0; + $line->ry = $y1 - $y0; + + return $line; + } + + /** + * Moves the line to the right relative the direction vector. + * + * @param float $distance The number of pixels to move the line. + */ + public function moveRight($distance) + { + // Ortogonal direction vector + $rx = -$this->ry; + $ry = $this->rx; + + $multiplier = $distance / sqrt($rx * $rx + $ry * $ry); + + $this->Px += $rx * $multiplier; + $this->Py += $ry * $multiplier; + } + + /** + * Computes the point at which two lines intersect. + * + * @return Point|null + */ + public static function intersection( + ImagickRendererLine $l1, + ImagickRendererLine $l2 + ) { + $rs = $l1->rx * $l2->ry - $l1->ry * $l2->rx; + + if ($rs == 0) { + return null; + } + + $u = (($l2->Px - $l1->Px) * $l1->ry - ($l2->Py - $l1->Py) * $l1->rx) / $rs; + + return new Point( + $l2->Px + $u * $l2->rx, + $l2->Py + $u * $l2->ry + ); + } + + /** + * X coordiate of a point on the line. + * @var float + */ + public $Px; + /** + * Y coordiate of a point on the line. + * @var float + */ + public $Py; + + /** + * X component of the direction vector. + * @var float + */ + public $rx; + /** + * Y component of the direction vector. + * @var float + */ + public $ry; +} + +/** + * Renders icons as PNG using ImageMagick. + * + * Unfortunately the ImageMagick vector renderer has a lot of quirks that + * we need to accomodate. The most obvious is that the renderer always render + * all polygons 1/2 pixel too large. This behavior is documented here: + * http://www.imagemagick.org/Usage/draw/#bounds + * + * To prevent this we shrink all polygons with 1/2 pixels before passing them + * to ImageMagick. + * + * Another quirk is that if the polygon including the 1/2 pixel invisible border + * align perfectly to the pixel grid, white pixels will appear near edge + * intersections. Paths containing arcs will sometimes appear with horizontal + * lines drawn to the right side of the image. + * + * To prevent this (in most cases) we add 0.00013 to all coordinates. + * + */ +class ImagickRenderer extends AbstractRenderer +{ + private $draw; + private $polygon; + private $width; + private $height; + + /** + * This constant is added to all coordinates to avoid white pixels + * that sometimes appear near edge intersections when a polygon including + * its 1/2 invisible border is perfectly aligned to the pixel grid. + */ + const PREVENT_WHITE_PIXELS_OFFSET = -0.00013; + + /** + * Creates an instance of the class ImagickRenderer. + * + * @param int $width The width of the icon in pixels. + * @param int $height The height of the icon in pixels. + */ + public function __construct($width, $height) + { + parent::__construct(); + $this->draw = new \ImagickDraw(); + $this->draw->setStrokeWidth(1); + + $this->width = $width; + $this->height = $height; + } + + /** + * Gets the MIME type of the renderer output. + * + * @return string + */ + public function getMimeType() + { + return 'image/png'; + } + + /** + * Adds a circle without translating its coordinates. + * + * @param float $x The x-coordinate of the bounding rectangle + * upper-left corner. + * @param float $y The y-coordinate of the bounding rectangle + * upper-left corner. + * @param float $size The size of the bounding rectangle. + * @param bool $counterClockwise If true the circle will be drawn + * counter clockwise. + */ + protected function addCircleNoTransform($x, $y, $size, $counterClockwise) + { + if ($counterClockwise) { + $x -= $size + 0.5; + $y -= 1; + } else { + $size -= 1; + $y -= 0.5; + } + + $radius = $size / 2; + $this->draw->pathMoveToAbsolute( + $x + $size + self::PREVENT_WHITE_PIXELS_OFFSET, + $y + $radius + self::PREVENT_WHITE_PIXELS_OFFSET); + $this->draw->pathEllipticArcRelative($radius, $radius, + M_PI * 2, true, $counterClockwise, 0, 1); + $this->draw->pathClose(); + } + + /** + * Adds a polygon without translating its coordinates. + * + * @param array $points An array of the points that the polygon consists of. + */ + protected function addPolygonNoTransform($points) + { + $firstPoint = $points[0]; + $lastPoint = end($points); + + // Ensure polygon is closed + if ($firstPoint->x != $lastPoint->x || + $firstPoint->y != $lastPoint->y + ) { + $points[] = $firstPoint; + } + + // Determine if polygon is an outer ring + // (source: https://stackoverflow.com/a/1165943) + $sum = 0; + $previousPoint = null; + + foreach ($points as $point) { + if ($previousPoint !== null) { + $sum += ($point->x - $previousPoint->x) * ($point->y + $previousPoint->y); + } + $previousPoint = $point; + } + + $isOuterRing = $sum < 0; + + // ImageMagick draws all polygons 1 pixel too large. To prevent this, + // shrink polygons by 1 pixel. + $lines = array(); + $previousPoint = null; + + // Transform all edges to lines. + foreach ($points as $point) { + if ($previousPoint !== null) { + $lines[] = $line = ImagickRendererLine::fromVector( + $previousPoint->x, $previousPoint->y, + $point->x, $point->y + ); + + // ImageMagick draws a 1px border along the outer ring. To + // prevent the border overlaps inner rings too close to the + // outer ring, only inflate inner rings by 1/4 pixel. + $line->moveRight($isOuterRing ? 0.5 : 0.25); + } + $previousPoint = $point; + } + + $first = true; + $previousLine = end($lines); + + // Reconstruct point array from line intersections and draw the polygon + foreach ($lines as $line) { + $points[] = $point = ImagickRendererLine::intersection($previousLine, $line); + + // Subtract 1/2 pixel to align the shapes to the pixel grid. + if ($first) { + $this->draw->pathMoveToAbsolute( + $point->x - 0.5 + self::PREVENT_WHITE_PIXELS_OFFSET, + $point->y - 0.5 + self::PREVENT_WHITE_PIXELS_OFFSET); + + $first = false; + } else { + $this->draw->pathLineToAbsolute( + $point->x - 0.5 + self::PREVENT_WHITE_PIXELS_OFFSET, + $point->y - 0.5 + self::PREVENT_WHITE_PIXELS_OFFSET); + } + + $previousLine = $line; + } + + $this->draw->pathClose(); + } + + /** + * Begins a new shape. The shape should be ended with a call to endShape. + * + * @param \Jdenticon\Color $color The color of the shape. + */ + public function beginShape(\Jdenticon\Color $color) + { + $this->draw->setFillColor($color->__toString()); + $this->draw->pathStart(); + } + + /** + * Ends the currently drawn shape. + */ + public function endShape() + { + $this->draw->pathFinish(); + } + + /** + * Renders this image as a PNG data stream. + * + * @return string + */ + public function getData() + { + $imagick = new \Imagick(); + $imagick->newImage($this->width, $this->height, $this->backgroundColor->__toString()); + $imagick->setImageFormat('png'); + + if (method_exists($imagick, 'setImageProperty')) { + $imagick->setImageProperty('Software', 'Jdenticon'); + } else { + $imagick->setImageAttribute('Software', 'Jdenticon'); + } + + $imagick->drawImage($this->draw); + return $imagick->getImageBlob(); + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php b/vendor/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php new file mode 100644 index 00000000..10c816be --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php @@ -0,0 +1,123 @@ +canvas = new Canvas($width, $height); + $this->ctx = $this->canvas->getContext(); + } + + /** + * Gets the MIME type of the renderer output. + * + * @return string + */ + public function getMimeType() + { + return 'image/png'; + } + + /** + * Adds a circle without translating its coordinates. + * + * @param float $x The x-coordinate of the bounding rectangle + * upper-left corner. + * @param float $y The y-coordinate of the bounding rectangle + * upper-left corner. + * @param float $size The size of the bounding rectangle. + * @param bool $counterClockwise If true the circle will be drawn + * counter clockwise. + */ + protected function addCircleNoTransform($x, $y, $size, $counterClockwise) + { + $radius = $size / 2; + $this->ctx->moveTo($x + $size, $y + $radius); + $this->ctx->arc( + $x + $radius, $y + $radius, + $radius, 0, M_PI * 2, + $counterClockwise); + $this->ctx->closePath(); + } + + /** + * Adds a polygon without translating its coordinates. + * + * @param array $points An array of the points that the polygon consists of. + */ + protected function addPolygonNoTransform($points) + { + $pointCount = count($points); + $this->ctx->moveTo($points[0]->x, $points[0]->y); + for ($i = 1; $i < $pointCount; $i++) { + $this->ctx->lineTo($points[$i]->x, $points[$i]->y); + } + $this->ctx->closePath(); + } + + /** + * Sets the background color of the icon. + * + * @param \Jdenticon\Color $color The background color. + */ + public function setBackgroundColor(\Jdenticon\Color $color) + { + parent::setBackgroundColor($color); + $this->canvas->backColor = $this->backgroundColor->toRgba(); + } + + /** + * Begins a new shape. The shape should be ended with a call to endShape. + * + * @param \Jdenticon\Color $color The color of the shape. + */ + public function beginShape(\Jdenticon\Color $color) + { + $this->ctx->fillStyle = $color->toRgba(); + $this->ctx->beginPath(); + } + + /** + * Ends the currently drawn shape. + */ + public function endShape() + { + $this->ctx->fill(); + } + + /** + * Gets the output from the renderer. + * + * @return string + */ + public function getData() + { + return $this->canvas->toPng(array('Software' => 'Jdenticon')); + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/Point.php b/vendor/jdenticon/jdenticon/src/Rendering/Point.php new file mode 100644 index 00000000..020845e6 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/Point.php @@ -0,0 +1,54 @@ +x = $x; + $this->y = $y; + } + + /** + * The X coordinate of this point. + * + * @var float + */ + public $x; + + /** + * The Y coordinate of this point. + * + * @var float + */ + public $y; + + /** + * Gets a string representation of the point. + * + * @return string + */ + public function __toString() + { + return $this->x + ", " + $this->y; + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/Rectangle.php b/vendor/jdenticon/jdenticon/src/Rendering/Rectangle.php new file mode 100644 index 00000000..27056c65 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/Rectangle.php @@ -0,0 +1,60 @@ +x = $x; + $this->y = $y; + $this->width = $width; + $this->height = $height; + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/RendererInterface.php b/vendor/jdenticon/jdenticon/src/Rendering/RendererInterface.php new file mode 100644 index 00000000..2e579e0c --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/RendererInterface.php @@ -0,0 +1,141 @@ +dataString = ''; + } + + /** + * Adds a circle to the SVG. + * + * @param float $x X coordinate of the left side of the containing rectangle. + * @param float $y Y coordinate of the top side of the containing rectangle. + * @param float $size The diameter of the circle. + * @param bool $counterClockwise If true the circle will be drawn counter + * clockwise. This affects the rendering since the evenodd filling rule + * is used by Jdenticon. + */ + public function addCircle($x, $y, $size, $counterClockwise) + { + $sweepFlag = $counterClockwise ? '0' : '1'; + $radiusAsString = number_format($size / 2, 2, '.', ''); + + $this->dataString .= + 'M'. number_format($x, 2, '.', '') .' '. + number_format($y + $size / 2, 2, '.', ''). + 'a'. $radiusAsString .','. $radiusAsString .' 0 1,'. + $sweepFlag .' '. number_format($size, 2, '.', '') .',0'. + 'a'. $radiusAsString .','. $radiusAsString .' 0 1,'. + $sweepFlag .' '. number_format(-$size, 2, '.', '') .',0'; + } + + /** + * Adds a polygon to the SVG. + * + * @param array(\Jdenticon\Rendering\Point) $points The corners of the + * polygon. + */ + public function addPolygon($points) + { + $pointCount = count($points); + + $this->dataString .= 'M'. + number_format($points[0]->x, 2, '.', '') .' '. + number_format($points[0]->y, 2, '.', ''); + + for ($i = 1; $i < $pointCount; $i++) { + $this->dataString .= 'L'. + number_format($points[$i]->x, 2, '.', '') .' '. + number_format($points[$i]->y, 2, '.', ''); + } + + $this->dataString .= 'Z'; + } + + /** + * Gets the path as a SVG path string. + * + * @return string + */ + public function __toString() + { + return $this->dataString; + } +} + diff --git a/vendor/jdenticon/jdenticon/src/Rendering/SvgRenderer.php b/vendor/jdenticon/jdenticon/src/Rendering/SvgRenderer.php new file mode 100644 index 00000000..3a1df854 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/SvgRenderer.php @@ -0,0 +1,133 @@ +width = $width; + $this->height = $height; + } + + /** + * Gets the MIME type of the renderer output. + * + * @return string + */ + public function getMimeType() + { + return 'image/svg+xml'; + } + + /** + * Adds a circle without translating its coordinates. + * + * @param float $x The x-coordinate of the bounding rectangle + * upper-left corner. + * @param float $y The y-coordinate of the bounding rectangle + * upper-left corner. + * @param float $size The size of the bounding rectangle. + * @param bool $counterClockwise If true the circle will be drawn + * counter clockwise. + */ + protected function addCircleNoTransform($x, $y, $size, $counterClockwise) + { + $this->path->addCircle($x, $y, $size, $counterClockwise); + } + + /** + * Adds a polygon without translating its coordinates. + * + * @param array $points An array of the points that the polygon consists of. + */ + protected function addPolygonNoTransform($points) + { + $this->path->addPolygon($points); + } + + /** + * Begins a new shape. The shape should be ended with a call to endShape. + * + * @param \Jdenticon\Color $color The color of the shape. + */ + public function beginShape(\Jdenticon\Color $color) + { + $colorString = $color->toHexString(6); + + if (isset($this->pathsByColor[$colorString])) { + $this->path = $this->pathsByColor[$colorString]; + } else { + $this->path = new SvgPath(); + $this->pathsByColor[$colorString] = $this->path; + } + } + + /** + * Ends the currently drawn shape. + */ + public function endShape() + { + } + + /** + * Generates an SVG string of the renderer output. + * + * @param bool $fragment If true an SVG string without the root svg element + * will be rendered. + */ + public function getData($fragment = false) + { + $svg = ''; + $widthAsString = number_format($this->width, 0, '.', ''); + $heightAsString = number_format($this->height, 0, '.', ''); + + if (!$fragment) { + $svg .= ''; + } + + if ($this->backgroundColor->a > 0) { + $opacity = (float)$this->backgroundColor->a / 255; + $svg .= ''; + } + + foreach ($this->pathsByColor as $color => $path) { + $svg .= ""; + } + + if (!$fragment) { + $svg .= ''; + } + + return $svg; + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/Transform.php b/vendor/jdenticon/jdenticon/src/Rendering/Transform.php new file mode 100644 index 00000000..f93de626 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/Transform.php @@ -0,0 +1,79 @@ +x = $x; + $this->y = $y; + $this->size = $size; + $this->rotation = $rotation; + } + + /** + * Gets a noop transform. + * + * @return \Jdenticon\Rendering\Transform + */ + public static function getEmpty() + { + return new Transform(0, 0, 0, 0); + } + + /** + * Transforms the specified point based on the translation and rotation + * specification for this Transform. + * + * @param float $x x-coordinate + * @param float $y y-coordinate + * @param float $width The width of the transformed rectangle. If greater + * than 0, this will ensure the returned point is of the upper left + * corner of the transformed rectangle. + * @param float $height The height of the transformed rectangle. If greater + * than 0, this will ensure the returned point is of the upper left + * corner of the transformed rectangle. + * @return \Jdenticon\Rendering\Point + */ + public function transformPoint($x, $y, $width = 0, $height = 0) + { + $right = $this->x + $this->size; + $bottom = $this->y + $this->size; + + switch ($this->rotation) { + case 1: return new Point($right - $y - $height, $this->y + $x); + case 2: return new Point($right - $x - $width, $bottom - $y - $height); + case 3: return new Point($this->x + $y, $bottom - $x - $width); + default: return new Point($this->x + $x, $this->y + $y); + } + } +} diff --git a/vendor/jdenticon/jdenticon/src/Rendering/TriangleDirection.php b/vendor/jdenticon/jdenticon/src/Rendering/TriangleDirection.php new file mode 100644 index 00000000..fb1fff91 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Rendering/TriangleDirection.php @@ -0,0 +1,35 @@ +definition = $definition; + $this->color = $color; + $this->positions = $positions; + $this->startRotationIndex = $startRotationIndex; + } +} diff --git a/vendor/jdenticon/jdenticon/src/Shapes/ShapeCategory.php b/vendor/jdenticon/jdenticon/src/Shapes/ShapeCategory.php new file mode 100644 index 00000000..202de814 --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Shapes/ShapeCategory.php @@ -0,0 +1,71 @@ +colorIndex = $colorIndex; + $this->shapes = $shapes; + $this->shapeIndex = $shapeIndex; + $this->rotationIndex = $rotationIndex; + $this->positions = $positions; + } +} + diff --git a/vendor/jdenticon/jdenticon/src/Shapes/ShapeDefinitions.php b/vendor/jdenticon/jdenticon/src/Shapes/ShapeDefinitions.php new file mode 100644 index 00000000..8278be0f --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Shapes/ShapeDefinitions.php @@ -0,0 +1,243 @@ +addTriangle(0, 0, $cell, $cell, 0); + }, + function ($renderer, $cell, $index) + { + $renderer->addTriangle(0, $cell / 2, $cell, $cell / 2, 0); + }, + function ($renderer, $cell, $index) + { + $renderer->addRhombus(0, 0, $cell, $cell); + }, + function ($renderer, $cell, $index) + { + $m = $cell / 6; + $renderer->addCircle($m, $m, $cell - 2 * $m); + } + ); + } + + private static function createCenterShapes() + { + return array( + function ($renderer, $cell, $index) + { + $k = $cell * 0.42; + $renderer->addPolygon(array( + new Point(0, 0), + new Point($cell, 0), + new Point($cell, $cell - $k * 2), + new Point($cell - $k, $cell), + new Point(0, $cell) + )); + }, + function ($renderer, $cell, $index) + { + $w = (int)($cell * 0.5); + $h = (int)($cell * 0.8); + $renderer->addTriangle( + $cell - $w, 0, $w, $h, + TriangleDirection::NORTH_EAST); + }, + function ($renderer, $cell, $index) + { + $s = (int)($cell / 3); + $renderer->addRectangle($s, $s, $cell - $s, $cell - $s); + }, + function ($renderer, $cell, $index) + { + $tmp = $cell * 0.1; + + if ($tmp > 1) { + // large icon => truncate decimals + $inner = (int)$tmp; + } elseif ($tmp > 0.5) { + // medium size icon => fixed width + $inner = 1; + } else { + // small icon => anti-aliased border + $inner = $tmp; + } + + // Use fixed outer border widths in small icons to ensure + // the border is drawn + if ($cell < 6) { + $outer = 1; + } elseif ($cell < 8) { + $outer = 2; + } else { + $outer = (int)($cell / 4); + } + + $renderer->addRectangle( + $outer, $outer, + $cell - $inner - $outer, $cell - $inner - $outer); + }, + function ($renderer, $cell, $index) + { + $m = (int)($cell * 0.15); + $s = (int)($cell * 0.5); + $renderer->addCircle($cell - $s - $m, $cell - $s - $m, $s); + }, + function ($renderer, $cell, $index) + { + $inner = $cell * 0.1; + $outer = $inner * 4; + + // Align edge to nearest pixel in large icons + if ($outer > 3) { + $outer = (int)$outer; + } + + $renderer->addRectangle(0, 0, $cell, $cell); + $renderer->addPolygon(array( + new Point($outer, $outer), + new Point($cell - $inner, $outer), + new Point($outer + ($cell - $outer - $inner) / 2, + $cell - $inner) + ), true); + }, + function ($renderer, $cell, $index) + { + $renderer->addPolygon(array( + new Point(0, 0), + new Point($cell, 0), + new Point($cell, $cell * 0.7), + new Point($cell * 0.4, $cell * 0.4), + new Point($cell * 0.7, $cell), + new Point(0, $cell) + )); + }, + function ($renderer, $cell, $index) + { + $renderer->addTriangle( + $cell / 2, $cell / 2, $cell / 2, $cell / 2, + TriangleDirection::SOUTH_EAST); + }, + function ($renderer, $cell, $index) + { + $renderer->addPolygon(array( + new Point(0, 0), + new Point($cell, 0), + new Point($cell, $cell / 2), + new Point($cell / 2, $cell), + new Point(0, $cell) + )); + }, + function ($renderer, $cell, $index) + { + $tmp = $cell * 0.14; + + if ($cell < 8) { + // small icon => anti-aliased border + $inner = $tmp; + } else { + // large icon => truncate decimals + $inner = (int)$tmp; + } + + // Use fixed outer border widths in small icons to ensure + // the border is drawn + if ($cell < 4) { + $outer = 1; + } elseif ($cell < 6) { + $outer = 2; + } else { + $outer = (int)($cell * 0.35); + } + + $renderer->addRectangle(0, 0, $cell, $cell); + $renderer->addRectangle( + $outer, $outer, + $cell - $outer - $inner, $cell - $outer - $inner, true); + }, + function ($renderer, $cell, $index) + { + $inner = $cell * 0.12; + $outer = $inner * 3; + + $renderer->addRectangle(0, 0, $cell, $cell); + $renderer->addCircle($outer, $outer, $cell - $inner - $outer, + true); + }, + function ($renderer, $cell, $index) + { + $renderer->addTriangle( + $cell / 2, $cell / 2, $cell / 2, $cell / 2, + TriangleDirection::SOUTH_EAST); + }, + function ($renderer, $cell, $index) + { + $m = $cell * 0.25; + + $renderer->addRectangle(0, 0, $cell, $cell); + $renderer->addRhombus($m, $m, $cell - $m, $cell - $m, true); + }, + function ($renderer, $cell, $index) + { + $m = $cell * 0.4; + $s = $cell * 1.2; + + if ($index != 0) { + $renderer->addCircle($m, $m, $s); + } + } + ); + } +} diff --git a/vendor/jdenticon/jdenticon/src/Shapes/ShapePosition.php b/vendor/jdenticon/jdenticon/src/Shapes/ShapePosition.php new file mode 100644 index 00000000..9c780fce --- /dev/null +++ b/vendor/jdenticon/jdenticon/src/Shapes/ShapePosition.php @@ -0,0 +1,45 @@ +x = $x; + $this->y = $y; + } +} + From d5e7e6e2ab4cd12b8d82fad5a9c5120d00fb86e5 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 07:11:02 +0200 Subject: [PATCH 138/506] document Jdenticon change --- CHANGELOG.md | 1 + cfg/conf.sample.php | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b897b676..1b6a607d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ * **1.4.1 (not yet released)** * ADDED: Translations for Turkish, Slovak and Greek * ADDED: S3 Storage backend (#994) + * CHANGED: Switched to Jdenticons as the default for comment icons (#793) * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) * CHANGED: Upgrading libraries to: zlib 1.2.13 * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index ba6fff55..c972f153 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -65,9 +65,9 @@ languageselection = false ; qrcode = true ; (optional) IP based icons are a weak mechanism to detect if a comment was from -; a different user when the same username was used in a comment. It might be -; used to get the IP of a non anonymous comment poster if the server salt is -; leaked and a SHA512 HMAC rainbow table is generated for all (relevant) IPs. +; a different user when the same username was used in a comment. It might get +; used to get the IP of a comment poster if the server salt is leaked and a +; SHA512 HMAC rainbow table is generated for all (relevant) IPs. ; Can be set to one these values: ; "none" / "vizhash" / "identicon" / "jdenticon" (default). ; icon = "none" From ae3a0b19ee450e017808a03878a297a6fc9d006c Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 07:23:37 +0200 Subject: [PATCH 139/506] update PHP version used in Scrutinizer CI to 7.4, fixing php-timer requirement --- .scrutinizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index cf69fbd8..3a811694 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -17,7 +17,7 @@ coding_style: build: environment: php: - version: '7.2' + version: '7.4' tests: override: - From 31f75ee138a8cdce953790a61488d0d064bba798 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 07:39:35 +0200 Subject: [PATCH 140/506] undo accidental PHP 8 induced upgrade of php-timer, making it incompatible with PHP 7 used on Scrutinizer --- composer.lock | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/composer.lock b/composer.lock index 17948976..b4aec46e 100644 --- a/composer.lock +++ b/composer.lock @@ -652,28 +652,28 @@ }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": ">=7.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { @@ -688,7 +688,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", + "email": "sb@sebastian-bergmann.de", "role": "lead" } ], @@ -697,17 +697,7 @@ "keywords": [ "timer" ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", From 78b3630eb5b150d09ae1c36d35813d2c31b91bcd Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 07:55:26 +0200 Subject: [PATCH 141/506] try updating that borked php-cs dependency on Scrutinizer --- .scrutinizer.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 3a811694..e5358c85 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -28,6 +28,9 @@ build: nodes: tests: true analysis: + dependencies: + after: + - composer require --dev "squizlabs/php_codesniffer=^3" tests: override: - From c91d20ae754fdcbaed05228c942e4464a01c99aa Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 08:03:55 +0200 Subject: [PATCH 142/506] try using the updated php-cs dependency on Scrutinizer --- .scrutinizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index e5358c85..83b659f2 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -34,6 +34,6 @@ build: tests: override: - - command: phpcs-run + command: vendor/bin/phpcs use_website_config: true - php-scrutinizer-run From 613e4e9d5780e74fef6d44baa8567d8b630e9d16 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 08:11:35 +0200 Subject: [PATCH 143/506] custom php-cs doesn't support website config on Scrutinizer --- .scrutinizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 83b659f2..3615df7a 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -35,5 +35,5 @@ build: override: - command: vendor/bin/phpcs - use_website_config: true + use_website_config: false - php-scrutinizer-run From 795c030bdbbf85e89ff5bc76261a63d2a559bd1e Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 26 Oct 2022 08:16:30 +0200 Subject: [PATCH 144/506] Revert several commits that didn't solve the Scrutinizer issues --- .scrutinizer.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 3615df7a..cf69fbd8 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -17,7 +17,7 @@ coding_style: build: environment: php: - version: '7.4' + version: '7.2' tests: override: - @@ -28,12 +28,9 @@ build: nodes: tests: true analysis: - dependencies: - after: - - composer require --dev "squizlabs/php_codesniffer=^3" tests: override: - - command: vendor/bin/phpcs - use_website_config: false + command: phpcs-run + use_website_config: true - php-scrutinizer-run From 432d3e71d3bdb69a740ab3edb4e9cb6dbe1abd30 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 29 Oct 2022 07:54:42 +0200 Subject: [PATCH 145/506] improve configuration wording, adjust self check --- cfg/conf.sample.php | 35 ++++++++++++++++++----------------- lib/YourlsProxy.php | 2 +- tst/JsonApiTest.php | 2 +- tst/YourlsProxyTest.php | 2 +- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index 7afe7aae..db058cd1 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -7,9 +7,10 @@ ; (optional) set a project name to be displayed on the website ; name = "PrivateBin" -; The full URL, with the domain name and directories that point to the PrivateBin files -; This URL is essential to allow Opengraph images to be displayed on social networks -; basepath = "" +; The full URL, with the domain name and directories that point to the +; PrivateBin files, including an ending slash (/). This URL is essential to +; allow Opengraph images to be displayed on social networks. +; basepath = "https://privatebin.example.com/" ; enable or disable the discussion feature, defaults to true discussion = true @@ -55,9 +56,9 @@ languageselection = false ; if this is set and language selection is disabled, this will be the only language ; languagedefault = "en" -; (optional) URL shortener address to offer after a new paste is created -; it is suggested to only use this with self-hosted shorteners as this will leak -; the pastes encryption key +; (optional) URL shortener address to offer after a new paste is created. +; It is suggested to only use this with self-hosted shorteners as this will leak +; the pastes encryption key. ; urlshortener = "https://shortener.example.com/api?link=" ; (optional) Let users create a QR code for sharing the paste URL with one click. @@ -229,18 +230,18 @@ dir = PATH "data" ;secretkey = "secret access key" [yourls] -; don't mix this up with "urlshortener" config item: -; - when using a standard configuration, "urlshortener" will point to the YOURLS -; API, including access credentials, and will be part of the PrivateBin public -; web page (insecure!) -; - when using the parameters in this section ("signature" and "apiurl"), -; "urlshortener" will point to a fixed PrivateBin page -; ("$basepath/shortenviayourls?link=") and that URL will in turn call YOURLS -; server-side, using the URL from "apiurl" and the "access signature" from the -; "signature" parameters below. +; When using YOURLS as a "urlshortener" config item: +; - By default, "urlshortener" will point to the YOURLS API URL, with or without +; credentials, and will be visible in public on the PrivateBin web page. +; Only use this if you allow short URL creation without credentials. +; - Alternatively, using the parameters in this section ("signature" and +; "apiurl"), "urlshortener" needs to point to the base URL of your PrivateBin +; instance with "shortenviayourls?link=" appended. For example: +; urlshortener = "${basepath}shortenviayourls?link=" +; This URL will in turn call YOURLS on the server side, using the URL from +; "apiurl" and the "access signature" from the "signature" parameters below. ; (optional) the "signature" (access key) issued by YOURLS for the using account ; signature = "" - ; (optional) the URL of the YOURLS API, called to shorten a PrivateBin URL -; apiurl = "" +; apiurl = "https://yourls.example.com/yourls-api.php" \ No newline at end of file diff --git a/lib/YourlsProxy.php b/lib/YourlsProxy.php index 858317a2..a9e98ad0 100644 --- a/lib/YourlsProxy.php +++ b/lib/YourlsProxy.php @@ -48,7 +48,7 @@ class YourlsProxy */ public function __construct(Configuration $conf, $link) { - if (strpos($link, $conf->getKey('basepath') . '/?') === false) { + if (strpos($link, $conf->getKey('basepath') . '?') === false) { $this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.'; return; } diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index 4ad629ee..5c508439 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -272,7 +272,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase { $mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json'; $options = parse_ini_file(CONF, true); - $options['main']['basepath'] = 'https://example.com/path'; + $options['main']['basepath'] = 'https://example.com/path/'; $options['main']['urlshortener'] = 'https://example.com/path/shortenviayourls?link='; $options['yourls']['apiurl'] = $mock_yourls_service; Helper::createIniFile(CONF, $options); diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 2e372995..bf0569f9 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -20,7 +20,7 @@ class YourlsProxyTest extends PHPUnit_Framework_TestCase } $this->_mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json'; $options = parse_ini_file(CONF_SAMPLE, true); - $options['main']['basepath'] = 'https://example.com'; + $options['main']['basepath'] = 'https://example.com/'; $options['main']['urlshortener'] = 'https://example.com/shortenviayourls?link='; $options['yourls']['apiurl'] = $this->_mock_yourls_service; Helper::confBackup(); From 922feb2779cc821dc84fd0f24a305efd92e1f80b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Oct 2022 06:07:06 +0000 Subject: [PATCH 146/506] Bump phpunit/phpunit from 5.2.7 to 5.6.3 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 5.2.7 to 5.6.3. - [Release notes](https://github.com/sebastianbergmann/phpunit/releases) - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/main/ChangeLog-8.5.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/5.2.7...5.6.3) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.lock | 514 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 357 insertions(+), 157 deletions(-) diff --git a/composer.lock b/composer.lock index b4aec46e..c4f0aaf5 100644 --- a/composer.lock +++ b/composer.lock @@ -241,32 +241,34 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.4.1", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": ">=5.3,<8.0-DEV" }, "require-dev": { - "doctrine/coding-standard": "^9", + "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -280,60 +282,42 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" + "homepage": "http://ocramius.github.com/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "homepage": "https://github.com/doctrine/instantiator", "keywords": [ "constructor", "instantiate" ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + "source": "https://github.com/doctrine/instantiator/tree/master" }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "php": "^5.6 || ^7.0" }, "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" }, "type": "library", "autoload": { @@ -358,49 +342,96 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.x" }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2017-10-19T19:58:43+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "2.0.5", + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b" + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e6a969a640b00d8daa3c66518b0405fb41ae0c4b", - "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" + "phpunit/phpunit": "^4.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "phpDocumentor": [ + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" + }, + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ "src/" ] } @@ -412,46 +443,101 @@ "authors": [ { "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" + "email": "me@mikevanriel.com" } ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/2.x" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/3.x" }, - "time": "2016-01-25T08:17:30+00:00" + "time": "2017-11-10T14:09:06+00:00" }, { - "name": "phpspec/prophecy", - "version": "v1.5.0", + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", "source": { "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", - "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1" + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { - "phpspec/phpspec": "~2.0" + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/master" + }, + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "v1.10.3", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "451c3cd1418cf640de218914901e51b064abb093" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", @@ -481,46 +567,46 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/master" + "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" }, - "time": "2015-08-13T10:07:40+00:00" + "time": "2020-03-05T15:02:03+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "3.2.0", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "85f5db2d0a0da79ad6a256eb54148ba383059ad9" + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85f5db2d0a0da79ad6a256eb54148ba383059ad9", - "reference": "85f5db2d0a0da79ad6a256eb54148ba383059ad9", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", "shasum": "" }, "require": { - "php": ">=5.6", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/code-unit-reverse-lookup": "~1.0", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0|~2.0" + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "^1.0 || ^2.0" }, "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~5" + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" }, "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" + "ext-xdebug": "^2.5.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { @@ -549,9 +635,9 @@ "support": { "irc": "irc://irc.freenode.net/phpunit", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/4.0" }, - "time": "2016-02-13T06:47:56+00:00" + "time": "2017-04-02T07:44:40+00:00" }, { "name": "phpunit/php-file-iterator", @@ -697,6 +783,10 @@ "keywords": [ "timer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/master" + }, "time": "2017-02-26T11:10:40+00:00" }, { @@ -755,42 +845,50 @@ }, { "name": "phpunit/phpunit", - "version": "5.2.7", + "version": "5.6.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "073701643835376cb2f15dc005ea8933f8d4edbd" + "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/073701643835376cb2f15dc005ea8933f8d4edbd", - "reference": "073701643835376cb2f15dc005ea8933f8d4edbd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9de0dbafeb6b1391b391fbb034734cb0af9f67c", + "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", "myclabs/deep-copy": "~1.3", - "php": ">=5.6", + "php": "^5.6 || ^7.0", "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~3.2", + "phpunit/php-code-coverage": "^4.0.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": ">=1.0.6", - "phpunit/phpunit-mock-objects": ">=3.0.5", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", + "sebastian/environment": "^1.3 || ^2.0", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", + "sebastian/object-enumerator": "~1.0", "sebastian/resource-operations": "~1.0", "sebastian/version": "~1.0|~2.0", "symfony/yaml": "~2.1|~3.0" }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" + }, + "require-dev": { + "ext-pdo": "*" + }, "suggest": { + "ext-xdebug": "*", "phpunit/php-invoker": "~1.1" }, "bin": [ @@ -799,7 +897,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.2.x-dev" + "dev-master": "5.6.x-dev" } }, "autoload": { @@ -826,34 +924,36 @@ "xunit" ], "support": { - "irc": "irc://irc.freenode.net/phpunit", "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/5.2.7" + "source": "https://github.com/sebastianbergmann/phpunit/tree/5.6.3" }, - "time": "2016-02-18T06:39:51+00:00" + "time": "2016-11-14T06:39:40+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.1.3", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "151c96874bff6fe61a25039df60e776613a61489" + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/151c96874bff6fe61a25039df60e776613a61489", - "reference": "151c96874bff6fe61a25039df60e776613a61489", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": ">=5.6", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2 || ^2.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^5.4" }, "suggest": { "ext-soap": "*" @@ -861,7 +961,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "3.2.x-dev" } }, "autoload": { @@ -889,10 +989,10 @@ "support": { "irc": "irc://irc.freenode.net/phpunit", "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", - "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/3.1" + "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/3.4" }, "abandoned": true, - "time": "2016-04-20T14:39:26+00:00" + "time": "2017-06-30T09:13:00+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1019,23 +1119,23 @@ }, { "name": "sebastian/diff", - "version": "1.4.1", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { @@ -1069,34 +1169,34 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/master" + "source": "https://github.com/sebastianbergmann/diff/tree/1.4" }, - "time": "2015-12-08T07:14:41+00:00" + "time": "2017-05-22T07:24:03+00:00" }, { "name": "sebastian/environment", - "version": "1.3.7", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", - "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1123,9 +1223,9 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/1.3.7" + "source": "https://github.com/sebastianbergmann/environment/tree/master" }, - "time": "2016-05-17T03:18:57+00:00" + "time": "2016-11-26T07:53:53+00:00" }, { "name": "sebastian/exporter", @@ -1253,6 +1353,56 @@ }, "time": "2015-10-12T03:26:01+00:00" }, + { + "name": "sebastian/object-enumerator", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/master" + }, + "time": "2016-01-28T13:25:10+00:00" + }, { "name": "sebastian/recursion-context", "version": "1.0.5", @@ -1405,23 +1555,20 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.26.0", + "version": "v1.19.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" + "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b", + "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" + "php": ">=5.3.3" }, "suggest": { "ext-ctype": "For best performance" @@ -1429,7 +1576,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.26-dev" + "dev-main": "1.19-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1467,7 +1614,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0" }, "funding": [ { @@ -1483,7 +1630,7 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2020-10-23T09:01:57+00:00" }, { "name": "symfony/yaml", @@ -1555,6 +1702,59 @@ } ], "time": "2020-10-24T10:57:07+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<3.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.9.1" + }, + "time": "2020-07-08T17:02:28+00:00" } ], "aliases": [], @@ -1566,5 +1766,5 @@ "php": "^5.6.0 || ^7.0 || ^8.0" }, "platform-dev": [], - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } From e39a2eeb61e7c894c06ca22136f389e2cb93870b Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 29 Oct 2022 13:09:30 +0200 Subject: [PATCH 147/506] New translations en.json (Corsican) --- i18n/co.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/co.json b/i18n/co.json index c0659b31..a4a75a37 100644 --- a/i18n/co.json +++ b/i18n/co.json @@ -187,7 +187,7 @@ "URL shortener may expose your decrypt key in URL.": "Un ammuzzatore d’indirizzu pò palisà a vostra chjave di dicifratura in l’indirizzu.", "Save paste": "Arregistrà l’appiccicu", "Your IP is not authorized to create pastes.": "U vostru indirizzu IP ùn hè micca auturizatu à creà l’appiccichi.", - "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", - "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Trying to shorten a URL that isn't pointing at our instance.": "Pruvate d’ammuzzà un indirizzu web chì ùn punta micca versu a vostra instanza.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Sbagliu à a chjama di YOURLS. Seria forse una cunfigurazione gattiva, tale una \"apiurl\" o \"signature\" falsa o assente.", + "Error parsing YOURLS response.": "Sbagliu durante l’analisa di a risposta di YOURLS." } From 1892264cf0bb19c191ca45968b9ae6462f5fc075 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 30 Oct 2022 09:04:27 +0100 Subject: [PATCH 148/506] add perf/size test for Jdenticons --- tst/IconTest | 62 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/tst/IconTest b/tst/IconTest index 7794e478..e39cc7be 100755 --- a/tst/IconTest +++ b/tst/IconTest @@ -9,6 +9,7 @@ use Identicon\Generator\GdGenerator; use Identicon\Generator\ImageMagickGenerator; use Identicon\Generator\SvgGenerator; use Identicon\Identicon; +use Jdenticon\Identicon as Jdenticon; use PrivateBin\Vizhash16x16; @@ -17,7 +18,18 @@ $vizhash = new Vizhash16x16(); $identiconGenerators = array( 'identicon GD' => new Identicon(new GdGenerator()), 'identicon ImageMagick' => new Identicon(new ImageMagickGenerator()), - 'identicon SVG' => new Identicon(new SvgGenerator()) + 'identicon SVG' => new Identicon(new SvgGenerator()), +); +$jdenticon = new Jdenticon(array( + 'size' => 16, + 'style' => array( + 'backgroundColor' => '#fff0', // fully transparent, for dark mode + 'padding' => 0, + ), +)); +$jdenticonGenerators = array( + 'jdenticon GD' => 'png', + 'jdenticon SVG' => 'svg', ); $results = array( 'vizhash' => array( @@ -35,21 +47,26 @@ $results = array( 'identicon SVG' => array( 'lengths' => array(), 'time' => 0 - ) + ), + 'jdenticon GD' => array( + 'lengths' => array(), + 'time' => 0 + ), + 'jdenticon SVG' => array( + 'lengths' => array(), + 'time' => 0 + ), ); $hmacs = array(); echo 'generate ', ITERATIONS, ' hmacs and pre-populate the result array, so tests wont be slowed down', PHP_EOL; for ($i = 0; $i < ITERATIONS; ++$i) { $hmacs[$i] = hash_hmac('sha512', '127.0.0.1', bin2hex(random_bytes(256))); - $results['vizhash']['lengths'][$i] = 0; - $results['identicon GD']['lengths'][$i] = 0; - $results['identicon ImageMagick']['lengths'][$i] = 0; - $results['identicon SVG']['lengths'][$i] = 0; + foreach (array_keys($results) as $test) { + $results[$test]['lengths'][$i] = 0; + } } - - echo 'run vizhash tests', PHP_EOL; $start = microtime(true); foreach ($hmacs as $i => $hmac) { @@ -60,7 +77,6 @@ foreach ($hmacs as $i => $hmac) { } $results['vizhash']['time'] = microtime(true) - $start; - foreach ($identiconGenerators as $key => $identicon) { echo 'run ', $key,' tests', PHP_EOL; $start = microtime(true); @@ -71,9 +87,30 @@ foreach ($identiconGenerators as $key => $identicon) { $results[$key]['time'] = microtime(true) - $start; } +foreach ($jdenticonGenerators as $key => $format) { + echo 'run ', $key,' tests', PHP_EOL; + $start = microtime(true); + foreach ($hmacs as $i => $hmac) { + $jdenticon->setHash($hmac); + $data = $jdenticon->getImageDataUri($format); + $results[$key]['lengths'][$i] = strlen($data); + } + $results[$key]['time'] = microtime(true) - $start; +} -define('PADDING_LENGTH', max(array_map(function ($key) { return strlen($key); }, array_keys($results))) + 1); +define( + 'PADDING_LENGTH', + max( + array_map( + function ($key) { + return strlen($key); + }, + array_keys($results) + ) + ) + 1 +); + function format_result_line($generator, $min, $max, $avg, $sec) { echo str_pad($generator, PADDING_LENGTH, ' '), "\t", str_pad($min, 4, ' ', STR_PAD_LEFT), "\t", @@ -84,7 +121,10 @@ function format_result_line($generator, $min, $max, $avg, $sec) { echo PHP_EOL; format_result_line('Generator:', 'min', 'max', 'avg', 'seconds'); -format_result_line(str_repeat('─', PADDING_LENGTH), str_repeat('─', 4), str_repeat('─', 4), str_repeat('─', 4), str_repeat('─', 7)); +format_result_line( + str_repeat('─', PADDING_LENGTH), str_repeat('─', 4), str_repeat('─', 4), + str_repeat('─', 4), str_repeat('─', 7) +); foreach ($results as $generator => $result) { sort($result['lengths']); format_result_line( From 89d575ace36406a78d47f3bb28fb4b8a70997604 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 30 Oct 2022 09:05:29 +0100 Subject: [PATCH 149/506] in light of the perf/size test results of Jdenticons, switch back to Identicons as the default --- CHANGELOG.md | 2 +- cfg/conf.sample.php | 2 +- lib/Configuration.php | 2 +- lib/Model/Comment.php | 8 ++++---- tst/ModelTest.php | 13 +++---------- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b6a607d..3fff7db7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ * **1.4.1 (not yet released)** * ADDED: Translations for Turkish, Slovak and Greek * ADDED: S3 Storage backend (#994) - * CHANGED: Switched to Jdenticons as the default for comment icons (#793) + * ADDED: Jdenticons as an option for comment icons (#793) * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) * CHANGED: Upgrading libraries to: zlib 1.2.13 * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index c972f153..e6a39d10 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -69,7 +69,7 @@ languageselection = false ; used to get the IP of a comment poster if the server salt is leaked and a ; SHA512 HMAC rainbow table is generated for all (relevant) IPs. ; Can be set to one these values: -; "none" / "vizhash" / "identicon" / "jdenticon" (default). +; "none" / "identicon" (default) / "jdenticon" / "vizhash". ; icon = "none" ; Content Security Policy headers allow a website to restrict what sources are diff --git a/lib/Configuration.php b/lib/Configuration.php index f4e537ef..6f3a8225 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -53,7 +53,7 @@ class Configuration 'languagedefault' => '', 'urlshortener' => '', 'qrcode' => true, - 'icon' => 'jdenticon', + 'icon' => 'identicon', 'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\'; style-src \'self\'; font-src \'self\'; frame-ancestors \'none\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads', 'zerobincompatibility' => false, 'httpwarning' => true, diff --git a/lib/Model/Comment.php b/lib/Model/Comment.php index 8e4142ee..ffb27fc4 100644 --- a/lib/Model/Comment.php +++ b/lib/Model/Comment.php @@ -165,7 +165,10 @@ class Comment extends AbstractModel if ($icon != 'none') { $pngdata = ''; $hmac = TrafficLimiter::getHash(); - if ($icon == 'jdenticon') { + if ($icon == 'identicon') { + $identicon = new Identicon(); + $pngdata = $identicon->getImageDataUri($hmac, 16); + } elseif ($icon == 'jdenticon') { $jdenticon = new Jdenticon(array( 'hash' => $hmac, 'size' => 16, @@ -175,9 +178,6 @@ class Comment extends AbstractModel ), )); $pngdata = $jdenticon->getImageDataUri('png'); - } elseif ($icon == 'identicon') { - $identicon = new Identicon(); - $pngdata = $identicon->getImageDataUri($hmac, 16); } elseif ($icon == 'vizhash') { $vh = new Vizhash16x16(); $pngdata = 'data:image/png;base64,' . base64_encode( diff --git a/tst/ModelTest.php b/tst/ModelTest.php index 49a2ae6b..a88e0296 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -1,6 +1,6 @@ get(); $comment->store(); - $identicon = new Identicon(array( - 'hash' => TrafficLimiter::getHash(), - 'size' => 16, - 'style' => array( - 'backgroundColor' => '#fff0', // fully transparent, for dark mode - 'padding' => 0, - ), - )); - $pngdata = $identicon->getImageDataUri('png'); + $identicon = new Identicon(); + $pngdata = $identicon->getImageDataUri(TrafficLimiter::getHash(), 16); $comment = current($this->_model->getPaste(Helper::getPasteId())->get()['comments']); $this->assertEquals($pngdata, $comment['meta']['icon'], 'icon gets set'); } From be1989b1179fa20642a397fa93491a8138219d97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:32:59 +0000 Subject: [PATCH 150/506] Bump jdenticon/jdenticon from 1.0.1 to 1.0.2 Bumps [jdenticon/jdenticon](https://github.com/dmester/jdenticon-php) from 1.0.1 to 1.0.2. - [Release notes](https://github.com/dmester/jdenticon-php/releases) - [Commits](https://github.com/dmester/jdenticon-php/compare/1.0.1...1.0.2) --- updated-dependencies: - dependency-name: jdenticon/jdenticon dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index c4f0aaf5..296be50b 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "jdenticon/jdenticon", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/dmester/jdenticon-php.git", - "reference": "994ee07293fb978f983393ffcb2c0250592a6ac4" + "reference": "cabb7a44c413c318392a341c5d3ca30fcdd57a6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dmester/jdenticon-php/zipball/994ee07293fb978f983393ffcb2c0250592a6ac4", - "reference": "994ee07293fb978f983393ffcb2c0250592a6ac4", + "url": "https://api.github.com/repos/dmester/jdenticon-php/zipball/cabb7a44c413c318392a341c5d3ca30fcdd57a6f", + "reference": "cabb7a44c413c318392a341c5d3ca30fcdd57a6f", "shasum": "" }, "require": { @@ -53,7 +53,7 @@ "issues": "https://github.com/dmester/jdenticon-php/issues", "source": "https://github.com/dmester/jdenticon-php" }, - "time": "2022-07-02T11:03:15+00:00" + "time": "2022-10-30T17:15:02+00:00" }, { "name": "mlocati/ip-lib", From b63de431a7002aa6d8de9ec4ef7fb125c3f581d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:33:10 +0000 Subject: [PATCH 151/506] Bump phpunit/phpunit from 5.6.3 to 5.7.27 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 5.6.3 to 5.7.27. - [Release notes](https://github.com/sebastianbergmann/phpunit/releases) - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/5.7.27/ChangeLog-5.7.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/5.6.3...5.7.27) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- composer.lock | 74 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/composer.lock b/composer.lock index c4f0aaf5..7b43219a 100644 --- a/composer.lock +++ b/composer.lock @@ -845,16 +845,16 @@ }, { "name": "phpunit/phpunit", - "version": "5.6.3", + "version": "5.7.27", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c" + "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9de0dbafeb6b1391b391fbb034734cb0af9f67c", - "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", "shasum": "" }, "require": { @@ -865,21 +865,21 @@ "ext-xml": "*", "myclabs/deep-copy": "~1.3", "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "^4.0.1", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "~1.1", - "sebastian/diff": "~1.2", - "sebastian/environment": "^1.3 || ^2.0", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/object-enumerator": "~1.0", + "sebastian/comparator": "^1.2.4", + "sebastian/diff": "^1.4.3", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.1", + "sebastian/object-enumerator": "~2.0", "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0|~2.0", - "symfony/yaml": "~2.1|~3.0" + "sebastian/version": "^1.0.6|^2.0.1", + "symfony/yaml": "~2.1|~3.0|~4.0" }, "conflict": { "phpdocumentor/reflection-docblock": "3.0.2" @@ -897,7 +897,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.6.x-dev" + "dev-master": "5.7.x-dev" } }, "autoload": { @@ -925,9 +925,9 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/5.6.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/5.7.27" }, - "time": "2016-11-14T06:39:40+00:00" + "time": "2018-02-01T05:50:59+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -1229,21 +1229,21 @@ }, { "name": "sebastian/exporter", - "version": "1.2.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", "shasum": "" }, "require": { "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "ext-mbstring": "*", @@ -1252,7 +1252,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1296,7 +1296,7 @@ "issues": "https://github.com/sebastianbergmann/exporter/issues", "source": "https://github.com/sebastianbergmann/exporter/tree/master" }, - "time": "2016-06-17T09:04:28+00:00" + "time": "2016-11-19T08:54:04+00:00" }, { "name": "sebastian/global-state", @@ -1355,21 +1355,21 @@ }, { "name": "sebastian/object-enumerator", - "version": "1.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", "shasum": "" }, "require": { "php": ">=5.6", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "phpunit/phpunit": "~5" @@ -1377,7 +1377,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1401,20 +1401,20 @@ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", "source": "https://github.com/sebastianbergmann/object-enumerator/tree/master" }, - "time": "2016-01-28T13:25:10+00:00" + "time": "2017-02-18T15:18:39+00:00" }, { "name": "sebastian/recursion-context", - "version": "1.0.5", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", "shasum": "" }, "require": { @@ -1426,7 +1426,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1458,7 +1458,7 @@ "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "source": "https://github.com/sebastianbergmann/recursion-context/tree/master" }, - "time": "2016-10-03T07:41:43+00:00" + "time": "2016-11-19T07:33:16+00:00" }, { "name": "sebastian/resource-operations", From a731a1143c5d6df967cfc21724764b76cf130b1f Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 31 Oct 2022 20:36:39 +0100 Subject: [PATCH 152/506] update jdenticon --- composer.lock | 1125 ++++++++++------- vendor/composer/installed.php | 10 +- .../Rasterization/SuperSampleBuffer.php | 9 + 3 files changed, 669 insertions(+), 475 deletions(-) diff --git a/composer.lock b/composer.lock index 40a1f21f..70e73039 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "17bceced29627163f7aa330a0697f68b", + "content-hash": "3ba2ecd907e375e7e1ae2d9c92a2dbb0", "packages": [ { "name": "jdenticon/jdenticon", @@ -241,34 +241,32 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1 || ^8.0" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^9", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -282,42 +280,60 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/master" + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" }, - "time": "2015-06-14T21:17:01+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-03-03T08:28:38+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { @@ -340,258 +356,204 @@ "object", "object graph" ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], - "time": "2020-11-13T09:40:50+00:00" + "time": "2022-03-03T13:19:32+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "name": "nikic/php-parser", + "version": "v4.15.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", "shasum": "" }, "require": { - "php": ">=5.5" + "ext-tokenizer": "*", + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "4.9-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "name": "Nikita Popov" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "description": "A PHP parser written in PHP", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" + "parser", + "php" ], "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" }, - "time": "2017-09-11T18:02:19+00:00" + "time": "2022-09-04T07:30:47+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "3.3.2", + "name": "phar-io/manifest", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", - "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/3.x" - }, - "time": "2017-11-10T14:09:06+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/master" - }, - "time": "2017-07-14T14:27:02+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" }, - "time": "2020-03-05T15:02:03+00:00" + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.13", + "version": "9.2.18", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8" + "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/deac8540cb7bd40b2b8cfa679b76202834fd04e8", - "reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/12fddc491826940cf9b7e88ad9664cf51f0f6d0a", + "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", + "nikic/php-parser": "^4.14", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -639,11 +601,16 @@ "xunit" ], "support": { - "irc": "irc://irc.freenode.net/phpunit", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/4.0" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.18" }, - "time": "2017-04-02T07:44:40+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-10-27T13:35:33+00:00" }, { "name": "phpunit/php-file-iterator", @@ -694,11 +661,16 @@ "iterator" ], "support": { - "irc": "irc://irc.freenode.net/phpunit", "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, - "time": "2017-11-27T13:52:08+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" }, { "name": "phpunit/php-invoker", @@ -752,10 +724,16 @@ "process" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" }, - "time": "2015-06-21T13:50:34+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" }, { "name": "phpunit/php-text-template", @@ -805,36 +783,41 @@ "template" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/master" + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" }, - "time": "2017-02-26T11:10:40+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "1.4.12", + "name": "phpunit/php-timer", + "version": "5.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -859,24 +842,29 @@ "timer" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", - "source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4" + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" }, - "abandoned": true, - "time": "2017-12-04T08:55:13+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", - "version": "5.7.27", + "version": "9.5.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" + "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", - "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2", + "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2", "shasum": "" }, "require": { @@ -886,30 +874,27 @@ "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.4", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "^1.2.4", - "sebastian/diff": "^1.4.3", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "~2.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "^1.0.6|^2.0.1", - "symfony/yaml": "~2.1|~3.0|~4.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" - }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" }, "suggest": { "ext-soap": "*", @@ -921,7 +906,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7.x-dev" + "dev-master": "9.5-dev" } }, "autoload": { @@ -952,13 +937,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/5.7.27" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26" }, - "time": "2018-02-01T05:50:59+00:00" + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2022-10-28T06:00:21+00:00" }, { - "name": "phpunit/phpunit-mock-objects", - "version": "3.4.4", + "name": "sebastian/cli-parser", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", @@ -971,19 +970,66 @@ "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "^9.3" }, - "suggest": { - "ext-soap": "*" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -1009,19 +1055,17 @@ ], "description": "Collection of value objects that represent the PHP code units", "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "support": { - "irc": "irc://irc.freenode.net/phpunit", - "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", - "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/3.4" - }, - "abandoned": true, - "time": "2017-06-30T09:13:00+00:00" + "time": "2020-10-26T13:08:54+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1068,7 +1112,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" }, "funding": [ { @@ -1080,16 +1124,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -1142,9 +1186,72 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/1.2" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, - "time": "2017-01-29T09:50:25+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" }, { "name": "sebastian/diff", @@ -1202,22 +1309,28 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/1.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" }, - "time": "2017-05-22T07:24:03+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:10:38+00:00" }, { "name": "sebastian/environment", - "version": "5.1.3", + "version": "5.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac" + "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", "shasum": "" }, "require": { @@ -1259,27 +1372,33 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/master" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" }, - "time": "2016-11-26T07:53:53+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-04-03T09:37:03+00:00" }, { "name": "sebastian/exporter", - "version": "2.0.0", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~2.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", @@ -1288,7 +1407,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1330,9 +1449,15 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/master" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" }, - "time": "2016-11-19T08:54:04+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", @@ -1388,27 +1513,33 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/1.1.1" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" }, - "time": "2015-10-12T03:26:01+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-14T08:28:10+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "2.0.1", + "name": "sebastian/lines-of-code", + "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", - "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", "shasum": "" }, "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~2.0" + "nikic/php-parser": "^4.6", + "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" @@ -1416,7 +1547,65 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -1438,22 +1627,28 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/master" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" }, - "time": "2017-02-18T15:18:39+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" }, { - "name": "sebastian/recursion-context", - "version": "2.0.0", + "name": "sebastian/object-reflector", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { @@ -1465,7 +1660,62 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { @@ -1495,9 +1745,15 @@ "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/master" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" }, - "time": "2016-11-19T07:33:16+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:17:30+00:00" }, { "name": "sebastian/resource-operations", @@ -1544,9 +1800,71 @@ "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/master" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" }, - "time": "2015-07-28T20:34:47+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-12T14:47:03+00:00" }, { "name": "sebastian/version", @@ -1591,115 +1909,35 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/master" - }, - "time": "2016-10-03T07:35:21+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b", - "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.19-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0" + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2020-10-23T09:01:57+00:00" + "time": "2020-09-28T06:39:44+00:00" }, { - "name": "symfony/yaml", - "version": "v3.4.47", + "name": "theseer/tokenizer", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "88289caa3c166321883f67fe5130188ebbb47094" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094", - "reference": "88289caa3c166321883f67fe5130188ebbb47094", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -1718,10 +1956,10 @@ "role": "Developer" } ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { - "source": "https://github.com/symfony/yaml/tree/v3.4.47" + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" }, "funding": [ { @@ -1729,60 +1967,7 @@ "type": "github" } ], - "time": "2020-10-24T10:57:07+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.9.1", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" - }, - "type": "library", - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.9.1" - }, - "time": "2020-07-08T17:02:28+00:00" + "time": "2021-07-28T10:34:58+00:00" } ], "aliases": [], @@ -1794,5 +1979,5 @@ "php": "^5.6.0 || ^7.0 || ^8.0" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 9756660e..e1f0c12e 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -5,18 +5,18 @@ 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => '78aa70e3ab9277172489f9d88f8fd08cc1d03c97', + 'reference' => '46013df6201304840c8dab82af63cc9000a6d239', 'name' => 'privatebin/privatebin', 'dev' => false, ), 'versions' => array( 'jdenticon/jdenticon' => array( - 'pretty_version' => '1.0.1', - 'version' => '1.0.1.0', + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', 'type' => 'library', 'install_path' => __DIR__ . '/../jdenticon/jdenticon', 'aliases' => array(), - 'reference' => '994ee07293fb978f983393ffcb2c0250592a6ac4', + 'reference' => 'cabb7a44c413c318392a341c5d3ca30fcdd57a6f', 'dev_requirement' => false, ), 'mlocati/ip-lib' => array( @@ -43,7 +43,7 @@ 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => '78aa70e3ab9277172489f9d88f8fd08cc1d03c97', + 'reference' => '46013df6201304840c8dab82af63cc9000a6d239', 'dev_requirement' => false, ), 'yzalis/identicon' => array( diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php index 82860e2e..45a611de 100644 --- a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php @@ -21,6 +21,15 @@ class SuperSampleBuffer const IDX_G = 3; const IDX_B = 4; + private $samples; + private $samplesPerPixel; + + private $pixelOffset; + private $subPixelOffset; + + private $width; + private $used; + /** * Creates a color buffer keeping an average color out of several * color samples per pixel. From 9a61e8fd48d193a79bb5203155c8303a719d3ff1 Mon Sep 17 00:00:00 2001 From: "Felix J. Ogris" Date: Fri, 28 Oct 2022 01:01:02 +0200 Subject: [PATCH 153/506] started script for storage backend migrations todo: GCS added GCS, no GLOBALS, two methods for saving pastes and comments use GLOBALS for verbosity again added getAllPastes() to all storage providers moved to bin, added --delete options, make use of $store->getAllPastes() added --delete-* options to help longopts without -- *sigh* fixed arguments drop singleton behaviour to allow multiple backends of the same type simultaneously remove singleton from Model, collapse loop in migrate.php comments is not indexed tests without data singleton fix exit if scandir() fails extended meta doc --- CREDITS.md | 1 + INSTALL.md | 8 +- bin/migrate.php | 194 ++++++++++++++ lib/Data/AbstractData.php | 62 +---- lib/Data/Database.php | 353 ++++++++++++------------- lib/Data/Filesystem.php | 159 ++++++----- lib/Data/GoogleCloudStorage.php | 111 ++++---- lib/Data/S3Storage.php | 151 ++++++----- lib/Model.php | 6 +- tst/ConfigurationTestGenerator.php | 2 +- tst/ControllerTest.php | 2 +- tst/ControllerWithDbTest.php | 2 +- tst/ControllerWithGcsTest.php | 2 +- tst/Data/DatabaseTest.php | 32 +-- tst/Data/FilesystemTest.php | 2 +- tst/Data/GoogleCloudStorageTest.php | 2 +- tst/JsonApiTest.php | 2 +- tst/ModelTest.php | 8 +- tst/Persistence/PurgeLimiterTest.php | 2 +- tst/Persistence/ServerSaltTest.php | 18 +- tst/Persistence/TrafficLimiterTest.php | 2 +- tst/Vizhash16x16Test.php | 2 +- 22 files changed, 658 insertions(+), 465 deletions(-) create mode 100644 bin/migrate.php diff --git a/CREDITS.md b/CREDITS.md index 97c11251..eb5f152e 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -31,6 +31,7 @@ * Austin Huang - Oracle database support * Felix J. Ogris - S3 Storage backend * Mounir Idrassi & J. Mozdzen - secure YOURLS integration +* Felix J. Ogris - script for data backend migrations, dropped singleton behaviour of data backends ## Translations * Hexalyse - French diff --git a/INSTALL.md b/INSTALL.md index f35d68bf..57777c94 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -38,10 +38,10 @@ install and configure PrivateBin on your server. It's available on ### Changing the Path In the index.php you can define a different `PATH`. This is useful to secure -your installation. You can move the configuration, data files, templates and PHP -libraries (directories cfg, doc, data, lib, tpl, tst and vendor) outside of your -document root. This new location must still be accessible to your webserver and -PHP process (see also +your installation. You can move the utilities, configuration, data files, +templates and PHP libraries (directories bin, cfg, doc, data, lib, tpl, tst and +vendor) outside of your document root. This new location must still be +accessible to your webserver and PHP process (see also [open_basedir setting](https://secure.php.net/manual/en/ini.core.php#ini.open-basedir)). > #### PATH Example diff --git a/bin/migrate.php b/bin/migrate.php new file mode 100644 index 00000000..193430e3 --- /dev/null +++ b/bin/migrate.php @@ -0,0 +1,194 @@ += $argc) { + dieerr("Missing source configuration directory"); +} +if ($delete_after && $delete_during) { + dieerr("--delete-after and --delete-during are mutually exclusive"); +} + +$srcconf = getConfig("source", $argv[$rest]); +$rest++; +$dstconf = getConfig("destination", ($rest < $argc ? $argv[$rest] : "")); + +if (($srcconf->getSection("model") == $dstconf->getSection("model")) && + ($srcconf->getSection("model_options") == $dstconf->getSection("model_options"))) { + dieerr("Source and destination storage configurations are identical"); +} + +$srcmodel = new Model($srcconf); +$srcstore = $srcmodel->getStore(); +$dstmodel = new Model($dstconf); +$dststore = $dstmodel->getStore(); +$ids = $srcstore->getAllPastes(); + +foreach ($ids as $id) { + debug("Reading paste id " . $id); + $paste = $srcstore->read($id); + $comments = $srcstore->readComments($id); + + savePaste($force_overwrite, $dryrun, $id, $paste, $dststore); + foreach ($comments as $comment) { + saveComment($force_overwrite, $dryrun, $id, $comment, $dststore); + } + if ($delete_during) { + deletePaste($dryrun, $id, $srcstore); + } +} + +if ($delete_after) { + foreach ($ids as $id) { + deletePaste($dryrun, $id, $srcstore); + } +} + +debug("Done."); + + +function deletePaste($dryrun, $pasteid, $srcstore) +{ + if (!$dryrun) { + debug("Deleting paste id " . $pasteid); + $srcstore->delete($pasteid); + } else { + debug("Would delete paste id " . $pasteid); + } +} + +function saveComment ($force_overwrite, $dryrun, $pasteid, $comment, $dststore) +{ + $parentid = $comment["parentid"]; + $commentid = $comment["id"]; + + if (!$dststore->existsComment($pasteid, $parentid, $commentid)) { + if (!$dryrun) { + debug("Saving paste id " . $pasteid . ", parent id " . + $parentid . ", comment id " . $commentid); + $dststore->createComment($pasteid, $parentid, $commentid, $comment); + } else { + debug("Would save paste id " . $pasteid . ", parent id " . + $parentid . ", comment id " . $commentid); + } + } else if ($force_overwrite) { + if (!$dryrun) { + debug("Overwriting paste id " . $pasteid . ", parent id " . + $parentid . ", comment id " . $commentid); + $dststore->createComment($pasteid, $parentid, $commentid, $comment); + } else { + debug("Would overwrite paste id " . $pasteid . ", parent id " . + $parentid . ", comment id " . $commentid); + } + } else { + if (!$dryrun) { + dieerr("Not overwriting paste id " . $pasteid . ", parent id " . + $parentid . ", comment id " . $commentid); + } else { + dieerr("Would not overwrite paste id " . $pasteid . ", parent id " . + $parentid . ", comment id " . $commentid); + } + } +} + +function savePaste ($force_overwrite, $dryrun, $pasteid, $paste, $dststore) +{ + if (!$dststore->exists($pasteid)) { + if (!$dryrun) { + debug("Saving paste id " . $pasteid); + $dststore->create($pasteid, $paste); + } else { + debug("Would save paste id " . $pasteid); + } + } else if ($force_overwrite) { + if (!$dryrun) { + debug("Overwriting paste id " . $pasteid); + $dststore->create($pasteid, $paste); + } else { + debug("Would overwrite paste id " . $pasteid); + } + } else { + if (!$dryrun) { + dieerr("Not overwriting paste id " . $pasteid); + } else { + dieerr("Would not overwrite paste id " . $pasteid); + } + } +} + +function getConfig ($target, $confdir) +{ + debug("Trying to load " . $target . " conf.php" . + ($confdir === "" ? "" : " from " . $confdir)); + + putenv("CONFIG_PATH=" . $confdir); + $conf = new Configuration; + putenv("CONFIG_PATH="); + + return $conf; +} + +function dieerr ($text) +{ + fprintf(STDERR, "ERROR: %s" . PHP_EOL, $text); + die(1); +} + +function debug ($text) { + if ($GLOBALS["verbose"]) { + printf("DEBUG: %s" . PHP_EOL, $text); + } +} + +function helpexit () +{ + print("migrate.php - Copy data between PrivateBin backends + +Usage: + php migrate.php [--delete-after] [--delete-during] [-f] [-n] [-v] srcconfdir + [] + php migrate.php [-h] + +Options: + --delete-after delete data from source after all pastes and comments have + successfully been copied to the destination + --delete-during delete data from source after the current paste and its + comments have successfully been copied to the destination + -f forcefully overwrite data which already exists at the + destination + -n dry run, do not copy data + -v be verbose + use storage backend configration from conf.php found in + this directory as source + optionally, use storage backend configration from conf.php + found in this directory as destination; defaults to: + " . PATH . "cfg" . DIRECTORY_SEPARATOR . "conf.php +"); + exit(); +} diff --git a/lib/Data/AbstractData.php b/lib/Data/AbstractData.php index 05353ce0..eddab09b 100644 --- a/lib/Data/AbstractData.php +++ b/lib/Data/AbstractData.php @@ -15,61 +15,17 @@ namespace PrivateBin\Data; /** * AbstractData * - * Abstract model for data access, implemented as a singleton. + * Abstract model for data access */ abstract class AbstractData { - /** - * Singleton instance - * - * @access protected - * @static - * @var AbstractData - */ - protected static $_instance = null; - /** * cache for the traffic limiter * - * @access private - * @static + * @access protected * @var array */ - protected static $_last_cache = array(); - - /** - * Enforce singleton, disable constructor - * - * Instantiate using {@link getInstance()}, this object implements the singleton pattern. - * - * @access protected - */ - protected function __construct() - { - } - - /** - * Enforce singleton, disable cloning - * - * Instantiate using {@link getInstance()}, this object implements the singleton pattern. - * - * @access private - */ - private function __clone() - { - } - - /** - * Get instance of singleton - * - * @access public - * @static - * @param array $options - * @return AbstractData - */ - public static function getInstance(array $options) - { - } + protected $_last_cache = array(); /** * Create a paste. @@ -150,9 +106,9 @@ abstract class AbstractData public function purgeValues($namespace, $time) { if ($namespace === 'traffic_limiter') { - foreach (self::$_last_cache as $key => $last_submission) { + foreach ($this->_last_cache as $key => $last_submission) { if ($last_submission <= $time) { - unset(self::$_last_cache[$key]); + unset($thi->_last_cache[$key]); } } } @@ -207,6 +163,14 @@ abstract class AbstractData } } + /** + * Returns all paste ids + * + * @access public + * @return array + */ + abstract public function getAllPastes(); + /** * Get next free slot for comment from postdate. * diff --git a/lib/Data/Database.php b/lib/Data/Database.php index 3ca7b756..05952a95 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -30,54 +30,45 @@ class Database extends AbstractData * * @var array */ - private static $_cache = array(); + private $_cache = array(); /** * instance of database connection * * @access private - * @static * @var PDO */ - private static $_db; + private $_db; /** * table prefix * * @access private - * @static * @var string */ - private static $_prefix = ''; + private $_prefix = ''; /** * database type * * @access private - * @static * @var string */ - private static $_type = ''; + private $_type = ''; /** - * get instance of singleton + * instantiates a new Database data backend * * @access public - * @static * @param array $options * @throws Exception - * @return Database + * @return */ - public static function getInstance(array $options) + public function __construct(array $options) { - // if needed initialize the singleton - if (!(self::$_instance instanceof self)) { - self::$_instance = new self; - } - // set table prefix if given if (array_key_exists('tbl', $options)) { - self::$_prefix = $options['tbl']; + $this->_prefix = $options['tbl']; } // initialize the db connection with new options @@ -94,16 +85,16 @@ class Database extends AbstractData $db_tables_exist = true; // setup type and dabase connection - self::$_type = strtolower( + $this->_type = strtolower( substr($options['dsn'], 0, strpos($options['dsn'], ':')) ); // MySQL uses backticks to quote identifiers by default, // tell it to expect ANSI SQL double quotes - if (self::$_type === 'mysql' && defined('PDO::MYSQL_ATTR_INIT_COMMAND')) { + if ($this->_type === 'mysql' && defined('PDO::MYSQL_ATTR_INIT_COMMAND')) { $options['opt'][PDO::MYSQL_ATTR_INIT_COMMAND] = "SET SESSION sql_mode='ANSI_QUOTES'"; } - $tableQuery = self::_getTableQuery(self::$_type); - self::$_db = new PDO( + $tableQuery = $this->_getTableQuery($this->_type); + $this->_db = new PDO( $options['dsn'], $options['usr'], $options['pwd'], @@ -111,43 +102,41 @@ class Database extends AbstractData ); // check if the database contains the required tables - $tables = self::$_db->query($tableQuery)->fetchAll(PDO::FETCH_COLUMN, 0); + $tables = $this->_db->query($tableQuery)->fetchAll(PDO::FETCH_COLUMN, 0); // create paste table if necessary - if (!in_array(self::_sanitizeIdentifier('paste'), $tables)) { - self::_createPasteTable(); + if (!in_array($this->_sanitizeIdentifier('paste'), $tables)) { + $this->_createPasteTable(); $db_tables_exist = false; } // create comment table if necessary - if (!in_array(self::_sanitizeIdentifier('comment'), $tables)) { - self::_createCommentTable(); + if (!in_array($this->_sanitizeIdentifier('comment'), $tables)) { + $this->_createCommentTable(); $db_tables_exist = false; } // create config table if necessary $db_version = Controller::VERSION; - if (!in_array(self::_sanitizeIdentifier('config'), $tables)) { - self::_createConfigTable(); + if (!in_array($this->_sanitizeIdentifier('config'), $tables)) { + $this->_createConfigTable(); // if we only needed to create the config table, the DB is older then 0.22 if ($db_tables_exist) { $db_version = '0.21'; } } else { - $db_version = self::_getConfig('VERSION'); + $db_version = $this->_getConfig('VERSION'); } // update database structure if necessary if (version_compare($db_version, Controller::VERSION, '<')) { - self::_upgradeDatabase($db_version); + $this->_upgradeDatabase($db_version); } } else { throw new Exception( 'Missing configuration for key dsn, usr, pwd or opt in the section model_options, please check your configuration file', 6 ); } - - return self::$_instance; } /** @@ -161,12 +150,12 @@ class Database extends AbstractData public function create($pasteid, array $paste) { if ( - array_key_exists($pasteid, self::$_cache) + array_key_exists($pasteid, $this->_cache) ) { - if (false !== self::$_cache[$pasteid]) { + if (false !== $this->_cache[$pasteid]) { return false; } else { - unset(self::$_cache[$pasteid]); + unset($this->_cache[$pasteid]); } } @@ -175,7 +164,7 @@ class Database extends AbstractData $attachment = $attachmentname = null; $meta = $paste['meta']; $isVersion1 = array_key_exists('data', $paste); - list($createdKey) = self::_getVersionedKeys($isVersion1 ? 1 : 2); + list($createdKey) = $this->_getVersionedKeys($isVersion1 ? 1 : 2); $created = (int) $meta[$createdKey]; unset($meta[$createdKey], $paste['meta']); if (array_key_exists('expire_date', $meta)) { @@ -204,8 +193,8 @@ class Database extends AbstractData $burnafterreading = $paste['adata'][3]; } try { - return self::_exec( - 'INSERT INTO "' . self::_sanitizeIdentifier('paste') . + return $this->_exec( + 'INSERT INTO "' . $this->_sanitizeIdentifier('paste') . '" VALUES(?,?,?,?,?,?,?,?,?)', array( $pasteid, @@ -233,14 +222,14 @@ class Database extends AbstractData */ public function read($pasteid) { - if (array_key_exists($pasteid, self::$_cache)) { - return self::$_cache[$pasteid]; + if (array_key_exists($pasteid, $this->_cache)) { + return $this->_cache[$pasteid]; } - self::$_cache[$pasteid] = false; + $this->_cache[$pasteid] = false; try { - $paste = self::_select( - 'SELECT * FROM "' . self::_sanitizeIdentifier('paste') . + $paste = $this->_select( + 'SELECT * FROM "' . $this->_sanitizeIdentifier('paste') . '" WHERE "dataid" = ?', array($pasteid), true ); } catch (Exception $e) { @@ -253,11 +242,11 @@ class Database extends AbstractData $data = Json::decode($paste['data']); $isVersion2 = array_key_exists('v', $data) && $data['v'] >= 2; if ($isVersion2) { - self::$_cache[$pasteid] = $data; - list($createdKey) = self::_getVersionedKeys(2); + $this->_cache[$pasteid] = $data; + list($createdKey) = $this->_getVersionedKeys(2); } else { - self::$_cache[$pasteid] = array('data' => $paste['data']); - list($createdKey) = self::_getVersionedKeys(1); + $this->_cache[$pasteid] = array('data' => $paste['data']); + list($createdKey) = $this->_getVersionedKeys(1); } try { @@ -266,31 +255,31 @@ class Database extends AbstractData $paste['meta'] = array(); } $paste = self::upgradePreV1Format($paste); - self::$_cache[$pasteid]['meta'] = $paste['meta']; - self::$_cache[$pasteid]['meta'][$createdKey] = (int) $paste['postdate']; + $this->_cache[$pasteid]['meta'] = $paste['meta']; + $this->_cache[$pasteid]['meta'][$createdKey] = (int) $paste['postdate']; $expire_date = (int) $paste['expiredate']; if ($expire_date > 0) { - self::$_cache[$pasteid]['meta']['expire_date'] = $expire_date; + $this->_cache[$pasteid]['meta']['expire_date'] = $expire_date; } if ($isVersion2) { - return self::$_cache[$pasteid]; + return $this->_cache[$pasteid]; } // support v1 attachments if (array_key_exists('attachment', $paste) && !empty($paste['attachment'])) { - self::$_cache[$pasteid]['attachment'] = $paste['attachment']; + $this->_cache[$pasteid]['attachment'] = $paste['attachment']; if (array_key_exists('attachmentname', $paste) && !empty($paste['attachmentname'])) { - self::$_cache[$pasteid]['attachmentname'] = $paste['attachmentname']; + $this->_cache[$pasteid]['attachmentname'] = $paste['attachmentname']; } } if ($paste['opendiscussion']) { - self::$_cache[$pasteid]['meta']['opendiscussion'] = true; + $this->_cache[$pasteid]['meta']['opendiscussion'] = true; } if ($paste['burnafterreading']) { - self::$_cache[$pasteid]['meta']['burnafterreading'] = true; + $this->_cache[$pasteid]['meta']['burnafterreading'] = true; } - return self::$_cache[$pasteid]; + return $this->_cache[$pasteid]; } /** @@ -301,18 +290,18 @@ class Database extends AbstractData */ public function delete($pasteid) { - self::_exec( - 'DELETE FROM "' . self::_sanitizeIdentifier('paste') . + $this->_exec( + 'DELETE FROM "' . $this->_sanitizeIdentifier('paste') . '" WHERE "dataid" = ?', array($pasteid) ); - self::_exec( - 'DELETE FROM "' . self::_sanitizeIdentifier('comment') . + $this->_exec( + 'DELETE FROM "' . $this->_sanitizeIdentifier('comment') . '" WHERE "pasteid" = ?', array($pasteid) ); if ( - array_key_exists($pasteid, self::$_cache) + array_key_exists($pasteid, $this->_cache) ) { - unset(self::$_cache[$pasteid]); + unset($this->_cache[$pasteid]); } } @@ -326,11 +315,11 @@ class Database extends AbstractData public function exists($pasteid) { if ( - !array_key_exists($pasteid, self::$_cache) + !array_key_exists($pasteid, $this->_cache) ) { - self::$_cache[$pasteid] = $this->read($pasteid); + $this->_cache[$pasteid] = $this->read($pasteid); } - return (bool) self::$_cache[$pasteid]; + return (bool) $this->_cache[$pasteid]; } /** @@ -352,7 +341,7 @@ class Database extends AbstractData $version = 2; $data = Json::encode($comment); } - list($createdKey, $iconKey) = self::_getVersionedKeys($version); + list($createdKey, $iconKey) = $this->_getVersionedKeys($version); $meta = $comment['meta']; unset($comment['meta']); foreach (array('nickname', $iconKey) as $key) { @@ -361,8 +350,8 @@ class Database extends AbstractData } } try { - return self::_exec( - 'INSERT INTO "' . self::_sanitizeIdentifier('comment') . + return $this->_exec( + 'INSERT INTO "' . $this->_sanitizeIdentifier('comment') . '" VALUES(?,?,?,?,?,?,?)', array( $commentid, @@ -388,8 +377,8 @@ class Database extends AbstractData */ public function readComments($pasteid) { - $rows = self::_select( - 'SELECT * FROM "' . self::_sanitizeIdentifier('comment') . + $rows = $this->_select( + 'SELECT * FROM "' . $this->_sanitizeIdentifier('comment') . '" WHERE "pasteid" = ?', array($pasteid) ); @@ -406,7 +395,7 @@ class Database extends AbstractData $version = 1; $comments[$i] = array('data' => $row['data']); } - list($createdKey, $iconKey) = self::_getVersionedKeys($version); + list($createdKey, $iconKey) = $this->_getVersionedKeys($version); $comments[$i]['id'] = $row['dataid']; $comments[$i]['parentid'] = $row['parentid']; $comments[$i]['meta'] = array($createdKey => (int) $row['postdate']); @@ -433,8 +422,8 @@ class Database extends AbstractData public function existsComment($pasteid, $parentid, $commentid) { try { - return (bool) self::_select( - 'SELECT "dataid" FROM "' . self::_sanitizeIdentifier('comment') . + return (bool) $this->_select( + 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('comment') . '" WHERE "pasteid" = ? AND "parentid" = ? AND "dataid" = ?', array($pasteid, $parentid, $commentid), true ); @@ -455,15 +444,15 @@ class Database extends AbstractData public function setValue($value, $namespace, $key = '') { if ($namespace === 'traffic_limiter') { - self::$_last_cache[$key] = $value; + $this->_last_cache[$key] = $value; try { - $value = Json::encode(self::$_last_cache); + $value = Json::encode($this->_last_cache); } catch (Exception $e) { return false; } } - return self::_exec( - 'UPDATE "' . self::_sanitizeIdentifier('config') . + return $this->_exec( + 'UPDATE "' . $this->_sanitizeIdentifier('config') . '" SET "value" = ? WHERE "id" = ?', array($value, strtoupper($namespace)) ); @@ -483,8 +472,8 @@ class Database extends AbstractData $value = $this->_getConfig($configKey); if ($value === '') { // initialize the row, so that setValue can rely on UPDATE queries - self::_exec( - 'INSERT INTO "' . self::_sanitizeIdentifier('config') . + $this->_exec( + 'INSERT INTO "' . $this->_sanitizeIdentifier('config') . '" VALUES(?,?)', array($configKey, '') ); @@ -492,7 +481,8 @@ class Database extends AbstractData // migrate filesystem based salt into database $file = 'data' . DIRECTORY_SEPARATOR . 'salt.php'; if ($namespace === 'salt' && is_readable($file)) { - $value = Filesystem::getInstance(array('dir' => 'data'))->getValue('salt'); + $fs = new Filesystem(array('dir' => 'data')); + $value = $fs->getValue('salt'); $this->setValue($value, 'salt'); @unlink($file); return $value; @@ -500,12 +490,12 @@ class Database extends AbstractData } if ($value && $namespace === 'traffic_limiter') { try { - self::$_last_cache = Json::decode($value); + $this->_last_cache = Json::decode($value); } catch (Exception $e) { - self::$_last_cache = array(); + $this->_last_cache = array(); } - if (array_key_exists($key, self::$_last_cache)) { - return self::$_last_cache[$key]; + if (array_key_exists($key, $this->_last_cache)) { + return $this->_last_cache[$key]; } } return (string) $value; @@ -521,10 +511,10 @@ class Database extends AbstractData protected function _getExpiredPastes($batchsize) { $pastes = array(); - $rows = self::_select( - 'SELECT "dataid" FROM "' . self::_sanitizeIdentifier('paste') . + $rows = $this->_select( + 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '" WHERE "expiredate" < ? AND "expiredate" != ? ' . - (self::$_type === 'oci' ? 'FETCH NEXT ? ROWS ONLY' : 'LIMIT ?'), + ($this->_type === 'oci' ? 'FETCH NEXT ? ROWS ONLY' : 'LIMIT ?'), array(time(), 0, $batchsize) ); if (is_array($rows) && count($rows)) { @@ -535,19 +525,36 @@ class Database extends AbstractData return $pastes; } + /** + * @inheritDoc + */ + public function getAllPastes() + { + $pastes = array(); + $rows = $this->_select( + 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '"', + array() + ); + if (is_array($rows) && count($rows)) { + foreach ($rows as $row) { + $pastes[] = $row['dataid']; + } + } + return $pastes; + } + /** * execute a statement * * @access private - * @static * @param string $sql * @param array $params * @throws PDOException * @return bool */ - private static function _exec($sql, array $params) + private function _exec($sql, array $params) { - $statement = self::$_db->prepare($sql); + $statement = $this->_db->prepare($sql); foreach ($params as $key => &$parameter) { $position = $key + 1; if (is_int($parameter)) { @@ -567,20 +574,19 @@ class Database extends AbstractData * run a select statement * * @access private - * @static * @param string $sql * @param array $params * @param bool $firstOnly if only the first row should be returned * @throws PDOException * @return array|false */ - private static function _select($sql, array $params, $firstOnly = false) + private function _select($sql, array $params, $firstOnly = false) { - $statement = self::$_db->prepare($sql); + $statement = $this->_db->prepare($sql); $statement->execute($params); if ($firstOnly) { $result = $statement->fetch(PDO::FETCH_ASSOC); - } elseif (self::$_type === 'oci') { + } elseif ($this->_type === 'oci') { // workaround for https://bugs.php.net/bug.php?id=46728 $result = array(); while ($row = $statement->fetch(PDO::FETCH_ASSOC)) { @@ -590,7 +596,7 @@ class Database extends AbstractData $result = $statement->fetchAll(PDO::FETCH_ASSOC); } $statement->closeCursor(); - if (self::$_type === 'oci' && is_array($result)) { + if ($this->_type === 'oci' && is_array($result)) { // returned CLOB values are streams, convert these into strings $result = $firstOnly ? array_map('PrivateBin\Data\Database::_sanitizeClob', $result) : @@ -603,11 +609,10 @@ class Database extends AbstractData * get version dependent key names * * @access private - * @static * @param int $version * @return array */ - private static function _getVersionedKeys($version) + private function _getVersionedKeys($version) { if ($version === 1) { return array('postdate', 'vizhash'); @@ -619,12 +624,11 @@ class Database extends AbstractData * get table list query, depending on the database type * * @access private - * @static * @param string $type * @throws Exception * @return string */ - private static function _getTableQuery($type) + private function _getTableQuery($type) { switch ($type) { case 'ibm': @@ -675,15 +679,14 @@ class Database extends AbstractData * get a value by key from the config table * * @access private - * @static * @param string $key * @return string */ - private static function _getConfig($key) + private function _getConfig($key) { try { - $row = self::_select( - 'SELECT "value" FROM "' . self::_sanitizeIdentifier('config') . + $row = $this->_select( + 'SELECT "value" FROM "' . $this->_sanitizeIdentifier('config') . '" WHERE "id" = ?', array($key), true ); } catch (PDOException $e) { @@ -696,14 +699,13 @@ class Database extends AbstractData * get the primary key clauses, depending on the database driver * * @access private - * @static * @param string $key * @return array */ - private static function _getPrimaryKeyClauses($key = 'dataid') + private function _getPrimaryKeyClauses($key = 'dataid') { $main_key = $after_key = ''; - switch (self::$_type) { + switch ($this->_type) { case 'mysql': case 'oci': $after_key = ", PRIMARY KEY (\"$key\")"; @@ -721,12 +723,11 @@ class Database extends AbstractData * PostgreSQL and OCI uses a different API for BLOBs then SQL, hence we use TEXT and CLOB * * @access private - * @static * @return string */ - private static function _getDataType() + private function _getDataType() { - switch (self::$_type) { + switch ($this->_type) { case 'oci': return 'CLOB'; case 'pgsql': @@ -742,12 +743,11 @@ class Database extends AbstractData * PostgreSQL and OCI use different APIs for BLOBs then SQL, hence we use TEXT and CLOB * * @access private - * @static * @return string */ - private static function _getAttachmentType() + private function _getAttachmentType() { - switch (self::$_type) { + switch ($this->_type) { case 'oci': return 'CLOB'; case 'pgsql': @@ -763,12 +763,11 @@ class Database extends AbstractData * OCI doesn't accept TEXT so it has to be VARCHAR2(4000) * * @access private - * @static * @return string */ - private static function _getMetaType() + private function _getMetaType() { - switch (self::$_type) { + switch ($this->_type) { case 'oci': return 'VARCHAR2(4000)'; default: @@ -780,16 +779,15 @@ class Database extends AbstractData * create the paste table * * @access private - * @static */ - private static function _createPasteTable() + private function _createPasteTable() { - list($main_key, $after_key) = self::_getPrimaryKeyClauses(); - $dataType = self::_getDataType(); - $attachmentType = self::_getAttachmentType(); - $metaType = self::_getMetaType(); - self::$_db->exec( - 'CREATE TABLE "' . self::_sanitizeIdentifier('paste') . '" ( ' . + list($main_key, $after_key) = $this->_getPrimaryKeyClauses(); + $dataType = $this->_getDataType(); + $attachmentType = $this->_getAttachmentType(); + $metaType = $this->_getMetaType(); + $this->_db->exec( + 'CREATE TABLE "' . $this->_sanitizeIdentifier('paste') . '" ( ' . "\"dataid\" CHAR(16) NOT NULL$main_key, " . "\"data\" $attachmentType, " . '"postdate" INT, ' . @@ -806,14 +804,13 @@ class Database extends AbstractData * create the paste table * * @access private - * @static */ - private static function _createCommentTable() + private function _createCommentTable() { - list($main_key, $after_key) = self::_getPrimaryKeyClauses(); - $dataType = self::_getDataType(); - self::$_db->exec( - 'CREATE TABLE "' . self::_sanitizeIdentifier('comment') . '" ( ' . + list($main_key, $after_key) = $this->_getPrimaryKeyClauses(); + $dataType = $this->_getDataType(); + $this->_db->exec( + 'CREATE TABLE "' . $this->_sanitizeIdentifier('comment') . '" ( ' . "\"dataid\" CHAR(16) NOT NULL$main_key, " . '"pasteid" CHAR(16), ' . '"parentid" CHAR(16), ' . @@ -822,15 +819,15 @@ class Database extends AbstractData "\"vizhash\" $dataType, " . "\"postdate\" INT$after_key )" ); - if (self::$_type === 'oci') { - self::$_db->exec( + if ($this->_type === 'oci') { + $this->_db->exec( 'declare already_exists exception; columns_indexed exception; pragma exception_init( already_exists, -955 ); pragma exception_init(columns_indexed, -1408); begin - execute immediate \'create index "comment_parent" on "' . self::_sanitizeIdentifier('comment') . '" ("pasteid")\'; + execute immediate \'create index "comment_parent" on "' . $this->_sanitizeIdentifier('comment') . '" ("pasteid")\'; exception when already_exists or columns_indexed then NULL; @@ -838,10 +835,10 @@ class Database extends AbstractData ); } else { // CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0 - self::$_db->exec( + $this->_db->exec( 'CREATE INDEX "' . - self::_sanitizeIdentifier('comment_parent') . '" ON "' . - self::_sanitizeIdentifier('comment') . '" ("pasteid")' + $this->_sanitizeIdentifier('comment_parent') . '" ON "' . + $this->_sanitizeIdentifier('comment') . '" ("pasteid")' ); } } @@ -850,19 +847,18 @@ class Database extends AbstractData * create the paste table * * @access private - * @static */ - private static function _createConfigTable() + private function _createConfigTable() { - list($main_key, $after_key) = self::_getPrimaryKeyClauses('id'); - $charType = self::$_type === 'oci' ? 'VARCHAR2(16)' : 'CHAR(16)'; - $textType = self::_getMetaType(); - self::$_db->exec( - 'CREATE TABLE "' . self::_sanitizeIdentifier('config') . + list($main_key, $after_key) = $this->_getPrimaryKeyClauses('id'); + $charType = $this->_type === 'oci' ? 'VARCHAR2(16)' : 'CHAR(16)'; + $textType = $this->_getMetaType(); + $this->_db->exec( + 'CREATE TABLE "' . $this->_sanitizeIdentifier('config') . "\" ( \"id\" $charType NOT NULL$main_key, \"value\" $textType$after_key )" ); - self::_exec( - 'INSERT INTO "' . self::_sanitizeIdentifier('config') . + $this->_exec( + 'INSERT INTO "' . $this->_sanitizeIdentifier('config') . '" VALUES(?,?)', array('VERSION', Controller::VERSION) ); @@ -874,11 +870,10 @@ class Database extends AbstractData * From: https://stackoverflow.com/questions/36200534/pdo-oci-into-a-clob-field * * @access public - * @static * @param int|string|resource $value * @return int|string */ - public static function _sanitizeClob($value) + public function _sanitizeClob($value) { if (is_resource($value)) { $value = stream_get_contents($value); @@ -890,90 +885,88 @@ class Database extends AbstractData * sanitizes identifiers * * @access private - * @static * @param string $identifier * @return string */ - private static function _sanitizeIdentifier($identifier) + private function _sanitizeIdentifier($identifier) { - return preg_replace('/[^A-Za-z0-9_]+/', '', self::$_prefix . $identifier); + return preg_replace('/[^A-Za-z0-9_]+/', '', $this->_prefix . $identifier); } /** * upgrade the database schema from an old version * * @access private - * @static * @param string $oldversion */ - private static function _upgradeDatabase($oldversion) + private function _upgradeDatabase($oldversion) { - $dataType = self::_getDataType(); - $attachmentType = self::_getAttachmentType(); + $dataType = $this->_getDataType(); + $attachmentType = $this->_getAttachmentType(); switch ($oldversion) { case '0.21': // create the meta column if necessary (pre 0.21 change) try { - self::$_db->exec( - 'SELECT "meta" FROM "' . self::_sanitizeIdentifier('paste') . '" ' . - (self::$_type === 'oci' ? 'FETCH NEXT 1 ROWS ONLY' : 'LIMIT 1') + $this->_db->exec( + 'SELECT "meta" FROM "' . $this->_sanitizeIdentifier('paste') . '" ' . + ($this->_type === 'oci' ? 'FETCH NEXT 1 ROWS ONLY' : 'LIMIT 1') ); } catch (PDOException $e) { - self::$_db->exec('ALTER TABLE "' . self::_sanitizeIdentifier('paste') . '" ADD COLUMN "meta" TEXT'); + $this->_db->exec('ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . '" ADD COLUMN "meta" TEXT'); } // SQLite only allows one ALTER statement at a time... - self::$_db->exec( - 'ALTER TABLE "' . self::_sanitizeIdentifier('paste') . + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachment\" $attachmentType" ); - self::$_db->exec( - 'ALTER TABLE "' . self::_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachmentname\" $dataType" + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachmentname\" $dataType" ); // SQLite doesn't support MODIFY, but it allows TEXT of similar // size as BLOB, so there is no need to change it there - if (self::$_type !== 'sqlite') { - self::$_db->exec( - 'ALTER TABLE "' . self::_sanitizeIdentifier('paste') . + if ($this->_type !== 'sqlite') { + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType" ); - self::$_db->exec( - 'ALTER TABLE "' . self::_sanitizeIdentifier('comment') . + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('comment') . "\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType, " . "MODIFY COLUMN \"nickname\" $dataType, MODIFY COLUMN \"vizhash\" $dataType" ); } else { - self::$_db->exec( + $this->_db->exec( 'CREATE UNIQUE INDEX IF NOT EXISTS "' . - self::_sanitizeIdentifier('paste_dataid') . '" ON "' . - self::_sanitizeIdentifier('paste') . '" ("dataid")' + $this->_sanitizeIdentifier('paste_dataid') . '" ON "' . + $this->_sanitizeIdentifier('paste') . '" ("dataid")' ); - self::$_db->exec( + $this->_db->exec( 'CREATE UNIQUE INDEX IF NOT EXISTS "' . - self::_sanitizeIdentifier('comment_dataid') . '" ON "' . - self::_sanitizeIdentifier('comment') . '" ("dataid")' + $this->_sanitizeIdentifier('comment_dataid') . '" ON "' . + $this->_sanitizeIdentifier('comment') . '" ("dataid")' ); } // CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0 - self::$_db->exec( + $this->_db->exec( 'CREATE INDEX "' . - self::_sanitizeIdentifier('comment_parent') . '" ON "' . - self::_sanitizeIdentifier('comment') . '" ("pasteid")' + $this->_sanitizeIdentifier('comment_parent') . '" ON "' . + $this->_sanitizeIdentifier('comment') . '" ("pasteid")' ); // no break, continue with updates for 0.22 and later case '1.3': // SQLite doesn't support MODIFY, but it allows TEXT of similar // size as BLOB and PostgreSQL uses TEXT, so there is no need // to change it there - if (self::$_type !== 'sqlite' && self::$_type !== 'pgsql') { - self::$_db->exec( - 'ALTER TABLE "' . self::_sanitizeIdentifier('paste') . + if ($this->_type !== 'sqlite' && $this->_type !== 'pgsql') { + $this->_db->exec( + 'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" MODIFY COLUMN \"data\" $attachmentType" ); } // no break, continue with updates for all newer versions default: - self::_exec( - 'UPDATE "' . self::_sanitizeIdentifier('config') . + $this->_exec( + 'UPDATE "' . $this->_sanitizeIdentifier('config') . '" SET "value" = ? WHERE "id" = ?', array(Controller::VERSION, 'VERSION') ); diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index 9674513c..3dd69578 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -40,33 +40,26 @@ class Filesystem extends AbstractData * path in which to persist something * * @access private - * @static * @var string */ - private static $_path = 'data'; + private $_path = 'data'; /** - * get instance of singleton + * instantiates a new Filesystem data backend * * @access public - * @static * @param array $options - * @return Filesystem + * @return */ - public static function getInstance(array $options) + public function __construct(array $options) { - // if needed initialize the singleton - if (!(self::$_instance instanceof self)) { - self::$_instance = new self; - } // if given update the data directory if ( is_array($options) && array_key_exists('dir', $options) ) { - self::$_path = $options['dir']; + $this->_path = $options['dir']; } - return self::$_instance; } /** @@ -79,7 +72,7 @@ class Filesystem extends AbstractData */ public function create($pasteid, array $paste) { - $storagedir = self::_dataid2path($pasteid); + $storagedir = $this->_dataid2path($pasteid); $file = $storagedir . $pasteid . '.php'; if (is_file($file)) { return false; @@ -87,7 +80,7 @@ class Filesystem extends AbstractData if (!is_dir($storagedir)) { mkdir($storagedir, 0700, true); } - return self::_store($file, $paste); + return $this->_store($file, $paste); } /** @@ -101,7 +94,7 @@ class Filesystem extends AbstractData { if ( !$this->exists($pasteid) || - !$paste = self::_get(self::_dataid2path($pasteid) . $pasteid . '.php') + !$paste = $this->_get($this->_dataid2path($pasteid) . $pasteid . '.php') ) { return false; } @@ -116,7 +109,7 @@ class Filesystem extends AbstractData */ public function delete($pasteid) { - $pastedir = self::_dataid2path($pasteid); + $pastedir = $this->_dataid2path($pasteid); if (is_dir($pastedir)) { // Delete the paste itself. if (is_file($pastedir . $pasteid . '.php')) { @@ -124,7 +117,7 @@ class Filesystem extends AbstractData } // Delete discussion if it exists. - $discdir = self::_dataid2discussionpath($pasteid); + $discdir = $this->_dataid2discussionpath($pasteid); if (is_dir($discdir)) { // Delete all files in discussion directory $dir = dir($discdir); @@ -148,20 +141,20 @@ class Filesystem extends AbstractData */ public function exists($pasteid) { - $basePath = self::_dataid2path($pasteid) . $pasteid; + $basePath = $this->_dataid2path($pasteid) . $pasteid; $pastePath = $basePath . '.php'; // convert to PHP protected files if needed if (is_readable($basePath)) { - self::_prependRename($basePath, $pastePath); + $this->_prependRename($basePath, $pastePath); // convert comments, too - $discdir = self::_dataid2discussionpath($pasteid); + $discdir = $this->_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'; - self::_prependRename($discdir . $filename, $commentFilename); + $this->_prependRename($discdir . $filename, $commentFilename); } } $dir->close(); @@ -182,7 +175,7 @@ class Filesystem extends AbstractData */ public function createComment($pasteid, $parentid, $commentid, array $comment) { - $storagedir = self::_dataid2discussionpath($pasteid); + $storagedir = $this->_dataid2discussionpath($pasteid); $file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid . '.php'; if (is_file($file)) { return false; @@ -190,7 +183,7 @@ class Filesystem extends AbstractData if (!is_dir($storagedir)) { mkdir($storagedir, 0700, true); } - return self::_store($file, $comment); + return $this->_store($file, $comment); } /** @@ -203,7 +196,7 @@ class Filesystem extends AbstractData public function readComments($pasteid) { $comments = array(); - $discdir = self::_dataid2discussionpath($pasteid); + $discdir = $this->_dataid2discussionpath($pasteid); if (is_dir($discdir)) { $dir = dir($discdir); while (false !== ($filename = $dir->read())) { @@ -212,7 +205,7 @@ class Filesystem extends AbstractData // - commentid is the comment identifier itself. // - parentid is the comment this comment replies to (It can be pasteid) if (is_file($discdir . $filename)) { - $comment = self::_get($discdir . $filename); + $comment = $this->_get($discdir . $filename); $items = explode('.', $filename); // Add some meta information not contained in file. $comment['id'] = $items[1]; @@ -243,7 +236,7 @@ class Filesystem extends AbstractData public function existsComment($pasteid, $parentid, $commentid) { return is_file( - self::_dataid2discussionpath($pasteid) . + $this->_dataid2discussionpath($pasteid) . $pasteid . '.' . $commentid . '.' . $parentid . '.php' ); } @@ -261,20 +254,20 @@ class Filesystem extends AbstractData { switch ($namespace) { case 'purge_limiter': - return self::_storeString( - self::$_path . DIRECTORY_SEPARATOR . 'purge_limiter.php', + return $this->_storeString( + $this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php', '_storeString( + $this->_path . DIRECTORY_SEPARATOR . 'salt.php', '_last_cache[$key] = $value; + return $this->_storeString( + $this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php', + '_last_cache, true) . ';' ); } return false; @@ -292,14 +285,14 @@ class Filesystem extends AbstractData { switch ($namespace) { case 'purge_limiter': - $file = self::$_path . DIRECTORY_SEPARATOR . 'purge_limiter.php'; + $file = $this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php'; if (is_readable($file)) { require $file; return $GLOBALS['purge_limiter']; } break; case 'salt': - $file = self::$_path . DIRECTORY_SEPARATOR . 'salt.php'; + $file = $this->_path . DIRECTORY_SEPARATOR . 'salt.php'; if (is_readable($file)) { $items = explode('|', file_get_contents($file)); if (is_array($items) && count($items) == 3) { @@ -308,12 +301,12 @@ class Filesystem extends AbstractData } break; case 'traffic_limiter': - $file = self::$_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php'; + $file = $this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php'; if (is_readable($file)) { require $file; - self::$_last_cache = $GLOBALS['traffic_limiter']; - if (array_key_exists($key, self::$_last_cache)) { - return self::$_last_cache[$key]; + $this->_last_cache = $GLOBALS['traffic_limiter']; + if (array_key_exists($key, $this->_last_cache)) { + return $this->_last_cache[$key]; } } break; @@ -325,11 +318,10 @@ class Filesystem extends AbstractData * get the data * * @access public - * @static * @param string $filename * @return array|false $data */ - private static function _get($filename) + private function _get($filename) { return Json::decode( substr( @@ -350,7 +342,7 @@ class Filesystem extends AbstractData { $pastes = array(); $firstLevel = array_filter( - scandir(self::$_path), + scandir($this->_path), 'PrivateBin\Data\Filesystem::_isFirstLevelDir' ); if (count($firstLevel) > 0) { @@ -358,7 +350,7 @@ class Filesystem extends AbstractData for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) { $firstKey = array_rand($firstLevel); $secondLevel = array_filter( - scandir(self::$_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]), + scandir($this->_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]), 'PrivateBin\Data\Filesystem::_isSecondLevelDir' ); @@ -369,7 +361,7 @@ class Filesystem extends AbstractData } $secondKey = array_rand($secondLevel); - $path = self::$_path . DIRECTORY_SEPARATOR . + $path = $this->_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey] . DIRECTORY_SEPARATOR . $secondLevel[$secondKey]; if (!is_dir($path)) { @@ -412,6 +404,46 @@ class Filesystem extends AbstractData return $pastes; } + /** + * @inheritDoc + */ + public function getAllPastes() + { + $pastes = array(); + $subdirs = scandir($this->_path); + if ($subdirs === false) { + dieerr("Unable to list directory " . $this->_path); + } + $subdirs = preg_grep("/^[^.].$/", $subdirs); + + foreach ($subdirs as $subdir) { + $subpath = $this->_path . DIRECTORY_SEPARATOR . $subdir; + + $subsubdirs = scandir($subpath); + if ($subsubdirs === false) { + dieerr("Unable to list directory " . $subpath); + } + $subsubdirs = preg_grep("/^[^.].$/", $subsubdirs); + foreach ($subsubdirs as $subsubdir) { + $subsubpath = $subpath . DIRECTORY_SEPARATOR . $subsubdir; + + $files = scandir($subsubpath); + if ($files === false) { + dieerr("Unable to list directory " . $subsubpath); + } + $files = preg_grep("/\.php$/", $files); + + foreach ($files as $file) { + if (substr($file, 0, 4) === $subdir . $subsubdir) { + $pastes[] = substr($file, 0, strlen($file) - 4); + } + } + } + } + + return $pastes; + } + /** * Convert paste id to storage path. * @@ -423,13 +455,12 @@ class Filesystem extends AbstractData * eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/' * * @access private - * @static * @param string $dataid * @return string */ - private static function _dataid2path($dataid) + private function _dataid2path($dataid) { - return self::$_path . DIRECTORY_SEPARATOR . + return $this->_path . DIRECTORY_SEPARATOR . substr($dataid, 0, 2) . DIRECTORY_SEPARATOR . substr($dataid, 2, 2) . DIRECTORY_SEPARATOR; } @@ -440,13 +471,12 @@ class Filesystem extends AbstractData * eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/e3570978f9e4aa90.discussion/' * * @access private - * @static * @param string $dataid * @return string */ - private static function _dataid2discussionpath($dataid) + private function _dataid2discussionpath($dataid) { - return self::_dataid2path($dataid) . $dataid . + return $this->_dataid2path($dataid) . $dataid . '.discussion' . DIRECTORY_SEPARATOR; } @@ -454,25 +484,23 @@ class Filesystem extends AbstractData * Check that the given element is a valid first level directory. * * @access private - * @static * @param string $element * @return bool */ - private static function _isFirstLevelDir($element) + private function _isFirstLevelDir($element) { - return self::_isSecondLevelDir($element) && - is_dir(self::$_path . DIRECTORY_SEPARATOR . $element); + return $this->_isSecondLevelDir($element) && + is_dir($this->_path . DIRECTORY_SEPARATOR . $element); } /** * Check that the given element is a valid second level directory. * * @access private - * @static * @param string $element * @return bool */ - private static function _isSecondLevelDir($element) + private function _isSecondLevelDir($element) { return (bool) preg_match('/^[a-f0-9]{2}$/', $element); } @@ -481,15 +509,14 @@ class Filesystem extends AbstractData * store the data * * @access public - * @static * @param string $filename * @param array $data * @return bool */ - private static function _store($filename, array $data) + private function _store($filename, array $data) { try { - return self::_storeString( + return $this->_storeString( $filename, self::PROTECTION_LINE . PHP_EOL . Json::encode($data) ); @@ -502,20 +529,19 @@ class Filesystem extends AbstractData * store a string * * @access public - * @static * @param string $filename * @param string $data * @return bool */ - private static function _storeString($filename, $data) + private function _storeString($filename, $data) { // Create storage directory if it does not exist. - if (!is_dir(self::$_path)) { - if (!@mkdir(self::$_path, 0700)) { + if (!is_dir($this->_path)) { + if (!@mkdir($this->_path, 0700)) { return false; } } - $file = self::$_path . DIRECTORY_SEPARATOR . '.htaccess'; + $file = $this->_path . DIRECTORY_SEPARATOR . '.htaccess'; if (!is_file($file)) { $writtenBytes = 0; if ($fileCreated = @touch($file)) { @@ -553,12 +579,11 @@ class Filesystem extends AbstractData * rename a file, prepending the protection line at the beginning * * @access public - * @static * @param string $srcFile * @param string $destFile * @return void */ - private static function _prependRename($srcFile, $destFile) + private function _prependRename($srcFile, $destFile) { // don't overwrite already converted file if (!is_readable($destFile)) { diff --git a/lib/Data/GoogleCloudStorage.php b/lib/Data/GoogleCloudStorage.php index e8763258..e271e2f8 100644 --- a/lib/Data/GoogleCloudStorage.php +++ b/lib/Data/GoogleCloudStorage.php @@ -14,54 +14,43 @@ class GoogleCloudStorage extends AbstractData * GCS client * * @access private - * @static * @var StorageClient */ - private static $_client = null; + private $_client = null; /** * GCS bucket * * @access private - * @static * @var Bucket */ - private static $_bucket = null; + private $_bucket = null; /** * object prefix * * @access private - * @static * @var string */ - private static $_prefix = 'pastes'; + private $_prefix = 'pastes'; /** * bucket acl type * * @access private - * @static * @var bool */ - private static $_uniformacl = false; + private $_uniformacl = false; /** - * returns a Google Cloud Storage data backend. + * instantiantes a new Google Cloud Storage data backend. * * @access public - * @static * @param array $options - * @return GoogleCloudStorage + * @return */ - public static function getInstance(array $options) + public function __construct(array $options) { - // if needed initialize the singleton - if (!(self::$_instance instanceof self)) { - self::$_instance = new self; - } - - $bucket = null; if (getenv('PRIVATEBIN_GCS_BUCKET')) { $bucket = getenv('PRIVATEBIN_GCS_BUCKET'); } @@ -69,24 +58,20 @@ class GoogleCloudStorage extends AbstractData $bucket = $options['bucket']; } if (is_array($options) && array_key_exists('prefix', $options)) { - self::$_prefix = $options['prefix']; + $this->_prefix = $options['prefix']; } if (is_array($options) && array_key_exists('uniformacl', $options)) { - self::$_uniformacl = $options['uniformacl']; + $this->_uniformacl = $options['uniformacl']; } - if (empty(self::$_client)) { - self::$_client = class_exists('StorageClientStub', false) ? - new \StorageClientStub(array()) : - new StorageClient(array('suppressKeyFileNotice' => true)); - } - self::$_bucket = self::$_client->bucket($bucket); - - return self::$_instance; + $this->_client = class_exists('StorageClientStub', false) ? + new \StorageClientStub(array()) : + new StorageClient(array('suppressKeyFileNotice' => true)); + $this->_bucket = $this->_client->bucket($bucket); } /** - * returns the google storage object key for $pasteid in self::$_bucket. + * returns the google storage object key for $pasteid in $this->_bucket. * * @access private * @param $pasteid string to get the key for @@ -94,14 +79,14 @@ class GoogleCloudStorage extends AbstractData */ private function _getKey($pasteid) { - if (self::$_prefix != '') { - return self::$_prefix . '/' . $pasteid; + if ($this->_prefix != '') { + return $this->_prefix . '/' . $pasteid; } return $pasteid; } /** - * Uploads the payload in the self::$_bucket under the specified key. + * Uploads the payload in the $this->_bucket under the specified key. * The entire payload is stored as a JSON document. The metadata is replicated * as the GCS object's metadata except for the fields attachment, attachmentname * and salt. @@ -126,12 +111,12 @@ class GoogleCloudStorage extends AbstractData 'metadata' => $metadata, ), ); - if (!self::$_uniformacl) { + if (!$this->_uniformacl) { $data['predefinedAcl'] = 'private'; } - self::$_bucket->upload(Json::encode($payload), $data); + $this->_bucket->upload(Json::encode($payload), $data); } catch (Exception $e) { - error_log('failed to upload ' . $key . ' to ' . self::$_bucket->name() . ', ' . + error_log('failed to upload ' . $key . ' to ' . $this->_bucket->name() . ', ' . trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); return false; } @@ -156,13 +141,13 @@ class GoogleCloudStorage extends AbstractData public function read($pasteid) { try { - $o = self::$_bucket->object($this->_getKey($pasteid)); + $o = $this->_bucket->object($this->_getKey($pasteid)); $data = $o->downloadAsString(); return Json::decode($data); } catch (NotFoundException $e) { return false; } catch (Exception $e) { - error_log('failed to read ' . $pasteid . ' from ' . self::$_bucket->name() . ', ' . + error_log('failed to read ' . $pasteid . ' from ' . $this->_bucket->name() . ', ' . trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); return false; } @@ -176,9 +161,9 @@ class GoogleCloudStorage extends AbstractData $name = $this->_getKey($pasteid); try { - foreach (self::$_bucket->objects(array('prefix' => $name . '/discussion/')) as $comment) { + foreach ($this->_bucket->objects(array('prefix' => $name . '/discussion/')) as $comment) { try { - self::$_bucket->object($comment->name())->delete(); + $this->_bucket->object($comment->name())->delete(); } catch (NotFoundException $e) { // ignore if already deleted. } @@ -188,7 +173,7 @@ class GoogleCloudStorage extends AbstractData } try { - self::$_bucket->object($name)->delete(); + $this->_bucket->object($name)->delete(); } catch (NotFoundException $e) { // ignore if already deleted } @@ -199,7 +184,7 @@ class GoogleCloudStorage extends AbstractData */ public function exists($pasteid) { - $o = self::$_bucket->object($this->_getKey($pasteid)); + $o = $this->_bucket->object($this->_getKey($pasteid)); return $o->exists(); } @@ -223,8 +208,8 @@ class GoogleCloudStorage extends AbstractData $comments = array(); $prefix = $this->_getKey($pasteid) . '/discussion/'; try { - foreach (self::$_bucket->objects(array('prefix' => $prefix)) as $key) { - $comment = JSON::decode(self::$_bucket->object($key->name())->downloadAsString()); + foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $key) { + $comment = JSON::decode($this->_bucket->object($key->name())->downloadAsString()); $comment['id'] = basename($key->name()); $slot = $this->getOpenSlot($comments, (int) $comment['meta']['created']); $comments[$slot] = $comment; @@ -241,7 +226,7 @@ class GoogleCloudStorage extends AbstractData public function existsComment($pasteid, $parentid, $commentid) { $name = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid; - $o = self::$_bucket->object($name); + $o = $this->_bucket->object($name); return $o->exists(); } @@ -252,7 +237,7 @@ class GoogleCloudStorage extends AbstractData { $path = 'config/' . $namespace; try { - foreach (self::$_bucket->objects(array('prefix' => $path)) as $object) { + foreach ($this->_bucket->objects(array('prefix' => $path)) as $object) { $name = $object->name(); if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') { continue; @@ -300,12 +285,12 @@ class GoogleCloudStorage extends AbstractData 'metadata' => $metadata, ), ); - if (!self::$_uniformacl) { + if (!$this->_uniformacl) { $data['predefinedAcl'] = 'private'; } - self::$_bucket->upload($value, $data); + $this->_bucket->upload($value, $data); } catch (Exception $e) { - error_log('failed to set key ' . $key . ' to ' . self::$_bucket->name() . ', ' . + error_log('failed to set key ' . $key . ' to ' . $this->_bucket->name() . ', ' . trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); return false; } @@ -323,7 +308,7 @@ class GoogleCloudStorage extends AbstractData $key = 'config/' . $namespace . '/' . $key; } try { - $o = self::$_bucket->object($key); + $o = $this->_bucket->object($key); return $o->downloadAsString(); } catch (NotFoundException $e) { return ''; @@ -338,12 +323,12 @@ class GoogleCloudStorage extends AbstractData $expired = array(); $now = time(); - $prefix = self::$_prefix; + $prefix = $this->_prefix; if ($prefix != '') { $prefix .= '/'; } try { - foreach (self::$_bucket->objects(array('prefix' => $prefix)) as $object) { + foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $object) { $metadata = $object->info()['metadata']; if ($metadata != null && array_key_exists('expire_date', $metadata)) { $expire_at = intval($metadata['expire_date']); @@ -361,4 +346,28 @@ class GoogleCloudStorage extends AbstractData } return $expired; } + + /** + * @inheritDoc + */ + public function getAllPastes() + { + $pastes = array(); + $prefix = $this->_prefix; + if ($prefix != '') { + $prefix .= '/'; + } + + try { + foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $object) { + $candidate = substr($object->name(), strlen($prefix)); + if (strpos($candidate, "/") === false) { + $pastes[] = $candidate; + } + } + } catch (NotFoundException $e) { + // no objects in the bucket yet + } + return $pastes; + } } diff --git a/lib/Data/S3Storage.php b/lib/Data/S3Storage.php index d741e099..c59aaaeb 100644 --- a/lib/Data/S3Storage.php +++ b/lib/Data/S3Storage.php @@ -45,86 +45,71 @@ class S3Storage extends AbstractData * S3 client * * @access private - * @static * @var S3Client */ - private static $_client = null; + private $_client = null; /** * S3 client options * * @access private - * @static * @var array */ - private static $_options = array(); + private $_options = array(); /** * S3 bucket * * @access private - * @static * @var string */ - private static $_bucket = null; + private $_bucket = null; /** * S3 prefix for all PrivateBin data in this bucket * * @access private - * @static * @var string */ - private static $_prefix = ''; + private $_prefix = ''; /** - * returns an S3 data backend. + * instantiates a new S3 data backend. * * @access public - * @static * @param array $options - * @return S3Storage + * @return */ - public static function getInstance(array $options) + public function __construct(array $options) { - // if needed initialize the singleton - if (!(self::$_instance instanceof self)) { - self::$_instance = new self; - } - - self::$_options = array(); - self::$_options['credentials'] = array(); + $this->_options['credentials'] = array(); if (is_array($options) && array_key_exists('region', $options)) { - self::$_options['region'] = $options['region']; + $this->_options['region'] = $options['region']; } if (is_array($options) && array_key_exists('version', $options)) { - self::$_options['version'] = $options['version']; + $this->_options['version'] = $options['version']; } if (is_array($options) && array_key_exists('endpoint', $options)) { - self::$_options['endpoint'] = $options['endpoint']; + $this->_options['endpoint'] = $options['endpoint']; } if (is_array($options) && array_key_exists('accesskey', $options)) { - self::$_options['credentials']['key'] = $options['accesskey']; + $this->_options['credentials']['key'] = $options['accesskey']; } if (is_array($options) && array_key_exists('secretkey', $options)) { - self::$_options['credentials']['secret'] = $options['secretkey']; + $this->_options['credentials']['secret'] = $options['secretkey']; } if (is_array($options) && array_key_exists('use_path_style_endpoint', $options)) { - self::$_options['use_path_style_endpoint'] = filter_var($options['use_path_style_endpoint'], FILTER_VALIDATE_BOOLEAN); + $this->_options['use_path_style_endpoint'] = filter_var($options['use_path_style_endpoint'], FILTER_VALIDATE_BOOLEAN); } if (is_array($options) && array_key_exists('bucket', $options)) { - self::$_bucket = $options['bucket']; + $this->_bucket = $options['bucket']; } if (is_array($options) && array_key_exists('prefix', $options)) { - self::$_prefix = $options['prefix']; + $this->_prefix = $options['prefix']; } - if (empty(self::$_client)) { - self::$_client = new S3Client(self::$_options); - } - - return self::$_instance; + $this->_client = new S3Client($this->_options); } /** @@ -138,12 +123,12 @@ class S3Storage extends AbstractData { $allObjects = array(); $options = array( - 'Bucket' => self::$_bucket, + 'Bucket' => $this->_bucket, 'Prefix' => $prefix, ); do { - $objectsListResponse = self::$_client->listObjects($options); + $objectsListResponse = $this->_client->listObjects($options); $objects = $objectsListResponse['Contents'] ?? array(); foreach ($objects as $object) { $allObjects[] = $object; @@ -155,7 +140,7 @@ class S3Storage extends AbstractData } /** - * returns the S3 storage object key for $pasteid in self::$_bucket. + * returns the S3 storage object key for $pasteid in $this->_bucket. * * @access private * @param $pasteid string to get the key for @@ -163,14 +148,14 @@ class S3Storage extends AbstractData */ private function _getKey($pasteid) { - if (self::$_prefix != '') { - return self::$_prefix . '/' . $pasteid; + if ($this->_prefix != '') { + return $this->_prefix . '/' . $pasteid; } return $pasteid; } /** - * Uploads the payload in the self::$_bucket under the specified key. + * Uploads the payload in the $this->_bucket under the specified key. * The entire payload is stored as a JSON document. The metadata is replicated * as the S3 object's metadata except for the fields attachment, attachmentname * and salt. @@ -187,15 +172,15 @@ class S3Storage extends AbstractData $metadata[$k] = strval($v); } try { - self::$_client->putObject(array( - 'Bucket' => self::$_bucket, + $this->_client->putObject(array( + 'Bucket' => $this->_bucket, 'Key' => $key, 'Body' => Json::encode($payload), 'ContentType' => 'application/json', 'Metadata' => $metadata, )); } catch (S3Exception $e) { - error_log('failed to upload ' . $key . ' to ' . self::$_bucket . ', ' . + error_log('failed to upload ' . $key . ' to ' . $this->_bucket . ', ' . trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); return false; } @@ -220,14 +205,14 @@ class S3Storage extends AbstractData public function read($pasteid) { try { - $object = self::$_client->getObject(array( - 'Bucket' => self::$_bucket, + $object = $this->_client->getObject(array( + 'Bucket' => $this->_bucket, 'Key' => $this->_getKey($pasteid), )); $data = $object['Body']->getContents(); return Json::decode($data); } catch (S3Exception $e) { - error_log('failed to read ' . $pasteid . ' from ' . self::$_bucket . ', ' . + error_log('failed to read ' . $pasteid . ' from ' . $this->_bucket . ', ' . trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); return false; } @@ -244,8 +229,8 @@ class S3Storage extends AbstractData $comments = $this->_listAllObjects($name . '/discussion/'); foreach ($comments as $comment) { try { - self::$_client->deleteObject(array( - 'Bucket' => self::$_bucket, + $this->_client->deleteObject(array( + 'Bucket' => $this->_bucket, 'Key' => $comment['Key'], )); } catch (S3Exception $e) { @@ -257,8 +242,8 @@ class S3Storage extends AbstractData } try { - self::$_client->deleteObject(array( - 'Bucket' => self::$_bucket, + $this->_client->deleteObject(array( + 'Bucket' => $this->_bucket, 'Key' => $name, )); } catch (S3Exception $e) { @@ -271,7 +256,7 @@ class S3Storage extends AbstractData */ public function exists($pasteid) { - return self::$_client->doesObjectExistV2(self::$_bucket, $this->_getKey($pasteid)); + return $this->_client->doesObjectExistV2($this->_bucket, $this->_getKey($pasteid)); } /** @@ -296,8 +281,8 @@ class S3Storage extends AbstractData try { $entries = $this->_listAllObjects($prefix); foreach ($entries as $entry) { - $object = self::$_client->getObject(array( - 'Bucket' => self::$_bucket, + $object = $this->_client->getObject(array( + 'Bucket' => $this->_bucket, 'Key' => $entry['Key'], )); $body = JSON::decode($object['Body']->getContents()); @@ -319,7 +304,7 @@ class S3Storage extends AbstractData public function existsComment($pasteid, $parentid, $commentid) { $name = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid; - return self::$_client->doesObjectExistV2(self::$_bucket, $name); + return $this->_client->doesObjectExistV2($this->_bucket, $name); } /** @@ -327,7 +312,7 @@ class S3Storage extends AbstractData */ public function purgeValues($namespace, $time) { - $path = self::$_prefix; + $path = $this->_prefix; if ($path != '') { $path .= '/'; } @@ -339,16 +324,16 @@ class S3Storage extends AbstractData if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') { continue; } - $head = self::$_client->headObject(array( - 'Bucket' => self::$_bucket, + $head = $this->_client->headObject(array( + 'Bucket' => $this->_bucket, 'Key' => $name, )); - if (array_key_exists('Metadata', $head) && array_key_exists('value', $head['Metadata'])) { - $value = $head['Metadata']['value']; + if ($head->get('Metadata') != null && array_key_exists('value', $head->get('Metadata'))) { + $value = $head->get('Metadata')['value']; if (is_numeric($value) && intval($value) < $time) { try { - self::$_client->deleteObject(array( - 'Bucket' => self::$_bucket, + $this->_client->deleteObject(array( + 'Bucket' => $this->_bucket, 'Key' => $name, )); } catch (S3Exception $e) { @@ -369,7 +354,7 @@ class S3Storage extends AbstractData */ public function setValue($value, $namespace, $key = '') { - $prefix = self::$_prefix; + $prefix = $this->_prefix; if ($prefix != '') { $prefix .= '/'; } @@ -385,15 +370,15 @@ class S3Storage extends AbstractData $metadata['value'] = strval($value); } try { - self::$_client->putObject(array( - 'Bucket' => self::$_bucket, + $this->_client->putObject(array( + 'Bucket' => $this->_bucket, 'Key' => $key, 'Body' => $value, 'ContentType' => 'application/json', 'Metadata' => $metadata, )); } catch (S3Exception $e) { - error_log('failed to set key ' . $key . ' to ' . self::$_bucket . ', ' . + error_log('failed to set key ' . $key . ' to ' . $this->_bucket . ', ' . trim(preg_replace('/\s\s+/', ' ', $e->getMessage()))); return false; } @@ -405,7 +390,7 @@ class S3Storage extends AbstractData */ public function getValue($namespace, $key = '') { - $prefix = self::$_prefix; + $prefix = $this->_prefix; if ($prefix != '') { $prefix .= '/'; } @@ -417,8 +402,8 @@ class S3Storage extends AbstractData } try { - $object = self::$_client->getObject(array( - 'Bucket' => self::$_bucket, + $object = $this->_client->getObject(array( + 'Bucket' => $this->_bucket, 'Key' => $key, )); return $object['Body']->getContents(); @@ -434,19 +419,19 @@ class S3Storage extends AbstractData { $expired = array(); $now = time(); - $prefix = self::$_prefix; + $prefix = $this->_prefix; if ($prefix != '') { $prefix .= '/'; } try { foreach ($this->_listAllObjects($prefix) as $object) { - $head = self::$_client->headObject(array( - 'Bucket' => self::$_bucket, + $head = $this->_client->headObject(array( + 'Bucket' => $this->_bucket, 'Key' => $object['Key'], )); - if (array_key_exists('Metadata', $head) && array_key_exists('expire_date', $head['Metadata'])) { - $expire_at = intval($head['Metadata']['expire_date']); + if ($head->get('Metadata') != null && array_key_exists('expire_date', $head->get('Metadata'))) { + $expire_at = intval($head->get('Metadata')['expire_date']); if ($expire_at != 0 && $expire_at < $now) { array_push($expired, $object['Key']); } @@ -461,4 +446,28 @@ class S3Storage extends AbstractData } return $expired; } + + /** + * @inheritDoc + */ + public function getAllPastes() + { + $pastes = array(); + $prefix = $this->_prefix; + if ($prefix != '') { + $prefix .= '/'; + } + + try { + foreach ($this->_listAllObjects($prefix) as $object) { + $candidate = substr($object["Key"], strlen($prefix)); + if (strpos($candidate, "/") === false) { + $pastes[] = $candidate; + } + } + } catch (S3Exception $e) { + // no objects in the bucket yet + } + return $pastes; + } } diff --git a/lib/Model.php b/lib/Model.php index 360cf68c..94f77007 100644 --- a/lib/Model.php +++ b/lib/Model.php @@ -81,10 +81,8 @@ class Model public function getStore() { if ($this->_store === null) { - $this->_store = forward_static_call( - 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model') . '::getInstance', - $this->_conf->getSection('model_options') - ); + $class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model'); + $this->_store = new $class($this->_conf->getSection('model_options')); } return $this->_store; } diff --git a/tst/ConfigurationTestGenerator.php b/tst/ConfigurationTestGenerator.php index 945fc479..a0106a3f 100755 --- a/tst/ConfigurationTestGenerator.php +++ b/tst/ConfigurationTestGenerator.php @@ -427,7 +427,7 @@ class ConfigurationCombinationsTest extends PHPUnit_Framework_TestCase /* Setup Routine */ Helper::confBackup(); $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; - $this->_model = Filesystem::getInstance(array('dir' => $this->_path)); + $this->_model = new Filesystem(array('dir' => $this->_path)); $this->reset(); } diff --git a/tst/ControllerTest.php b/tst/ControllerTest.php index e1637c11..698d5f86 100644 --- a/tst/ControllerTest.php +++ b/tst/ControllerTest.php @@ -16,7 +16,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; - $this->_data = Filesystem::getInstance(array('dir' => $this->_path)); + $this->_data = new Filesystem(array('dir' => $this->_path)); ServerSalt::setStore($this->_data); TrafficLimiter::setStore($this->_data); $this->reset(); diff --git a/tst/ControllerWithDbTest.php b/tst/ControllerWithDbTest.php index bc8cd7be..d5bbe534 100644 --- a/tst/ControllerWithDbTest.php +++ b/tst/ControllerWithDbTest.php @@ -25,7 +25,7 @@ class ControllerWithDbTest extends ControllerTest mkdir($this->_path); } $this->_options['dsn'] = 'sqlite:' . $this->_path . DIRECTORY_SEPARATOR . 'tst.sq3'; - $this->_data = Database::getInstance($this->_options); + $this->_data = new Database($this->_options); ServerSalt::setStore($this->_data); TrafficLimiter::setStore($this->_data); $this->reset(); diff --git a/tst/ControllerWithGcsTest.php b/tst/ControllerWithGcsTest.php index 39833417..5490db8d 100644 --- a/tst/ControllerWithGcsTest.php +++ b/tst/ControllerWithGcsTest.php @@ -39,7 +39,7 @@ class ControllerWithGcsTest extends ControllerTest 'bucket' => self::$_bucket->name(), 'prefix' => 'pastes', ); - $this->_data = GoogleCloudStorage::getInstance($this->_options); + $this->_data = new GoogleCloudStorage($this->_options); ServerSalt::setStore($this->_data); TrafficLimiter::setStore($this->_data); $this->reset(); diff --git a/tst/Data/DatabaseTest.php b/tst/Data/DatabaseTest.php index 16e6fcb8..3e65933a 100644 --- a/tst/Data/DatabaseTest.php +++ b/tst/Data/DatabaseTest.php @@ -22,7 +22,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; - $this->_model = Database::getInstance($this->_options); + $this->_model = new Database($this->_options); } public function tearDown() @@ -35,7 +35,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase public function testSaltMigration() { - ServerSalt::setStore(Filesystem::getInstance(array('dir' => 'data'))); + ServerSalt::setStore(new Filesystem(array('dir' => 'data'))); $salt = ServerSalt::get(); $file = 'data' . DIRECTORY_SEPARATOR . 'salt.php'; $this->assertFileExists($file, 'ServerSalt got initialized and stored on disk'); @@ -141,7 +141,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase */ public function testGetIbmInstance() { - Database::getInstance(array( + new Database(array( 'dsn' => 'ibm:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); @@ -152,7 +152,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase */ public function testGetInformixInstance() { - Database::getInstance(array( + new Database(array( 'dsn' => 'informix:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); @@ -163,7 +163,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase */ public function testGetMssqlInstance() { - Database::getInstance(array( + new Database(array( 'dsn' => 'mssql:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); @@ -174,7 +174,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase */ public function testGetMysqlInstance() { - Database::getInstance(array( + new Database(array( 'dsn' => 'mysql:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); @@ -185,7 +185,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase */ public function testGetOciInstance() { - Database::getInstance(array( + new Database(array( 'dsn' => 'oci:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); @@ -196,7 +196,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase */ public function testGetPgsqlInstance() { - Database::getInstance(array( + new Database(array( 'dsn' => 'pgsql:', 'usr' => null, 'pwd' => null, 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), )); @@ -208,7 +208,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase */ public function testGetFooInstance() { - Database::getInstance(array( + new Database(array( 'dsn' => 'foo:', 'usr' => null, 'pwd' => null, 'opt' => null, )); } @@ -221,7 +221,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase { $options = $this->_options; unset($options['dsn']); - Database::getInstance($options); + new Database($options); } /** @@ -232,7 +232,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase { $options = $this->_options; unset($options['usr']); - Database::getInstance($options); + new Database($options); } /** @@ -243,7 +243,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase { $options = $this->_options; unset($options['pwd']); - Database::getInstance($options); + new Database($options); } /** @@ -254,7 +254,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase { $options = $this->_options; unset($options['opt']); - Database::getInstance($options); + new Database($options); } public function testOldAttachments() @@ -266,7 +266,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase } $this->_options['dsn'] = 'sqlite:' . $path; $this->_options['tbl'] = 'bar_'; - $model = Database::getInstance($this->_options); + $model = new Database($this->_options); $original = $paste = Helper::getPasteWithAttachment(1, array('expire_date' => 1344803344)); $meta = $paste['meta']; @@ -311,7 +311,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase } $this->_options['dsn'] = 'sqlite:' . $path; $this->_options['tbl'] = 'baz_'; - $model = Database::getInstance($this->_options); + $model = new Database($this->_options); $paste = Helper::getPaste(1, array('expire_date' => 1344803344)); unset($paste['meta']['formatter'], $paste['meta']['opendiscussion'], $paste['meta']['salt']); $model->delete(Helper::getPasteId()); @@ -378,7 +378,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase 'vizhash BLOB, ' . 'postdate INT );' ); - $this->assertInstanceOf('PrivateBin\\Data\\Database', Database::getInstance($this->_options)); + $this->assertInstanceOf('PrivateBin\\Data\\Database', new Database($this->_options)); // check if version number was upgraded in created configuration table $statement = $db->prepare('SELECT value FROM foo_config WHERE id LIKE ?'); diff --git a/tst/Data/FilesystemTest.php b/tst/Data/FilesystemTest.php index 684c2940..bc9dcd06 100644 --- a/tst/Data/FilesystemTest.php +++ b/tst/Data/FilesystemTest.php @@ -15,7 +15,7 @@ class FilesystemTest extends PHPUnit_Framework_TestCase /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_invalidPath = $this->_path . DIRECTORY_SEPARATOR . 'bar'; - $this->_model = Filesystem::getInstance(array('dir' => $this->_path)); + $this->_model = new Filesystem(array('dir' => $this->_path)); if (!is_dir($this->_path)) { mkdir($this->_path); } diff --git a/tst/Data/GoogleCloudStorageTest.php b/tst/Data/GoogleCloudStorageTest.php index 3b101c40..5f1389a3 100644 --- a/tst/Data/GoogleCloudStorageTest.php +++ b/tst/Data/GoogleCloudStorageTest.php @@ -26,7 +26,7 @@ class GoogleCloudStorageTest extends PHPUnit_Framework_TestCase public function setUp() { ini_set('error_log', stream_get_meta_data(tmpfile())['uri']); - $this->_model = GoogleCloudStorage::getInstance(array( + $this->_model = new GoogleCloudStorage(array( 'bucket' => self::$_bucket->name(), 'prefix' => 'pastes', )); diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index 4ad629ee..3fa0665e 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -18,7 +18,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase if (!is_dir($this->_path)) { mkdir($this->_path); } - $this->_model = Filesystem::getInstance(array('dir' => $this->_path)); + $this->_model = new Filesystem(array('dir' => $this->_path)); ServerSalt::setStore($this->_model); $_POST = array(); diff --git a/tst/ModelTest.php b/tst/ModelTest.php index a88e0296..0d715c2a 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -38,7 +38,7 @@ class ModelTest extends PHPUnit_Framework_TestCase ); Helper::confBackup(); Helper::createIniFile(CONF, $options); - ServerSalt::setStore(Database::getInstance($options['model_options'])); + ServerSalt::setStore(new Database($options['model_options'])); $this->_conf = new Configuration; $this->_model = new Model($this->_conf); $_SERVER['REMOTE_ADDR'] = '::1'; @@ -156,10 +156,10 @@ class ModelTest extends PHPUnit_Framework_TestCase public function testCommentDefaults() { + $class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model'); $comment = new Comment( $this->_conf, - forward_static_call( - 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model') . '::getInstance', + new $class( $this->_conf->getSection('model_options') ) ); @@ -445,7 +445,7 @@ class ModelTest extends PHPUnit_Framework_TestCase public function testPurge() { $conf = new Configuration; - $store = Database::getInstance($conf->getSection('model_options')); + $store = new Database($conf->getSection('model_options')); $store->delete(Helper::getPasteId()); $expired = Helper::getPaste(2, array('expire_date' => 1344803344)); $paste = Helper::getPaste(2, array('expire_date' => time() + 3600)); diff --git a/tst/Persistence/PurgeLimiterTest.php b/tst/Persistence/PurgeLimiterTest.php index adb96ffd..899576fe 100644 --- a/tst/Persistence/PurgeLimiterTest.php +++ b/tst/Persistence/PurgeLimiterTest.php @@ -15,7 +15,7 @@ class PurgeLimiterTest extends PHPUnit_Framework_TestCase mkdir($this->_path); } PurgeLimiter::setStore( - Filesystem::getInstance(array('dir' => $this->_path)) + new Filesystem(array('dir' => $this->_path)) ); } diff --git a/tst/Persistence/ServerSaltTest.php b/tst/Persistence/ServerSaltTest.php index 3db5f7d7..ce4fc681 100644 --- a/tst/Persistence/ServerSaltTest.php +++ b/tst/Persistence/ServerSaltTest.php @@ -21,7 +21,7 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase mkdir($this->_path); } ServerSalt::setStore( - Filesystem::getInstance(array('dir' => $this->_path)) + new Filesystem(array('dir' => $this->_path)) ); $this->_otherPath = $this->_path . DIRECTORY_SEPARATOR . 'foo'; @@ -44,17 +44,17 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase { // generating new salt ServerSalt::setStore( - Filesystem::getInstance(array('dir' => $this->_path)) + new Filesystem(array('dir' => $this->_path)) ); $salt = ServerSalt::get(); // try setting a different path and resetting it ServerSalt::setStore( - Filesystem::getInstance(array('dir' => $this->_otherPath)) + new Filesystem(array('dir' => $this->_otherPath)) ); $this->assertNotEquals($salt, ServerSalt::get()); ServerSalt::setStore( - Filesystem::getInstance(array('dir' => $this->_path)) + new Filesystem(array('dir' => $this->_path)) ); $this->assertEquals($salt, ServerSalt::get()); } @@ -63,7 +63,7 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase { // try setting an invalid path chmod($this->_invalidPath, 0000); - $store = Filesystem::getInstance(array('dir' => $this->_invalidPath)); + $store = new Filesystem(array('dir' => $this->_invalidPath)); ServerSalt::setStore($store); $salt = ServerSalt::get(); ServerSalt::setStore($store); @@ -76,7 +76,7 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase chmod($this->_invalidPath, 0700); file_put_contents($this->_invalidFile, ''); chmod($this->_invalidFile, 0000); - $store = Filesystem::getInstance(array('dir' => $this->_invalidPath)); + $store = new Filesystem(array('dir' => $this->_invalidPath)); ServerSalt::setStore($store); $salt = ServerSalt::get(); ServerSalt::setStore($store); @@ -93,7 +93,7 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase } file_put_contents($this->_invalidPath . DIRECTORY_SEPARATOR . '.htaccess', ''); chmod($this->_invalidPath, 0500); - $store = Filesystem::getInstance(array('dir' => $this->_invalidPath)); + $store = new Filesystem(array('dir' => $this->_invalidPath)); ServerSalt::setStore($store); $salt = ServerSalt::get(); ServerSalt::setStore($store); @@ -105,9 +105,9 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase // try creating an invalid path chmod($this->_invalidPath, 0000); ServerSalt::setStore( - Filesystem::getInstance(array('dir' => $this->_invalidPath . DIRECTORY_SEPARATOR . 'baz')) + new Filesystem(array('dir' => $this->_invalidPath . DIRECTORY_SEPARATOR . 'baz')) ); - $store = Filesystem::getInstance(array('dir' => $this->_invalidPath)); + $store = new Filesystem(array('dir' => $this->_invalidPath)); ServerSalt::setStore($store); $salt = ServerSalt::get(); ServerSalt::setStore($store); diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index 84e0bae8..011b9eeb 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -12,7 +12,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase { /* Setup Routine */ $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'trafficlimit'; - $store = Filesystem::getInstance(array('dir' => $this->_path)); + $store = new Filesystem(array('dir' => $this->_path)); ServerSalt::setStore($store); TrafficLimiter::setStore($store); } diff --git a/tst/Vizhash16x16Test.php b/tst/Vizhash16x16Test.php index abfb8c49..cdc0ad3d 100644 --- a/tst/Vizhash16x16Test.php +++ b/tst/Vizhash16x16Test.php @@ -18,7 +18,7 @@ class Vizhash16x16Test extends PHPUnit_Framework_TestCase mkdir($this->_path); } $this->_file = $this->_path . DIRECTORY_SEPARATOR . 'vizhash.png'; - ServerSalt::setStore(Filesystem::getInstance(array('dir' => $this->_path))); + ServerSalt::setStore(new Filesystem(array('dir' => $this->_path))); } public function tearDown() From bde5802a3aff22c3144277defc5f0a3fed35bab0 Mon Sep 17 00:00:00 2001 From: "Felix J. Ogris" Date: Tue, 1 Nov 2022 16:38:06 +0100 Subject: [PATCH 154/506] syntax fix, changelog --- CHANGELOG.md | 1 + lib/Data/Database.php | 2 +- lib/Data/Filesystem.php | 14 +++++++------- lib/Data/GoogleCloudStorage.php | 4 ++-- lib/Data/S3Storage.php | 8 ++++---- lib/Model.php | 2 +- tst/ModelTest.php | 2 +- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b897b676..61d258c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # PrivateBin version history * **1.4.1 (not yet released)** + * ADDED: script for data storage backend migrations (#1012) * ADDED: Translations for Turkish, Slovak and Greek * ADDED: S3 Storage backend (#994) * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index 05952a95..f4318589 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -481,7 +481,7 @@ class Database extends AbstractData // migrate filesystem based salt into database $file = 'data' . DIRECTORY_SEPARATOR . 'salt.php'; if ($namespace === 'salt' && is_readable($file)) { - $fs = new Filesystem(array('dir' => 'data')); + $fs = new Filesystem(array('dir' => 'data')); $value = $fs->getValue('salt'); $this->setValue($value, 'salt'); @unlink($file); diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index 3dd69578..2d082144 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -409,29 +409,29 @@ class Filesystem extends AbstractData */ public function getAllPastes() { - $pastes = array(); + $pastes = array(); $subdirs = scandir($this->_path); if ($subdirs === false) { - dieerr("Unable to list directory " . $this->_path); + dieerr('Unable to list directory ' . $this->_path); } - $subdirs = preg_grep("/^[^.].$/", $subdirs); + $subdirs = preg_grep('/^[^.].$/', $subdirs); foreach ($subdirs as $subdir) { $subpath = $this->_path . DIRECTORY_SEPARATOR . $subdir; $subsubdirs = scandir($subpath); if ($subsubdirs === false) { - dieerr("Unable to list directory " . $subpath); + dieerr('Unable to list directory ' . $subpath); } - $subsubdirs = preg_grep("/^[^.].$/", $subsubdirs); + $subsubdirs = preg_grep('/^[^.].$/', $subsubdirs); foreach ($subsubdirs as $subsubdir) { $subsubpath = $subpath . DIRECTORY_SEPARATOR . $subsubdir; $files = scandir($subsubpath); if ($files === false) { - dieerr("Unable to list directory " . $subsubpath); + dieerr('Unable to list directory ' . $subsubpath); } - $files = preg_grep("/\.php$/", $files); + $files = preg_grep('/\.php$/', $files); foreach ($files as $file) { if (substr($file, 0, 4) === $subdir . $subsubdir) { diff --git a/lib/Data/GoogleCloudStorage.php b/lib/Data/GoogleCloudStorage.php index e271e2f8..dd2aff39 100644 --- a/lib/Data/GoogleCloudStorage.php +++ b/lib/Data/GoogleCloudStorage.php @@ -353,7 +353,7 @@ class GoogleCloudStorage extends AbstractData public function getAllPastes() { $pastes = array(); - $prefix = $this->_prefix; + $prefix = $this->_prefix; if ($prefix != '') { $prefix .= '/'; } @@ -361,7 +361,7 @@ class GoogleCloudStorage extends AbstractData try { foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $object) { $candidate = substr($object->name(), strlen($prefix)); - if (strpos($candidate, "/") === false) { + if (strpos($candidate, '/') === false) { $pastes[] = $candidate; } } diff --git a/lib/Data/S3Storage.php b/lib/Data/S3Storage.php index c59aaaeb..f2746507 100644 --- a/lib/Data/S3Storage.php +++ b/lib/Data/S3Storage.php @@ -78,7 +78,7 @@ class S3Storage extends AbstractData * * @access public * @param array $options - * @return + * @return */ public function __construct(array $options) { @@ -453,15 +453,15 @@ class S3Storage extends AbstractData public function getAllPastes() { $pastes = array(); - $prefix = $this->_prefix; + $prefix = $this->_prefix; if ($prefix != '') { $prefix .= '/'; } try { foreach ($this->_listAllObjects($prefix) as $object) { - $candidate = substr($object["Key"], strlen($prefix)); - if (strpos($candidate, "/") === false) { + $candidate = substr($object['Key'], strlen($prefix)); + if (strpos($candidate, '/') === false) { $pastes[] = $candidate; } } diff --git a/lib/Model.php b/lib/Model.php index 94f77007..f7fdc232 100644 --- a/lib/Model.php +++ b/lib/Model.php @@ -81,7 +81,7 @@ class Model public function getStore() { if ($this->_store === null) { - $class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model'); + $class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model'); $this->_store = new $class($this->_conf->getSection('model_options')); } return $this->_store; diff --git a/tst/ModelTest.php b/tst/ModelTest.php index 0d715c2a..cf04b4db 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -156,7 +156,7 @@ class ModelTest extends PHPUnit_Framework_TestCase public function testCommentDefaults() { - $class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model'); + $class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model'); $comment = new Comment( $this->_conf, new $class( From 987ead271955935be850b9e4ac2435912cd494f6 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 3 Nov 2022 07:47:50 +0100 Subject: [PATCH 155/506] ensure the basepath ends in a slash, if one is set --- lib/Configuration.php | 8 ++++++++ tst/JsonApiTest.php | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index 6f3a8225..5588791a 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -236,6 +236,14 @@ class Configuration if (!array_key_exists($this->_configuration['expire']['default'], $this->_configuration['expire_options'])) { $this->_configuration['expire']['default'] = key($this->_configuration['expire_options']); } + + // ensure the basepath ends in a slash, if one is set + if ( + strlen($this->_configuration['main']['basepath']) && + substr_compare($this->_configuration['main']['basepath'], '/', -1) !== 0 + ) { + $this->_configuration['main']['basepath'] .= '/'; + } } /** diff --git a/tst/JsonApiTest.php b/tst/JsonApiTest.php index 5c508439..61a2870d 100644 --- a/tst/JsonApiTest.php +++ b/tst/JsonApiTest.php @@ -272,7 +272,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase { $mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json'; $options = parse_ini_file(CONF, true); - $options['main']['basepath'] = 'https://example.com/path/'; + $options['main']['basepath'] = 'https://example.com/path'; // missing slash gets added by Configuration constructor $options['main']['urlshortener'] = 'https://example.com/path/shortenviayourls?link='; $options['yourls']['apiurl'] = $mock_yourls_service; Helper::createIniFile(CONF, $options); From 726f54ce9e0476cbf3c82e0a29ca13ab432e0b7e Mon Sep 17 00:00:00 2001 From: "Felix J. Ogris" Date: Fri, 4 Nov 2022 20:19:41 +0100 Subject: [PATCH 156/506] typos --- lib/Data/AbstractData.php | 2 +- lib/Data/Database.php | 13 +++---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/Data/AbstractData.php b/lib/Data/AbstractData.php index eddab09b..b28fd539 100644 --- a/lib/Data/AbstractData.php +++ b/lib/Data/AbstractData.php @@ -108,7 +108,7 @@ abstract class AbstractData if ($namespace === 'traffic_limiter') { foreach ($this->_last_cache as $key => $last_submission) { if ($last_submission <= $time) { - unset($thi->_last_cache[$key]); + unset($this->_last_cache[$key]); } } } diff --git a/lib/Data/Database.php b/lib/Data/Database.php index f4318589..5502573c 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -530,16 +530,9 @@ class Database extends AbstractData */ public function getAllPastes() { - $pastes = array(); - $rows = $this->_select( - 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '"', - array() - ); - if (is_array($rows) && count($rows)) { - foreach ($rows as $row) { - $pastes[] = $row['dataid']; - } - } + $pastes = $this->_db->_query( + 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '"' + )->fetchAll(PDO::FETCH_COLUMN, 0); return $pastes; } From 3d485ecd7f9dbc508aa1bc072fb7b0a403f0f38c Mon Sep 17 00:00:00 2001 From: "Felix J. Ogris" Date: Fri, 4 Nov 2022 21:04:18 +0100 Subject: [PATCH 157/506] let GCS backends talk to the same "storage account" during testing --- tst/Bootstrap.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tst/Bootstrap.php b/tst/Bootstrap.php index 5b6012f0..f3b77870 100644 --- a/tst/Bootstrap.php +++ b/tst/Bootstrap.php @@ -34,7 +34,7 @@ class StorageClientStub extends StorageClient { private $_config = null; private $_connection = null; - private $_buckets = array(); + private static $_buckets = array(); public function __construct(array $config = array()) { @@ -44,11 +44,11 @@ class StorageClientStub extends StorageClient public function bucket($name, $userProject = false) { - if (!key_exists($name, $this->_buckets)) { + if (!key_exists($name, self::$_buckets)) { $b = new BucketStub($this->_connection, $name, array(), $this); - $this->_buckets[$name] = $b; + self::$_buckets[$name] = $b; } - return $this->_buckets[$name]; + return self::$_buckets[$name]; } /** @@ -56,8 +56,8 @@ class StorageClientStub extends StorageClient */ public function deleteBucket($name) { - if (key_exists($name, $this->_buckets)) { - unset($this->_buckets[$name]); + if (key_exists($name, self::$_buckets)) { + unset(self::$_buckets[$name]); } else { throw new NotFoundException(); } @@ -110,11 +110,11 @@ class StorageClientStub extends StorageClient public function createBucket($name, array $options = array()) { - if (key_exists($name, $this->_buckets)) { + if (key_exists($name, self::$_buckets)) { throw new BadRequestException('already exists'); } $b = new BucketStub($this->_connection, $name, array(), $this); - $this->_buckets[$name] = $b; + self::$_buckets[$name] = $b; return $b; } } From 604c9318751f71a4922b7afcd98eaf277974170b Mon Sep 17 00:00:00 2001 From: "Felix J. Ogris" Date: Fri, 4 Nov 2022 21:19:47 +0100 Subject: [PATCH 158/506] remove cache from database backend --- lib/Data/Database.php | 90 ++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 57 deletions(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index 5502573c..3aaac84d 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -25,13 +25,6 @@ use PrivateBin\Json; */ class Database extends AbstractData { - /** - * cache for select queries - * - * @var array - */ - private $_cache = array(); - /** * instance of database connection * @@ -149,16 +142,6 @@ class Database extends AbstractData */ public function create($pasteid, array $paste) { - if ( - array_key_exists($pasteid, $this->_cache) - ) { - if (false !== $this->_cache[$pasteid]) { - return false; - } else { - unset($this->_cache[$pasteid]); - } - } - $expire_date = 0; $opendiscussion = $burnafterreading = false; $attachment = $attachmentname = null; @@ -222,64 +205,59 @@ class Database extends AbstractData */ public function read($pasteid) { - if (array_key_exists($pasteid, $this->_cache)) { - return $this->_cache[$pasteid]; - } - - $this->_cache[$pasteid] = false; try { - $paste = $this->_select( + $row = $this->_select( 'SELECT * FROM "' . $this->_sanitizeIdentifier('paste') . '" WHERE "dataid" = ?', array($pasteid), true ); } catch (Exception $e) { - $paste = false; + $row = false; } - if ($paste === false) { + if ($row === false) { return false; } // create array - $data = Json::decode($paste['data']); + $data = Json::decode($row['data']); $isVersion2 = array_key_exists('v', $data) && $data['v'] >= 2; if ($isVersion2) { - $this->_cache[$pasteid] = $data; - list($createdKey) = $this->_getVersionedKeys(2); + $paste = $data; + list($createdKey) = $this->_getVersionedKeys(2); } else { - $this->_cache[$pasteid] = array('data' => $paste['data']); - list($createdKey) = $this->_getVersionedKeys(1); + $paste = array('data' => $row['data']); + list($createdKey) = $this->_getVersionedKeys(1); } try { - $paste['meta'] = Json::decode($paste['meta']); + $row['meta'] = Json::decode($row['meta']); } catch (Exception $e) { - $paste['meta'] = array(); + $row['meta'] = array(); } - $paste = self::upgradePreV1Format($paste); - $this->_cache[$pasteid]['meta'] = $paste['meta']; - $this->_cache[$pasteid]['meta'][$createdKey] = (int) $paste['postdate']; - $expire_date = (int) $paste['expiredate']; + $row = self::upgradePreV1Format($row); + $paste['meta'] = $row['meta']; + $paste['meta'][$createdKey] = (int) $row['postdate']; + $expire_date = (int) $row['expiredate']; if ($expire_date > 0) { - $this->_cache[$pasteid]['meta']['expire_date'] = $expire_date; + $paste['meta']['expire_date'] = $expire_date; } if ($isVersion2) { - return $this->_cache[$pasteid]; + return $paste; } // support v1 attachments - if (array_key_exists('attachment', $paste) && !empty($paste['attachment'])) { - $this->_cache[$pasteid]['attachment'] = $paste['attachment']; - if (array_key_exists('attachmentname', $paste) && !empty($paste['attachmentname'])) { - $this->_cache[$pasteid]['attachmentname'] = $paste['attachmentname']; + if (array_key_exists('attachment', $row) && !empty($row['attachment'])) { + $paste['attachment'] = $row['attachment']; + if (array_key_exists('attachmentname', $row) && !empty($row['attachmentname'])) { + $paste['attachmentname'] = $row['attachmentname']; } } - if ($paste['opendiscussion']) { - $this->_cache[$pasteid]['meta']['opendiscussion'] = true; + if ($row['opendiscussion']) { + $paste['meta']['opendiscussion'] = true; } - if ($paste['burnafterreading']) { - $this->_cache[$pasteid]['meta']['burnafterreading'] = true; + if ($row['burnafterreading']) { + $paste['meta']['burnafterreading'] = true; } - return $this->_cache[$pasteid]; + return $paste; } /** @@ -298,11 +276,6 @@ class Database extends AbstractData 'DELETE FROM "' . $this->_sanitizeIdentifier('comment') . '" WHERE "pasteid" = ?', array($pasteid) ); - if ( - array_key_exists($pasteid, $this->_cache) - ) { - unset($this->_cache[$pasteid]); - } } /** @@ -314,12 +287,15 @@ class Database extends AbstractData */ public function exists($pasteid) { - if ( - !array_key_exists($pasteid, $this->_cache) - ) { - $this->_cache[$pasteid] = $this->read($pasteid); + try { + $row = $this->_select( + 'SELECT * FROM "' . $this->_sanitizeIdentifier('paste') . + '" WHERE "dataid" = ?', array($pasteid), true + ); + } catch (Exception $e) { + $row = false; } - return (bool) $this->_cache[$pasteid]; + return (bool) $row; } /** From 75d28ef423e77b23acb14e0b5c526bcec94a5b90 Mon Sep 17 00:00:00 2001 From: "Felix J. Ogris" Date: Fri, 4 Nov 2022 21:25:53 +0100 Subject: [PATCH 159/506] _sanitizeClob touches no instance variables --- lib/Data/Database.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index 3aaac84d..3771b5d8 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -839,10 +839,11 @@ class Database extends AbstractData * From: https://stackoverflow.com/questions/36200534/pdo-oci-into-a-clob-field * * @access public + * @static * @param int|string|resource $value * @return int|string */ - public function _sanitizeClob($value) + public static function _sanitizeClob($value) { if (is_resource($value)) { $value = stream_get_contents($value); From 10013ad09209c068c69d4222ff05f4a2940d4024 Mon Sep 17 00:00:00 2001 From: "Felix J. Ogris" Date: Fri, 4 Nov 2022 21:27:27 +0100 Subject: [PATCH 160/506] syntax bot --- tst/Bootstrap.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tst/Bootstrap.php b/tst/Bootstrap.php index f3b77870..48a91cb8 100644 --- a/tst/Bootstrap.php +++ b/tst/Bootstrap.php @@ -32,9 +32,9 @@ Helper::updateSubresourceIntegrity(); */ class StorageClientStub extends StorageClient { - private $_config = null; - private $_connection = null; - private static $_buckets = array(); + private $_config = null; + private $_connection = null; + private static $_buckets = array(); public function __construct(array $config = array()) { From 8389c2a2d6f9d8085f5dabdbcb588248e58898f0 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 5 Nov 2022 08:46:42 +0100 Subject: [PATCH 161/506] minor optimization, let the PDO driver do that for us --- lib/Data/Database.php | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index 3771b5d8..e0678994 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -486,19 +486,13 @@ class Database extends AbstractData */ protected function _getExpiredPastes($batchsize) { - $pastes = array(); - $rows = $this->_select( + $statement = $this->_db->prepare( 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '" WHERE "expiredate" < ? AND "expiredate" != ? ' . - ($this->_type === 'oci' ? 'FETCH NEXT ? ROWS ONLY' : 'LIMIT ?'), - array(time(), 0, $batchsize) + ($this->_type === 'oci' ? 'FETCH NEXT ? ROWS ONLY' : 'LIMIT ?') ); - if (is_array($rows) && count($rows)) { - foreach ($rows as $row) { - $pastes[] = $row['dataid']; - } - } - return $pastes; + $statement->execute(array(time(), 0, $batchsize)); + return $statement->fetchAll(PDO::FETCH_COLUMN, 0); } /** @@ -506,10 +500,9 @@ class Database extends AbstractData */ public function getAllPastes() { - $pastes = $this->_db->_query( + return $this->_db->_query( 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '"' )->fetchAll(PDO::FETCH_COLUMN, 0); - return $pastes; } /** From 62bb68344c129d120b02a9d4b1886fd9f865f0c8 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 5 Nov 2022 09:32:30 +0100 Subject: [PATCH 162/506] move all scripts into one location - standardize includes, namings - made migrate executable - updated ConfigurationCombinationsTest generator to work with current persistance API --- .gitattributes | 2 ++ .../configuration-test-generator | 8 ++++++-- tst/IconTest => bin/icon-test | 0 bin/{migrate.php => migrate} | 9 +++++---- tst/phpunit.xml | 1 - 5 files changed, 13 insertions(+), 7 deletions(-) rename tst/ConfigurationTestGenerator.php => bin/configuration-test-generator (98%) rename tst/IconTest => bin/icon-test (100%) rename bin/{migrate.php => migrate} (96%) mode change 100644 => 100755 diff --git a/.gitattributes b/.gitattributes index 60629c04..c01ff779 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,5 @@ +bin/configuration-test-generator export-ignore +bin/icon-test export-ignore doc/ export-ignore tst/ export-ignore img/browserstack.svg export-ignore diff --git a/tst/ConfigurationTestGenerator.php b/bin/configuration-test-generator similarity index 98% rename from tst/ConfigurationTestGenerator.php rename to bin/configuration-test-generator index a0106a3f..432a2295 100755 --- a/tst/ConfigurationTestGenerator.php +++ b/bin/configuration-test-generator @@ -9,7 +9,9 @@ * DANGER: Too many options/settings and too high max iteration setting may trigger * a fork bomb. Please save your work before executing this script. */ -include 'Bootstrap.php'; + +define('PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR); +include PATH . 'tst' . DIRECTORY_SEPARATOR . 'Bootstrap.php'; $vd = array('view', 'delete'); $vcd = array('view', 'create', 'delete'); @@ -392,7 +394,7 @@ class ConfigurationTestGenerator } } $code .= '}' . PHP_EOL; - file_put_contents('ConfigurationCombinationsTest.php', $code); + file_put_contents(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'tst' . DIRECTORY_SEPARATOR . 'ConfigurationCombinationsTest.php', $code); } /** @@ -428,6 +430,8 @@ class ConfigurationCombinationsTest extends PHPUnit_Framework_TestCase Helper::confBackup(); $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_model = new Filesystem(array('dir' => $this->_path)); + ServerSalt::setStore($this->_model); + TrafficLimiter::setStore($this->_model); $this->reset(); } diff --git a/tst/IconTest b/bin/icon-test similarity index 100% rename from tst/IconTest rename to bin/icon-test diff --git a/bin/migrate.php b/bin/migrate old mode 100644 new mode 100755 similarity index 96% rename from bin/migrate.php rename to bin/migrate index 193430e3..4dbe052b --- a/bin/migrate.php +++ b/bin/migrate @@ -1,7 +1,8 @@ +#!/usr/bin/env php ] - php migrate.php [-h] + migrate [--delete-after] [--delete-during] [-f] [-n] [-v] srcconfdir + [] + migrate [-h] Options: --delete-after delete data from source after all pastes and comments have diff --git a/tst/phpunit.xml b/tst/phpunit.xml index caaa67d7..20eb4d5b 100644 --- a/tst/phpunit.xml +++ b/tst/phpunit.xml @@ -1,7 +1,6 @@ ./ - ConfigurationTestGenerator.php From 833cf93209637d4e88530d08db7e8cc932d0549f Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 5 Nov 2022 09:35:06 +0100 Subject: [PATCH 163/506] address Scrutinizer warning > The variable $bucket does not seem to be defined for all execution paths leading up to this point. --- lib/Data/GoogleCloudStorage.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Data/GoogleCloudStorage.php b/lib/Data/GoogleCloudStorage.php index dd2aff39..e07e8182 100644 --- a/lib/Data/GoogleCloudStorage.php +++ b/lib/Data/GoogleCloudStorage.php @@ -67,7 +67,9 @@ class GoogleCloudStorage extends AbstractData $this->_client = class_exists('StorageClientStub', false) ? new \StorageClientStub(array()) : new StorageClient(array('suppressKeyFileNotice' => true)); - $this->_bucket = $this->_client->bucket($bucket); + if (isset($bucket)) { + $this->_bucket = $this->_client->bucket($bucket); + } } /** From 07ad9ad0f4be3cf6647c8ab8945839178321d15d Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 5 Nov 2022 09:37:24 +0100 Subject: [PATCH 164/506] typo, found by Scrutinizer --- lib/Data/Database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index e0678994..d4933b00 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -500,7 +500,7 @@ class Database extends AbstractData */ public function getAllPastes() { - return $this->_db->_query( + return $this->_db->query( 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '"' )->fetchAll(PDO::FETCH_COLUMN, 0); } From 9a1f3aeca505695e54840a1861eceaeddc7bfe11 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 5 Nov 2022 09:44:35 +0100 Subject: [PATCH 165/506] update Jdenticon library --- composer.lock | 418 +++++++----------- vendor/composer/ClassLoader.php | 157 +------ vendor/composer/autoload_classmap.php | 2 +- vendor/composer/autoload_real.php | 15 +- vendor/composer/autoload_static.php | 2 +- .../Rasterization/SuperSampleBuffer.php | 9 + 6 files changed, 196 insertions(+), 407 deletions(-) diff --git a/composer.lock b/composer.lock index 8b17d339..5d13c27b 100644 --- a/composer.lock +++ b/composer.lock @@ -48,11 +48,6 @@ "identicon", "jdenticon" ], - "support": { - "docs": "https://jdenticon.com/php-api.html", - "issues": "https://github.com/dmester/jdenticon-php/issues", - "source": "https://github.com/dmester/jdenticon-php" - }, "time": "2022-10-30T17:15:02+00:00" }, { @@ -110,10 +105,6 @@ "range", "subnet" ], - "support": { - "issues": "https://github.com/mlocati/ip-lib/issues", - "source": "https://github.com/mlocati/ip-lib/tree/1.18.0" - }, "funding": [ { "url": "https://github.com/sponsors/mlocati", @@ -173,11 +164,6 @@ "pseudorandom", "random" ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" - }, "time": "2022-02-16T17:07:03+00:00" }, { @@ -230,10 +216,6 @@ "identicon", "image" ], - "support": { - "issues": "https://github.com/yzalis/Identicon/issues", - "source": "https://github.com/yzalis/Identicon/tree/master" - }, "abandoned": true, "time": "2019-10-14T09:30:57+00:00" } @@ -241,34 +223,32 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1 || ^8.0" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^9", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -282,42 +262,56 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/master" - }, - "time": "2015-06-14T21:17:01+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-03-03T08:28:38+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { @@ -340,43 +334,40 @@ "object", "object graph" ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.x" - }, - "time": "2017-10-19T19:58:43+00:00" + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2022-03-03T13:19:32+00:00" }, { "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", "shasum": "" }, "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-2.x": "2.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -398,94 +389,97 @@ "reflection", "static analysis" ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" - }, - "time": "2017-09-11T18:02:19+00:00" + "time": "2020-06-27T09:03:43+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.3.2", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", - "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/3.x" - }, - "time": "2017-11-10T14:09:06+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2021-10-19T17:43:47+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.6.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d", + "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -498,11 +492,8 @@ "email": "me@mikevanriel.com" } ], - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/master" - }, - "time": "2017-07-14T14:27:02+00:00" + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2022-10-14T12:47:21+00:00" }, { "name": "phpspec/prophecy", @@ -565,10 +556,6 @@ "spy", "stub" ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" - }, "time": "2020-03-05T15:02:03+00:00" }, { @@ -632,11 +619,6 @@ "testing", "xunit" ], - "support": { - "irc": "irc://irc.freenode.net/phpunit", - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/4.0" - }, "time": "2017-04-02T07:44:40+00:00" }, { @@ -684,11 +666,6 @@ "filesystem", "iterator" ], - "support": { - "irc": "irc://irc.freenode.net/phpunit", - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" - }, "time": "2017-11-27T13:52:08+00:00" }, { @@ -730,10 +707,6 @@ "keywords": [ "template" ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" - }, "time": "2015-06-21T13:50:34+00:00" }, { @@ -783,37 +756,33 @@ "keywords": [ "timer" ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/master" - }, "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.12", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" + "reference": "791198a2c6254db10131eecfe8c06670700904db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -836,12 +805,8 @@ "keywords": [ "tokenizer" ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", - "source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4" - }, "abandoned": true, - "time": "2017-12-04T08:55:13+00:00" + "time": "2017-11-27T05:48:46+00:00" }, { "name": "phpunit/phpunit", @@ -923,10 +888,6 @@ "testing", "xunit" ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/5.7.27" - }, "time": "2018-02-01T05:50:59+00:00" }, { @@ -986,11 +947,6 @@ "mock", "xunit" ], - "support": { - "irc": "irc://irc.freenode.net/phpunit", - "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", - "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/3.4" - }, "abandoned": true, "time": "2017-06-30T09:13:00+00:00" }, @@ -1037,10 +993,6 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" - }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1111,10 +1063,6 @@ "compare", "equality" ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/1.2" - }, "time": "2017-01-29T09:50:25+00:00" }, { @@ -1167,10 +1115,6 @@ "keywords": [ "diff" ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/1.4" - }, "time": "2017-05-22T07:24:03+00:00" }, { @@ -1221,10 +1165,6 @@ "environment", "hhvm" ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/master" - }, "time": "2016-11-26T07:53:53+00:00" }, { @@ -1292,10 +1232,6 @@ "export", "exporter" ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/master" - }, "time": "2016-11-19T08:54:04+00:00" }, { @@ -1347,10 +1283,6 @@ "keywords": [ "global state" ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/1.1.1" - }, "time": "2015-10-12T03:26:01+00:00" }, { @@ -1397,10 +1329,6 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/master" - }, "time": "2017-02-18T15:18:39+00:00" }, { @@ -1454,10 +1382,6 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/master" - }, "time": "2016-11-19T07:33:16+00:00" }, { @@ -1500,10 +1424,6 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/master" - }, "time": "2015-07-28T20:34:47+00:00" }, { @@ -1547,28 +1467,27 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/master" - }, "time": "2016-10-03T07:35:21+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.19.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b" + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b", - "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" }, "suggest": { "ext-ctype": "For best performance" @@ -1576,7 +1495,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.19-dev" + "dev-main": "1.26-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1613,9 +1532,6 @@ "polyfill", "portable" ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0" - }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1630,31 +1546,31 @@ "type": "tidelift" } ], - "time": "2020-10-23T09:01:57+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/yaml", - "version": "v3.4.47", + "version": "v4.4.45", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "88289caa3c166321883f67fe5130188ebbb47094" + "reference": "aeccc4dc52a9e634f1d1eebeb21eacfdcff1053d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094", - "reference": "88289caa3c166321883f67fe5130188ebbb47094", + "url": "https://api.github.com/repos/symfony/yaml/zipball/aeccc4dc52a9e634f1d1eebeb21eacfdcff1053d", + "reference": "aeccc4dc52a9e634f1d1eebeb21eacfdcff1053d", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": ">=7.1.3", "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/console": "<3.4" }, "require-dev": { - "symfony/console": "~3.4|~4.0" + "symfony/console": "^3.4|^4.0|^5.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" @@ -1682,11 +1598,8 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Yaml Component", + "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/yaml/tree/v3.4.47" - }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1701,34 +1614,39 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2022-08-02T15:47:23+00:00" }, { "name": "webmozart/assert", - "version": "1.9.1", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", - "symfony/polyfill-ctype": "^1.8" + "ext-ctype": "*", + "php": "^7.2 || ^8.0" }, "conflict": { "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" + "phpunit/phpunit": "^8.5.13" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -1750,11 +1668,7 @@ "check", "validate" ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.9.1" - }, - "time": "2020-07-08T17:02:28+00:00" + "time": "2022-06-03T18:03:27+00:00" } ], "aliases": [], @@ -1766,5 +1680,5 @@ "php": "^5.6.0 || ^7.0 || ^8.0" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "1.1.0" } diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index afef3fa2..fce8549f 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -37,130 +37,57 @@ namespace Composer\Autoload; * * @author Fabien Potencier * @author Jordi Boggiano - * @see https://www.php-fig.org/psr/psr-0/ - * @see https://www.php-fig.org/psr/psr-4/ + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ */ class ClassLoader { - /** @var ?string */ - private $vendorDir; - // PSR-4 - /** - * @var array[] - * @psalm-var array> - */ private $prefixLengthsPsr4 = array(); - /** - * @var array[] - * @psalm-var array> - */ private $prefixDirsPsr4 = array(); - /** - * @var array[] - * @psalm-var array - */ private $fallbackDirsPsr4 = array(); // PSR-0 - /** - * @var array[] - * @psalm-var array> - */ private $prefixesPsr0 = array(); - /** - * @var array[] - * @psalm-var array - */ private $fallbackDirsPsr0 = array(); - /** @var bool */ private $useIncludePath = false; - - /** - * @var string[] - * @psalm-var array - */ private $classMap = array(); - - /** @var bool */ private $classMapAuthoritative = false; - - /** - * @var bool[] - * @psalm-var array - */ private $missingClasses = array(); - - /** @var ?string */ private $apcuPrefix; - /** - * @var self[] - */ - private static $registeredLoaders = array(); - - /** - * @param ?string $vendorDir - */ - public function __construct($vendorDir = null) - { - $this->vendorDir = $vendorDir; - } - - /** - * @return string[] - */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + return call_user_func_array('array_merge', $this->prefixesPsr0); } return array(); } - /** - * @return array[] - * @psalm-return array> - */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } - /** - * @return array[] - * @psalm-return array - */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } - /** - * @return array[] - * @psalm-return array - */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } - /** - * @return string[] Array of classname => path - * @psalm-return array - */ public function getClassMap() { return $this->classMap; } /** - * @param string[] $classMap Class to filename map - * @psalm-param array $classMap - * - * @return void + * @param array $classMap Class to filename map */ public function addClassMap(array $classMap) { @@ -175,11 +102,9 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - * - * @return void + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories */ public function add($prefix, $paths, $prepend = false) { @@ -222,13 +147,11 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException - * - * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -272,10 +195,8 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 base directories - * - * @return void + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories */ public function set($prefix, $paths) { @@ -290,12 +211,10 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException - * - * @return void */ public function setPsr4($prefix, $paths) { @@ -315,8 +234,6 @@ class ClassLoader * Turns on searching the include path for class files. * * @param bool $useIncludePath - * - * @return void */ public function setUseIncludePath($useIncludePath) { @@ -339,8 +256,6 @@ class ClassLoader * that have not been registered with the class map. * * @param bool $classMapAuthoritative - * - * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -361,8 +276,6 @@ class ClassLoader * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix - * - * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -383,44 +296,25 @@ class ClassLoader * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not - * - * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); - - if (null === $this->vendorDir) { - return; - } - - if ($prepend) { - self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; - } else { - unset(self::$registeredLoaders[$this->vendorDir]); - self::$registeredLoaders[$this->vendorDir] = $this; - } } /** * Unregisters this instance as an autoloader. - * - * @return void */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); - - if (null !== $this->vendorDir) { - unset(self::$registeredLoaders[$this->vendorDir]); - } } /** * Loads the given class or interface. * * @param string $class The name of the class - * @return true|null True if loaded, null otherwise + * @return bool|null True if loaded, null otherwise */ public function loadClass($class) { @@ -429,8 +323,6 @@ class ClassLoader return true; } - - return null; } /** @@ -475,21 +367,6 @@ class ClassLoader return $file; } - /** - * Returns the currently registered loaders indexed by their corresponding vendor directories. - * - * @return self[] - */ - public static function getRegisteredLoaders() - { - return self::$registeredLoaders; - } - - /** - * @param string $class - * @param string $ext - * @return string|false - */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -561,10 +438,6 @@ class ClassLoader * Scope isolated include. * * Prevents access to $this/self from included files. - * - * @param string $file - * @return void - * @private */ function includeFile($file) { diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index ef2b6e97..12566b84 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,7 +6,6 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'IPLib\\Address\\AddressInterface' => $vendorDir . '/mlocati/ip-lib/src/Address/AddressInterface.php', 'IPLib\\Address\\AssignedRange' => $vendorDir . '/mlocati/ip-lib/src/Address/AssignedRange.php', 'IPLib\\Address\\IPv4' => $vendorDir . '/mlocati/ip-lib/src/Address/IPv4.php', @@ -53,6 +52,7 @@ return array( 'Jdenticon\\Rendering\\ColorTheme' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/ColorTheme.php', 'Jdenticon\\Rendering\\IconGenerator' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/IconGenerator.php', 'Jdenticon\\Rendering\\ImagickRenderer' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php', + 'Jdenticon\\Rendering\\ImagickRendererLine' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php', 'Jdenticon\\Rendering\\InternalPngRenderer' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php', 'Jdenticon\\Rendering\\Point' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Point.php', 'Jdenticon\\Rendering\\Rectangle' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Rectangle.php', diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 5b03524d..7a6fd4c0 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -22,15 +22,13 @@ class ComposerAutoloaderInitDontChange return self::$loader; } - require __DIR__ . '/platform_check.php'; - spl_autoload_register(array('ComposerAutoloaderInitDontChange', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInitDontChange', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; + require_once __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInitDontChange::getInitializer($loader)); } else { @@ -65,16 +63,11 @@ class ComposerAutoloaderInitDontChange } } -/** - * @param string $fileIdentifier - * @param string $file - * @return void - */ function composerRequireDontChange($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; } } diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index b03812eb..d6b11453 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -46,7 +46,6 @@ class ComposerStaticInitDontChange ); public static $classMap = array ( - 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'IPLib\\Address\\AddressInterface' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AddressInterface.php', 'IPLib\\Address\\AssignedRange' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AssignedRange.php', 'IPLib\\Address\\IPv4' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/IPv4.php', @@ -93,6 +92,7 @@ class ComposerStaticInitDontChange 'Jdenticon\\Rendering\\ColorTheme' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/ColorTheme.php', 'Jdenticon\\Rendering\\IconGenerator' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/IconGenerator.php', 'Jdenticon\\Rendering\\ImagickRenderer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php', + 'Jdenticon\\Rendering\\ImagickRendererLine' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/ImagickRenderer.php', 'Jdenticon\\Rendering\\InternalPngRenderer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php', 'Jdenticon\\Rendering\\Point' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Point.php', 'Jdenticon\\Rendering\\Rectangle' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Rectangle.php', diff --git a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php index 82860e2e..45a611de 100644 --- a/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php +++ b/vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleBuffer.php @@ -21,6 +21,15 @@ class SuperSampleBuffer const IDX_G = 3; const IDX_B = 4; + private $samples; + private $samplesPerPixel; + + private $pixelOffset; + private $subPixelOffset; + + private $width; + private $used; + /** * Creates a color buffer keeping an average color out of several * color samples per pixel. From f4eed668e7d7e0d689957db1b04e33dc7bdfb319 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 5 Nov 2022 10:00:12 +0100 Subject: [PATCH 166/506] seems impacted by removal of cache, let's see if we can adjust the test --- tst/ModelTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tst/ModelTest.php b/tst/ModelTest.php index e693856c..dbbbbc22 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -261,6 +261,9 @@ class ModelTest extends PHPUnit_Framework_TestCase $paste->store(); $paste->exists(); + $comment = $paste->getComment(Helper::getPasteId()); + $comment->setData($commentData); + $db = new PDO( $options['model_options']['dsn'], $options['model_options']['usr'], @@ -271,8 +274,6 @@ class ModelTest extends PHPUnit_Framework_TestCase $statement->execute(); $statement->closeCursor(); - $comment = $paste->getComment(Helper::getPasteId()); - $comment->setData($commentData); $comment->store(); } From 15ce736bc87f335439dfe1c195622531d0ec72b1 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:25:29 +0100 Subject: [PATCH 167/506] New translations en.json (Thai) --- i18n/th.json | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 i18n/th.json diff --git a/i18n/th.json b/i18n/th.json new file mode 100644 index 00000000..a4d6d350 --- /dev/null +++ b/i18n/th.json @@ -0,0 +1,193 @@ +{ + "PrivateBin": "PrivateBin", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.", + "More information on the project page.": "More information on the project page.", + "Because ignorance is bliss": "Because ignorance is bliss", + "en": "en", + "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.", + "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.", + "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", + "Please wait %d seconds between each post.": [ + "Please wait %d second between each post. (singular)", + "Please wait %d seconds between each post. (1st plural)", + "Please wait %d seconds between each post. (2nd plural)", + "Please wait %d seconds between each post. (3rd plural)" + ], + "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", + "Invalid data.": "Invalid data.", + "You are unlucky. Try again.": "You are unlucky. Try again.", + "Error saving comment. Sorry.": "Error saving comment. Sorry.", + "Error saving paste. Sorry.": "Error saving paste. Sorry.", + "Invalid paste ID.": "Invalid paste ID.", + "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", + "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", + "Paste was properly deleted.": "Paste was properly deleted.", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", + "%s requires a modern browser to work.": "%s requires a modern browser to work.", + "New": "New", + "Send": "Send", + "Clone": "Clone", + "Raw text": "Raw text", + "Expires": "Expires", + "Burn after reading": "Burn after reading", + "Open discussion": "Open discussion", + "Password (recommended)": "Password (recommended)", + "Discussion": "Discussion", + "Toggle navigation": "Toggle navigation", + "%d seconds": [ + "%d second (singular)", + "%d seconds (1st plural)", + "%d seconds (2nd plural)", + "%d seconds (3rd plural)" + ], + "%d minutes": [ + "%d minute (singular)", + "%d minutes (1st plural)", + "%d minutes (2nd plural)", + "%d minutes (3rd plural)" + ], + "%d hours": [ + "%d hour (singular)", + "%d hours (1st plural)", + "%d hours (2nd plural)", + "%d hours (3rd plural)" + ], + "%d days": [ + "%d day (singular)", + "%d days (1st plural)", + "%d days (2nd plural)", + "%d days (3rd plural)" + ], + "%d weeks": [ + "%d week (singular)", + "%d weeks (1st plural)", + "%d weeks (2nd plural)", + "%d weeks (3rd plural)" + ], + "%d months": [ + "%d month (singular)", + "%d months (1st plural)", + "%d months (2nd plural)", + "%d months (3rd plural)" + ], + "%d years": [ + "%d year (singular)", + "%d years (1st plural)", + "%d years (2nd plural)", + "%d years (3rd plural)" + ], + "Never": "Never", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "This document will expire in %d seconds.": [ + "This document will expire in %d second. (singular)", + "This document will expire in %d seconds. (1st plural)", + "This document will expire in %d seconds. (2nd plural)", + "This document will expire in %d seconds. (3rd plural)" + ], + "This document will expire in %d minutes.": [ + "This document will expire in %d minute. (singular)", + "This document will expire in %d minutes. (1st plural)", + "This document will expire in %d minutes. (2nd plural)", + "This document will expire in %d minutes. (3rd plural)" + ], + "This document will expire in %d hours.": [ + "This document will expire in %d hour. (singular)", + "This document will expire in %d hours. (1st plural)", + "This document will expire in %d hours. (2nd plural)", + "This document will expire in %d hours. (3rd plural)" + ], + "This document will expire in %d days.": [ + "This document will expire in %d day. (singular)", + "This document will expire in %d days. (1st plural)", + "This document will expire in %d days. (2nd plural)", + "This document will expire in %d days. (3rd plural)" + ], + "This document will expire in %d months.": [ + "This document will expire in %d month. (singular)", + "This document will expire in %d months. (1st plural)", + "This document will expire in %d months. (2nd plural)", + "This document will expire in %d months. (3rd plural)" + ], + "Please enter the password for this paste:": "Please enter the password for this paste:", + "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", + "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", + "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", + "Reply": "Reply", + "Anonymous": "Anonymous", + "Avatar generated from IP address": "Avatar generated from IP address", + "Add comment": "Add comment", + "Optional nickname…": "Optional nickname…", + "Post comment": "Post comment", + "Sending comment…": "Sending comment…", + "Comment posted.": "Comment posted.", + "Could not refresh display: %s": "Could not refresh display: %s", + "unknown status": "unknown status", + "server error or not responding": "server error or not responding", + "Could not post comment: %s": "Could not post comment: %s", + "Sending paste…": "Sending paste…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", + "Delete data": "Delete data", + "Could not create paste: %s": "Could not create paste: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "B": "B", + "KiB": "KiB", + "MiB": "MiB", + "GiB": "GiB", + "TiB": "TiB", + "PiB": "PiB", + "EiB": "EiB", + "ZiB": "ZiB", + "YiB": "YiB", + "Format": "Format", + "Plain Text": "Plain Text", + "Source Code": "Source Code", + "Markdown": "Markdown", + "Download attachment": "Download attachment", + "Cloned: '%s'": "Cloned: '%s'", + "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", + "Attach a file": "Attach a file", + "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", + "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", + "Remove attachment": "Remove attachment", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", + "Invalid attachment.": "Invalid attachment.", + "Options": "Options", + "Shorten URL": "Shorten URL", + "Editor": "Editor", + "Preview": "Preview", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", + "Decrypt": "Decrypt", + "Enter password": "Enter password", + "Loading…": "Loading…", + "Decrypting paste…": "Decrypting paste…", + "Preparing new paste…": "Preparing new paste…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", + "+++ no paste text +++": "+++ no paste text +++", + "Could not get paste data: %s": "Could not get paste data: %s", + "QR code": "QR code", + "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", + "For more information see this FAQ entry.": "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", + "waiting on user to provide a password": "waiting on user to provide a password", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", + "Retry": "Retry", + "Showing raw text…": "Showing raw text…", + "Notice:": "Notice:", + "This link will expire after %s.": "This link will expire after %s.", + "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", + "Link:": "Link:", + "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", + "Use Current Timezone": "Use Current Timezone", + "Convert To UTC": "Convert To UTC", + "Close": "Close", + "Encrypted note on %s": "Encrypted note on %s", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", + "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", + "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", + "Error parsing YOURLS response.": "Error parsing YOURLS response." +} From d46398fc22264e196614f95b88071b29edcee5c5 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sat, 5 Nov 2022 23:30:32 +0100 Subject: [PATCH 168/506] New translations en.json (Thai) --- i18n/th.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/th.json b/i18n/th.json index a4d6d350..1bba8504 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -3,7 +3,7 @@ "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.", "More information on the project page.": "More information on the project page.", "Because ignorance is bliss": "Because ignorance is bliss", - "en": "en", + "en": "th", "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.", "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.", "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", From 3e3d93c9c24ab996a140142d82a35b3d50447d84 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 6 Nov 2022 02:18:55 +0100 Subject: [PATCH 169/506] New translations en.json (Thai) --- i18n/th.json | 306 +++++++++++++++++++++++++-------------------------- 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/i18n/th.json b/i18n/th.json index 1bba8504..35e6209e 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -1,135 +1,135 @@ { "PrivateBin": "PrivateBin", - "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.", - "More information on the project page.": "More information on the project page.", - "Because ignorance is bliss": "Because ignorance is bliss", + "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s เป็น pastebin ออนไลน์แบบโอเพ่นซอร์สที่มีสไตล์แบบมินิมัลลิสท์ เซิร์ฟเวอร์ไม่สามารถรู้ได้ว่าข้อมูลโค้ดที่มาฝากนั้นเป็นข้อมูลอะไร โดยจะถูก %sเข้ารหัส/ถอดรหัส%s ด้วยกระบวนการ AES จำนวน 256 บิตผ่านเบราว์เซอร์", + "More information on the project page.": "ข้อมูลเพิ่มเติมในหน้าโครงการ", + "Because ignorance is bliss": "ไม่รู้ไม่ชี้ดีที่สุด", "en": "th", - "Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.", - "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.", - "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.", + "Paste does not exist, has expired or has been deleted.": "การฝากโค้ดไม่มีอยู่ อาจจะหมดอายุหรือถูกลบไปแล้ว", + "%s requires php %s or above to work. Sorry.": "ขออภัย %s ต้องใช้ PHP %s ขึ้นไปจึงจะใช้งานได้", + "%s requires configuration section [%s] to be present in configuration file.": "%s จำเป็นต้องตั้งค่าตัวแปร [%s] ในไฟล์กำหนดค่า", "Please wait %d seconds between each post.": [ - "Please wait %d second between each post. (singular)", - "Please wait %d seconds between each post. (1st plural)", - "Please wait %d seconds between each post. (2nd plural)", - "Please wait %d seconds between each post. (3rd plural)" + "กรุณาเว้นระยะเวลาการส่งข้อมูลอย่างน้อย %d วินาที", + "กรุณาเว้นระยะเวลาการส่งข้อมูลอย่างน้อย %d วินาที", + "กรุณาเว้นระยะเวลาการส่งข้อมูลอย่างน้อย %d วินาที", + "กรุณาเว้นระยะเวลาการส่งข้อมูลอย่างน้อย %d วินาที" ], - "Paste is limited to %s of encrypted data.": "Paste is limited to %s of encrypted data.", - "Invalid data.": "Invalid data.", - "You are unlucky. Try again.": "You are unlucky. Try again.", - "Error saving comment. Sorry.": "Error saving comment. Sorry.", - "Error saving paste. Sorry.": "Error saving paste. Sorry.", - "Invalid paste ID.": "Invalid paste ID.", - "Paste is not of burn-after-reading type.": "Paste is not of burn-after-reading type.", - "Wrong deletion token. Paste was not deleted.": "Wrong deletion token. Paste was not deleted.", - "Paste was properly deleted.": "Paste was properly deleted.", - "JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript is required for %s to work. Sorry for the inconvenience.", - "%s requires a modern browser to work.": "%s requires a modern browser to work.", - "New": "New", - "Send": "Send", - "Clone": "Clone", - "Raw text": "Raw text", - "Expires": "Expires", - "Burn after reading": "Burn after reading", - "Open discussion": "Open discussion", - "Password (recommended)": "Password (recommended)", - "Discussion": "Discussion", - "Toggle navigation": "Toggle navigation", + "Paste is limited to %s of encrypted data.": "การฝากโค้ดแบบเข้ารหัส ขีดจำกัดสูงสุดคือ %s", + "Invalid data.": "ข้อมูลไม่ถูกต้อง", + "You are unlucky. Try again.": "วันนี้คุณดวงไม่เฮงเลย ลองใหม่อีกครั้งนะ", + "Error saving comment. Sorry.": "ขออภัย เกิดข้อผิดพลาดในระหว่างบันทึกความคิดเห็น", + "Error saving paste. Sorry.": "ขออภัย เกิดข้อผิดพลาดในระหว่างบันทึกการฝากโค้ด", + "Invalid paste ID.": "ID การฝากโค้ดไม่ถูกต้อง", + "Paste is not of burn-after-reading type.": "ข้อมูลการฝากโค้ดนี้ไม่ได้เป็นรูปแบบลบทันทีเมื่อเปิดอ่าน", + "Wrong deletion token. Paste was not deleted.": "โทเค็นการลบไม่ถูกต้อง ข้อมูลการฝากโค้ดไม่ถูกลบ", + "Paste was properly deleted.": "ข้อมูลการฝากโค้ดถูกลบออกเรียบร้อยแล้ว", + "JavaScript is required for %s to work. Sorry for the inconvenience.": "จำเป็นต้องใช้ JavaScript เพื่อให้ %s สามารถทำงานได้ ขออภัยในความไม่สะดวก", + "%s requires a modern browser to work.": "%s ต้องใช้เบราว์เซอร์สมัยใหม่ถึงจะสามารถใช้งานได้", + "New": "ใหม่", + "Send": "ส่ง", + "Clone": "โคลน", + "Raw text": "ข้อความล้วน", + "Expires": "หมดอายุ", + "Burn after reading": "ลบทันทีเมื่อเปิดอ่าน", + "Open discussion": "แสดงความคิดเห็นได้", + "Password (recommended)": "รหัสผ่าน (แนะนำให้ใส่)", + "Discussion": "ความคิดเห็น", + "Toggle navigation": "สลับเปิดปิดการนำทาง", "%d seconds": [ - "%d second (singular)", - "%d seconds (1st plural)", - "%d seconds (2nd plural)", - "%d seconds (3rd plural)" + "%d วินาที", + "%d วินาที", + "%d วินาที", + "%d วินาที" ], "%d minutes": [ - "%d minute (singular)", - "%d minutes (1st plural)", - "%d minutes (2nd plural)", - "%d minutes (3rd plural)" + "%d นาที", + "%d นาที", + "%d นาที", + "%d นาที" ], "%d hours": [ - "%d hour (singular)", - "%d hours (1st plural)", - "%d hours (2nd plural)", - "%d hours (3rd plural)" + "%d ชั่วโมง", + "%d ชั่วโมง", + "%d ชั่วโมง", + "%d ชั่วโมง" ], "%d days": [ - "%d day (singular)", - "%d days (1st plural)", - "%d days (2nd plural)", - "%d days (3rd plural)" + "%d วัน", + "%d วัน", + "%d วัน", + "%d วัน" ], "%d weeks": [ - "%d week (singular)", - "%d weeks (1st plural)", - "%d weeks (2nd plural)", - "%d weeks (3rd plural)" + "%d สัปดาห์", + "%d สัปดาห์", + "%d สัปดาห์", + "%d สัปดาห์" ], "%d months": [ - "%d month (singular)", - "%d months (1st plural)", - "%d months (2nd plural)", - "%d months (3rd plural)" + "%d เดือน", + "%d เดือน", + "%d เดือน", + "%d เดือน" ], "%d years": [ - "%d year (singular)", - "%d years (1st plural)", - "%d years (2nd plural)", - "%d years (3rd plural)" + "%d ปี", + "%d ปี", + "%d ปี", + "%d ปี" ], - "Never": "Never", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "Never": "ไม่หมดอายุ", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "หมายเหตุ: เว็บไซต์นี่เป็นบริการเบต้าและข้อมูลอาจถูกลบได้ตลอดเวลา หากคุณใช้บริการนี้ในทางที่ผิดอาจจะทำให้ข้อมูลของคุณสูญหายอย่างถาวรได้", "This document will expire in %d seconds.": [ - "This document will expire in %d second. (singular)", - "This document will expire in %d seconds. (1st plural)", - "This document will expire in %d seconds. (2nd plural)", - "This document will expire in %d seconds. (3rd plural)" + "เอกสารนี้จะหมดอายุใน %d วินาที", + "เอกสารนี้จะหมดอายุใน %d วินาที", + "เอกสารนี้จะหมดอายุใน %d วินาที", + "เอกสารนี้จะหมดอายุใน %d วินาที" ], "This document will expire in %d minutes.": [ - "This document will expire in %d minute. (singular)", - "This document will expire in %d minutes. (1st plural)", - "This document will expire in %d minutes. (2nd plural)", - "This document will expire in %d minutes. (3rd plural)" + "เอกสารนี้จะหมดอายุใน %d นาที", + "เอกสารนี้จะหมดอายุใน %d นาที", + "เอกสารนี้จะหมดอายุใน %d นาที", + "เอกสารนี้จะหมดอายุใน %d นาที" ], "This document will expire in %d hours.": [ - "This document will expire in %d hour. (singular)", - "This document will expire in %d hours. (1st plural)", - "This document will expire in %d hours. (2nd plural)", - "This document will expire in %d hours. (3rd plural)" + "เอกสารนี้จะหมดอายุใน %d ชั่วโมง", + "เอกสารนี้จะหมดอายุใน %d ชั่วโมง", + "เอกสารนี้จะหมดอายุใน %d ชั่วโมง", + "เอกสารนี้จะหมดอายุใน %d ชั่วโมง" ], "This document will expire in %d days.": [ - "This document will expire in %d day. (singular)", - "This document will expire in %d days. (1st plural)", - "This document will expire in %d days. (2nd plural)", - "This document will expire in %d days. (3rd plural)" + "เอกสารนี้จะหมดอายุใน %d วัน", + "เอกสารนี้จะหมดอายุใน %d วัน", + "เอกสารนี้จะหมดอายุใน %d วัน", + "เอกสารนี้จะหมดอายุใน %d วัน" ], "This document will expire in %d months.": [ - "This document will expire in %d month. (singular)", - "This document will expire in %d months. (1st plural)", - "This document will expire in %d months. (2nd plural)", - "This document will expire in %d months. (3rd plural)" + "เอกสารนี้จะหมดอายุใน %d เดือน", + "เอกสารนี้จะหมดอายุใน %d เดือน", + "เอกสารนี้จะหมดอายุใน %d เดือน", + "เอกสารนี้จะหมดอายุใน %d เดือน" ], - "Please enter the password for this paste:": "Please enter the password for this paste:", - "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)", - "Could not delete the paste, it was not stored in burn after reading mode.": "Could not delete the paste, it was not stored in burn after reading mode.", - "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", - "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?", - "Reply": "Reply", - "Anonymous": "Anonymous", - "Avatar generated from IP address": "Avatar generated from IP address", - "Add comment": "Add comment", - "Optional nickname…": "Optional nickname…", - "Post comment": "Post comment", - "Sending comment…": "Sending comment…", - "Comment posted.": "Comment posted.", - "Could not refresh display: %s": "Could not refresh display: %s", - "unknown status": "unknown status", - "server error or not responding": "server error or not responding", - "Could not post comment: %s": "Could not post comment: %s", - "Sending paste…": "Sending paste…", - "Your paste is %s (Hit [Ctrl]+[c] to copy)": "Your paste is %s (Hit [Ctrl]+[c] to copy)", - "Delete data": "Delete data", - "Could not create paste: %s": "Could not create paste: %s", - "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)", + "Please enter the password for this paste:": "กรุณากรอกรหัสผ่านเพื่อเปิดข้อมูลการฝากโค้ดนี้:", + "Could not decrypt data (Wrong key?)": "ไม่สามารถถอดรหัสข้อมูลได้ (คีย์ไม่ถูกต้องหรือไม่)", + "Could not delete the paste, it was not stored in burn after reading mode.": "ไม่สามารถลบการฝากโค้ดนี้ได้ เนื่องจากว่าไม่ได้ถูกเก็บไว้ในโหมดลบทันทีเมื่อเปิดอ่าน", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": "เก็บไว้ดูคนเดียวนะ อย่าปิดหน้าต่างนี้ ข้อความนี้จะไม่สามารถแสดงได้อีก", + "Could not decrypt comment; Wrong key?": "ไม่สามารถถอดรหัสความคิดเห็นได้ คีย์ไม่ถูกต้องหรือไม่", + "Reply": "ตอบกลับ", + "Anonymous": "ไม่ระบุชื่อ", + "Avatar generated from IP address": "อวาตารสร้างมาจากไอพี", + "Add comment": "เพิ่มความคิดเห็น", + "Optional nickname…": "ใส่ชื่อคนให้ความคิดเห็น…", + "Post comment": "ส่งความคิดเห็น", + "Sending comment…": "กำลังส่งความคิดเห็น…", + "Comment posted.": "ส่งความคิดเห็นแล้ว", + "Could not refresh display: %s": "ไม่สามารถรีเฟรชการแสดงผลได้: %s", + "unknown status": "ไม่ทราบสถานะ", + "server error or not responding": "เซิร์ฟเวอร์มีข้อผิดพลาดหรือไม่ตอบสนอง", + "Could not post comment: %s": "ไม่สามารถส่งความคิดเห็นได้: %s", + "Sending paste…": "กำลังส่งข้อมูล…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": "การฝากโค้ดของคุณอยู่ที่ %s (กดปุ่ม [Ctrl]+[c] เพื่อคัดลอก)", + "Delete data": "ลบข้อมูล", + "Could not create paste: %s": "ไม่สามารถสร้างข้อมูลการฝากโค้ดได้: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "ไม่สามารถถอดรหัสข้อมูลการฝากโค้ดได้: คีย์ถอดรหัสที่อยู่ใน URL หายไป (คุณได้ใช้ตัวเปลี่ยนเส้นทางหรือตัวย่อ URL ที่มีการตัดส่วนของ URL ออกหรือไม่)", "B": "B", "KiB": "KiB", "MiB": "MiB", @@ -139,55 +139,55 @@ "EiB": "EiB", "ZiB": "ZiB", "YiB": "YiB", - "Format": "Format", - "Plain Text": "Plain Text", - "Source Code": "Source Code", + "Format": "รูปแบบ", + "Plain Text": "ข้อความล้วน", + "Source Code": "ซอร์สโค้ด", "Markdown": "Markdown", - "Download attachment": "Download attachment", - "Cloned: '%s'": "Cloned: '%s'", - "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", - "Attach a file": "Attach a file", - "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", - "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.", - "Remove attachment": "Remove attachment", - "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.", - "Invalid attachment.": "Invalid attachment.", - "Options": "Options", - "Shorten URL": "Shorten URL", - "Editor": "Editor", - "Preview": "Preview", - "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", - "Decrypt": "Decrypt", - "Enter password": "Enter password", - "Loading…": "Loading…", - "Decrypting paste…": "Decrypting paste…", - "Preparing new paste…": "Preparing new paste…", - "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", - "+++ no paste text +++": "+++ no paste text +++", - "Could not get paste data: %s": "Could not get paste data: %s", - "QR code": "QR code", - "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", - "For more information see this FAQ entry.": "For more information see this FAQ entry.", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.", - "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.", - "waiting on user to provide a password": "waiting on user to provide a password", - "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.", - "Retry": "Retry", - "Showing raw text…": "Showing raw text…", - "Notice:": "Notice:", - "This link will expire after %s.": "This link will expire after %s.", - "This link can only be accessed once, do not use back or refresh button in your browser.": "This link can only be accessed once, do not use back or refresh button in your browser.", - "Link:": "Link:", - "Recipient may become aware of your timezone, convert time to UTC?": "Recipient may become aware of your timezone, convert time to UTC?", - "Use Current Timezone": "Use Current Timezone", - "Convert To UTC": "Convert To UTC", - "Close": "Close", - "Encrypted note on %s": "Encrypted note on %s", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", - "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste", - "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", - "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", - "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", - "Error parsing YOURLS response.": "Error parsing YOURLS response." + "Download attachment": "ดาวน์โหลดไฟล์แนบ", + "Cloned: '%s'": "โคลนแล้ว: '%s'", + "The cloned file '%s' was attached to this paste.": "การโคลนข้อมูลการฝากโค้ด มีไฟล์ '%s' แนบมาด้วย", + "Attach a file": "แนบไฟล์", + "alternatively drag & drop a file or paste an image from the clipboard": "หรือสามารถลากและวางไฟล์หรือวางรูปภาพจากคลิปบอร์ดได้", + "File too large, to display a preview. Please download the attachment.": "ไฟล์มีขนาดใหญ่เกินไปที่จะแสดงตัวอย่าง กรุณาดาวน์โหลดเป็นไฟล์แนบแทน", + "Remove attachment": "ลบไฟล์แนบ", + "Your browser does not support uploading encrypted files. Please use a newer browser.": "เบราว์เซอร์ของคุณไม่สนับสนุนการอัปโหลดไฟล์แบบเข้ารหัสได้ กรุณาใช้เบราว์เซอร์ที่ใหม่กว่า", + "Invalid attachment.": "ไฟล์แนบไม่ถูกต้อง", + "Options": "ตัวเลือก", + "Shorten URL": "สร้างลิงก์ย่อ", + "Editor": "ตัวแก้ไข", + "Preview": "ดูตัวอย่าง", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s กำหนดให้ PATH ลงท้ายด้วย \"%s\" กรุณาอัปเดต PATH ในไฟล์ index.php ของคุณ", + "Decrypt": "ถอดรหัส", + "Enter password": "กรอกรหัสผ่าน", + "Loading…": "กำลังโหลด…", + "Decrypting paste…": "กำลังถอดรหัสข้อมูลการฝากโค้ด…", + "Preparing new paste…": "กำลังเตรียมข้อมูลการฝากโค้ดใหม่…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": "ในกรณีที่ข้อความนี้ยังปรากฎให้เห็นอยู่ กรุณาดูคำถามที่พบบ่อยนี้เพื่อใช้แก้ไขปัญหา", + "+++ no paste text +++": "+++ ไม่มีข้อความการฝากโค้ด +++", + "Could not get paste data: %s": "ไม่สามารถดึงข้อมูลการฝากโค้ดได้: %s", + "QR code": "คิวอาร์โค้ด", + "This website is using an insecure HTTP connection! Please use it only for testing.": "เว็บไซต์นี้ใช้การเชื่อมต่อแบบ HTTP ที่ไม่ปลอดภัย! กรุณาใช้เพื่อการทดสอบเท่านั้น", + "For more information see this FAQ entry.": "สำหรับข้อมูลเพิ่มเติม กรุณาดูรายการคำถามที่พบบ่อยนี้", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "เบราว์เซอร์ของคุณอาจต้องใช้การเชื่อมต่อแบบ HTTPS เพื่อสนับสนุน API แบบ WebCrypto ลองเปลี่ยนเป็น HTTPS", + "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "เบราว์เซอร์ของคุณไม่สนับสนุน WebAssembly ที่ทำหน้าที่ในการบีบอัดข้อมูลในรูปแบบ zlib คุณยังสามารถสร้างเอกสารที่ไม่บีบอัด แต่จะไม่สามารถอ่านเอกสารที่บีบอัดได้", + "waiting on user to provide a password": "กำลังรอผู้ใช้กรอกรหัสผ่าน", + "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "ไม่สามารถถอดรหัสข้อมูลได้ คุณกรอกรหัสผ่านผิดหรือเปล่า กดปุ่มลองอีกครั้งด้านบน", + "Retry": "ลองอีกครั้ง", + "Showing raw text…": "กำลังแสดงข้อความล้วน…", + "Notice:": "โปรดทราบ:", + "This link will expire after %s.": "ลิงก์นี้จะหมดอายุหลังจาก %s", + "This link can only be accessed once, do not use back or refresh button in your browser.": "ลิงก์นี้สามารถเข้าถึงได้เพียงครั้งเดียว ห้ามใช้ปุ่มย้อนกลับหรือรีเฟรชในเบราว์เซอร์ของคุณ", + "Link:": "ลิงก์:", + "Recipient may become aware of your timezone, convert time to UTC?": "ผู้รับอีเมลอาจทราบโซนเวลาของคุณได้ คุณต้องการแปลงโซนเวลาเป็น UTC หรือไม่", + "Use Current Timezone": "ใช้โซนเวลาปัจจุบัน", + "Convert To UTC": "แปลงเป็น UTC", + "Close": "ปิด", + "Encrypted note on %s": "เขารหัสบันทึกย่อบน %s", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "ไปที่ลิงก์นี้เพื่อดูบันทึกย่อทั้งหมด ส่ง URL นี้ให้ใครก็ได้เพื่อให้สามารถเข้าถึงโน้ตได้", + "URL shortener may expose your decrypt key in URL.": "เครื่องมือสร้างลิงก์ย่ออาจเปิดเผยคีย์ถอดรหัสของคุณใน URL ได้", + "Save paste": "ดาวน์โหลดข้อมูลการฝากโค้ด", + "Your IP is not authorized to create pastes.": "IP ของคุณไม่ได้รับอนุญาตให้สร้างการฝากโค้ด", + "Trying to shorten a URL that isn't pointing at our instance.": "กำลังพยายามใช้เครื่องมือสร้างลิงก์ย่อ ที่ไม่ได้ชี้ไปที่อินสแตนซ์ของเรา", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "เกิดข้อผิดพลาดในการเรียก YOURLS อาจเป็นปัญหามาจากการกำหนดค่า เช่น \"apiurl\" หรือ \"signature\" ไม่ถูกต้องหรือขาดหายไป", + "Error parsing YOURLS response.": "เกิดข้อผิดพลาดในการแยกวิเคราะห์การตอบสนองของ YOURLS" } From 9f1e95f588a2b66e52d3e2ee6b3eef3d8e54cec6 Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Sun, 6 Nov 2022 03:21:05 +0100 Subject: [PATCH 170/506] New translations en.json (Thai) --- i18n/th.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/th.json b/i18n/th.json index 35e6209e..7cb789ea 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -1,7 +1,7 @@ { "PrivateBin": "PrivateBin", "%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s เป็น pastebin ออนไลน์แบบโอเพ่นซอร์สที่มีสไตล์แบบมินิมัลลิสท์ เซิร์ฟเวอร์ไม่สามารถรู้ได้ว่าข้อมูลโค้ดที่มาฝากนั้นเป็นข้อมูลอะไร โดยจะถูก %sเข้ารหัส/ถอดรหัส%s ด้วยกระบวนการ AES จำนวน 256 บิตผ่านเบราว์เซอร์", - "More information on the project page.": "ข้อมูลเพิ่มเติมในหน้าโครงการ", + "More information on the project page.": "ข้อมูลเพิ่มเติม ดูได้ที่หน้าโครงการ", "Because ignorance is bliss": "ไม่รู้ไม่ชี้ดีที่สุด", "en": "th", "Paste does not exist, has expired or has been deleted.": "การฝากโค้ดไม่มีอยู่ อาจจะหมดอายุหรือถูกลบไปแล้ว", @@ -168,7 +168,7 @@ "QR code": "คิวอาร์โค้ด", "This website is using an insecure HTTP connection! Please use it only for testing.": "เว็บไซต์นี้ใช้การเชื่อมต่อแบบ HTTP ที่ไม่ปลอดภัย! กรุณาใช้เพื่อการทดสอบเท่านั้น", "For more information see this FAQ entry.": "สำหรับข้อมูลเพิ่มเติม กรุณาดูรายการคำถามที่พบบ่อยนี้", - "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "เบราว์เซอร์ของคุณอาจต้องใช้การเชื่อมต่อแบบ HTTPS เพื่อสนับสนุน API แบบ WebCrypto ลองเปลี่ยนเป็น HTTPS", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": "เบราว์เซอร์ของคุณอาจต้องใช้การเชื่อมต่อ HTTPS เพื่อสนับสนุน API แบบ WebCrypto ลองเปลี่ยนเป็น HTTPS", "Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.": "เบราว์เซอร์ของคุณไม่สนับสนุน WebAssembly ที่ทำหน้าที่ในการบีบอัดข้อมูลในรูปแบบ zlib คุณยังสามารถสร้างเอกสารที่ไม่บีบอัด แต่จะไม่สามารถอ่านเอกสารที่บีบอัดได้", "waiting on user to provide a password": "กำลังรอผู้ใช้กรอกรหัสผ่าน", "Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.": "ไม่สามารถถอดรหัสข้อมูลได้ คุณกรอกรหัสผ่านผิดหรือเปล่า กดปุ่มลองอีกครั้งด้านบน", @@ -176,7 +176,7 @@ "Showing raw text…": "กำลังแสดงข้อความล้วน…", "Notice:": "โปรดทราบ:", "This link will expire after %s.": "ลิงก์นี้จะหมดอายุหลังจาก %s", - "This link can only be accessed once, do not use back or refresh button in your browser.": "ลิงก์นี้สามารถเข้าถึงได้เพียงครั้งเดียว ห้ามใช้ปุ่มย้อนกลับหรือรีเฟรชในเบราว์เซอร์ของคุณ", + "This link can only be accessed once, do not use back or refresh button in your browser.": "ลิงก์นี้สามารถเข้าถึงได้เพียงครั้งเดียวเท่านั้น ไม่ควรใช้ปุ่มย้อนกลับหรือรีเฟรชหน้าเว็บบนเบราว์เซอร์ของคุณ", "Link:": "ลิงก์:", "Recipient may become aware of your timezone, convert time to UTC?": "ผู้รับอีเมลอาจทราบโซนเวลาของคุณได้ คุณต้องการแปลงโซนเวลาเป็น UTC หรือไม่", "Use Current Timezone": "ใช้โซนเวลาปัจจุบัน", From 3028c22c20a1f8fa5a2ecd9389d9219e49c75860 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 07:40:39 +0100 Subject: [PATCH 171/506] be more efficient --- lib/Data/Database.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Data/Database.php b/lib/Data/Database.php index d4933b00..4636f3ce 100644 --- a/lib/Data/Database.php +++ b/lib/Data/Database.php @@ -289,11 +289,11 @@ class Database extends AbstractData { try { $row = $this->_select( - 'SELECT * FROM "' . $this->_sanitizeIdentifier('paste') . + 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '" WHERE "dataid" = ?', array($pasteid), true ); } catch (Exception $e) { - $row = false; + return false; } return (bool) $row; } From 5195adfdb91a4a3c87813ecbafa04500ccec24ab Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 07:41:05 +0100 Subject: [PATCH 172/506] simple migration test --- tst/MigrateTest.php | 81 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tst/MigrateTest.php diff --git a/tst/MigrateTest.php b/tst/MigrateTest.php new file mode 100644 index 00000000..14feca0a --- /dev/null +++ b/tst/MigrateTest.php @@ -0,0 +1,81 @@ +_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; + $this->_path_instance_1 = $this->_path . DIRECTORY_SEPARATOR . 'instance_1'; + $this->_path_instance_2 = $this->_path . DIRECTORY_SEPARATOR . 'instance_2'; + if (!is_dir($this->_path)) { + mkdir($this->_path); + } + mkdir($this->_path_instance_1); + mkdir($this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg'); + mkdir($this->_path_instance_2); + mkdir($this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg'); + $options = parse_ini_file(CONF_SAMPLE, true); + $options['purge']['limit'] = 0; + $options['model_options']['dir'] = $this->_path_instance_1 . DIRECTORY_SEPARATOR . 'data'; + $this->_model_1 = new Filesystem($options['model_options']); + Helper::createIniFile($this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php', $options); + + $options['model'] = array( + 'class' => 'Database', + ); + $options['model_options'] = array( + 'dsn' => 'sqlite:' . $this->_path_instance_2 . DIRECTORY_SEPARATOR . 'test.sq3', + 'usr' => null, + 'pwd' => null, + 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), + ); + $this->_model_2 = new Database($options['model_options']); + Helper::createIniFile($this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php', $options); + } + + public function tearDown() + { + /* Tear Down Routine */ + Helper::rmDir($this->_path); + } + + public function testMigrate() + { + $this->_model_1->delete(Helper::getPasteId()); + $this->_model_2->delete(Helper::getPasteId()); + + // storing paste & comment + $this->_model_1->create(Helper::getPasteId(), Helper::getPaste()); + $this->_model_1->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()); + + // migrate files to database + $output = null; + $exit_code = 255; + exec('php ' . PATH . "bin" . DIRECTORY_SEPARATOR . 'migrate --delete-after ' . $this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg '. $this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg', $output, $exit_code); + $this->assertEquals(0, $exit_code, 'migrate script exits 0'); + $this->assertFalse($this->_model_1->exists(Helper::getPasteId()), 'paste removed after migrating it'); + $this->assertFalse($this->_model_1->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment removed after migrating it'); + $this->assertTrue($this->_model_2->exists(Helper::getPasteId()), 'paste migrated'); + $this->assertTrue($this->_model_2->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment migrated'); + + // migrate back to files + $exit_code = 255; + exec('php ' . PATH . "bin" . DIRECTORY_SEPARATOR . 'migrate ' . $this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg '. $this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg', $output, $exit_code); + $this->assertEquals(0, $exit_code, 'migrate script exits 0'); + $this->assertTrue($this->_model_1->exists(Helper::getPasteId()), 'paste migrated back'); + $this->assertTrue($this->_model_1->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment migrated back'); + } +} \ No newline at end of file From bde7a199712a03122e7439e431ef40a54f8cd13e Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 07:43:19 +0100 Subject: [PATCH 173/506] apply StyleCI patch --- tst/MigrateTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tst/MigrateTest.php b/tst/MigrateTest.php index 14feca0a..d1fbb30e 100644 --- a/tst/MigrateTest.php +++ b/tst/MigrateTest.php @@ -17,7 +17,7 @@ class MigrateTest extends PHPUnit_Framework_TestCase public function setUp() { /* Setup Routine */ - $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; + $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_path_instance_1 = $this->_path . DIRECTORY_SEPARATOR . 'instance_1'; $this->_path_instance_2 = $this->_path . DIRECTORY_SEPARATOR . 'instance_2'; if (!is_dir($this->_path)) { @@ -27,10 +27,10 @@ class MigrateTest extends PHPUnit_Framework_TestCase mkdir($this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg'); mkdir($this->_path_instance_2); mkdir($this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg'); - $options = parse_ini_file(CONF_SAMPLE, true); - $options['purge']['limit'] = 0; + $options = parse_ini_file(CONF_SAMPLE, true); + $options['purge']['limit'] = 0; $options['model_options']['dir'] = $this->_path_instance_1 . DIRECTORY_SEPARATOR . 'data'; - $this->_model_1 = new Filesystem($options['model_options']); + $this->_model_1 = new Filesystem($options['model_options']); Helper::createIniFile($this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php', $options); $options['model'] = array( @@ -62,9 +62,9 @@ class MigrateTest extends PHPUnit_Framework_TestCase $this->_model_1->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()); // migrate files to database - $output = null; + $output = null; $exit_code = 255; - exec('php ' . PATH . "bin" . DIRECTORY_SEPARATOR . 'migrate --delete-after ' . $this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg '. $this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg', $output, $exit_code); + exec('php ' . PATH . 'bin' . DIRECTORY_SEPARATOR . 'migrate --delete-after ' . $this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg ' . $this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg', $output, $exit_code); $this->assertEquals(0, $exit_code, 'migrate script exits 0'); $this->assertFalse($this->_model_1->exists(Helper::getPasteId()), 'paste removed after migrating it'); $this->assertFalse($this->_model_1->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment removed after migrating it'); @@ -73,9 +73,9 @@ class MigrateTest extends PHPUnit_Framework_TestCase // migrate back to files $exit_code = 255; - exec('php ' . PATH . "bin" . DIRECTORY_SEPARATOR . 'migrate ' . $this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg '. $this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg', $output, $exit_code); + exec('php ' . PATH . 'bin' . DIRECTORY_SEPARATOR . 'migrate ' . $this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg ' . $this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg', $output, $exit_code); $this->assertEquals(0, $exit_code, 'migrate script exits 0'); $this->assertTrue($this->_model_1->exists(Helper::getPasteId()), 'paste migrated back'); $this->assertTrue($this->_model_1->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment migrated back'); } -} \ No newline at end of file +} From 14075cea78ddd569322dc7a5fa5910cbc429f4d4 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 07:53:43 +0100 Subject: [PATCH 174/506] trying a different approach to get that exception 70 triggered reliably --- tst/ModelTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/ModelTest.php b/tst/ModelTest.php index dbbbbc22..5813d853 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -270,7 +270,7 @@ class ModelTest extends PHPUnit_Framework_TestCase $options['model_options']['pwd'], $options['model_options']['opt'] ); - $statement = $db->prepare('DROP TABLE comment'); + $statement = $db->prepare('ALTER TABLE comment DROP COLUMN data'); $statement->execute(); $statement->closeCursor(); From 669c98550c22bbe4b1a777c924cdae36c25bd939 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 08:05:41 +0100 Subject: [PATCH 175/506] add a version check, the third argument in getopt requires PHP >= 7.1 --- bin/migrate | 4 ++++ tst/MigrateTest.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/bin/migrate b/bin/migrate index 4dbe052b..515a5e80 100755 --- a/bin/migrate +++ b/bin/migrate @@ -10,6 +10,10 @@ require PATH . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; use PrivateBin\Configuration; use PrivateBin\Model; +// third argument in getopt requires PHP >= 7.1 +if (version_compare(PHP_VERSION, '7.1.0') < 0) { + dieerr('migrate requires php 7.1 or above to work. Sorry.'); +} $longopts = array( "delete-after", diff --git a/tst/MigrateTest.php b/tst/MigrateTest.php index d1fbb30e..eccca266 100644 --- a/tst/MigrateTest.php +++ b/tst/MigrateTest.php @@ -54,6 +54,10 @@ class MigrateTest extends PHPUnit_Framework_TestCase public function testMigrate() { + if (version_compare(PHP_VERSION, '7.1.0') < 0) { + return; // skip test on unsupported PHP versions + } + $this->_model_1->delete(Helper::getPasteId()); $this->_model_2->delete(Helper::getPasteId()); From 6caf1143df94afe5f97a88b48087e44a10b83896 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 08:13:07 +0100 Subject: [PATCH 176/506] add a verification step for investigating failures in tests below PHP 7.2 --- tst/ModelTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/ModelTest.php b/tst/ModelTest.php index 5813d853..91da5580 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -259,7 +259,7 @@ class ModelTest extends PHPUnit_Framework_TestCase $paste = $model->getPaste(); $paste->setData($pasteData); $paste->store(); - $paste->exists(); + $this->assertTrue($paste->exists(), 'paste exists before creating comment'); $comment = $paste->getComment(Helper::getPasteId()); $comment->setData($commentData); From 8ede84f000ad16b4c2fe444057c8945337437e43 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 08:21:28 +0100 Subject: [PATCH 177/506] disable test when PHP < 7.2 It started failing after we removed the cache from the Database class, but the behaviour is still correct (exception when something goes wrong during comment storing). --- tst/ModelTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tst/ModelTest.php b/tst/ModelTest.php index 91da5580..00a172db 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -270,10 +270,13 @@ class ModelTest extends PHPUnit_Framework_TestCase $options['model_options']['pwd'], $options['model_options']['opt'] ); - $statement = $db->prepare('ALTER TABLE comment DROP COLUMN data'); + $statement = $db->prepare('DROP TABLE comment'); $statement->execute(); $statement->closeCursor(); + if (version_compare(PHP_VERSION, '7.2.0') < 0) { + throw new Exception('For some reason, this test stopped working in PHP < 7.2', 70); + } $comment->store(); } From a799351db33861e0b7aeb2172ed8108f8729ef78 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 09:09:50 +0100 Subject: [PATCH 178/506] re-use logic from _getExpiredPastes() Scrutinizer pointed out that the dieerr() function isn't available in this class. Code does work when invoked by migrate script, but this way it would also work in other contexts. --- lib/Data/Filesystem.php | 57 ++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index 2d082144..abaa51db 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -410,37 +410,46 @@ class Filesystem extends AbstractData public function getAllPastes() { $pastes = array(); - $subdirs = scandir($this->_path); - if ($subdirs === false) { - dieerr('Unable to list directory ' . $this->_path); - } - $subdirs = preg_grep('/^[^.].$/', $subdirs); + $firstLevel = array_filter( + scandir($this->_path), + 'PrivateBin\Data\Filesystem::_isFirstLevelDir' + ); + if (count($firstLevel) > 0) { + foreach ($firstLevel as $firstKey) { + $secondLevel = array_filter( + scandir($this->_path . DIRECTORY_SEPARATOR . $firstKey), + 'PrivateBin\Data\Filesystem::_isSecondLevelDir' + ); - foreach ($subdirs as $subdir) { - $subpath = $this->_path . DIRECTORY_SEPARATOR . $subdir; - - $subsubdirs = scandir($subpath); - if ($subsubdirs === false) { - dieerr('Unable to list directory ' . $subpath); - } - $subsubdirs = preg_grep('/^[^.].$/', $subsubdirs); - foreach ($subsubdirs as $subsubdir) { - $subsubpath = $subpath . DIRECTORY_SEPARATOR . $subsubdir; - - $files = scandir($subsubpath); - if ($files === false) { - dieerr('Unable to list directory ' . $subsubpath); + // skip this folder + if (count($secondLevel) == 0) { + continue; } - $files = preg_grep('/\.php$/', $files); - foreach ($files as $file) { - if (substr($file, 0, 4) === $subdir . $subsubdir) { - $pastes[] = substr($file, 0, strlen($file) - 4); + foreach ($secondLevel as $secondKey) { + $path = $this->_path . DIRECTORY_SEPARATOR . $firstKey . + DIRECTORY_SEPARATOR . $secondKey; + if (!is_dir($path)) { + continue; } + $thirdLevel = array_filter( + array_map( + function ($filename) { + return strlen($filename) >= 20 ? + substr($filename, 0, -4) : + $filename; + }, + scandir($path) + ), + 'PrivateBin\\Model\\Paste::isValidId' + ); + if (count($thirdLevel) == 0) { + continue; + } + $pastes += $thirdLevel; } } } - return $pastes; } From 94aab6d64b4913996d543b520a6ad58282f3ca67 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 09:12:42 +0100 Subject: [PATCH 179/506] apply StyleCI patch --- lib/Data/Filesystem.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index abaa51db..966506fd 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -409,7 +409,7 @@ class Filesystem extends AbstractData */ public function getAllPastes() { - $pastes = array(); + $pastes = array(); $firstLevel = array_filter( scandir($this->_path), 'PrivateBin\Data\Filesystem::_isFirstLevelDir' From 0288d94a68c23b940a057f60b073017aa45babb8 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 6 Nov 2022 09:27:51 +0100 Subject: [PATCH 180/506] regenerate composer.lock with PHP 7.2 for Scrutinizer --- composer.lock | 128 +++++++----------------------- vendor/composer/autoload_real.php | 3 - 2 files changed, 29 insertions(+), 102 deletions(-) diff --git a/composer.lock b/composer.lock index 5d13c27b..3f4e65f0 100644 --- a/composer.lock +++ b/composer.lock @@ -105,16 +105,6 @@ "range", "subnet" ], - "funding": [ - { - "url": "https://github.com/sponsors/mlocati", - "type": "github" - }, - { - "url": "https://paypal.me/mlocati", - "type": "other" - } - ], "time": "2022-01-13T18:05:33+00:00" }, { @@ -271,20 +261,6 @@ "constructor", "instantiate" ], - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], "time": "2022-03-03T08:28:38+00:00" }, { @@ -334,12 +310,6 @@ "object", "object graph" ], - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], "time": "2022-03-03T13:19:32+00:00" }, { @@ -446,30 +416,25 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.6.2", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d" + "reference": "77a32518733312af16a44300404e945338981de3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d", - "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", + "reference": "77a32518733312af16a44300404e945338981de3", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", + "php": "^7.2 || ^8.0", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { "ext-tokenizer": "*", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -493,7 +458,7 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2022-10-14T12:47:21+00:00" + "time": "2022-03-15T21:29:03+00:00" }, { "name": "phpspec/prophecy", @@ -560,35 +525,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "4.0.8", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + "reference": "ca060f645beeddebedb1885c97bf163e93264c35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca060f645beeddebedb1885c97bf163e93264c35", + "reference": "ca060f645beeddebedb1885c97bf163e93264c35", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/code-unit-reverse-lookup": "~1.0", "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" + "sebastian/version": "~1.0|~2.0" }, "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "^5.4" }, "suggest": { - "ext-xdebug": "^2.5.1" + "ext-dom": "*", + "ext-xdebug": ">=2.4.0", + "ext-xmlwriter": "*" }, "type": "library", "extra": { @@ -619,7 +584,7 @@ "testing", "xunit" ], - "time": "2017-04-02T07:44:40+00:00" + "time": "2017-02-23T07:38:02+00:00" }, { "name": "phpunit/php-file-iterator", @@ -993,12 +958,6 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], "time": "2020-11-30T08:15:22+00:00" }, { @@ -1532,20 +1491,6 @@ "polyfill", "portable" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], "time": "2022-05-24T11:49:31+00:00" }, { @@ -1600,39 +1545,25 @@ ], "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], "time": "2022-08-02T15:47:23+00:00" }, { "name": "webmozart/assert", - "version": "1.11.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", "shasum": "" }, "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" }, "conflict": { "phpstan/phpstan": "<0.12.20", @@ -1668,7 +1599,7 @@ "check", "validate" ], - "time": "2022-06-03T18:03:27+00:00" + "time": "2021-03-09T10:59:23+00:00" } ], "aliases": [], @@ -1679,6 +1610,5 @@ "platform": { "php": "^5.6.0 || ^7.0 || ^8.0" }, - "platform-dev": [], - "plugin-api-version": "1.1.0" + "platform-dev": [] } diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 7a6fd4c0..2e234b96 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -13,9 +13,6 @@ class ComposerAutoloaderInitDontChange } } - /** - * @return \Composer\Autoload\ClassLoader - */ public static function getLoader() { if (null !== self::$loader) { From d4d4687464b92a4cdf527ea1e1a316b92b97ef8b Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:01:51 +0100 Subject: [PATCH 181/506] New translations en.json (Thai) --- i18n/th.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/th.json b/i18n/th.json index 7cb789ea..881e5aab 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -77,7 +77,7 @@ "%d ปี" ], "Never": "ไม่หมดอายุ", - "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "หมายเหตุ: เว็บไซต์นี่เป็นบริการเบต้าและข้อมูลอาจถูกลบได้ตลอดเวลา หากคุณใช้บริการนี้ในทางที่ผิดอาจจะทำให้ข้อมูลของคุณสูญหายอย่างถาวรได้", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "โปรดทราบ: เว็บไซต์นี้เป็นการให้บริการแบบเบต้า ข้อมูลอาจถูกลบได้ตลอดเวลา หากคุณใช้บริการนี้ในทางที่ผิดอาจจะทำให้ข้อมูลของคุณสูญหายอย่างถาวรได้", "This document will expire in %d seconds.": [ "เอกสารนี้จะหมดอายุใน %d วินาที", "เอกสารนี้จะหมดอายุใน %d วินาที", From b0c61cc208ee4dd9cd6273d1a52c96856f65b7ac Mon Sep 17 00:00:00 2001 From: PrivateBin Translator Bot <72346835+privatebin-translator@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:58:25 +0100 Subject: [PATCH 182/506] New translations en.json (Thai) --- i18n/th.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/th.json b/i18n/th.json index 881e5aab..d3c955db 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -183,7 +183,7 @@ "Convert To UTC": "แปลงเป็น UTC", "Close": "ปิด", "Encrypted note on %s": "เขารหัสบันทึกย่อบน %s", - "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "ไปที่ลิงก์นี้เพื่อดูบันทึกย่อทั้งหมด ส่ง URL นี้ให้ใครก็ได้เพื่อให้สามารถเข้าถึงโน้ตได้", + "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "ไปที่ลิงก์นี้เพื่อดูบันทึกย่อทั้งหมด ส่ง URL นี้ให้ใครก็ได้เพื่อให้สามารถเข้าถึงบันทึกย่อได้", "URL shortener may expose your decrypt key in URL.": "เครื่องมือสร้างลิงก์ย่ออาจเปิดเผยคีย์ถอดรหัสของคุณใน URL ได้", "Save paste": "ดาวน์โหลดข้อมูลการฝากโค้ด", "Your IP is not authorized to create pastes.": "IP ของคุณไม่ได้รับอนุญาตให้สร้างการฝากโค้ด", From 89df4a54ec3b6f2d3522f0bcd87ddc50417cb336 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 7 Nov 2022 07:12:40 +0100 Subject: [PATCH 183/506] enable and credit Thai translation --- CHANGELOG.md | 2 +- CREDITS.md | 1 + js/privatebin.js | 3 ++- lib/I18n.php | 1 + tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- 6 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02c39505..d8ac2cb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ * **1.4.1 (not yet released)** * ADDED: script for data storage backend migrations (#1012) - * ADDED: Translations for Turkish, Slovak and Greek + * ADDED: Translations for Turkish, Slovak, Greek and Thai * ADDED: S3 Storage backend (#994) * CHANGED: Switched to Jdenticons as the default for comment icons (#793) * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) diff --git a/CREDITS.md b/CREDITS.md index eb5f152e..7a19c5fd 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -62,3 +62,4 @@ * Emir Ensar Rahmanlar - Turkish * Stevo984 - Slovak * Christos Karamolegkos - Greek +* jaideejung007 - Thai diff --git a/js/privatebin.js b/js/privatebin.js index fe326b49..5171477d 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -627,7 +627,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @prop {string[]} * @readonly */ - const supportedLanguages = ['bg', 'ca', 'co', 'cs', 'de', 'el', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sk', 'sl', 'tr', 'uk', 'zh']; + const supportedLanguages = ['bg', 'ca', 'co', 'cs', 'de', 'el', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sk', 'sl', 'th', 'tr', 'uk', 'zh']; /** * built in language @@ -815,6 +815,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { return n === 1 ? 0 : (n === 2 ? 1 : ((n < 0 || n > 10) && (n % 10 === 0) ? 2 : 3)); case 'id': case 'jbo': + case 'th': return 0; case 'lt': return n % 10 === 1 && n % 100 !== 11 ? 0 : ((n % 10 >= 2 && n % 100 < 10 || n % 100 >= 20) ? 1 : 2); diff --git a/lib/I18n.php b/lib/I18n.php index c3c635f7..5c469381 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -328,6 +328,7 @@ class I18n return $n === 1 ? 0 : ($n === 2 ? 1 : (($n < 0 || $n > 10) && ($n % 10 === 0) ? 2 : 3)); case 'id': case 'jbo': + case 'th': return 0; case 'lt': return $n % 10 === 1 && $n % 100 !== 11 ? 0 : (($n % 10 >= 2 && $n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 3dd49135..b3441a74 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -73,7 +73,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index f91cb7dd..42380abc 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -51,7 +51,7 @@ endif; ?> - + From c0758e7bbb921ea44dab28b743d8c96c98ec07c1 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 7 Nov 2022 19:09:16 +0100 Subject: [PATCH 184/506] correct labels, Jdenticon renders PNG or SVG, both in pure PHP --- tst/IconTest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tst/IconTest b/tst/IconTest index e39cc7be..75dbb279 100755 --- a/tst/IconTest +++ b/tst/IconTest @@ -28,7 +28,7 @@ $jdenticon = new Jdenticon(array( ), )); $jdenticonGenerators = array( - 'jdenticon GD' => 'png', + 'jdenticon PNG' => 'png', 'jdenticon SVG' => 'svg', ); $results = array( @@ -48,7 +48,7 @@ $results = array( 'lengths' => array(), 'time' => 0 ), - 'jdenticon GD' => array( + 'jdenticon PNG' => array( 'lengths' => array(), 'time' => 0 ), From b2ef205411984f2c40a075da0774123ddfa61335 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Mon, 7 Nov 2022 19:42:20 +0100 Subject: [PATCH 185/506] extended script to test jdenticon ImageMagick and documented option to work without GD --- INSTALL.md | 2 +- tst/IconTest | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index f35d68bf..24749d34 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -26,7 +26,7 @@ install and configure PrivateBin on your server. It's available on - `open_basedir` access to `/dev/urandom` - mcrypt extension AND `open_basedir` access to `/dev/urandom` - com_dotnet extension -- GD extension +- GD extension (when using identicon or vizhash icons, jdenticon works without it) - zlib extension - some disk space or a database supported by [PDO](https://php.net/manual/book.pdo.php) - ability to create files and folders in the installation directory and the PATH diff --git a/tst/IconTest b/tst/IconTest index 75dbb279..57145e13 100755 --- a/tst/IconTest +++ b/tst/IconTest @@ -28,7 +28,8 @@ $jdenticon = new Jdenticon(array( ), )); $jdenticonGenerators = array( - 'jdenticon PNG' => 'png', + 'jdenticon' => 'png', + 'jdenticon ImageMagick' => 'png', 'jdenticon SVG' => 'svg', ); $results = array( @@ -48,7 +49,11 @@ $results = array( 'lengths' => array(), 'time' => 0 ), - 'jdenticon PNG' => array( + 'jdenticon' => array( + 'lengths' => array(), + 'time' => 0 + ), + 'jdenticon ImageMagick' => array( 'lengths' => array(), 'time' => 0 ), @@ -89,6 +94,11 @@ foreach ($identiconGenerators as $key => $identicon) { foreach ($jdenticonGenerators as $key => $format) { echo 'run ', $key,' tests', PHP_EOL; + if ($key === 'jdenticon ImageMagick') { + $jdenticon->enableImageMagick = true; + } else { + $jdenticon->enableImageMagick = false; + } $start = microtime(true); foreach ($hmacs as $i => $hmac) { $jdenticon->setHash($hmac); From b8593b1bf2bb23d1946dff96450092b8bde34453 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 10 Nov 2022 20:36:15 +0100 Subject: [PATCH 186/506] use a glob iterator to stream through as many matches as needed --- lib/Data/Filesystem.php | 148 +++++++++------------------------------- 1 file changed, 34 insertions(+), 114 deletions(-) diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index 966506fd..1f00b577 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -340,63 +340,25 @@ class Filesystem extends AbstractData */ protected function _getExpiredPastes($batchsize) { - $pastes = array(); - $firstLevel = array_filter( - scandir($this->_path), - 'PrivateBin\Data\Filesystem::_isFirstLevelDir' - ); - if (count($firstLevel) > 0) { - // try at most 10 times the $batchsize pastes before giving up - for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) { - $firstKey = array_rand($firstLevel); - $secondLevel = array_filter( - scandir($this->_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]), - 'PrivateBin\Data\Filesystem::_isSecondLevelDir' - ); - - // skip this folder in the next checks if it is empty - if (count($secondLevel) == 0) { - unset($firstLevel[$firstKey]); - continue; - } - - $secondKey = array_rand($secondLevel); - $path = $this->_path . DIRECTORY_SEPARATOR . - $firstLevel[$firstKey] . DIRECTORY_SEPARATOR . - $secondLevel[$secondKey]; - if (!is_dir($path)) { - continue; - } - $thirdLevel = array_filter( - array_map( - function ($filename) { - return strlen($filename) >= 20 ? - substr($filename, 0, -4) : - $filename; - }, - scandir($path) - ), - 'PrivateBin\\Model\\Paste::isValidId' - ); - if (count($thirdLevel) == 0) { - continue; - } - $thirdKey = array_rand($thirdLevel); - $pasteid = $thirdLevel[$thirdKey]; - if (in_array($pasteid, $pastes)) { - continue; - } - - if ($this->exists($pasteid)) { - $data = $this->read($pasteid); - if ( - array_key_exists('expire_date', $data['meta']) && - $data['meta']['expire_date'] < time() - ) { - $pastes[] = $pasteid; - if (count($pastes) >= $batchsize) { - break; - } + $pastes = array(); + $files = $this->_getPasteIterator(); + $count = 0; + $time = time(); + foreach ($files as $file) { + if ($file->isDir()) { + continue; + } + $pasteid = $file->getBasename('.php'); + if ($this->exists($pasteid)) { + $data = $this->read($pasteid); + if ( + array_key_exists('expire_date', $data['meta']) && + $data['meta']['expire_date'] < $time + ) { + $pastes[] = $pasteid; + ++$count; + if ($count >= $batchsize) { + break; } } } @@ -409,45 +371,11 @@ class Filesystem extends AbstractData */ public function getAllPastes() { - $pastes = array(); - $firstLevel = array_filter( - scandir($this->_path), - 'PrivateBin\Data\Filesystem::_isFirstLevelDir' - ); - if (count($firstLevel) > 0) { - foreach ($firstLevel as $firstKey) { - $secondLevel = array_filter( - scandir($this->_path . DIRECTORY_SEPARATOR . $firstKey), - 'PrivateBin\Data\Filesystem::_isSecondLevelDir' - ); - - // skip this folder - if (count($secondLevel) == 0) { - continue; - } - - foreach ($secondLevel as $secondKey) { - $path = $this->_path . DIRECTORY_SEPARATOR . $firstKey . - DIRECTORY_SEPARATOR . $secondKey; - if (!is_dir($path)) { - continue; - } - $thirdLevel = array_filter( - array_map( - function ($filename) { - return strlen($filename) >= 20 ? - substr($filename, 0, -4) : - $filename; - }, - scandir($path) - ), - 'PrivateBin\\Model\\Paste::isValidId' - ); - if (count($thirdLevel) == 0) { - continue; - } - $pastes += $thirdLevel; - } + $pastes = array(); + $files = $this->_getPasteIterator(); + foreach ($files as $file) { + if ($file->isFile()) { + $pastes[] = $file->getBasename('.php'); } } return $pastes; @@ -490,28 +418,20 @@ class Filesystem extends AbstractData } /** - * Check that the given element is a valid first level directory. + * Get an iterator matching paste files. * * @access private - * @param string $element - * @return bool + * @return \GlobIterator */ - private function _isFirstLevelDir($element) + private function _getPasteIterator() { - return $this->_isSecondLevelDir($element) && - is_dir($this->_path . DIRECTORY_SEPARATOR . $element); - } - - /** - * Check that the given element is a valid second level directory. - * - * @access private - * @param string $element - * @return bool - */ - private function _isSecondLevelDir($element) - { - return (bool) preg_match('/^[a-f0-9]{2}$/', $element); + return new \GlobIterator($this->_path . DIRECTORY_SEPARATOR . + '[a-f0-9][a-f0-9]' . DIRECTORY_SEPARATOR . + '[a-f0-9][a-f0-9]' . DIRECTORY_SEPARATOR . + '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]' . + '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]*'); + // need to return both files with and without .php suffix, so they can + // be hardened by _prependRename(), which is hooked into exists() } /** From 97047a6ef6db420c09945a15e93b957ded30079e Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 13 Nov 2022 06:37:23 +0100 Subject: [PATCH 187/506] upgrade JS libraries --- CHANGELOG.md | 4 ++-- js/common.js | 6 +++--- js/jquery-3.6.0.js | 2 -- js/jquery-3.6.1.js | 2 ++ js/purify-2.3.6.js | 2 -- js/purify-2.4.6.js | 2 ++ js/{showdown-2.0.3.js => showdown-2.1.0.js} | 2 +- tpl/bootstrap.php | 6 +++--- tpl/page.php | 6 +++--- 9 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 js/jquery-3.6.0.js create mode 100644 js/jquery-3.6.1.js delete mode 100644 js/purify-2.3.6.js create mode 100644 js/purify-2.4.6.js rename js/{showdown-2.0.3.js => showdown-2.1.0.js} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index edd85024..2f23d523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,12 @@ # PrivateBin version history - * **1.4.1 (not yet released)** + * **1.5 (not yet released)** * ADDED: script for data storage backend migrations (#1012) * ADDED: Translations for Turkish, Slovak, Greek and Thai * ADDED: S3 Storage backend (#994) * ADDED: Jdenticons as an option for comment icons (#793) * CHANGED: Avoid `SUPER` privilege for setting the `sql_mode` for MariaDB/MySQL (#919) - * CHANGED: Upgrading libraries to: zlib 1.2.13 + * CHANGED: Upgrading libraries to: DOMpurify 2.4.6, jQuery 3.6.1, Showdown 2.1.0 & zlib 1.2.13 * FIXED: Revert to CREATE INDEX without IF NOT EXISTS clauses, to support MySQL (#943) * FIXED: Apply table prefix to indexes as well, to support multiple instances sharing a single database (#943) * FIXED: YOURLS integration via new proxy, storing signature in configuration (#725) diff --git a/js/common.js b/js/common.js index 12e4c882..0d1b6738 100644 --- a/js/common.js +++ b/js/common.js @@ -10,14 +10,14 @@ global.fs = require('fs'); global.WebCrypto = require('@peculiar/webcrypto').Crypto; // application libraries to test -global.$ = global.jQuery = require('./jquery-3.6.0'); +global.$ = global.jQuery = require('./jquery-3.6.1'); global.RawDeflate = require('./rawinflate-0.3').RawDeflate; global.zlib = require('./zlib-1.2.13').zlib; require('./prettify'); global.prettyPrint = window.PR.prettyPrint; global.prettyPrintOne = window.PR.prettyPrintOne; -global.showdown = require('./showdown-2.0.3'); -global.DOMPurify = require('./purify-2.3.6'); +global.showdown = require('./showdown-2.1.0'); +global.DOMPurify = require('./purify-2.4.6'); global.baseX = require('./base-x-4.0.0').baseX; global.Legacy = require('./legacy').Legacy; require('./bootstrap-3.4.1'); diff --git a/js/jquery-3.6.0.js b/js/jquery-3.6.0.js deleted file mode 100644 index c4c6022f..00000000 --- a/js/jquery-3.6.0.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 01?n-1:0),o=1;o/gm),z=a(/^data-[\-\w.\u00B7-\uFFFF]/),B=a(/^aria-[\-\w]+$/),P=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),j=a(/^(?:\w+script|data):/i),G=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),W=a(/^html$/i),q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function Y(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t0&&void 0!==arguments[0]?arguments[0]:K(),n=function(t){return e(t)};if(n.version="2.3.6",n.removed=[],!t||!t.document||9!==t.document.nodeType)return n.isSupported=!1,n;var r=t.document,o=t.document,a=t.DocumentFragment,l=t.HTMLTemplateElement,c=t.Node,s=t.Element,u=t.NodeFilter,m=t.NamedNodeMap,A=void 0===m?t.NamedNodeMap||t.MozNamedAttrMap:m,$=t.HTMLFormElement,X=t.DOMParser,Z=t.trustedTypes,J=s.prototype,Q=w(J,"cloneNode"),ee=w(J,"nextSibling"),te=w(J,"childNodes"),ne=w(J,"parentNode");if("function"==typeof l){var re=o.createElement("template");re.content&&re.content.ownerDocument&&(o=re.content.ownerDocument)}var oe=V(Z,r),ie=oe?oe.createHTML(""):"",ae=o,le=ae.implementation,ce=ae.createNodeIterator,se=ae.createDocumentFragment,ue=ae.getElementsByTagName,me=r.importNode,fe={};try{fe=x(o).documentMode?o.documentMode:{}}catch(e){}var de={};n.isSupported="function"==typeof ne&&le&&void 0!==le.createHTMLDocument&&9!==fe;var pe=H,he=U,ge=z,ye=B,ve=j,be=G,Te=P,Ne=null,Ae=E({},[].concat(Y(k),Y(S),Y(_),Y(O),Y(M))),Ee=null,xe=E({},[].concat(Y(L),Y(R),Y(I),Y(F))),we=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),ke=null,Se=null,_e=!0,De=!0,Oe=!1,Ce=!1,Me=!1,Le=!1,Re=!1,Ie=!1,Fe=!1,He=!1,Ue=!0,ze=!0,Be=!1,Pe={},je=null,Ge=E({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),We=null,qe=E({},["audio","video","img","source","image","track"]),Ye=null,Ke=E({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Ve="http://www.w3.org/1998/Math/MathML",$e="http://www.w3.org/2000/svg",Xe="http://www.w3.org/1999/xhtml",Ze=Xe,Je=!1,Qe=void 0,et=["application/xhtml+xml","text/html"],tt="text/html",nt=void 0,rt=null,ot=o.createElement("form"),it=function(e){return e instanceof RegExp||e instanceof Function},at=function(e){rt&&rt===e||(e&&"object"===(void 0===e?"undefined":q(e))||(e={}),e=x(e),Ne="ALLOWED_TAGS"in e?E({},e.ALLOWED_TAGS):Ae,Ee="ALLOWED_ATTR"in e?E({},e.ALLOWED_ATTR):xe,Ye="ADD_URI_SAFE_ATTR"in e?E(x(Ke),e.ADD_URI_SAFE_ATTR):Ke,We="ADD_DATA_URI_TAGS"in e?E(x(qe),e.ADD_DATA_URI_TAGS):qe,je="FORBID_CONTENTS"in e?E({},e.FORBID_CONTENTS):Ge,ke="FORBID_TAGS"in e?E({},e.FORBID_TAGS):{},Se="FORBID_ATTR"in e?E({},e.FORBID_ATTR):{},Pe="USE_PROFILES"in e&&e.USE_PROFILES,_e=!1!==e.ALLOW_ARIA_ATTR,De=!1!==e.ALLOW_DATA_ATTR,Oe=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Ce=e.SAFE_FOR_TEMPLATES||!1,Me=e.WHOLE_DOCUMENT||!1,Ie=e.RETURN_DOM||!1,Fe=e.RETURN_DOM_FRAGMENT||!1,He=e.RETURN_TRUSTED_TYPE||!1,Re=e.FORCE_BODY||!1,Ue=!1!==e.SANITIZE_DOM,ze=!1!==e.KEEP_CONTENT,Be=e.IN_PLACE||!1,Te=e.ALLOWED_URI_REGEXP||Te,Ze=e.NAMESPACE||Xe,e.CUSTOM_ELEMENT_HANDLING&&it(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(we.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&it(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(we.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(we.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Qe=Qe=-1===et.indexOf(e.PARSER_MEDIA_TYPE)?tt:e.PARSER_MEDIA_TYPE,nt="application/xhtml+xml"===Qe?function(e){return e}:h,Ce&&(De=!1),Fe&&(Ie=!0),Pe&&(Ne=E({},[].concat(Y(M))),Ee=[],!0===Pe.html&&(E(Ne,k),E(Ee,L)),!0===Pe.svg&&(E(Ne,S),E(Ee,R),E(Ee,F)),!0===Pe.svgFilters&&(E(Ne,_),E(Ee,R),E(Ee,F)),!0===Pe.mathMl&&(E(Ne,O),E(Ee,I),E(Ee,F))),e.ADD_TAGS&&(Ne===Ae&&(Ne=x(Ne)),E(Ne,e.ADD_TAGS)),e.ADD_ATTR&&(Ee===xe&&(Ee=x(Ee)),E(Ee,e.ADD_ATTR)),e.ADD_URI_SAFE_ATTR&&E(Ye,e.ADD_URI_SAFE_ATTR),e.FORBID_CONTENTS&&(je===Ge&&(je=x(je)),E(je,e.FORBID_CONTENTS)),ze&&(Ne["#text"]=!0),Me&&E(Ne,["html","head","body"]),Ne.table&&(E(Ne,["tbody"]),delete ke.tbody),i&&i(e),rt=e)},lt=E({},["mi","mo","mn","ms","mtext"]),ct=E({},["foreignobject","desc","title","annotation-xml"]),st=E({},S);E(st,_),E(st,D);var ut=E({},O);E(ut,C);var mt=function(e){var t=ne(e);t&&t.tagName||(t={namespaceURI:Xe,tagName:"template"});var n=h(e.tagName),r=h(t.tagName);if(e.namespaceURI===$e)return t.namespaceURI===Xe?"svg"===n:t.namespaceURI===Ve?"svg"===n&&("annotation-xml"===r||lt[r]):Boolean(st[n]);if(e.namespaceURI===Ve)return t.namespaceURI===Xe?"math"===n:t.namespaceURI===$e?"math"===n&&ct[r]:Boolean(ut[n]);if(e.namespaceURI===Xe){if(t.namespaceURI===$e&&!ct[r])return!1;if(t.namespaceURI===Ve&&!lt[r])return!1;var o=E({},["title","style","font","a","script"]);return!ut[n]&&(o[n]||!st[n])}return!1},ft=function(e){p(n.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){try{e.outerHTML=ie}catch(t){e.remove()}}},dt=function(e,t){try{p(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){p(n.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Ee[e])if(Ie||Fe)try{ft(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},pt=function(e){var t=void 0,n=void 0;if(Re)e=""+e;else{var r=g(e,/^[\r\n\t ]+/);n=r&&r[0]}"application/xhtml+xml"===Qe&&(e=''+e+"");var i=oe?oe.createHTML(e):e;if(Ze===Xe)try{t=(new X).parseFromString(i,Qe)}catch(e){}if(!t||!t.documentElement){t=le.createDocument(Ze,"template",null);try{t.documentElement.innerHTML=Je?"":i}catch(e){}}var a=t.body||t.documentElement;return e&&n&&a.insertBefore(o.createTextNode(n),a.childNodes[0]||null),Ze===Xe?ue.call(t,Me?"html":"body")[0]:Me?t.documentElement:a},ht=function(e){return ce.call(e.ownerDocument||e,e,u.SHOW_ELEMENT|u.SHOW_COMMENT|u.SHOW_TEXT,null,!1)},gt=function(e){return e instanceof $&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof A)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore)},yt=function(e){return"object"===(void 0===c?"undefined":q(c))?e instanceof c:e&&"object"===(void 0===e?"undefined":q(e))&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName},vt=function(e,t,r){de[e]&&f(de[e],(function(e){e.call(n,t,r,rt)}))},bt=function(e){var t=void 0;if(vt("beforeSanitizeElements",e,null),gt(e))return ft(e),!0;if(g(e.nodeName,/[\u0080-\uFFFF]/))return ft(e),!0;var r=nt(e.nodeName);if(vt("uponSanitizeElement",e,{tagName:r,allowedTags:Ne}),!yt(e.firstElementChild)&&(!yt(e.content)||!yt(e.content.firstElementChild))&&T(/<[/\w]/g,e.innerHTML)&&T(/<[/\w]/g,e.textContent))return ft(e),!0;if("select"===r&&T(/