added Google Cloud Storage support

This commit is contained in:
Mark van Holsteijn 2021-05-28 22:39:50 +02:00
parent b6460616ba
commit 342270d6dd
19 changed files with 1621 additions and 16 deletions

1
.gitattributes vendored
View file

@ -16,6 +16,7 @@ js/test/ export-ignore
.jshintrc export-ignore .jshintrc export-ignore
.nsprc export-ignore .nsprc export-ignore
.php_cs export-ignore .php_cs export-ignore
.scrutinizer.yml export-ignore
.styleci.yml export-ignore .styleci.yml export-ignore
.travis.yml export-ignore .travis.yml export-ignore
composer.json export-ignore composer.json export-ignore

View file

@ -11,6 +11,8 @@ jobs:
run: composer validate run: composer validate
- name: Install dependencies - name: Install dependencies
run: /usr/bin/php7.4 $(which composer) install --prefer-dist --no-suggest run: /usr/bin/php7.4 $(which composer) install --prefer-dist --no-suggest
- name: Install Google Cloud Storage
run: /usr/bin/php7.4 $(which composer) require google/cloud-storage
PHPunit: PHPunit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
@ -29,6 +31,8 @@ jobs:
run: rm composer.lock run: rm composer.lock
- name: Setup PHPunit - name: Setup PHPunit
run: composer install -n run: composer install -n
- name: Install Google Cloud Storage
run: composer require google/cloud-storage
- name: Run unit tests - name: Run unit tests
run: ../vendor/bin/phpunit --no-coverage run: ../vendor/bin/phpunit --no-coverage
working-directory: tst working-directory: tst

4
.gitignore vendored
View file

@ -6,7 +6,7 @@ cfg/*
!cfg/.htaccess !cfg/.htaccess
# Ignore data/ # Ignore data/
data/ /data/
# Ignore PhpDoc # Ignore PhpDoc
doc/* doc/*
@ -36,3 +36,5 @@ tst/ConfigurationCombinationsTest.php
.project .project
.externalToolBuilders .externalToolBuilders
.c9 .c9
/.idea/
*.iml

39
.scrutinizer.yml Normal file
View file

@ -0,0 +1,39 @@
checks:
php: true
javascript: true
filter:
paths:
- "css/privatebin.css"
- "css/bootstrap/privatebin.css"
- "js/privatebin.js"
- "lib/*.php"
- "index.php"
excluded_paths:
- lib/Data/GoogleCloudStorage.php
- tst/Data/GoogleCloudStorageTest.php
coding_style:
php:
spaces:
around_operators:
additive: false
concatenation: true
build:
environment:
php:
version: '7.2'
tests:
override:
-
command: 'composer require google/cloud-storage && cd tst && ../vendor/bin/phpunit'
coverage:
file: 'tst/log/coverage-clover.xml'
format: 'clover'
nodes:
tests: true
analysis:
tests:
override:
-
command: phpcs-run
use_website_config: true
- php-scrutinizer-run

View file

@ -191,3 +191,15 @@ INSERT INTO prefix_config VALUES('VERSION', '1.3.5');
``` ```
In **PostgreSQL**, the data, attachment, nickname and vizhash columns needs to be TEXT and not BLOB or MEDIUMBLOB. In **PostgreSQL**, the data, attachment, nickname and vizhash columns needs to be TEXT and not BLOB or MEDIUMBLOB.
### Using Google Cloud Storage
If you want to deploy PrivateBin in a serverless manner, you can choose the `GoogleCloudStorage` as backend.
To use this backend, you create a GCS bucket and specify the name as the model option `bucket`. Alternatively,
you can set the name through the environment variable PASTEBIN_GCS_BUCKET.
The default prefix for pastes stored in the bucket is `pastes`. To change the prefix, specify the option `prefix`.
Google Cloud Storage buckets may be significantly slower than a `FileSystem` or `Database` backend. The big advantage
is that the deployment on Google Cloud Platform using Google Cloud Run is easy and cheap.
To use the Google Cloud Storage backend you have to install the suggested google/cloud-storage library.

View file

@ -167,6 +167,13 @@ class = Filesystem
[model_options] [model_options]
dir = PATH "data" dir = PATH "data"
[model]
; example of a Google Cloud Storage configuration
;class = GoogleCloudStorage
;[model_options]
;bucket = "my-private-bin"
;prefix = "pastes"
;[model] ;[model]
; example of DB configuration for MySQL ; example of DB configuration for MySQL
;class = Database ;class = Database

View file

@ -29,6 +29,9 @@
"yzalis/identicon" : "2.0.0", "yzalis/identicon" : "2.0.0",
"mlocati/ip-lib" : "1.14.0" "mlocati/ip-lib" : "1.14.0"
}, },
"suggest": {
"google/cloud-storage": "1.23.1"
},
"require-dev" : { "require-dev" : {
"phpunit/phpunit" : "^4.6 || ^5.0" "phpunit/phpunit" : "^4.6 || ^5.0"
}, },

132
composer.lock generated
View file

@ -62,6 +62,10 @@
"range", "range",
"subnet" "subnet"
], ],
"support": {
"issues": "https://github.com/mlocati/ip-lib/issues",
"source": "https://github.com/mlocati/ip-lib/tree/1.14.0"
},
"funding": [ "funding": [
{ {
"url": "https://github.com/sponsors/mlocati", "url": "https://github.com/sponsors/mlocati",
@ -121,6 +125,11 @@
"pseudorandom", "pseudorandom",
"random" "random"
], ],
"support": {
"email": "info@paragonie.com",
"issues": "https://github.com/paragonie/random_compat/issues",
"source": "https://github.com/paragonie/random_compat"
},
"time": "2021-04-17T09:33:01+00:00" "time": "2021-04-17T09:33:01+00:00"
}, },
{ {
@ -173,6 +182,10 @@
"identicon", "identicon",
"image" "image"
], ],
"support": {
"issues": "https://github.com/yzalis/Identicon/issues",
"source": "https://github.com/yzalis/Identicon/tree/master"
},
"abandoned": true, "abandoned": true,
"time": "2019-10-14T09:30:57+00:00" "time": "2019-10-14T09:30:57+00:00"
} }
@ -227,6 +240,10 @@
"constructor", "constructor",
"instantiate" "instantiate"
], ],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.0"
},
"funding": [ "funding": [
{ {
"url": "https://www.doctrine-project.org/sponsorship.html", "url": "https://www.doctrine-project.org/sponsorship.html",
@ -289,6 +306,10 @@
"object", "object",
"object graph" "object graph"
], ],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.10.2"
},
"funding": [ "funding": [
{ {
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
@ -344,6 +365,10 @@
"reflection", "reflection",
"static analysis" "static analysis"
], ],
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
},
"time": "2020-06-27T09:03:43+00:00" "time": "2020-06-27T09:03:43+00:00"
}, },
{ {
@ -396,6 +421,10 @@
} }
], ],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "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/master"
},
"time": "2020-09-03T19:13:55+00:00" "time": "2020-09-03T19:13:55+00:00"
}, },
{ {
@ -441,6 +470,10 @@
} }
], ],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0"
},
"time": "2020-09-17T18:55:26+00:00" "time": "2020-09-17T18:55:26+00:00"
}, },
{ {
@ -504,6 +537,10 @@
"spy", "spy",
"stub" "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" "time": "2020-03-05T15:02:03+00:00"
}, },
{ {
@ -567,6 +604,11 @@
"testing", "testing",
"xunit" "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" "time": "2017-04-02T07:44:40+00:00"
}, },
{ {
@ -614,6 +656,11 @@
"filesystem", "filesystem",
"iterator" "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" "time": "2017-11-27T13:52:08+00:00"
}, },
{ {
@ -655,6 +702,10 @@
"keywords": [ "keywords": [
"template" "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" "time": "2015-06-21T13:50:34+00:00"
}, },
{ {
@ -704,6 +755,10 @@
"keywords": [ "keywords": [
"timer" "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" "time": "2017-02-26T11:10:40+00:00"
}, },
{ {
@ -753,6 +808,10 @@
"keywords": [ "keywords": [
"tokenizer" "tokenizer"
], ],
"support": {
"issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
"source": "https://github.com/sebastianbergmann/php-token-stream/tree/master"
},
"abandoned": true, "abandoned": true,
"time": "2017-11-27T05:48:46+00:00" "time": "2017-11-27T05:48:46+00:00"
}, },
@ -836,6 +895,10 @@
"testing", "testing",
"xunit" "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" "time": "2018-02-01T05:50:59+00:00"
}, },
{ {
@ -895,6 +958,11 @@
"mock", "mock",
"xunit" "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, "abandoned": true,
"time": "2017-06-30T09:13:00+00:00" "time": "2017-06-30T09:13:00+00:00"
}, },
@ -941,6 +1009,10 @@
], ],
"description": "Looks up which function or method a line of code belongs to", "description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "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": [ "funding": [
{ {
"url": "https://github.com/sebastianbergmann", "url": "https://github.com/sebastianbergmann",
@ -1011,6 +1083,10 @@
"compare", "compare",
"equality" "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" "time": "2017-01-29T09:50:25+00:00"
}, },
{ {
@ -1063,6 +1139,10 @@
"keywords": [ "keywords": [
"diff" "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" "time": "2017-05-22T07:24:03+00:00"
}, },
{ {
@ -1113,6 +1193,10 @@
"environment", "environment",
"hhvm" "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" "time": "2016-11-26T07:53:53+00:00"
}, },
{ {
@ -1180,6 +1264,10 @@
"export", "export",
"exporter" "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" "time": "2016-11-19T08:54:04+00:00"
}, },
{ {
@ -1231,6 +1319,10 @@
"keywords": [ "keywords": [
"global state" "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" "time": "2015-10-12T03:26:01+00:00"
}, },
{ {
@ -1277,6 +1369,10 @@
], ],
"description": "Traverses array structures and object graphs to enumerate all referenced objects", "description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/", "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" "time": "2017-02-18T15:18:39+00:00"
}, },
{ {
@ -1330,6 +1426,10 @@
], ],
"description": "Provides functionality to recursively process PHP variables", "description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context", "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" "time": "2016-11-19T07:33:16+00:00"
}, },
{ {
@ -1372,6 +1472,10 @@
], ],
"description": "Provides a list of PHP built-in functions that operate on resources", "description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations", "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" "time": "2015-07-28T20:34:47+00:00"
}, },
{ {
@ -1415,20 +1519,24 @@
], ],
"description": "Library that helps with managing the version number of Git-hosted PHP projects", "description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version", "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" "time": "2016-10-03T07:35:21+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.22.1", "version": "v1.23.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git", "url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "c6c942b1ac76c82448322025e084cadc56048b4e" "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"reference": "c6c942b1ac76c82448322025e084cadc56048b4e", "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1440,7 +1548,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "1.22-dev" "dev-main": "1.23-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
@ -1477,6 +1585,9 @@
"polyfill", "polyfill",
"portable" "portable"
], ],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
},
"funding": [ "funding": [
{ {
"url": "https://symfony.com/sponsor", "url": "https://symfony.com/sponsor",
@ -1491,7 +1602,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-01-07T16:49:33+00:00" "time": "2021-02-19T12:13:01+00:00"
}, },
{ {
"name": "symfony/yaml", "name": "symfony/yaml",
@ -1545,6 +1656,9 @@
], ],
"description": "Loads and dumps YAML files", "description": "Loads and dumps YAML files",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v4.4.24"
},
"funding": [ "funding": [
{ {
"url": "https://symfony.com/sponsor", "url": "https://symfony.com/sponsor",
@ -1613,6 +1727,10 @@
"check", "check",
"validate" "validate"
], ],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.10.0"
},
"time": "2021-03-09T10:59:23+00:00" "time": "2021-03-09T10:59:23+00:00"
} }
], ],
@ -1625,5 +1743,5 @@
"php": "^5.6.0 || ^7.0 || ^8.0" "php": "^5.6.0 || ^7.0 || ^8.0"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "1.1.0" "plugin-api-version": "2.0.0"
} }

View file

@ -153,6 +153,16 @@ class Configuration
'pwd' => null, 'pwd' => null,
'opt' => array(PDO::ATTR_PERSISTENT => true), 'opt' => array(PDO::ATTR_PERSISTENT => true),
); );
} elseif (
$section == 'model_options' && in_array(
$this->_configuration['model']['class'],
array('GoogleCloudStorage')
)
) {
$values = array(
'bucket' => getenv('PRIVATEBIN_GCS_BUCKET') ? getenv('PRIVATEBIN_GCS_BUCKET') : null,
'prefix' => 'pastes',
);
} }
// "*_options" sections don't require all defaults to be set // "*_options" sections don't require all defaults to be set

View file

@ -0,0 +1,251 @@
<?php
namespace PrivateBin\Data;
use Exception;
use Google\Cloud\Core\Exception\NotFoundException;
use Google\Cloud\Storage\StorageClient;
use PrivateBin\Json;
class GoogleCloudStorage extends AbstractData
{
/**
* returns a Google Cloud Storage data backend.
*
* @access public
* @static
* @param array $options
* @return GoogleCloudStorage
*/
public static function getInstance(array $options)
{
$client = null;
$bucket = null;
$prefix = 'pastes';
if (getenv('PRIVATEBIN_GCS_BUCKET')) {
$bucket = getenv('PRIVATEBIN_GCS_BUCKET');
}
if (is_array($options) && array_key_exists('bucket', $options)) {
$bucket = $options['bucket'];
}
if (is_array($options) && array_key_exists('prefix', $options)) {
$prefix = $options['prefix'];
}
if (is_array($options) && array_key_exists('client', $options)) {
$client = $options['client'];
}
if (!(self::$_instance instanceof self)) {
self::$_instance = new self($bucket, $prefix, $client);
}
return self::$_instance;
}
protected $_client = null;
protected $_bucket = null;
protected $_prefix = 'pastes';
public function __construct($bucket, $prefix, $client = null)
{
parent::__construct();
if ($client == null) {
$this->_client = new StorageClient(array('suppressKeyFileNotice' => true));
} else {
// use given client for test purposes
$this->_client = $client;
}
$this->_bucket = $this->_client->bucket($bucket);
if ($prefix != null) {
$this->_prefix = $prefix;
}
}
/**
* returns the google storage object key for $pasteid in $this->_bucket.
* @param $pasteid string to get the key for
* @return string
*/
private function _getKey($pasteid)
{
if ($this->_prefix != '') {
return $this->_prefix . '/' . $pasteid;
}
return $pasteid;
}
/**
* Uploads the payload in the $this->_bucket under the specified key.
* The entire payload is stored as a JSON document. The metadata is replicated
* as the GCS object's metadata except for the fields attachment, attachmentname
* and salt.
*
* @param $key string to store the payload under
* @param $payload array to store
* @return bool true if successful, otherwise false.
*/
private function upload($key, $payload)
{
$metadata = array_key_exists('meta', $payload) ? $payload['meta'] : array();
unset($metadata['attachment'], $metadata['attachmentname'], $metadata['salt']);
foreach ($metadata as $k => $v) {
$metadata[$k] = strval($v);
}
try {
$this->_bucket->upload(Json::encode($payload), array(
'name' => $key,
'chunkSize' => 262144,
'predefinedAcl' => 'private',
'metadata' => array(
'content-type' => 'application/json',
'metadata' => $metadata,
),
));
} catch (Exception $e) {
error_log('failed to upload ' . $key . ' to ' . $this->_bucket->name() . ', ' .
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 {
$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 ' . $this->_bucket->name() . ', ' .
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
return false;
}
}
/**
* @inheritDoc
*/
public function delete($pasteid)
{
$name = $this->_getKey($pasteid);
try {
foreach ($this->_bucket->objects(array('prefix' => $name . '/discussion/')) as $comment) {
try {
$this->_bucket->object($comment->name())->delete();
} catch (NotFoundException $e) {
// ignore if already deleted.
}
}
} catch (NotFoundException $e) {
// there are no discussions associated with the paste
}
try {
$this->_bucket->object($name)->delete();
} catch (NotFoundException $e) {
// ignore if already deleted
}
}
/**
* @inheritDoc
*/
public function exists($pasteid)
{
$o = $this->_bucket->object($this->_getKey($pasteid));
return $o->exists();
}
/**
* @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 {
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;
}
} catch (NotFoundException $e) {
// no comments found
}
return $comments;
}
/**
* @inheritDoc
*/
public function existsComment($pasteid, $parentid, $commentid)
{
$name = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid;
$o = $this->_bucket->object($name);
return $o->exists();
}
/**
* @inheritDoc
*/
protected function _getExpiredPastes($batchsize)
{
$expired = array();
$now = time();
$prefix = $this->_prefix;
if ($prefix != '') {
$prefix = $prefix . '/';
}
try {
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']);
if ($expire_at != 0 && $expire_at < $now) {
array_push($expired, basename($object->name()));
}
}
if (count($expired) > $batchsize) {
break;
}
}
} catch (NotFoundException $e) {
// no objects in the bucket yet
}
return $expired;
}
}

View file

@ -126,11 +126,11 @@ class TrafficLimiter extends AbstractPersistence
$range = Factory::rangeFromString($ipRange); $range = Factory::rangeFromString($ipRange);
// address could not be parsed, we might not be in IP space and try a string comparison instead // address could not be parsed, we might not be in IP space and try a string comparison instead
if ($address == null) { if (is_null($address)) {
return $_SERVER[self::$_ipKey] === $ipRange; return $_SERVER[self::$_ipKey] === $ipRange;
} }
// range could not be parsed, possibly an invalid ip range given in config // range could not be parsed, possibly an invalid ip range given in config
if ($range == null) { if (is_null($range)) {
return false; return false;
} }

View file

@ -0,0 +1,715 @@
<?php
use Google\Auth\HttpHandler\HttpHandlerFactory;
use Google\Cloud\Core\Exception\BadRequestException;
use Google\Cloud\Core\Exception\NotFoundException;
use Google\Cloud\Storage\Bucket;
use Google\Cloud\Storage\Connection\ConnectionInterface;
use Google\Cloud\Storage\StorageClient;
use Google\Cloud\Storage\StorageObject;
use GuzzleHttp\Client;
use PrivateBin\Data\GoogleCloudStorage;
class GoogleCloudStorageTest extends PHPUnit_Framework_TestCase
{
private static $_client;
private static $_bucket;
public static function setUpBeforeClass()
{
$httpClient = new Client(array('debug'=>false));
$handler = HttpHandlerFactory::build($httpClient);
$name = 'pb-';
$alphabet = 'abcdefghijklmnopqrstuvwxyz';
for ($i = 0; $i < 29; ++$i) {
$name .= $alphabet[rand(0, strlen($alphabet) - 1)];
}
self::$_client = new StorageClientStub(array());
self::$_bucket = self::$_client->createBucket($name);
}
public function setUp()
{
// do not report E_NOTICE as fsouza/fake-gcs-server does not return a `generation` value in the response
// which the Google Cloud Storage PHP library expects.
error_reporting(E_ERROR | E_WARNING | E_PARSE);
$this->_model = GoogleCloudStorage::getInstance(array(
'bucket' => self::$_bucket->name(),
'prefix' => 'pastes',
'client' => self::$_client, ));
}
public function tearDown()
{
foreach (self::$_bucket->objects() as $object) {
$object->delete();
}
error_reporting(E_ALL);
}
public static function tearDownAfterClass()
{
self::$_bucket->delete();
}
public function testFileBasedDataStoreWorks()
{
$this->_model->delete(Helper::getPasteId());
// storing pastes
$paste = Helper::getPaste(2, array('expire_date' => 1344803344));
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
$this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
$this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store the same paste twice');
$this->assertEquals($paste, $this->_model->read(Helper::getPasteId()));
// storing comments
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does not yet exist');
$this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()), 'store comment');
$this->assertTrue($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment exists after storing it');
$this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()), 'unable to store the same comment twice');
$comment = Helper::getComment();
$comment['id'] = Helper::getCommentId();
$comment['parentid'] = Helper::getPasteId();
$this->assertEquals(
array($comment['meta']['created'] => $comment),
$this->_model->readComments(Helper::getPasteId())
);
// deleting pastes
$this->_model->delete(Helper::getPasteId());
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment was deleted with paste');
$this->assertFalse($this->_model->read(Helper::getPasteId()), 'paste can no longer be found');
}
/**
* pastes a-g are expired and should get deleted, x never expires and y-z expire in an hour
*/
public function testPurge()
{
$expired = Helper::getPaste(2, array('expire_date' => 1344803344));
$paste = Helper::getPaste(2, array('expire_date' => time() + 3600));
$keys = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z');
$ids = array();
foreach ($keys as $key) {
$ids[$key] = hash('fnv164', $key);
$this->assertFalse($this->_model->exists($ids[$key]), "paste $key does not yet exist");
if (in_array($key, array('x', 'y', 'z'))) {
$this->assertTrue($this->_model->create($ids[$key], $paste), "store $key paste");
} elseif ($key === 'x') {
$this->assertTrue($this->_model->create($ids[$key], Helper::getPaste()), "store $key paste");
} else {
$this->assertTrue($this->_model->create($ids[$key], $expired), "store $key paste");
}
$this->assertTrue($this->_model->exists($ids[$key]), "paste $key exists after storing it");
}
$this->_model->purge(10);
foreach ($ids as $key => $id) {
if (in_array($key, array('x', 'y', 'z'))) {
$this->assertTrue($this->_model->exists($id), "paste $key exists after purge");
$this->_model->delete($id);
} else {
$this->assertFalse($this->_model->exists($id), "paste $key was purged");
}
}
}
public function testErrorDetection()
{
$this->_model->delete(Helper::getPasteId());
$paste = Helper::getPaste(2, array('expire' => "Invalid UTF-8 sequence: \xB1\x31"));
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
$this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store broken paste');
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does still not exist');
}
public function testCommentErrorDetection()
{
$this->_model->delete(Helper::getPasteId());
$comment = Helper::getComment(1, array('nickname' => "Invalid UTF-8 sequence: \xB1\x31"));
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
$this->assertTrue($this->_model->create(Helper::getPasteId(), Helper::getPaste()), 'store new paste');
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does not yet exist');
$this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), $comment), 'unable to store broken comment');
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does still not exist');
}
}
/**
* Class StorageClientStub provides a limited stub for performing the unit test
*/
class StorageClientStub extends StorageClient
{
private $_config = null;
private $_connection = null;
private $_buckets = array();
public function __construct(array $config = array())
{
$this->_config = $config;
$this->_connection = new ConnectionInterfaceStub();
}
public function bucket($name, $userProject = false)
{
if (!key_exists($name, $this->_buckets)) {
$b = new BucketStub($this->_connection, $name, array(), $this);
$this->_buckets[$name] = $b;
}
return $this->_buckets[$name];
}
/**
* @throws \Google\Cloud\Core\Exception\NotFoundException
*/
public function deleteBucket($name)
{
if (key_exists($name, $this->_buckets)) {
unset($this->_buckets[$name]);
} else {
throw new NotFoundException();
}
}
public function buckets(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function registerStreamWrapper($protocol = null)
{
throw new BadMethodCallException('not supported by this stub');
}
public function unregisterStreamWrapper($protocol = null)
{
throw new BadMethodCallException('not supported by this stub');
}
public function signedUrlUploader($uri, $data, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function timestamp(\DateTimeInterface $timestamp, $nanoSeconds = null)
{
throw new BadMethodCallException('not supported by this stub');
}
public function getServiceAccount(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function hmacKeys(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function hmacKey($accessId, $projectId = null, array $metadata = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function createHmacKey($serviceAccountEmail, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function createBucket($name, array $options = array())
{
if (key_exists($name, $this->_buckets)) {
throw new BadRequestException('already exists');
}
$b = new BucketStub($this->_connection, $name, array(), $this);
$this->_buckets[$name] = $b;
return $b;
}
}
/**
* Class BucketStub stubs a GCS bucket.
*/
class BucketStub extends Bucket
{
public $_objects;
private $_name;
private $_info;
private $_connection;
private $_client;
public function __construct(ConnectionInterface $connection, $name, array $info = array(), $client = null)
{
$this->_name = $name;
$this->_info = $info;
$this->_connection = $connection;
$this->_objects = array();
$this->_client = $client;
}
public function acl()
{
throw new BadMethodCallException('not supported by this stub');
}
public function defaultAcl()
{
throw new BadMethodCallException('not supported by this stub');
}
public function exists()
{
return true;
}
public function upload($data, array $options = array())
{
if (!is_string($data) || !key_exists('name', $options)) {
throw new BadMethodCallException('not supported by this stub');
}
$name = $options['name'];
$generation = '1';
$o = new StorageObjectStub($this->_connection, $name, $this, $generation, $options);
$this->_objects[$options['name']] = $o;
$o->setData($data);
}
public function uploadAsync($data, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getResumableUploader($data, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getStreamableUploader($data, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function object($name, array $options = array())
{
if (key_exists($name, $this->_objects)) {
return $this->_objects[$name];
} else {
return new StorageObjectStub($this->_connection, $name, $this, null, $options);
}
}
public function objects(array $options = array())
{
$prefix = key_exists('prefix', $options) ? $options['prefix'] : '';
return new CallbackFilterIterator(
new ArrayIterator($this->_objects),
function ($current, $key, $iterator) use ($prefix) {
return substr($key, 0, strlen($prefix)) == $prefix;
}
);
}
public function createNotification($topic, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function notification($id)
{
throw new BadMethodCallException('not supported by this stub');
}
public function notifications(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function delete(array $options = array())
{
$this->_client->deleteBucket($this->_name);
}
public function update(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function compose(array $sourceObjects, $name, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function info(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function reload(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function name()
{
return $this->_name;
}
public static function lifecycle(array $lifecycle = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function currentLifecycle(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function isWritable($file = null)
{
throw new BadMethodCallException('not supported by this stub');
}
public function iam()
{
throw new BadMethodCallException('not supported by this stub');
}
public function lockRetentionPolicy(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function signedUrl($expires, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function generateSignedPostPolicyV4($objectName, $expires, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
}
/**
* Class StorageObjectStub stubs a GCS storage object.
*/
class StorageObjectStub extends StorageObject
{
private $_name;
private $_data;
private $_info;
private $_bucket;
private $_generation;
private $_exists = false;
private $_connection;
public function __construct(ConnectionInterface $connection, $name, $bucket, $generation = null, array $info = array(), $encryptionKey = null, $encryptionKeySHA256 = null)
{
$this->_name = $name;
$this->_bucket = $bucket;
$this->_generation = $generation;
$this->_info = $info;
$this->_connection = $connection;
}
public function acl()
{
throw new BadMethodCallException('not supported by this stub');
}
public function exists(array $options = array())
{
return key_exists($this->_name, $this->_bucket->_objects);
}
/**
* @throws NotFoundException
*/
public function delete(array $options = array())
{
if (key_exists($this->_name, $this->_bucket->_objects)) {
unset($this->_bucket->_objects[$this->_name]);
} else {
throw new NotFoundException('key ' . $this->_name . ' not found.');
}
}
/**
* @throws NotFoundException
*/
public function update(array $metadata, array $options = array())
{
if (!$this->_exists) {
throw new NotFoundException('key ' . $this->_name . ' not found.');
}
$this->_info = $metadata;
}
public function copy($destination, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function rewrite($destination, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function rename($name, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
/**
* @throws NotFoundException
*/
public function downloadAsString(array $options = array())
{
if (!$this->_exists) {
throw new NotFoundException('key ' . $this->_name . ' not found.');
}
return $this->_data;
}
public function downloadToFile($path, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function downloadAsStream(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function downloadAsStreamAsync(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function signedUrl($expires, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function signedUploadUrl($expires, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function beginSignedUploadSession(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function info(array $options = array())
{
return key_exists('metadata',$this->_info) ? $this->_info['metadata'] : array();
}
public function reload(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function name()
{
return $this->_name;
}
public function identity()
{
throw new BadMethodCallException('not supported by this stub');
}
public function gcsUri()
{
return sprintf(
'gs://%s/%s',
$this->_bucket->name(),
$this->_name
);
}
public function setData($data)
{
$this->_data = $data;
$this->_exists = true;
}
}
/**
* Class ConnectionInterfaceStub required for the stubs.
*/
class ConnectionInterfaceStub implements ConnectionInterface
{
public function deleteAcl(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getAcl(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function listAcl(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function insertAcl(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function patchAcl(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function deleteBucket(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getBucket(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function listBuckets(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function insertBucket(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getBucketIamPolicy(array $args)
{
throw new BadMethodCallException('not supported by this stub');
}
public function setBucketIamPolicy(array $args)
{
throw new BadMethodCallException('not supported by this stub');
}
public function testBucketIamPermissions(array $args)
{
throw new BadMethodCallException('not supported by this stub');
}
public function patchBucket(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function deleteObject(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function copyObject(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function rewriteObject(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function composeObject(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getObject(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function listObjects(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function patchObject(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function downloadObject(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function insertObject(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getNotification(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function deleteNotification(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function insertNotification(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function listNotifications(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getServiceAccount(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function lockRetentionPolicy(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function createHmacKey(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function deleteHmacKey(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function getHmacKey(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function updateHmacKey(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function listHmacKeys(array $args = array())
{
throw new BadMethodCallException('not supported by this stub');
}
}

View file

@ -37,11 +37,13 @@ namespace Composer\Autoload;
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/ * @see https://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/ * @see https://www.php-fig.org/psr/psr-4/
*/ */
class ClassLoader class ClassLoader
{ {
private $vendorDir;
// PSR-4 // PSR-4
private $prefixLengthsPsr4 = array(); private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array(); private $prefixDirsPsr4 = array();
@ -57,10 +59,17 @@ class ClassLoader
private $missingClasses = array(); private $missingClasses = array();
private $apcuPrefix; private $apcuPrefix;
private static $registeredLoaders = array();
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
public function getPrefixes() public function getPrefixes()
{ {
if (!empty($this->prefixesPsr0)) { 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();
@ -300,6 +309,17 @@ class ClassLoader
public function register($prepend = false) public function register($prepend = false)
{ {
spl_autoload_register(array($this, 'loadClass'), true, $prepend); 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;
}
} }
/** /**
@ -308,6 +328,10 @@ class ClassLoader
public function unregister() public function unregister()
{ {
spl_autoload_unregister(array($this, 'loadClass')); spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
} }
/** /**
@ -367,6 +391,16 @@ class ClassLoader
return $file; return $file;
} }
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
private function findFileWithExtension($class, $ext) private function findFileWithExtension($class, $ext)
{ {
// PSR-4 lookup // PSR-4 lookup

326
vendor/composer/InstalledVersions.php vendored Normal file
View file

@ -0,0 +1,326 @@
<?php
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
class InstalledVersions
{
private static $installed = array (
'root' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => 'b6460616baa2d7f0a940dffd3f5b5efb9ecd00fd',
'name' => 'privatebin/privatebin',
),
'versions' =>
array (
'mlocati/ip-lib' =>
array (
'pretty_version' => '1.14.0',
'version' => '1.14.0.0',
'aliases' =>
array (
),
'reference' => '882bc0e115970a536b13bcfa59f312783fce08c8',
),
'paragonie/random_compat' =>
array (
'pretty_version' => 'v2.0.20',
'version' => '2.0.20.0',
'aliases' =>
array (
),
'reference' => '0f1f60250fccffeaf5dda91eea1c018aed1adc2a',
),
'privatebin/privatebin' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => 'b6460616baa2d7f0a940dffd3f5b5efb9ecd00fd',
),
'yzalis/identicon' =>
array (
'pretty_version' => '2.0.0',
'version' => '2.0.0.0',
'aliases' =>
array (
),
'reference' => 'ff5ed090129cab9bfa2a322857d4a01d107aa0ae',
),
),
);
private static $canGetVendors;
private static $installedByVendor = array();
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)));
}
public static function isInstalled($packageName)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return true;
}
}
return false;
}
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
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');
}
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');
}
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');
}
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');
}
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
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);
return self::$installed;
}
public static function getAllRawData()
{
return self::getInstalled();
}
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
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';
}
}
}
$installed[] = self::$installed;
return $installed;
}
}

View file

@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'IPLib\\Address\\AddressInterface' => $vendorDir . '/mlocati/ip-lib/src/Address/AddressInterface.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\\AssignedRange' => $vendorDir . '/mlocati/ip-lib/src/Address/AssignedRange.php',
'IPLib\\Address\\IPv4' => $vendorDir . '/mlocati/ip-lib/src/Address/IPv4.php', 'IPLib\\Address\\IPv4' => $vendorDir . '/mlocati/ip-lib/src/Address/IPv4.php',
@ -31,6 +32,7 @@ return array(
'PrivateBin\\Data\\AbstractData' => $baseDir . '/lib/Data/AbstractData.php', 'PrivateBin\\Data\\AbstractData' => $baseDir . '/lib/Data/AbstractData.php',
'PrivateBin\\Data\\Database' => $baseDir . '/lib/Data/Database.php', 'PrivateBin\\Data\\Database' => $baseDir . '/lib/Data/Database.php',
'PrivateBin\\Data\\Filesystem' => $baseDir . '/lib/Data/Filesystem.php', 'PrivateBin\\Data\\Filesystem' => $baseDir . '/lib/Data/Filesystem.php',
'PrivateBin\\Data\\GoogleCloudStorage' => $baseDir . '/lib/Data/GoogleCloudStorage.php',
'PrivateBin\\Filter' => $baseDir . '/lib/Filter.php', 'PrivateBin\\Filter' => $baseDir . '/lib/Filter.php',
'PrivateBin\\FormatV2' => $baseDir . '/lib/FormatV2.php', 'PrivateBin\\FormatV2' => $baseDir . '/lib/FormatV2.php',
'PrivateBin\\I18n' => $baseDir . '/lib/I18n.php', 'PrivateBin\\I18n' => $baseDir . '/lib/I18n.php',

View file

@ -22,13 +22,15 @@ class ComposerAutoloaderInitDontChange
return self::$loader; return self::$loader;
} }
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInitDontChange', 'loadClassLoader'), true, true); 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')); spl_autoload_unregister(array('ComposerAutoloaderInitDontChange', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) { if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php'; require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitDontChange::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInitDontChange::getInitializer($loader));
} else { } else {

View file

@ -38,6 +38,7 @@ class ComposerStaticInitDontChange
); );
public static $classMap = array ( public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'IPLib\\Address\\AddressInterface' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AddressInterface.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\\AssignedRange' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/AssignedRange.php',
'IPLib\\Address\\IPv4' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/IPv4.php', 'IPLib\\Address\\IPv4' => __DIR__ . '/..' . '/mlocati/ip-lib/src/Address/IPv4.php',
@ -63,6 +64,7 @@ class ComposerStaticInitDontChange
'PrivateBin\\Data\\AbstractData' => __DIR__ . '/../..' . '/lib/Data/AbstractData.php', 'PrivateBin\\Data\\AbstractData' => __DIR__ . '/../..' . '/lib/Data/AbstractData.php',
'PrivateBin\\Data\\Database' => __DIR__ . '/../..' . '/lib/Data/Database.php', 'PrivateBin\\Data\\Database' => __DIR__ . '/../..' . '/lib/Data/Database.php',
'PrivateBin\\Data\\Filesystem' => __DIR__ . '/../..' . '/lib/Data/Filesystem.php', 'PrivateBin\\Data\\Filesystem' => __DIR__ . '/../..' . '/lib/Data/Filesystem.php',
'PrivateBin\\Data\\GoogleCloudStorage' => __DIR__ . '/../..' . '/lib/Data/GoogleCloudStorage.php',
'PrivateBin\\Filter' => __DIR__ . '/../..' . '/lib/Filter.php', 'PrivateBin\\Filter' => __DIR__ . '/../..' . '/lib/Filter.php',
'PrivateBin\\FormatV2' => __DIR__ . '/../..' . '/lib/FormatV2.php', 'PrivateBin\\FormatV2' => __DIR__ . '/../..' . '/lib/FormatV2.php',
'PrivateBin\\I18n' => __DIR__ . '/../..' . '/lib/I18n.php', 'PrivateBin\\I18n' => __DIR__ . '/../..' . '/lib/I18n.php',

51
vendor/composer/installed.php vendored Normal file
View file

@ -0,0 +1,51 @@
<?php return array (
'root' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => 'b6460616baa2d7f0a940dffd3f5b5efb9ecd00fd',
'name' => 'privatebin/privatebin',
),
'versions' =>
array (
'mlocati/ip-lib' =>
array (
'pretty_version' => '1.14.0',
'version' => '1.14.0.0',
'aliases' =>
array (
),
'reference' => '882bc0e115970a536b13bcfa59f312783fce08c8',
),
'paragonie/random_compat' =>
array (
'pretty_version' => 'v2.0.20',
'version' => '2.0.20.0',
'aliases' =>
array (
),
'reference' => '0f1f60250fccffeaf5dda91eea1c018aed1adc2a',
),
'privatebin/privatebin' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => 'b6460616baa2d7f0a940dffd3f5b5efb9ecd00fd',
),
'yzalis/identicon' =>
array (
'pretty_version' => '2.0.0',
'version' => '2.0.0.0',
'aliases' =>
array (
),
'reference' => 'ff5ed090129cab9bfa2a322857d4a01d107aa0ae',
),
),
);

26
vendor/composer/platform_check.php vendored Normal file
View file

@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 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
);
}