Compare commits
32 Commits
jdenticons
...
bin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0288d94a68 | ||
|
|
94aab6d64b | ||
|
|
a799351db3 | ||
|
|
8ede84f000 | ||
|
|
6caf1143df | ||
|
|
669c98550c | ||
|
|
14075cea78 | ||
|
|
bde7a19971 | ||
|
|
5195adfdb9 | ||
|
|
3028c22c20 | ||
|
|
f4eed668e7 | ||
|
|
9a1f3aeca5 | ||
|
|
07ad9ad0f4 | ||
|
|
833cf93209 | ||
|
|
62bb68344c | ||
|
|
8389c2a2d6 | ||
|
|
05f77e45bc | ||
|
|
a33721e3ab | ||
|
|
10013ad092 | ||
|
|
75d28ef423 | ||
|
|
604c931875 | ||
|
|
3d485ecd7f | ||
|
|
726f54ce9e | ||
|
|
66600e5eb3 | ||
|
|
987ead2719 | ||
|
|
bde5802a3a | ||
|
|
9a61e8fd48 | ||
|
|
449dbb8377 | ||
|
|
606d70863e | ||
|
|
b63de431a7 | ||
|
|
be1989b117 | ||
|
|
432d3e71d3 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
bin/configuration-test-generator export-ignore
|
||||||
|
bin/icon-test export-ignore
|
||||||
doc/ export-ignore
|
doc/ export-ignore
|
||||||
tst/ export-ignore
|
tst/ export-ignore
|
||||||
img/browserstack.svg export-ignore
|
img/browserstack.svg export-ignore
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# PrivateBin version history
|
# PrivateBin version history
|
||||||
|
|
||||||
* **1.4.1 (not yet released)**
|
* **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 and Greek
|
||||||
* ADDED: S3 Storage backend (#994)
|
* ADDED: S3 Storage backend (#994)
|
||||||
* CHANGED: Switched to Jdenticons as the default for comment icons (#793)
|
* CHANGED: Switched to Jdenticons as the default for comment icons (#793)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
* Austin Huang - Oracle database support
|
* Austin Huang - Oracle database support
|
||||||
* Felix J. Ogris - S3 Storage backend
|
* Felix J. Ogris - S3 Storage backend
|
||||||
* Mounir Idrassi & J. Mozdzen - secure YOURLS integration
|
* Mounir Idrassi & J. Mozdzen - secure YOURLS integration
|
||||||
|
* Felix J. Ogris - script for data backend migrations, dropped singleton behaviour of data backends
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
* Hexalyse - French
|
* Hexalyse - French
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ install and configure PrivateBin on your server. It's available on
|
|||||||
### Changing the Path
|
### Changing the Path
|
||||||
|
|
||||||
In the index.php you can define a different `PATH`. This is useful to secure
|
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
|
your installation. You can move the utilities, configuration, data files,
|
||||||
libraries (directories cfg, doc, data, lib, tpl, tst and vendor) outside of your
|
templates and PHP libraries (directories bin, cfg, doc, data, lib, tpl, tst and
|
||||||
document root. This new location must still be accessible to your webserver and
|
vendor) outside of your document root. This new location must still be
|
||||||
PHP process (see also
|
accessible to your webserver and PHP process (see also
|
||||||
[open_basedir setting](https://secure.php.net/manual/en/ini.core.php#ini.open-basedir)).
|
[open_basedir setting](https://secure.php.net/manual/en/ini.core.php#ini.open-basedir)).
|
||||||
|
|
||||||
> #### PATH Example
|
> #### PATH Example
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
* DANGER: Too many options/settings and too high max iteration setting may trigger
|
* DANGER: Too many options/settings and too high max iteration setting may trigger
|
||||||
* a fork bomb. Please save your work before executing this script.
|
* 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');
|
$vd = array('view', 'delete');
|
||||||
$vcd = array('view', 'create', 'delete');
|
$vcd = array('view', 'create', 'delete');
|
||||||
@@ -392,7 +394,7 @@ class ConfigurationTestGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$code .= '}' . PHP_EOL;
|
$code .= '}' . PHP_EOL;
|
||||||
file_put_contents('ConfigurationCombinationsTest.php', $code);
|
file_put_contents(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'tst' . DIRECTORY_SEPARATOR . 'ConfigurationCombinationsTest.php', $code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -427,7 +429,9 @@ class ConfigurationCombinationsTest extends PHPUnit_Framework_TestCase
|
|||||||
/* Setup Routine */
|
/* Setup Routine */
|
||||||
Helper::confBackup();
|
Helper::confBackup();
|
||||||
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
||||||
$this->_model = Filesystem::getInstance(array('dir' => $this->_path));
|
$this->_model = new Filesystem(array('dir' => $this->_path));
|
||||||
|
ServerSalt::setStore($this->_model);
|
||||||
|
TrafficLimiter::setStore($this->_model);
|
||||||
$this->reset();
|
$this->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
199
bin/migrate
Executable file
199
bin/migrate
Executable file
@@ -0,0 +1,199 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// change this, if your php files and data is outside of your webservers document root
|
||||||
|
define('PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
|
define('PUBLIC_PATH', __DIR__ . DIRECTORY_SEPARATOR);
|
||||||
|
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",
|
||||||
|
"delete-during"
|
||||||
|
);
|
||||||
|
$opts_arr = getopt("fhnv", $longopts, $rest);
|
||||||
|
if ($opts_arr === false) {
|
||||||
|
dieerr("Erroneous command line options. Please use -h");
|
||||||
|
}
|
||||||
|
if (array_key_exists("h", $opts_arr)) {
|
||||||
|
helpexit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$delete_after = array_key_exists("delete-after", $opts_arr);
|
||||||
|
$delete_during = array_key_exists("delete-during", $opts_arr);
|
||||||
|
$force_overwrite = array_key_exists("f", $opts_arr);
|
||||||
|
$dryrun = array_key_exists("n", $opts_arr);
|
||||||
|
$verbose = array_key_exists("v", $opts_arr);
|
||||||
|
|
||||||
|
if ($rest >= $argc) {
|
||||||
|
dieerr("Missing source configuration directory");
|
||||||
|
}
|
||||||
|
if ($delete_after && $delete_during) {
|
||||||
|
dieerr("--delete-after and --delete-during are mutually exclusive");
|
||||||
|
}
|
||||||
|
|
||||||
|
$srcconf = getConfig("source", $argv[$rest]);
|
||||||
|
$rest++;
|
||||||
|
$dstconf = getConfig("destination", ($rest < $argc ? $argv[$rest] : ""));
|
||||||
|
|
||||||
|
if (($srcconf->getSection("model") == $dstconf->getSection("model")) &&
|
||||||
|
($srcconf->getSection("model_options") == $dstconf->getSection("model_options"))) {
|
||||||
|
dieerr("Source and destination storage configurations are identical");
|
||||||
|
}
|
||||||
|
|
||||||
|
$srcmodel = new Model($srcconf);
|
||||||
|
$srcstore = $srcmodel->getStore();
|
||||||
|
$dstmodel = new Model($dstconf);
|
||||||
|
$dststore = $dstmodel->getStore();
|
||||||
|
$ids = $srcstore->getAllPastes();
|
||||||
|
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
debug("Reading paste id " . $id);
|
||||||
|
$paste = $srcstore->read($id);
|
||||||
|
$comments = $srcstore->readComments($id);
|
||||||
|
|
||||||
|
savePaste($force_overwrite, $dryrun, $id, $paste, $dststore);
|
||||||
|
foreach ($comments as $comment) {
|
||||||
|
saveComment($force_overwrite, $dryrun, $id, $comment, $dststore);
|
||||||
|
}
|
||||||
|
if ($delete_during) {
|
||||||
|
deletePaste($dryrun, $id, $srcstore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($delete_after) {
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
deletePaste($dryrun, $id, $srcstore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("Done.");
|
||||||
|
|
||||||
|
|
||||||
|
function deletePaste($dryrun, $pasteid, $srcstore)
|
||||||
|
{
|
||||||
|
if (!$dryrun) {
|
||||||
|
debug("Deleting paste id " . $pasteid);
|
||||||
|
$srcstore->delete($pasteid);
|
||||||
|
} else {
|
||||||
|
debug("Would delete paste id " . $pasteid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveComment ($force_overwrite, $dryrun, $pasteid, $comment, $dststore)
|
||||||
|
{
|
||||||
|
$parentid = $comment["parentid"];
|
||||||
|
$commentid = $comment["id"];
|
||||||
|
|
||||||
|
if (!$dststore->existsComment($pasteid, $parentid, $commentid)) {
|
||||||
|
if (!$dryrun) {
|
||||||
|
debug("Saving paste id " . $pasteid . ", parent id " .
|
||||||
|
$parentid . ", comment id " . $commentid);
|
||||||
|
$dststore->createComment($pasteid, $parentid, $commentid, $comment);
|
||||||
|
} else {
|
||||||
|
debug("Would save paste id " . $pasteid . ", parent id " .
|
||||||
|
$parentid . ", comment id " . $commentid);
|
||||||
|
}
|
||||||
|
} else if ($force_overwrite) {
|
||||||
|
if (!$dryrun) {
|
||||||
|
debug("Overwriting paste id " . $pasteid . ", parent id " .
|
||||||
|
$parentid . ", comment id " . $commentid);
|
||||||
|
$dststore->createComment($pasteid, $parentid, $commentid, $comment);
|
||||||
|
} else {
|
||||||
|
debug("Would overwrite paste id " . $pasteid . ", parent id " .
|
||||||
|
$parentid . ", comment id " . $commentid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!$dryrun) {
|
||||||
|
dieerr("Not overwriting paste id " . $pasteid . ", parent id " .
|
||||||
|
$parentid . ", comment id " . $commentid);
|
||||||
|
} else {
|
||||||
|
dieerr("Would not overwrite paste id " . $pasteid . ", parent id " .
|
||||||
|
$parentid . ", comment id " . $commentid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function savePaste ($force_overwrite, $dryrun, $pasteid, $paste, $dststore)
|
||||||
|
{
|
||||||
|
if (!$dststore->exists($pasteid)) {
|
||||||
|
if (!$dryrun) {
|
||||||
|
debug("Saving paste id " . $pasteid);
|
||||||
|
$dststore->create($pasteid, $paste);
|
||||||
|
} else {
|
||||||
|
debug("Would save paste id " . $pasteid);
|
||||||
|
}
|
||||||
|
} else if ($force_overwrite) {
|
||||||
|
if (!$dryrun) {
|
||||||
|
debug("Overwriting paste id " . $pasteid);
|
||||||
|
$dststore->create($pasteid, $paste);
|
||||||
|
} else {
|
||||||
|
debug("Would overwrite paste id " . $pasteid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!$dryrun) {
|
||||||
|
dieerr("Not overwriting paste id " . $pasteid);
|
||||||
|
} else {
|
||||||
|
dieerr("Would not overwrite paste id " . $pasteid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConfig ($target, $confdir)
|
||||||
|
{
|
||||||
|
debug("Trying to load " . $target . " conf.php" .
|
||||||
|
($confdir === "" ? "" : " from " . $confdir));
|
||||||
|
|
||||||
|
putenv("CONFIG_PATH=" . $confdir);
|
||||||
|
$conf = new Configuration;
|
||||||
|
putenv("CONFIG_PATH=");
|
||||||
|
|
||||||
|
return $conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dieerr ($text)
|
||||||
|
{
|
||||||
|
fprintf(STDERR, "ERROR: %s" . PHP_EOL, $text);
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug ($text) {
|
||||||
|
if ($GLOBALS["verbose"]) {
|
||||||
|
printf("DEBUG: %s" . PHP_EOL, $text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function helpexit ()
|
||||||
|
{
|
||||||
|
print("migrate.php - Copy data between PrivateBin backends
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
migrate [--delete-after] [--delete-during] [-f] [-n] [-v] srcconfdir
|
||||||
|
[<dstconfdir>]
|
||||||
|
migrate [-h]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--delete-after delete data from source after all pastes and comments have
|
||||||
|
successfully been copied to the destination
|
||||||
|
--delete-during delete data from source after the current paste and its
|
||||||
|
comments have successfully been copied to the destination
|
||||||
|
-f forcefully overwrite data which already exists at the
|
||||||
|
destination
|
||||||
|
-n dry run, do not copy data
|
||||||
|
-v be verbose
|
||||||
|
<srcconfdir> use storage backend configration from conf.php found in
|
||||||
|
this directory as source
|
||||||
|
<dstconfdir> optionally, use storage backend configration from conf.php
|
||||||
|
found in this directory as destination; defaults to:
|
||||||
|
" . PATH . "cfg" . DIRECTORY_SEPARATOR . "conf.php
|
||||||
|
");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
@@ -7,9 +7,10 @@
|
|||||||
; (optional) set a project name to be displayed on the website
|
; (optional) set a project name to be displayed on the website
|
||||||
; name = "PrivateBin"
|
; name = "PrivateBin"
|
||||||
|
|
||||||
; The full URL, with the domain name and directories that point to the PrivateBin files
|
; The full URL, with the domain name and directories that point to the
|
||||||
; This URL is essential to allow Opengraph images to be displayed on social networks
|
; PrivateBin files, including an ending slash (/). This URL is essential to
|
||||||
; basepath = ""
|
; allow Opengraph images to be displayed on social networks.
|
||||||
|
; basepath = "https://privatebin.example.com/"
|
||||||
|
|
||||||
; enable or disable the discussion feature, defaults to true
|
; enable or disable the discussion feature, defaults to true
|
||||||
discussion = true
|
discussion = true
|
||||||
@@ -55,9 +56,9 @@ languageselection = false
|
|||||||
; if this is set and language selection is disabled, this will be the only language
|
; if this is set and language selection is disabled, this will be the only language
|
||||||
; languagedefault = "en"
|
; languagedefault = "en"
|
||||||
|
|
||||||
; (optional) URL shortener address to offer after a new paste is created
|
; (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
|
; It is suggested to only use this with self-hosted shorteners as this will leak
|
||||||
; the pastes encryption key
|
; the pastes encryption key.
|
||||||
; urlshortener = "https://shortener.example.com/api?link="
|
; urlshortener = "https://shortener.example.com/api?link="
|
||||||
|
|
||||||
; (optional) Let users create a QR code for sharing the paste URL with one click.
|
; (optional) Let users create a QR code for sharing the paste URL with one click.
|
||||||
@@ -230,18 +231,18 @@ dir = PATH "data"
|
|||||||
;secretkey = "secret access key"
|
;secretkey = "secret access key"
|
||||||
|
|
||||||
[yourls]
|
[yourls]
|
||||||
; don't mix this up with "urlshortener" config item:
|
; When using YOURLS as a "urlshortener" config item:
|
||||||
; - when using a standard configuration, "urlshortener" will point to the YOURLS
|
; - By default, "urlshortener" will point to the YOURLS API URL, with or without
|
||||||
; API, including access credentials, and will be part of the PrivateBin public
|
; credentials, and will be visible in public on the PrivateBin web page.
|
||||||
; web page (insecure!)
|
; Only use this if you allow short URL creation without credentials.
|
||||||
; - when using the parameters in this section ("signature" and "apiurl"),
|
; - Alternatively, using the parameters in this section ("signature" and
|
||||||
; "urlshortener" will point to a fixed PrivateBin page
|
; "apiurl"), "urlshortener" needs to point to the base URL of your PrivateBin
|
||||||
; ("$basepath/shortenviayourls?link=") and that URL will in turn call YOURLS
|
; instance with "shortenviayourls?link=" appended. For example:
|
||||||
; server-side, using the URL from "apiurl" and the "access signature" from the
|
; urlshortener = "${basepath}shortenviayourls?link="
|
||||||
; "signature" parameters below.
|
; 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
|
; (optional) the "signature" (access key) issued by YOURLS for the using account
|
||||||
; signature = ""
|
; signature = ""
|
||||||
|
|
||||||
; (optional) the URL of the YOURLS API, called to shorten a PrivateBin URL
|
; (optional) the URL of the YOURLS API, called to shorten a PrivateBin URL
|
||||||
; apiurl = ""
|
; apiurl = "https://yourls.example.com/yourls-api.php"
|
||||||
546
composer.lock
generated
546
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -236,6 +236,14 @@ class Configuration
|
|||||||
if (!array_key_exists($this->_configuration['expire']['default'], $this->_configuration['expire_options'])) {
|
if (!array_key_exists($this->_configuration['expire']['default'], $this->_configuration['expire_options'])) {
|
||||||
$this->_configuration['expire']['default'] = key($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'] .= '/';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,61 +15,17 @@ namespace PrivateBin\Data;
|
|||||||
/**
|
/**
|
||||||
* AbstractData
|
* AbstractData
|
||||||
*
|
*
|
||||||
* Abstract model for data access, implemented as a singleton.
|
* Abstract model for data access
|
||||||
*/
|
*/
|
||||||
abstract class AbstractData
|
abstract class AbstractData
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Singleton instance
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @static
|
|
||||||
* @var AbstractData
|
|
||||||
*/
|
|
||||||
protected static $_instance = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cache for the traffic limiter
|
* cache for the traffic limiter
|
||||||
*
|
*
|
||||||
* @access private
|
* @access protected
|
||||||
* @static
|
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected static $_last_cache = array();
|
protected $_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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a paste.
|
* Create a paste.
|
||||||
@@ -150,9 +106,9 @@ abstract class AbstractData
|
|||||||
public function purgeValues($namespace, $time)
|
public function purgeValues($namespace, $time)
|
||||||
{
|
{
|
||||||
if ($namespace === 'traffic_limiter') {
|
if ($namespace === 'traffic_limiter') {
|
||||||
foreach (self::$_last_cache as $key => $last_submission) {
|
foreach ($this->_last_cache as $key => $last_submission) {
|
||||||
if ($last_submission <= $time) {
|
if ($last_submission <= $time) {
|
||||||
unset(self::$_last_cache[$key]);
|
unset($this->_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.
|
* Get next free slot for comment from postdate.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -25,59 +25,43 @@ use PrivateBin\Json;
|
|||||||
*/
|
*/
|
||||||
class Database extends AbstractData
|
class Database extends AbstractData
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* cache for select queries
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $_cache = array();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* instance of database connection
|
* instance of database connection
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var PDO
|
* @var PDO
|
||||||
*/
|
*/
|
||||||
private static $_db;
|
private $_db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* table prefix
|
* table prefix
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $_prefix = '';
|
private $_prefix = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* database type
|
* database type
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $_type = '';
|
private $_type = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get instance of singleton
|
* instantiates a new Database data backend
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @static
|
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @throws Exception
|
* @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
|
// set table prefix if given
|
||||||
if (array_key_exists('tbl', $options)) {
|
if (array_key_exists('tbl', $options)) {
|
||||||
self::$_prefix = $options['tbl'];
|
$this->_prefix = $options['tbl'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize the db connection with new options
|
// initialize the db connection with new options
|
||||||
@@ -94,16 +78,16 @@ class Database extends AbstractData
|
|||||||
$db_tables_exist = true;
|
$db_tables_exist = true;
|
||||||
|
|
||||||
// setup type and dabase connection
|
// setup type and dabase connection
|
||||||
self::$_type = strtolower(
|
$this->_type = strtolower(
|
||||||
substr($options['dsn'], 0, strpos($options['dsn'], ':'))
|
substr($options['dsn'], 0, strpos($options['dsn'], ':'))
|
||||||
);
|
);
|
||||||
// MySQL uses backticks to quote identifiers by default,
|
// MySQL uses backticks to quote identifiers by default,
|
||||||
// tell it to expect ANSI SQL double quotes
|
// 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'";
|
$options['opt'][PDO::MYSQL_ATTR_INIT_COMMAND] = "SET SESSION sql_mode='ANSI_QUOTES'";
|
||||||
}
|
}
|
||||||
$tableQuery = self::_getTableQuery(self::$_type);
|
$tableQuery = $this->_getTableQuery($this->_type);
|
||||||
self::$_db = new PDO(
|
$this->_db = new PDO(
|
||||||
$options['dsn'],
|
$options['dsn'],
|
||||||
$options['usr'],
|
$options['usr'],
|
||||||
$options['pwd'],
|
$options['pwd'],
|
||||||
@@ -111,43 +95,41 @@ class Database extends AbstractData
|
|||||||
);
|
);
|
||||||
|
|
||||||
// check if the database contains the required tables
|
// 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
|
// create paste table if necessary
|
||||||
if (!in_array(self::_sanitizeIdentifier('paste'), $tables)) {
|
if (!in_array($this->_sanitizeIdentifier('paste'), $tables)) {
|
||||||
self::_createPasteTable();
|
$this->_createPasteTable();
|
||||||
$db_tables_exist = false;
|
$db_tables_exist = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create comment table if necessary
|
// create comment table if necessary
|
||||||
if (!in_array(self::_sanitizeIdentifier('comment'), $tables)) {
|
if (!in_array($this->_sanitizeIdentifier('comment'), $tables)) {
|
||||||
self::_createCommentTable();
|
$this->_createCommentTable();
|
||||||
$db_tables_exist = false;
|
$db_tables_exist = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create config table if necessary
|
// create config table if necessary
|
||||||
$db_version = Controller::VERSION;
|
$db_version = Controller::VERSION;
|
||||||
if (!in_array(self::_sanitizeIdentifier('config'), $tables)) {
|
if (!in_array($this->_sanitizeIdentifier('config'), $tables)) {
|
||||||
self::_createConfigTable();
|
$this->_createConfigTable();
|
||||||
// if we only needed to create the config table, the DB is older then 0.22
|
// if we only needed to create the config table, the DB is older then 0.22
|
||||||
if ($db_tables_exist) {
|
if ($db_tables_exist) {
|
||||||
$db_version = '0.21';
|
$db_version = '0.21';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$db_version = self::_getConfig('VERSION');
|
$db_version = $this->_getConfig('VERSION');
|
||||||
}
|
}
|
||||||
|
|
||||||
// update database structure if necessary
|
// update database structure if necessary
|
||||||
if (version_compare($db_version, Controller::VERSION, '<')) {
|
if (version_compare($db_version, Controller::VERSION, '<')) {
|
||||||
self::_upgradeDatabase($db_version);
|
$this->_upgradeDatabase($db_version);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
'Missing configuration for key dsn, usr, pwd or opt in the section model_options, please check your configuration file', 6
|
'Missing configuration for key dsn, usr, pwd or opt in the section model_options, please check your configuration file', 6
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$_instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,22 +142,12 @@ class Database extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function create($pasteid, array $paste)
|
public function create($pasteid, array $paste)
|
||||||
{
|
{
|
||||||
if (
|
|
||||||
array_key_exists($pasteid, self::$_cache)
|
|
||||||
) {
|
|
||||||
if (false !== self::$_cache[$pasteid]) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
unset(self::$_cache[$pasteid]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$expire_date = 0;
|
$expire_date = 0;
|
||||||
$opendiscussion = $burnafterreading = false;
|
$opendiscussion = $burnafterreading = false;
|
||||||
$attachment = $attachmentname = null;
|
$attachment = $attachmentname = null;
|
||||||
$meta = $paste['meta'];
|
$meta = $paste['meta'];
|
||||||
$isVersion1 = array_key_exists('data', $paste);
|
$isVersion1 = array_key_exists('data', $paste);
|
||||||
list($createdKey) = self::_getVersionedKeys($isVersion1 ? 1 : 2);
|
list($createdKey) = $this->_getVersionedKeys($isVersion1 ? 1 : 2);
|
||||||
$created = (int) $meta[$createdKey];
|
$created = (int) $meta[$createdKey];
|
||||||
unset($meta[$createdKey], $paste['meta']);
|
unset($meta[$createdKey], $paste['meta']);
|
||||||
if (array_key_exists('expire_date', $meta)) {
|
if (array_key_exists('expire_date', $meta)) {
|
||||||
@@ -204,8 +176,8 @@ class Database extends AbstractData
|
|||||||
$burnafterreading = $paste['adata'][3];
|
$burnafterreading = $paste['adata'][3];
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return self::_exec(
|
return $this->_exec(
|
||||||
'INSERT INTO "' . self::_sanitizeIdentifier('paste') .
|
'INSERT INTO "' . $this->_sanitizeIdentifier('paste') .
|
||||||
'" VALUES(?,?,?,?,?,?,?,?,?)',
|
'" VALUES(?,?,?,?,?,?,?,?,?)',
|
||||||
array(
|
array(
|
||||||
$pasteid,
|
$pasteid,
|
||||||
@@ -233,64 +205,59 @@ class Database extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function read($pasteid)
|
public function read($pasteid)
|
||||||
{
|
{
|
||||||
if (array_key_exists($pasteid, self::$_cache)) {
|
|
||||||
return self::$_cache[$pasteid];
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$_cache[$pasteid] = false;
|
|
||||||
try {
|
try {
|
||||||
$paste = self::_select(
|
$row = $this->_select(
|
||||||
'SELECT * FROM "' . self::_sanitizeIdentifier('paste') .
|
'SELECT * FROM "' . $this->_sanitizeIdentifier('paste') .
|
||||||
'" WHERE "dataid" = ?', array($pasteid), true
|
'" WHERE "dataid" = ?', array($pasteid), true
|
||||||
);
|
);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$paste = false;
|
$row = false;
|
||||||
}
|
}
|
||||||
if ($paste === false) {
|
if ($row === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// create array
|
// create array
|
||||||
$data = Json::decode($paste['data']);
|
$data = Json::decode($row['data']);
|
||||||
$isVersion2 = array_key_exists('v', $data) && $data['v'] >= 2;
|
$isVersion2 = array_key_exists('v', $data) && $data['v'] >= 2;
|
||||||
if ($isVersion2) {
|
if ($isVersion2) {
|
||||||
self::$_cache[$pasteid] = $data;
|
$paste = $data;
|
||||||
list($createdKey) = self::_getVersionedKeys(2);
|
list($createdKey) = $this->_getVersionedKeys(2);
|
||||||
} else {
|
} else {
|
||||||
self::$_cache[$pasteid] = array('data' => $paste['data']);
|
$paste = array('data' => $row['data']);
|
||||||
list($createdKey) = self::_getVersionedKeys(1);
|
list($createdKey) = $this->_getVersionedKeys(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$paste['meta'] = Json::decode($paste['meta']);
|
$row['meta'] = Json::decode($row['meta']);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$paste['meta'] = array();
|
$row['meta'] = array();
|
||||||
}
|
}
|
||||||
$paste = self::upgradePreV1Format($paste);
|
$row = self::upgradePreV1Format($row);
|
||||||
self::$_cache[$pasteid]['meta'] = $paste['meta'];
|
$paste['meta'] = $row['meta'];
|
||||||
self::$_cache[$pasteid]['meta'][$createdKey] = (int) $paste['postdate'];
|
$paste['meta'][$createdKey] = (int) $row['postdate'];
|
||||||
$expire_date = (int) $paste['expiredate'];
|
$expire_date = (int) $row['expiredate'];
|
||||||
if ($expire_date > 0) {
|
if ($expire_date > 0) {
|
||||||
self::$_cache[$pasteid]['meta']['expire_date'] = $expire_date;
|
$paste['meta']['expire_date'] = $expire_date;
|
||||||
}
|
}
|
||||||
if ($isVersion2) {
|
if ($isVersion2) {
|
||||||
return self::$_cache[$pasteid];
|
return $paste;
|
||||||
}
|
}
|
||||||
|
|
||||||
// support v1 attachments
|
// support v1 attachments
|
||||||
if (array_key_exists('attachment', $paste) && !empty($paste['attachment'])) {
|
if (array_key_exists('attachment', $row) && !empty($row['attachment'])) {
|
||||||
self::$_cache[$pasteid]['attachment'] = $paste['attachment'];
|
$paste['attachment'] = $row['attachment'];
|
||||||
if (array_key_exists('attachmentname', $paste) && !empty($paste['attachmentname'])) {
|
if (array_key_exists('attachmentname', $row) && !empty($row['attachmentname'])) {
|
||||||
self::$_cache[$pasteid]['attachmentname'] = $paste['attachmentname'];
|
$paste['attachmentname'] = $row['attachmentname'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($paste['opendiscussion']) {
|
if ($row['opendiscussion']) {
|
||||||
self::$_cache[$pasteid]['meta']['opendiscussion'] = true;
|
$paste['meta']['opendiscussion'] = true;
|
||||||
}
|
}
|
||||||
if ($paste['burnafterreading']) {
|
if ($row['burnafterreading']) {
|
||||||
self::$_cache[$pasteid]['meta']['burnafterreading'] = true;
|
$paste['meta']['burnafterreading'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$_cache[$pasteid];
|
return $paste;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -301,19 +268,14 @@ class Database extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function delete($pasteid)
|
public function delete($pasteid)
|
||||||
{
|
{
|
||||||
self::_exec(
|
$this->_exec(
|
||||||
'DELETE FROM "' . self::_sanitizeIdentifier('paste') .
|
'DELETE FROM "' . $this->_sanitizeIdentifier('paste') .
|
||||||
'" WHERE "dataid" = ?', array($pasteid)
|
'" WHERE "dataid" = ?', array($pasteid)
|
||||||
);
|
);
|
||||||
self::_exec(
|
$this->_exec(
|
||||||
'DELETE FROM "' . self::_sanitizeIdentifier('comment') .
|
'DELETE FROM "' . $this->_sanitizeIdentifier('comment') .
|
||||||
'" WHERE "pasteid" = ?', array($pasteid)
|
'" WHERE "pasteid" = ?', array($pasteid)
|
||||||
);
|
);
|
||||||
if (
|
|
||||||
array_key_exists($pasteid, self::$_cache)
|
|
||||||
) {
|
|
||||||
unset(self::$_cache[$pasteid]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -325,12 +287,15 @@ class Database extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function exists($pasteid)
|
public function exists($pasteid)
|
||||||
{
|
{
|
||||||
if (
|
try {
|
||||||
!array_key_exists($pasteid, self::$_cache)
|
$row = $this->_select(
|
||||||
) {
|
'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') .
|
||||||
self::$_cache[$pasteid] = $this->read($pasteid);
|
'" WHERE "dataid" = ?', array($pasteid), true
|
||||||
|
);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return (bool) self::$_cache[$pasteid];
|
return (bool) $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -352,7 +317,7 @@ class Database extends AbstractData
|
|||||||
$version = 2;
|
$version = 2;
|
||||||
$data = Json::encode($comment);
|
$data = Json::encode($comment);
|
||||||
}
|
}
|
||||||
list($createdKey, $iconKey) = self::_getVersionedKeys($version);
|
list($createdKey, $iconKey) = $this->_getVersionedKeys($version);
|
||||||
$meta = $comment['meta'];
|
$meta = $comment['meta'];
|
||||||
unset($comment['meta']);
|
unset($comment['meta']);
|
||||||
foreach (array('nickname', $iconKey) as $key) {
|
foreach (array('nickname', $iconKey) as $key) {
|
||||||
@@ -361,8 +326,8 @@ class Database extends AbstractData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return self::_exec(
|
return $this->_exec(
|
||||||
'INSERT INTO "' . self::_sanitizeIdentifier('comment') .
|
'INSERT INTO "' . $this->_sanitizeIdentifier('comment') .
|
||||||
'" VALUES(?,?,?,?,?,?,?)',
|
'" VALUES(?,?,?,?,?,?,?)',
|
||||||
array(
|
array(
|
||||||
$commentid,
|
$commentid,
|
||||||
@@ -388,8 +353,8 @@ class Database extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function readComments($pasteid)
|
public function readComments($pasteid)
|
||||||
{
|
{
|
||||||
$rows = self::_select(
|
$rows = $this->_select(
|
||||||
'SELECT * FROM "' . self::_sanitizeIdentifier('comment') .
|
'SELECT * FROM "' . $this->_sanitizeIdentifier('comment') .
|
||||||
'" WHERE "pasteid" = ?', array($pasteid)
|
'" WHERE "pasteid" = ?', array($pasteid)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -406,7 +371,7 @@ class Database extends AbstractData
|
|||||||
$version = 1;
|
$version = 1;
|
||||||
$comments[$i] = array('data' => $row['data']);
|
$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]['id'] = $row['dataid'];
|
||||||
$comments[$i]['parentid'] = $row['parentid'];
|
$comments[$i]['parentid'] = $row['parentid'];
|
||||||
$comments[$i]['meta'] = array($createdKey => (int) $row['postdate']);
|
$comments[$i]['meta'] = array($createdKey => (int) $row['postdate']);
|
||||||
@@ -433,8 +398,8 @@ class Database extends AbstractData
|
|||||||
public function existsComment($pasteid, $parentid, $commentid)
|
public function existsComment($pasteid, $parentid, $commentid)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return (bool) self::_select(
|
return (bool) $this->_select(
|
||||||
'SELECT "dataid" FROM "' . self::_sanitizeIdentifier('comment') .
|
'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('comment') .
|
||||||
'" WHERE "pasteid" = ? AND "parentid" = ? AND "dataid" = ?',
|
'" WHERE "pasteid" = ? AND "parentid" = ? AND "dataid" = ?',
|
||||||
array($pasteid, $parentid, $commentid), true
|
array($pasteid, $parentid, $commentid), true
|
||||||
);
|
);
|
||||||
@@ -455,15 +420,15 @@ class Database extends AbstractData
|
|||||||
public function setValue($value, $namespace, $key = '')
|
public function setValue($value, $namespace, $key = '')
|
||||||
{
|
{
|
||||||
if ($namespace === 'traffic_limiter') {
|
if ($namespace === 'traffic_limiter') {
|
||||||
self::$_last_cache[$key] = $value;
|
$this->_last_cache[$key] = $value;
|
||||||
try {
|
try {
|
||||||
$value = Json::encode(self::$_last_cache);
|
$value = Json::encode($this->_last_cache);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self::_exec(
|
return $this->_exec(
|
||||||
'UPDATE "' . self::_sanitizeIdentifier('config') .
|
'UPDATE "' . $this->_sanitizeIdentifier('config') .
|
||||||
'" SET "value" = ? WHERE "id" = ?',
|
'" SET "value" = ? WHERE "id" = ?',
|
||||||
array($value, strtoupper($namespace))
|
array($value, strtoupper($namespace))
|
||||||
);
|
);
|
||||||
@@ -483,8 +448,8 @@ class Database extends AbstractData
|
|||||||
$value = $this->_getConfig($configKey);
|
$value = $this->_getConfig($configKey);
|
||||||
if ($value === '') {
|
if ($value === '') {
|
||||||
// initialize the row, so that setValue can rely on UPDATE queries
|
// initialize the row, so that setValue can rely on UPDATE queries
|
||||||
self::_exec(
|
$this->_exec(
|
||||||
'INSERT INTO "' . self::_sanitizeIdentifier('config') .
|
'INSERT INTO "' . $this->_sanitizeIdentifier('config') .
|
||||||
'" VALUES(?,?)',
|
'" VALUES(?,?)',
|
||||||
array($configKey, '')
|
array($configKey, '')
|
||||||
);
|
);
|
||||||
@@ -492,7 +457,8 @@ class Database extends AbstractData
|
|||||||
// migrate filesystem based salt into database
|
// migrate filesystem based salt into database
|
||||||
$file = 'data' . DIRECTORY_SEPARATOR . 'salt.php';
|
$file = 'data' . DIRECTORY_SEPARATOR . 'salt.php';
|
||||||
if ($namespace === 'salt' && is_readable($file)) {
|
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');
|
$this->setValue($value, 'salt');
|
||||||
@unlink($file);
|
@unlink($file);
|
||||||
return $value;
|
return $value;
|
||||||
@@ -500,12 +466,12 @@ class Database extends AbstractData
|
|||||||
}
|
}
|
||||||
if ($value && $namespace === 'traffic_limiter') {
|
if ($value && $namespace === 'traffic_limiter') {
|
||||||
try {
|
try {
|
||||||
self::$_last_cache = Json::decode($value);
|
$this->_last_cache = Json::decode($value);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
self::$_last_cache = array();
|
$this->_last_cache = array();
|
||||||
}
|
}
|
||||||
if (array_key_exists($key, self::$_last_cache)) {
|
if (array_key_exists($key, $this->_last_cache)) {
|
||||||
return self::$_last_cache[$key];
|
return $this->_last_cache[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (string) $value;
|
return (string) $value;
|
||||||
@@ -520,34 +486,37 @@ class Database extends AbstractData
|
|||||||
*/
|
*/
|
||||||
protected function _getExpiredPastes($batchsize)
|
protected function _getExpiredPastes($batchsize)
|
||||||
{
|
{
|
||||||
$pastes = array();
|
$statement = $this->_db->prepare(
|
||||||
$rows = self::_select(
|
'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') .
|
||||||
'SELECT "dataid" FROM "' . self::_sanitizeIdentifier('paste') .
|
|
||||||
'" WHERE "expiredate" < ? AND "expiredate" != ? ' .
|
'" 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)) {
|
$statement->execute(array(time(), 0, $batchsize));
|
||||||
foreach ($rows as $row) {
|
return $statement->fetchAll(PDO::FETCH_COLUMN, 0);
|
||||||
$pastes[] = $row['dataid'];
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
return $pastes;
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getAllPastes()
|
||||||
|
{
|
||||||
|
return $this->_db->query(
|
||||||
|
'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') . '"'
|
||||||
|
)->fetchAll(PDO::FETCH_COLUMN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* execute a statement
|
* execute a statement
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $sql
|
* @param string $sql
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @throws PDOException
|
* @throws PDOException
|
||||||
* @return bool
|
* @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) {
|
foreach ($params as $key => &$parameter) {
|
||||||
$position = $key + 1;
|
$position = $key + 1;
|
||||||
if (is_int($parameter)) {
|
if (is_int($parameter)) {
|
||||||
@@ -567,20 +536,19 @@ class Database extends AbstractData
|
|||||||
* run a select statement
|
* run a select statement
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $sql
|
* @param string $sql
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @param bool $firstOnly if only the first row should be returned
|
* @param bool $firstOnly if only the first row should be returned
|
||||||
* @throws PDOException
|
* @throws PDOException
|
||||||
* @return array|false
|
* @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);
|
$statement->execute($params);
|
||||||
if ($firstOnly) {
|
if ($firstOnly) {
|
||||||
$result = $statement->fetch(PDO::FETCH_ASSOC);
|
$result = $statement->fetch(PDO::FETCH_ASSOC);
|
||||||
} elseif (self::$_type === 'oci') {
|
} elseif ($this->_type === 'oci') {
|
||||||
// workaround for https://bugs.php.net/bug.php?id=46728
|
// workaround for https://bugs.php.net/bug.php?id=46728
|
||||||
$result = array();
|
$result = array();
|
||||||
while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
|
||||||
@@ -590,7 +558,7 @@ class Database extends AbstractData
|
|||||||
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
|
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
$statement->closeCursor();
|
$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
|
// returned CLOB values are streams, convert these into strings
|
||||||
$result = $firstOnly ?
|
$result = $firstOnly ?
|
||||||
array_map('PrivateBin\Data\Database::_sanitizeClob', $result) :
|
array_map('PrivateBin\Data\Database::_sanitizeClob', $result) :
|
||||||
@@ -603,11 +571,10 @@ class Database extends AbstractData
|
|||||||
* get version dependent key names
|
* get version dependent key names
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param int $version
|
* @param int $version
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private static function _getVersionedKeys($version)
|
private function _getVersionedKeys($version)
|
||||||
{
|
{
|
||||||
if ($version === 1) {
|
if ($version === 1) {
|
||||||
return array('postdate', 'vizhash');
|
return array('postdate', 'vizhash');
|
||||||
@@ -619,12 +586,11 @@ class Database extends AbstractData
|
|||||||
* get table list query, depending on the database type
|
* get table list query, depending on the database type
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function _getTableQuery($type)
|
private function _getTableQuery($type)
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'ibm':
|
case 'ibm':
|
||||||
@@ -675,15 +641,14 @@ class Database extends AbstractData
|
|||||||
* get a value by key from the config table
|
* get a value by key from the config table
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function _getConfig($key)
|
private function _getConfig($key)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$row = self::_select(
|
$row = $this->_select(
|
||||||
'SELECT "value" FROM "' . self::_sanitizeIdentifier('config') .
|
'SELECT "value" FROM "' . $this->_sanitizeIdentifier('config') .
|
||||||
'" WHERE "id" = ?', array($key), true
|
'" WHERE "id" = ?', array($key), true
|
||||||
);
|
);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
@@ -696,14 +661,13 @@ class Database extends AbstractData
|
|||||||
* get the primary key clauses, depending on the database driver
|
* get the primary key clauses, depending on the database driver
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private static function _getPrimaryKeyClauses($key = 'dataid')
|
private function _getPrimaryKeyClauses($key = 'dataid')
|
||||||
{
|
{
|
||||||
$main_key = $after_key = '';
|
$main_key = $after_key = '';
|
||||||
switch (self::$_type) {
|
switch ($this->_type) {
|
||||||
case 'mysql':
|
case 'mysql':
|
||||||
case 'oci':
|
case 'oci':
|
||||||
$after_key = ", PRIMARY KEY (\"$key\")";
|
$after_key = ", PRIMARY KEY (\"$key\")";
|
||||||
@@ -721,12 +685,11 @@ class Database extends AbstractData
|
|||||||
* PostgreSQL and OCI uses a different API for BLOBs then SQL, hence we use TEXT and CLOB
|
* PostgreSQL and OCI uses a different API for BLOBs then SQL, hence we use TEXT and CLOB
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function _getDataType()
|
private function _getDataType()
|
||||||
{
|
{
|
||||||
switch (self::$_type) {
|
switch ($this->_type) {
|
||||||
case 'oci':
|
case 'oci':
|
||||||
return 'CLOB';
|
return 'CLOB';
|
||||||
case 'pgsql':
|
case 'pgsql':
|
||||||
@@ -742,12 +705,11 @@ class Database extends AbstractData
|
|||||||
* PostgreSQL and OCI use different APIs for BLOBs then SQL, hence we use TEXT and CLOB
|
* PostgreSQL and OCI use different APIs for BLOBs then SQL, hence we use TEXT and CLOB
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function _getAttachmentType()
|
private function _getAttachmentType()
|
||||||
{
|
{
|
||||||
switch (self::$_type) {
|
switch ($this->_type) {
|
||||||
case 'oci':
|
case 'oci':
|
||||||
return 'CLOB';
|
return 'CLOB';
|
||||||
case 'pgsql':
|
case 'pgsql':
|
||||||
@@ -763,12 +725,11 @@ class Database extends AbstractData
|
|||||||
* OCI doesn't accept TEXT so it has to be VARCHAR2(4000)
|
* OCI doesn't accept TEXT so it has to be VARCHAR2(4000)
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function _getMetaType()
|
private function _getMetaType()
|
||||||
{
|
{
|
||||||
switch (self::$_type) {
|
switch ($this->_type) {
|
||||||
case 'oci':
|
case 'oci':
|
||||||
return 'VARCHAR2(4000)';
|
return 'VARCHAR2(4000)';
|
||||||
default:
|
default:
|
||||||
@@ -780,16 +741,15 @@ class Database extends AbstractData
|
|||||||
* create the paste table
|
* create the paste table
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
*/
|
*/
|
||||||
private static function _createPasteTable()
|
private function _createPasteTable()
|
||||||
{
|
{
|
||||||
list($main_key, $after_key) = self::_getPrimaryKeyClauses();
|
list($main_key, $after_key) = $this->_getPrimaryKeyClauses();
|
||||||
$dataType = self::_getDataType();
|
$dataType = $this->_getDataType();
|
||||||
$attachmentType = self::_getAttachmentType();
|
$attachmentType = $this->_getAttachmentType();
|
||||||
$metaType = self::_getMetaType();
|
$metaType = $this->_getMetaType();
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'CREATE TABLE "' . self::_sanitizeIdentifier('paste') . '" ( ' .
|
'CREATE TABLE "' . $this->_sanitizeIdentifier('paste') . '" ( ' .
|
||||||
"\"dataid\" CHAR(16) NOT NULL$main_key, " .
|
"\"dataid\" CHAR(16) NOT NULL$main_key, " .
|
||||||
"\"data\" $attachmentType, " .
|
"\"data\" $attachmentType, " .
|
||||||
'"postdate" INT, ' .
|
'"postdate" INT, ' .
|
||||||
@@ -806,14 +766,13 @@ class Database extends AbstractData
|
|||||||
* create the paste table
|
* create the paste table
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
*/
|
*/
|
||||||
private static function _createCommentTable()
|
private function _createCommentTable()
|
||||||
{
|
{
|
||||||
list($main_key, $after_key) = self::_getPrimaryKeyClauses();
|
list($main_key, $after_key) = $this->_getPrimaryKeyClauses();
|
||||||
$dataType = self::_getDataType();
|
$dataType = $this->_getDataType();
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'CREATE TABLE "' . self::_sanitizeIdentifier('comment') . '" ( ' .
|
'CREATE TABLE "' . $this->_sanitizeIdentifier('comment') . '" ( ' .
|
||||||
"\"dataid\" CHAR(16) NOT NULL$main_key, " .
|
"\"dataid\" CHAR(16) NOT NULL$main_key, " .
|
||||||
'"pasteid" CHAR(16), ' .
|
'"pasteid" CHAR(16), ' .
|
||||||
'"parentid" CHAR(16), ' .
|
'"parentid" CHAR(16), ' .
|
||||||
@@ -822,15 +781,15 @@ class Database extends AbstractData
|
|||||||
"\"vizhash\" $dataType, " .
|
"\"vizhash\" $dataType, " .
|
||||||
"\"postdate\" INT$after_key )"
|
"\"postdate\" INT$after_key )"
|
||||||
);
|
);
|
||||||
if (self::$_type === 'oci') {
|
if ($this->_type === 'oci') {
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'declare
|
'declare
|
||||||
already_exists exception;
|
already_exists exception;
|
||||||
columns_indexed exception;
|
columns_indexed exception;
|
||||||
pragma exception_init( already_exists, -955 );
|
pragma exception_init( already_exists, -955 );
|
||||||
pragma exception_init(columns_indexed, -1408);
|
pragma exception_init(columns_indexed, -1408);
|
||||||
begin
|
begin
|
||||||
execute immediate \'create index "comment_parent" on "' . self::_sanitizeIdentifier('comment') . '" ("pasteid")\';
|
execute immediate \'create index "comment_parent" on "' . $this->_sanitizeIdentifier('comment') . '" ("pasteid")\';
|
||||||
exception
|
exception
|
||||||
when already_exists or columns_indexed then
|
when already_exists or columns_indexed then
|
||||||
NULL;
|
NULL;
|
||||||
@@ -838,10 +797,10 @@ class Database extends AbstractData
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0
|
// CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'CREATE INDEX "' .
|
'CREATE INDEX "' .
|
||||||
self::_sanitizeIdentifier('comment_parent') . '" ON "' .
|
$this->_sanitizeIdentifier('comment_parent') . '" ON "' .
|
||||||
self::_sanitizeIdentifier('comment') . '" ("pasteid")'
|
$this->_sanitizeIdentifier('comment') . '" ("pasteid")'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -850,19 +809,18 @@ class Database extends AbstractData
|
|||||||
* create the paste table
|
* create the paste table
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
*/
|
*/
|
||||||
private static function _createConfigTable()
|
private function _createConfigTable()
|
||||||
{
|
{
|
||||||
list($main_key, $after_key) = self::_getPrimaryKeyClauses('id');
|
list($main_key, $after_key) = $this->_getPrimaryKeyClauses('id');
|
||||||
$charType = self::$_type === 'oci' ? 'VARCHAR2(16)' : 'CHAR(16)';
|
$charType = $this->_type === 'oci' ? 'VARCHAR2(16)' : 'CHAR(16)';
|
||||||
$textType = self::_getMetaType();
|
$textType = $this->_getMetaType();
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'CREATE TABLE "' . self::_sanitizeIdentifier('config') .
|
'CREATE TABLE "' . $this->_sanitizeIdentifier('config') .
|
||||||
"\" ( \"id\" $charType NOT NULL$main_key, \"value\" $textType$after_key )"
|
"\" ( \"id\" $charType NOT NULL$main_key, \"value\" $textType$after_key )"
|
||||||
);
|
);
|
||||||
self::_exec(
|
$this->_exec(
|
||||||
'INSERT INTO "' . self::_sanitizeIdentifier('config') .
|
'INSERT INTO "' . $this->_sanitizeIdentifier('config') .
|
||||||
'" VALUES(?,?)',
|
'" VALUES(?,?)',
|
||||||
array('VERSION', Controller::VERSION)
|
array('VERSION', Controller::VERSION)
|
||||||
);
|
);
|
||||||
@@ -890,90 +848,88 @@ class Database extends AbstractData
|
|||||||
* sanitizes identifiers
|
* sanitizes identifiers
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $identifier
|
* @param string $identifier
|
||||||
* @return string
|
* @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
|
* upgrade the database schema from an old version
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $oldversion
|
* @param string $oldversion
|
||||||
*/
|
*/
|
||||||
private static function _upgradeDatabase($oldversion)
|
private function _upgradeDatabase($oldversion)
|
||||||
{
|
{
|
||||||
$dataType = self::_getDataType();
|
$dataType = $this->_getDataType();
|
||||||
$attachmentType = self::_getAttachmentType();
|
$attachmentType = $this->_getAttachmentType();
|
||||||
switch ($oldversion) {
|
switch ($oldversion) {
|
||||||
case '0.21':
|
case '0.21':
|
||||||
// create the meta column if necessary (pre 0.21 change)
|
// create the meta column if necessary (pre 0.21 change)
|
||||||
try {
|
try {
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'SELECT "meta" FROM "' . self::_sanitizeIdentifier('paste') . '" ' .
|
'SELECT "meta" FROM "' . $this->_sanitizeIdentifier('paste') . '" ' .
|
||||||
(self::$_type === 'oci' ? 'FETCH NEXT 1 ROWS ONLY' : 'LIMIT 1')
|
($this->_type === 'oci' ? 'FETCH NEXT 1 ROWS ONLY' : 'LIMIT 1')
|
||||||
);
|
);
|
||||||
} catch (PDOException $e) {
|
} 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...
|
// SQLite only allows one ALTER statement at a time...
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'ALTER TABLE "' . self::_sanitizeIdentifier('paste') .
|
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
|
||||||
"\" ADD COLUMN \"attachment\" $attachmentType"
|
"\" ADD COLUMN \"attachment\" $attachmentType"
|
||||||
);
|
);
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'ALTER TABLE "' . self::_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachmentname\" $dataType"
|
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachmentname\" $dataType"
|
||||||
);
|
);
|
||||||
// SQLite doesn't support MODIFY, but it allows TEXT of similar
|
// SQLite doesn't support MODIFY, but it allows TEXT of similar
|
||||||
// size as BLOB, so there is no need to change it there
|
// size as BLOB, so there is no need to change it there
|
||||||
if (self::$_type !== 'sqlite') {
|
if ($this->_type !== 'sqlite') {
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'ALTER TABLE "' . self::_sanitizeIdentifier('paste') .
|
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
|
||||||
"\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType"
|
"\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType"
|
||||||
);
|
);
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'ALTER TABLE "' . self::_sanitizeIdentifier('comment') .
|
'ALTER TABLE "' . $this->_sanitizeIdentifier('comment') .
|
||||||
"\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType, " .
|
"\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType, " .
|
||||||
"MODIFY COLUMN \"nickname\" $dataType, MODIFY COLUMN \"vizhash\" $dataType"
|
"MODIFY COLUMN \"nickname\" $dataType, MODIFY COLUMN \"vizhash\" $dataType"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'CREATE UNIQUE INDEX IF NOT EXISTS "' .
|
'CREATE UNIQUE INDEX IF NOT EXISTS "' .
|
||||||
self::_sanitizeIdentifier('paste_dataid') . '" ON "' .
|
$this->_sanitizeIdentifier('paste_dataid') . '" ON "' .
|
||||||
self::_sanitizeIdentifier('paste') . '" ("dataid")'
|
$this->_sanitizeIdentifier('paste') . '" ("dataid")'
|
||||||
);
|
);
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'CREATE UNIQUE INDEX IF NOT EXISTS "' .
|
'CREATE UNIQUE INDEX IF NOT EXISTS "' .
|
||||||
self::_sanitizeIdentifier('comment_dataid') . '" ON "' .
|
$this->_sanitizeIdentifier('comment_dataid') . '" ON "' .
|
||||||
self::_sanitizeIdentifier('comment') . '" ("dataid")'
|
$this->_sanitizeIdentifier('comment') . '" ("dataid")'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0
|
// CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'CREATE INDEX "' .
|
'CREATE INDEX "' .
|
||||||
self::_sanitizeIdentifier('comment_parent') . '" ON "' .
|
$this->_sanitizeIdentifier('comment_parent') . '" ON "' .
|
||||||
self::_sanitizeIdentifier('comment') . '" ("pasteid")'
|
$this->_sanitizeIdentifier('comment') . '" ("pasteid")'
|
||||||
);
|
);
|
||||||
// no break, continue with updates for 0.22 and later
|
// no break, continue with updates for 0.22 and later
|
||||||
case '1.3':
|
case '1.3':
|
||||||
// SQLite doesn't support MODIFY, but it allows TEXT of similar
|
// SQLite doesn't support MODIFY, but it allows TEXT of similar
|
||||||
// size as BLOB and PostgreSQL uses TEXT, so there is no need
|
// size as BLOB and PostgreSQL uses TEXT, so there is no need
|
||||||
// to change it there
|
// to change it there
|
||||||
if (self::$_type !== 'sqlite' && self::$_type !== 'pgsql') {
|
if ($this->_type !== 'sqlite' && $this->_type !== 'pgsql') {
|
||||||
self::$_db->exec(
|
$this->_db->exec(
|
||||||
'ALTER TABLE "' . self::_sanitizeIdentifier('paste') .
|
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
|
||||||
"\" MODIFY COLUMN \"data\" $attachmentType"
|
"\" MODIFY COLUMN \"data\" $attachmentType"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// no break, continue with updates for all newer versions
|
// no break, continue with updates for all newer versions
|
||||||
default:
|
default:
|
||||||
self::_exec(
|
$this->_exec(
|
||||||
'UPDATE "' . self::_sanitizeIdentifier('config') .
|
'UPDATE "' . $this->_sanitizeIdentifier('config') .
|
||||||
'" SET "value" = ? WHERE "id" = ?',
|
'" SET "value" = ? WHERE "id" = ?',
|
||||||
array(Controller::VERSION, 'VERSION')
|
array(Controller::VERSION, 'VERSION')
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -40,33 +40,26 @@ class Filesystem extends AbstractData
|
|||||||
* path in which to persist something
|
* path in which to persist something
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $_path = 'data';
|
private $_path = 'data';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get instance of singleton
|
* instantiates a new Filesystem data backend
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @static
|
|
||||||
* @param array $options
|
* @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 given update the data directory
|
||||||
if (
|
if (
|
||||||
is_array($options) &&
|
is_array($options) &&
|
||||||
array_key_exists('dir', $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)
|
public function create($pasteid, array $paste)
|
||||||
{
|
{
|
||||||
$storagedir = self::_dataid2path($pasteid);
|
$storagedir = $this->_dataid2path($pasteid);
|
||||||
$file = $storagedir . $pasteid . '.php';
|
$file = $storagedir . $pasteid . '.php';
|
||||||
if (is_file($file)) {
|
if (is_file($file)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -87,7 +80,7 @@ class Filesystem extends AbstractData
|
|||||||
if (!is_dir($storagedir)) {
|
if (!is_dir($storagedir)) {
|
||||||
mkdir($storagedir, 0700, true);
|
mkdir($storagedir, 0700, true);
|
||||||
}
|
}
|
||||||
return self::_store($file, $paste);
|
return $this->_store($file, $paste);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,7 +94,7 @@ class Filesystem extends AbstractData
|
|||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
!$this->exists($pasteid) ||
|
!$this->exists($pasteid) ||
|
||||||
!$paste = self::_get(self::_dataid2path($pasteid) . $pasteid . '.php')
|
!$paste = $this->_get($this->_dataid2path($pasteid) . $pasteid . '.php')
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -116,7 +109,7 @@ class Filesystem extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function delete($pasteid)
|
public function delete($pasteid)
|
||||||
{
|
{
|
||||||
$pastedir = self::_dataid2path($pasteid);
|
$pastedir = $this->_dataid2path($pasteid);
|
||||||
if (is_dir($pastedir)) {
|
if (is_dir($pastedir)) {
|
||||||
// Delete the paste itself.
|
// Delete the paste itself.
|
||||||
if (is_file($pastedir . $pasteid . '.php')) {
|
if (is_file($pastedir . $pasteid . '.php')) {
|
||||||
@@ -124,7 +117,7 @@ class Filesystem extends AbstractData
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete discussion if it exists.
|
// Delete discussion if it exists.
|
||||||
$discdir = self::_dataid2discussionpath($pasteid);
|
$discdir = $this->_dataid2discussionpath($pasteid);
|
||||||
if (is_dir($discdir)) {
|
if (is_dir($discdir)) {
|
||||||
// Delete all files in discussion directory
|
// Delete all files in discussion directory
|
||||||
$dir = dir($discdir);
|
$dir = dir($discdir);
|
||||||
@@ -148,20 +141,20 @@ class Filesystem extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function exists($pasteid)
|
public function exists($pasteid)
|
||||||
{
|
{
|
||||||
$basePath = self::_dataid2path($pasteid) . $pasteid;
|
$basePath = $this->_dataid2path($pasteid) . $pasteid;
|
||||||
$pastePath = $basePath . '.php';
|
$pastePath = $basePath . '.php';
|
||||||
// convert to PHP protected files if needed
|
// convert to PHP protected files if needed
|
||||||
if (is_readable($basePath)) {
|
if (is_readable($basePath)) {
|
||||||
self::_prependRename($basePath, $pastePath);
|
$this->_prependRename($basePath, $pastePath);
|
||||||
|
|
||||||
// convert comments, too
|
// convert comments, too
|
||||||
$discdir = self::_dataid2discussionpath($pasteid);
|
$discdir = $this->_dataid2discussionpath($pasteid);
|
||||||
if (is_dir($discdir)) {
|
if (is_dir($discdir)) {
|
||||||
$dir = dir($discdir);
|
$dir = dir($discdir);
|
||||||
while (false !== ($filename = $dir->read())) {
|
while (false !== ($filename = $dir->read())) {
|
||||||
if (substr($filename, -4) !== '.php' && strlen($filename) >= 16) {
|
if (substr($filename, -4) !== '.php' && strlen($filename) >= 16) {
|
||||||
$commentFilename = $discdir . $filename . '.php';
|
$commentFilename = $discdir . $filename . '.php';
|
||||||
self::_prependRename($discdir . $filename, $commentFilename);
|
$this->_prependRename($discdir . $filename, $commentFilename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$dir->close();
|
$dir->close();
|
||||||
@@ -182,7 +175,7 @@ class Filesystem extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function createComment($pasteid, $parentid, $commentid, array $comment)
|
public function createComment($pasteid, $parentid, $commentid, array $comment)
|
||||||
{
|
{
|
||||||
$storagedir = self::_dataid2discussionpath($pasteid);
|
$storagedir = $this->_dataid2discussionpath($pasteid);
|
||||||
$file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid . '.php';
|
$file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid . '.php';
|
||||||
if (is_file($file)) {
|
if (is_file($file)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -190,7 +183,7 @@ class Filesystem extends AbstractData
|
|||||||
if (!is_dir($storagedir)) {
|
if (!is_dir($storagedir)) {
|
||||||
mkdir($storagedir, 0700, true);
|
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)
|
public function readComments($pasteid)
|
||||||
{
|
{
|
||||||
$comments = array();
|
$comments = array();
|
||||||
$discdir = self::_dataid2discussionpath($pasteid);
|
$discdir = $this->_dataid2discussionpath($pasteid);
|
||||||
if (is_dir($discdir)) {
|
if (is_dir($discdir)) {
|
||||||
$dir = dir($discdir);
|
$dir = dir($discdir);
|
||||||
while (false !== ($filename = $dir->read())) {
|
while (false !== ($filename = $dir->read())) {
|
||||||
@@ -212,7 +205,7 @@ class Filesystem extends AbstractData
|
|||||||
// - commentid is the comment identifier itself.
|
// - commentid is the comment identifier itself.
|
||||||
// - parentid is the comment this comment replies to (It can be pasteid)
|
// - parentid is the comment this comment replies to (It can be pasteid)
|
||||||
if (is_file($discdir . $filename)) {
|
if (is_file($discdir . $filename)) {
|
||||||
$comment = self::_get($discdir . $filename);
|
$comment = $this->_get($discdir . $filename);
|
||||||
$items = explode('.', $filename);
|
$items = explode('.', $filename);
|
||||||
// Add some meta information not contained in file.
|
// Add some meta information not contained in file.
|
||||||
$comment['id'] = $items[1];
|
$comment['id'] = $items[1];
|
||||||
@@ -243,7 +236,7 @@ class Filesystem extends AbstractData
|
|||||||
public function existsComment($pasteid, $parentid, $commentid)
|
public function existsComment($pasteid, $parentid, $commentid)
|
||||||
{
|
{
|
||||||
return is_file(
|
return is_file(
|
||||||
self::_dataid2discussionpath($pasteid) .
|
$this->_dataid2discussionpath($pasteid) .
|
||||||
$pasteid . '.' . $commentid . '.' . $parentid . '.php'
|
$pasteid . '.' . $commentid . '.' . $parentid . '.php'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -261,20 +254,20 @@ class Filesystem extends AbstractData
|
|||||||
{
|
{
|
||||||
switch ($namespace) {
|
switch ($namespace) {
|
||||||
case 'purge_limiter':
|
case 'purge_limiter':
|
||||||
return self::_storeString(
|
return $this->_storeString(
|
||||||
self::$_path . DIRECTORY_SEPARATOR . 'purge_limiter.php',
|
$this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php',
|
||||||
'<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . $value . ';'
|
'<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . $value . ';'
|
||||||
);
|
);
|
||||||
case 'salt':
|
case 'salt':
|
||||||
return self::_storeString(
|
return $this->_storeString(
|
||||||
self::$_path . DIRECTORY_SEPARATOR . 'salt.php',
|
$this->_path . DIRECTORY_SEPARATOR . 'salt.php',
|
||||||
'<?php # |' . $value . '|'
|
'<?php # |' . $value . '|'
|
||||||
);
|
);
|
||||||
case 'traffic_limiter':
|
case 'traffic_limiter':
|
||||||
self::$_last_cache[$key] = $value;
|
$this->_last_cache[$key] = $value;
|
||||||
return self::_storeString(
|
return $this->_storeString(
|
||||||
self::$_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php',
|
$this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php',
|
||||||
'<?php' . PHP_EOL . '$GLOBALS[\'traffic_limiter\'] = ' . var_export(self::$_last_cache, true) . ';'
|
'<?php' . PHP_EOL . '$GLOBALS[\'traffic_limiter\'] = ' . var_export($this->_last_cache, true) . ';'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -292,14 +285,14 @@ class Filesystem extends AbstractData
|
|||||||
{
|
{
|
||||||
switch ($namespace) {
|
switch ($namespace) {
|
||||||
case 'purge_limiter':
|
case 'purge_limiter':
|
||||||
$file = self::$_path . DIRECTORY_SEPARATOR . 'purge_limiter.php';
|
$file = $this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php';
|
||||||
if (is_readable($file)) {
|
if (is_readable($file)) {
|
||||||
require $file;
|
require $file;
|
||||||
return $GLOBALS['purge_limiter'];
|
return $GLOBALS['purge_limiter'];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'salt':
|
case 'salt':
|
||||||
$file = self::$_path . DIRECTORY_SEPARATOR . 'salt.php';
|
$file = $this->_path . DIRECTORY_SEPARATOR . 'salt.php';
|
||||||
if (is_readable($file)) {
|
if (is_readable($file)) {
|
||||||
$items = explode('|', file_get_contents($file));
|
$items = explode('|', file_get_contents($file));
|
||||||
if (is_array($items) && count($items) == 3) {
|
if (is_array($items) && count($items) == 3) {
|
||||||
@@ -308,12 +301,12 @@ class Filesystem extends AbstractData
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'traffic_limiter':
|
case 'traffic_limiter':
|
||||||
$file = self::$_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php';
|
$file = $this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php';
|
||||||
if (is_readable($file)) {
|
if (is_readable($file)) {
|
||||||
require $file;
|
require $file;
|
||||||
self::$_last_cache = $GLOBALS['traffic_limiter'];
|
$this->_last_cache = $GLOBALS['traffic_limiter'];
|
||||||
if (array_key_exists($key, self::$_last_cache)) {
|
if (array_key_exists($key, $this->_last_cache)) {
|
||||||
return self::$_last_cache[$key];
|
return $this->_last_cache[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -325,11 +318,10 @@ class Filesystem extends AbstractData
|
|||||||
* get the data
|
* get the data
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @static
|
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @return array|false $data
|
* @return array|false $data
|
||||||
*/
|
*/
|
||||||
private static function _get($filename)
|
private function _get($filename)
|
||||||
{
|
{
|
||||||
return Json::decode(
|
return Json::decode(
|
||||||
substr(
|
substr(
|
||||||
@@ -350,7 +342,7 @@ class Filesystem extends AbstractData
|
|||||||
{
|
{
|
||||||
$pastes = array();
|
$pastes = array();
|
||||||
$firstLevel = array_filter(
|
$firstLevel = array_filter(
|
||||||
scandir(self::$_path),
|
scandir($this->_path),
|
||||||
'PrivateBin\Data\Filesystem::_isFirstLevelDir'
|
'PrivateBin\Data\Filesystem::_isFirstLevelDir'
|
||||||
);
|
);
|
||||||
if (count($firstLevel) > 0) {
|
if (count($firstLevel) > 0) {
|
||||||
@@ -358,7 +350,7 @@ class Filesystem extends AbstractData
|
|||||||
for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) {
|
for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) {
|
||||||
$firstKey = array_rand($firstLevel);
|
$firstKey = array_rand($firstLevel);
|
||||||
$secondLevel = array_filter(
|
$secondLevel = array_filter(
|
||||||
scandir(self::$_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]),
|
scandir($this->_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]),
|
||||||
'PrivateBin\Data\Filesystem::_isSecondLevelDir'
|
'PrivateBin\Data\Filesystem::_isSecondLevelDir'
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -369,7 +361,7 @@ class Filesystem extends AbstractData
|
|||||||
}
|
}
|
||||||
|
|
||||||
$secondKey = array_rand($secondLevel);
|
$secondKey = array_rand($secondLevel);
|
||||||
$path = self::$_path . DIRECTORY_SEPARATOR .
|
$path = $this->_path . DIRECTORY_SEPARATOR .
|
||||||
$firstLevel[$firstKey] . DIRECTORY_SEPARATOR .
|
$firstLevel[$firstKey] . DIRECTORY_SEPARATOR .
|
||||||
$secondLevel[$secondKey];
|
$secondLevel[$secondKey];
|
||||||
if (!is_dir($path)) {
|
if (!is_dir($path)) {
|
||||||
@@ -412,6 +404,55 @@ class Filesystem extends AbstractData
|
|||||||
return $pastes;
|
return $pastes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $pastes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert paste id to storage path.
|
* Convert paste id to storage path.
|
||||||
*
|
*
|
||||||
@@ -423,13 +464,12 @@ class Filesystem extends AbstractData
|
|||||||
* eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/'
|
* eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/'
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $dataid
|
* @param string $dataid
|
||||||
* @return string
|
* @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, 0, 2) . DIRECTORY_SEPARATOR .
|
||||||
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR;
|
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR;
|
||||||
}
|
}
|
||||||
@@ -440,13 +480,12 @@ class Filesystem extends AbstractData
|
|||||||
* eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/e3570978f9e4aa90.discussion/'
|
* eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/e3570978f9e4aa90.discussion/'
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $dataid
|
* @param string $dataid
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function _dataid2discussionpath($dataid)
|
private function _dataid2discussionpath($dataid)
|
||||||
{
|
{
|
||||||
return self::_dataid2path($dataid) . $dataid .
|
return $this->_dataid2path($dataid) . $dataid .
|
||||||
'.discussion' . DIRECTORY_SEPARATOR;
|
'.discussion' . DIRECTORY_SEPARATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,25 +493,23 @@ class Filesystem extends AbstractData
|
|||||||
* Check that the given element is a valid first level directory.
|
* Check that the given element is a valid first level directory.
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $element
|
* @param string $element
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private static function _isFirstLevelDir($element)
|
private function _isFirstLevelDir($element)
|
||||||
{
|
{
|
||||||
return self::_isSecondLevelDir($element) &&
|
return $this->_isSecondLevelDir($element) &&
|
||||||
is_dir(self::$_path . DIRECTORY_SEPARATOR . $element);
|
is_dir($this->_path . DIRECTORY_SEPARATOR . $element);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the given element is a valid second level directory.
|
* Check that the given element is a valid second level directory.
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @param string $element
|
* @param string $element
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private static function _isSecondLevelDir($element)
|
private function _isSecondLevelDir($element)
|
||||||
{
|
{
|
||||||
return (bool) preg_match('/^[a-f0-9]{2}$/', $element);
|
return (bool) preg_match('/^[a-f0-9]{2}$/', $element);
|
||||||
}
|
}
|
||||||
@@ -481,15 +518,14 @@ class Filesystem extends AbstractData
|
|||||||
* store the data
|
* store the data
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @static
|
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private static function _store($filename, array $data)
|
private function _store($filename, array $data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return self::_storeString(
|
return $this->_storeString(
|
||||||
$filename,
|
$filename,
|
||||||
self::PROTECTION_LINE . PHP_EOL . Json::encode($data)
|
self::PROTECTION_LINE . PHP_EOL . Json::encode($data)
|
||||||
);
|
);
|
||||||
@@ -502,20 +538,19 @@ class Filesystem extends AbstractData
|
|||||||
* store a string
|
* store a string
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @static
|
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @param string $data
|
* @param string $data
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private static function _storeString($filename, $data)
|
private function _storeString($filename, $data)
|
||||||
{
|
{
|
||||||
// Create storage directory if it does not exist.
|
// Create storage directory if it does not exist.
|
||||||
if (!is_dir(self::$_path)) {
|
if (!is_dir($this->_path)) {
|
||||||
if (!@mkdir(self::$_path, 0700)) {
|
if (!@mkdir($this->_path, 0700)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$file = self::$_path . DIRECTORY_SEPARATOR . '.htaccess';
|
$file = $this->_path . DIRECTORY_SEPARATOR . '.htaccess';
|
||||||
if (!is_file($file)) {
|
if (!is_file($file)) {
|
||||||
$writtenBytes = 0;
|
$writtenBytes = 0;
|
||||||
if ($fileCreated = @touch($file)) {
|
if ($fileCreated = @touch($file)) {
|
||||||
@@ -553,12 +588,11 @@ class Filesystem extends AbstractData
|
|||||||
* rename a file, prepending the protection line at the beginning
|
* rename a file, prepending the protection line at the beginning
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @static
|
|
||||||
* @param string $srcFile
|
* @param string $srcFile
|
||||||
* @param string $destFile
|
* @param string $destFile
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private static function _prependRename($srcFile, $destFile)
|
private function _prependRename($srcFile, $destFile)
|
||||||
{
|
{
|
||||||
// don't overwrite already converted file
|
// don't overwrite already converted file
|
||||||
if (!is_readable($destFile)) {
|
if (!is_readable($destFile)) {
|
||||||
|
|||||||
@@ -14,54 +14,43 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
* GCS client
|
* GCS client
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var StorageClient
|
* @var StorageClient
|
||||||
*/
|
*/
|
||||||
private static $_client = null;
|
private $_client = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GCS bucket
|
* GCS bucket
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var Bucket
|
* @var Bucket
|
||||||
*/
|
*/
|
||||||
private static $_bucket = null;
|
private $_bucket = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* object prefix
|
* object prefix
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $_prefix = 'pastes';
|
private $_prefix = 'pastes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bucket acl type
|
* bucket acl type
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var bool
|
* @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
|
* @access public
|
||||||
* @static
|
|
||||||
* @param array $options
|
* @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')) {
|
if (getenv('PRIVATEBIN_GCS_BUCKET')) {
|
||||||
$bucket = getenv('PRIVATEBIN_GCS_BUCKET');
|
$bucket = getenv('PRIVATEBIN_GCS_BUCKET');
|
||||||
}
|
}
|
||||||
@@ -69,24 +58,22 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
$bucket = $options['bucket'];
|
$bucket = $options['bucket'];
|
||||||
}
|
}
|
||||||
if (is_array($options) && array_key_exists('prefix', $options)) {
|
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)) {
|
if (is_array($options) && array_key_exists('uniformacl', $options)) {
|
||||||
self::$_uniformacl = $options['uniformacl'];
|
$this->_uniformacl = $options['uniformacl'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty(self::$_client)) {
|
$this->_client = class_exists('StorageClientStub', false) ?
|
||||||
self::$_client = class_exists('StorageClientStub', false) ?
|
new \StorageClientStub(array()) :
|
||||||
new \StorageClientStub(array()) :
|
new StorageClient(array('suppressKeyFileNotice' => true));
|
||||||
new StorageClient(array('suppressKeyFileNotice' => true));
|
if (isset($bucket)) {
|
||||||
|
$this->_bucket = $this->_client->bucket($bucket);
|
||||||
}
|
}
|
||||||
self::$_bucket = self::$_client->bucket($bucket);
|
|
||||||
|
|
||||||
return self::$_instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the google storage object key for $pasteid in self::$_bucket.
|
* returns the google storage object key for $pasteid in $this->_bucket.
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @param $pasteid string to get the key for
|
* @param $pasteid string to get the key for
|
||||||
@@ -94,14 +81,14 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
*/
|
*/
|
||||||
private function _getKey($pasteid)
|
private function _getKey($pasteid)
|
||||||
{
|
{
|
||||||
if (self::$_prefix != '') {
|
if ($this->_prefix != '') {
|
||||||
return self::$_prefix . '/' . $pasteid;
|
return $this->_prefix . '/' . $pasteid;
|
||||||
}
|
}
|
||||||
return $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
|
* 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
|
* as the GCS object's metadata except for the fields attachment, attachmentname
|
||||||
* and salt.
|
* and salt.
|
||||||
@@ -126,12 +113,12 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
'metadata' => $metadata,
|
'metadata' => $metadata,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (!self::$_uniformacl) {
|
if (!$this->_uniformacl) {
|
||||||
$data['predefinedAcl'] = 'private';
|
$data['predefinedAcl'] = 'private';
|
||||||
}
|
}
|
||||||
self::$_bucket->upload(Json::encode($payload), $data);
|
$this->_bucket->upload(Json::encode($payload), $data);
|
||||||
} catch (Exception $e) {
|
} 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())));
|
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -156,13 +143,13 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
public function read($pasteid)
|
public function read($pasteid)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$o = self::$_bucket->object($this->_getKey($pasteid));
|
$o = $this->_bucket->object($this->_getKey($pasteid));
|
||||||
$data = $o->downloadAsString();
|
$data = $o->downloadAsString();
|
||||||
return Json::decode($data);
|
return Json::decode($data);
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
return false;
|
return false;
|
||||||
} catch (Exception $e) {
|
} 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())));
|
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -176,9 +163,9 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
$name = $this->_getKey($pasteid);
|
$name = $this->_getKey($pasteid);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
foreach (self::$_bucket->objects(array('prefix' => $name . '/discussion/')) as $comment) {
|
foreach ($this->_bucket->objects(array('prefix' => $name . '/discussion/')) as $comment) {
|
||||||
try {
|
try {
|
||||||
self::$_bucket->object($comment->name())->delete();
|
$this->_bucket->object($comment->name())->delete();
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
// ignore if already deleted.
|
// ignore if already deleted.
|
||||||
}
|
}
|
||||||
@@ -188,7 +175,7 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
self::$_bucket->object($name)->delete();
|
$this->_bucket->object($name)->delete();
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
// ignore if already deleted
|
// ignore if already deleted
|
||||||
}
|
}
|
||||||
@@ -199,7 +186,7 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function exists($pasteid)
|
public function exists($pasteid)
|
||||||
{
|
{
|
||||||
$o = self::$_bucket->object($this->_getKey($pasteid));
|
$o = $this->_bucket->object($this->_getKey($pasteid));
|
||||||
return $o->exists();
|
return $o->exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,8 +210,8 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
$comments = array();
|
$comments = array();
|
||||||
$prefix = $this->_getKey($pasteid) . '/discussion/';
|
$prefix = $this->_getKey($pasteid) . '/discussion/';
|
||||||
try {
|
try {
|
||||||
foreach (self::$_bucket->objects(array('prefix' => $prefix)) as $key) {
|
foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $key) {
|
||||||
$comment = JSON::decode(self::$_bucket->object($key->name())->downloadAsString());
|
$comment = JSON::decode($this->_bucket->object($key->name())->downloadAsString());
|
||||||
$comment['id'] = basename($key->name());
|
$comment['id'] = basename($key->name());
|
||||||
$slot = $this->getOpenSlot($comments, (int) $comment['meta']['created']);
|
$slot = $this->getOpenSlot($comments, (int) $comment['meta']['created']);
|
||||||
$comments[$slot] = $comment;
|
$comments[$slot] = $comment;
|
||||||
@@ -241,7 +228,7 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
public function existsComment($pasteid, $parentid, $commentid)
|
public function existsComment($pasteid, $parentid, $commentid)
|
||||||
{
|
{
|
||||||
$name = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid;
|
$name = $this->_getKey($pasteid) . '/discussion/' . $parentid . '/' . $commentid;
|
||||||
$o = self::$_bucket->object($name);
|
$o = $this->_bucket->object($name);
|
||||||
return $o->exists();
|
return $o->exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +239,7 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
{
|
{
|
||||||
$path = 'config/' . $namespace;
|
$path = 'config/' . $namespace;
|
||||||
try {
|
try {
|
||||||
foreach (self::$_bucket->objects(array('prefix' => $path)) as $object) {
|
foreach ($this->_bucket->objects(array('prefix' => $path)) as $object) {
|
||||||
$name = $object->name();
|
$name = $object->name();
|
||||||
if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') {
|
if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') {
|
||||||
continue;
|
continue;
|
||||||
@@ -300,12 +287,12 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
'metadata' => $metadata,
|
'metadata' => $metadata,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (!self::$_uniformacl) {
|
if (!$this->_uniformacl) {
|
||||||
$data['predefinedAcl'] = 'private';
|
$data['predefinedAcl'] = 'private';
|
||||||
}
|
}
|
||||||
self::$_bucket->upload($value, $data);
|
$this->_bucket->upload($value, $data);
|
||||||
} catch (Exception $e) {
|
} 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())));
|
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -323,7 +310,7 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
$key = 'config/' . $namespace . '/' . $key;
|
$key = 'config/' . $namespace . '/' . $key;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$o = self::$_bucket->object($key);
|
$o = $this->_bucket->object($key);
|
||||||
return $o->downloadAsString();
|
return $o->downloadAsString();
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
return '';
|
return '';
|
||||||
@@ -338,12 +325,12 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
$expired = array();
|
$expired = array();
|
||||||
|
|
||||||
$now = time();
|
$now = time();
|
||||||
$prefix = self::$_prefix;
|
$prefix = $this->_prefix;
|
||||||
if ($prefix != '') {
|
if ($prefix != '') {
|
||||||
$prefix .= '/';
|
$prefix .= '/';
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
foreach (self::$_bucket->objects(array('prefix' => $prefix)) as $object) {
|
foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $object) {
|
||||||
$metadata = $object->info()['metadata'];
|
$metadata = $object->info()['metadata'];
|
||||||
if ($metadata != null && array_key_exists('expire_date', $metadata)) {
|
if ($metadata != null && array_key_exists('expire_date', $metadata)) {
|
||||||
$expire_at = intval($metadata['expire_date']);
|
$expire_at = intval($metadata['expire_date']);
|
||||||
@@ -361,4 +348,28 @@ class GoogleCloudStorage extends AbstractData
|
|||||||
}
|
}
|
||||||
return $expired;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,86 +45,71 @@ class S3Storage extends AbstractData
|
|||||||
* S3 client
|
* S3 client
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var S3Client
|
* @var S3Client
|
||||||
*/
|
*/
|
||||||
private static $_client = null;
|
private $_client = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* S3 client options
|
* S3 client options
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $_options = array();
|
private $_options = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* S3 bucket
|
* S3 bucket
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $_bucket = null;
|
private $_bucket = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* S3 prefix for all PrivateBin data in this bucket
|
* S3 prefix for all PrivateBin data in this bucket
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @static
|
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $_prefix = '';
|
private $_prefix = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns an S3 data backend.
|
* instantiates a new S3 data backend.
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @static
|
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return S3Storage
|
* @return
|
||||||
*/
|
*/
|
||||||
public static function getInstance(array $options)
|
public function __construct(array $options)
|
||||||
{
|
{
|
||||||
// if needed initialize the singleton
|
$this->_options['credentials'] = array();
|
||||||
if (!(self::$_instance instanceof self)) {
|
|
||||||
self::$_instance = new self;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$_options = array();
|
|
||||||
self::$_options['credentials'] = array();
|
|
||||||
|
|
||||||
if (is_array($options) && array_key_exists('region', $options)) {
|
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)) {
|
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)) {
|
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)) {
|
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)) {
|
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)) {
|
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)) {
|
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)) {
|
if (is_array($options) && array_key_exists('prefix', $options)) {
|
||||||
self::$_prefix = $options['prefix'];
|
$this->_prefix = $options['prefix'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty(self::$_client)) {
|
$this->_client = new S3Client($this->_options);
|
||||||
self::$_client = new S3Client(self::$_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$_instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -138,12 +123,12 @@ class S3Storage extends AbstractData
|
|||||||
{
|
{
|
||||||
$allObjects = array();
|
$allObjects = array();
|
||||||
$options = array(
|
$options = array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Prefix' => $prefix,
|
'Prefix' => $prefix,
|
||||||
);
|
);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$objectsListResponse = self::$_client->listObjects($options);
|
$objectsListResponse = $this->_client->listObjects($options);
|
||||||
$objects = $objectsListResponse['Contents'] ?? array();
|
$objects = $objectsListResponse['Contents'] ?? array();
|
||||||
foreach ($objects as $object) {
|
foreach ($objects as $object) {
|
||||||
$allObjects[] = $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
|
* @access private
|
||||||
* @param $pasteid string to get the key for
|
* @param $pasteid string to get the key for
|
||||||
@@ -163,14 +148,14 @@ class S3Storage extends AbstractData
|
|||||||
*/
|
*/
|
||||||
private function _getKey($pasteid)
|
private function _getKey($pasteid)
|
||||||
{
|
{
|
||||||
if (self::$_prefix != '') {
|
if ($this->_prefix != '') {
|
||||||
return self::$_prefix . '/' . $pasteid;
|
return $this->_prefix . '/' . $pasteid;
|
||||||
}
|
}
|
||||||
return $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
|
* 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
|
* as the S3 object's metadata except for the fields attachment, attachmentname
|
||||||
* and salt.
|
* and salt.
|
||||||
@@ -187,15 +172,15 @@ class S3Storage extends AbstractData
|
|||||||
$metadata[$k] = strval($v);
|
$metadata[$k] = strval($v);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
self::$_client->putObject(array(
|
$this->_client->putObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $key,
|
'Key' => $key,
|
||||||
'Body' => Json::encode($payload),
|
'Body' => Json::encode($payload),
|
||||||
'ContentType' => 'application/json',
|
'ContentType' => 'application/json',
|
||||||
'Metadata' => $metadata,
|
'Metadata' => $metadata,
|
||||||
));
|
));
|
||||||
} catch (S3Exception $e) {
|
} 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())));
|
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -220,14 +205,14 @@ class S3Storage extends AbstractData
|
|||||||
public function read($pasteid)
|
public function read($pasteid)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$object = self::$_client->getObject(array(
|
$object = $this->_client->getObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $this->_getKey($pasteid),
|
'Key' => $this->_getKey($pasteid),
|
||||||
));
|
));
|
||||||
$data = $object['Body']->getContents();
|
$data = $object['Body']->getContents();
|
||||||
return Json::decode($data);
|
return Json::decode($data);
|
||||||
} catch (S3Exception $e) {
|
} 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())));
|
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -244,8 +229,8 @@ class S3Storage extends AbstractData
|
|||||||
$comments = $this->_listAllObjects($name . '/discussion/');
|
$comments = $this->_listAllObjects($name . '/discussion/');
|
||||||
foreach ($comments as $comment) {
|
foreach ($comments as $comment) {
|
||||||
try {
|
try {
|
||||||
self::$_client->deleteObject(array(
|
$this->_client->deleteObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $comment['Key'],
|
'Key' => $comment['Key'],
|
||||||
));
|
));
|
||||||
} catch (S3Exception $e) {
|
} catch (S3Exception $e) {
|
||||||
@@ -257,8 +242,8 @@ class S3Storage extends AbstractData
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
self::$_client->deleteObject(array(
|
$this->_client->deleteObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $name,
|
'Key' => $name,
|
||||||
));
|
));
|
||||||
} catch (S3Exception $e) {
|
} catch (S3Exception $e) {
|
||||||
@@ -271,7 +256,7 @@ class S3Storage extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function exists($pasteid)
|
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 {
|
try {
|
||||||
$entries = $this->_listAllObjects($prefix);
|
$entries = $this->_listAllObjects($prefix);
|
||||||
foreach ($entries as $entry) {
|
foreach ($entries as $entry) {
|
||||||
$object = self::$_client->getObject(array(
|
$object = $this->_client->getObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $entry['Key'],
|
'Key' => $entry['Key'],
|
||||||
));
|
));
|
||||||
$body = JSON::decode($object['Body']->getContents());
|
$body = JSON::decode($object['Body']->getContents());
|
||||||
@@ -319,7 +304,7 @@ class S3Storage extends AbstractData
|
|||||||
public function existsComment($pasteid, $parentid, $commentid)
|
public function existsComment($pasteid, $parentid, $commentid)
|
||||||
{
|
{
|
||||||
$name = $this->_getKey($pasteid) . '/discussion/' . $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)
|
public function purgeValues($namespace, $time)
|
||||||
{
|
{
|
||||||
$path = self::$_prefix;
|
$path = $this->_prefix;
|
||||||
if ($path != '') {
|
if ($path != '') {
|
||||||
$path .= '/';
|
$path .= '/';
|
||||||
}
|
}
|
||||||
@@ -339,16 +324,16 @@ class S3Storage extends AbstractData
|
|||||||
if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') {
|
if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$head = self::$_client->headObject(array(
|
$head = $this->_client->headObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $name,
|
'Key' => $name,
|
||||||
));
|
));
|
||||||
if (array_key_exists('Metadata', $head) && array_key_exists('value', $head['Metadata'])) {
|
if ($head->get('Metadata') != null && array_key_exists('value', $head->get('Metadata'))) {
|
||||||
$value = $head['Metadata']['value'];
|
$value = $head->get('Metadata')['value'];
|
||||||
if (is_numeric($value) && intval($value) < $time) {
|
if (is_numeric($value) && intval($value) < $time) {
|
||||||
try {
|
try {
|
||||||
self::$_client->deleteObject(array(
|
$this->_client->deleteObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $name,
|
'Key' => $name,
|
||||||
));
|
));
|
||||||
} catch (S3Exception $e) {
|
} catch (S3Exception $e) {
|
||||||
@@ -369,7 +354,7 @@ class S3Storage extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function setValue($value, $namespace, $key = '')
|
public function setValue($value, $namespace, $key = '')
|
||||||
{
|
{
|
||||||
$prefix = self::$_prefix;
|
$prefix = $this->_prefix;
|
||||||
if ($prefix != '') {
|
if ($prefix != '') {
|
||||||
$prefix .= '/';
|
$prefix .= '/';
|
||||||
}
|
}
|
||||||
@@ -385,15 +370,15 @@ class S3Storage extends AbstractData
|
|||||||
$metadata['value'] = strval($value);
|
$metadata['value'] = strval($value);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
self::$_client->putObject(array(
|
$this->_client->putObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $key,
|
'Key' => $key,
|
||||||
'Body' => $value,
|
'Body' => $value,
|
||||||
'ContentType' => 'application/json',
|
'ContentType' => 'application/json',
|
||||||
'Metadata' => $metadata,
|
'Metadata' => $metadata,
|
||||||
));
|
));
|
||||||
} catch (S3Exception $e) {
|
} 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())));
|
trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -405,7 +390,7 @@ class S3Storage extends AbstractData
|
|||||||
*/
|
*/
|
||||||
public function getValue($namespace, $key = '')
|
public function getValue($namespace, $key = '')
|
||||||
{
|
{
|
||||||
$prefix = self::$_prefix;
|
$prefix = $this->_prefix;
|
||||||
if ($prefix != '') {
|
if ($prefix != '') {
|
||||||
$prefix .= '/';
|
$prefix .= '/';
|
||||||
}
|
}
|
||||||
@@ -417,8 +402,8 @@ class S3Storage extends AbstractData
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$object = self::$_client->getObject(array(
|
$object = $this->_client->getObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $key,
|
'Key' => $key,
|
||||||
));
|
));
|
||||||
return $object['Body']->getContents();
|
return $object['Body']->getContents();
|
||||||
@@ -434,19 +419,19 @@ class S3Storage extends AbstractData
|
|||||||
{
|
{
|
||||||
$expired = array();
|
$expired = array();
|
||||||
$now = time();
|
$now = time();
|
||||||
$prefix = self::$_prefix;
|
$prefix = $this->_prefix;
|
||||||
if ($prefix != '') {
|
if ($prefix != '') {
|
||||||
$prefix .= '/';
|
$prefix .= '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
foreach ($this->_listAllObjects($prefix) as $object) {
|
foreach ($this->_listAllObjects($prefix) as $object) {
|
||||||
$head = self::$_client->headObject(array(
|
$head = $this->_client->headObject(array(
|
||||||
'Bucket' => self::$_bucket,
|
'Bucket' => $this->_bucket,
|
||||||
'Key' => $object['Key'],
|
'Key' => $object['Key'],
|
||||||
));
|
));
|
||||||
if (array_key_exists('Metadata', $head) && array_key_exists('expire_date', $head['Metadata'])) {
|
if ($head->get('Metadata') != null && array_key_exists('expire_date', $head->get('Metadata'))) {
|
||||||
$expire_at = intval($head['Metadata']['expire_date']);
|
$expire_at = intval($head->get('Metadata')['expire_date']);
|
||||||
if ($expire_at != 0 && $expire_at < $now) {
|
if ($expire_at != 0 && $expire_at < $now) {
|
||||||
array_push($expired, $object['Key']);
|
array_push($expired, $object['Key']);
|
||||||
}
|
}
|
||||||
@@ -461,4 +446,28 @@ class S3Storage extends AbstractData
|
|||||||
}
|
}
|
||||||
return $expired;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,10 +81,8 @@ class Model
|
|||||||
public function getStore()
|
public function getStore()
|
||||||
{
|
{
|
||||||
if ($this->_store === null) {
|
if ($this->_store === null) {
|
||||||
$this->_store = forward_static_call(
|
$class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model');
|
||||||
'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model') . '::getInstance',
|
$this->_store = new $class($this->_conf->getSection('model_options'));
|
||||||
$this->_conf->getSection('model_options')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return $this->_store;
|
return $this->_store;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class YourlsProxy
|
|||||||
*/
|
*/
|
||||||
public function __construct(Configuration $conf, $link)
|
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.';
|
$this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ Helper::updateSubresourceIntegrity();
|
|||||||
*/
|
*/
|
||||||
class StorageClientStub extends StorageClient
|
class StorageClientStub extends StorageClient
|
||||||
{
|
{
|
||||||
private $_config = null;
|
private $_config = null;
|
||||||
private $_connection = null;
|
private $_connection = null;
|
||||||
private $_buckets = array();
|
private static $_buckets = array();
|
||||||
|
|
||||||
public function __construct(array $config = array())
|
public function __construct(array $config = array())
|
||||||
{
|
{
|
||||||
@@ -44,11 +44,11 @@ class StorageClientStub extends StorageClient
|
|||||||
|
|
||||||
public function bucket($name, $userProject = false)
|
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);
|
$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)
|
public function deleteBucket($name)
|
||||||
{
|
{
|
||||||
if (key_exists($name, $this->_buckets)) {
|
if (key_exists($name, self::$_buckets)) {
|
||||||
unset($this->_buckets[$name]);
|
unset(self::$_buckets[$name]);
|
||||||
} else {
|
} else {
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
@@ -110,11 +110,11 @@ class StorageClientStub extends StorageClient
|
|||||||
|
|
||||||
public function createBucket($name, array $options = array())
|
public function createBucket($name, array $options = array())
|
||||||
{
|
{
|
||||||
if (key_exists($name, $this->_buckets)) {
|
if (key_exists($name, self::$_buckets)) {
|
||||||
throw new BadRequestException('already exists');
|
throw new BadRequestException('already exists');
|
||||||
}
|
}
|
||||||
$b = new BucketStub($this->_connection, $name, array(), $this);
|
$b = new BucketStub($this->_connection, $name, array(), $this);
|
||||||
$this->_buckets[$name] = $b;
|
self::$_buckets[$name] = $b;
|
||||||
return $b;
|
return $b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
/* Setup Routine */
|
/* Setup Routine */
|
||||||
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
||||||
$this->_data = Filesystem::getInstance(array('dir' => $this->_path));
|
$this->_data = new Filesystem(array('dir' => $this->_path));
|
||||||
ServerSalt::setStore($this->_data);
|
ServerSalt::setStore($this->_data);
|
||||||
TrafficLimiter::setStore($this->_data);
|
TrafficLimiter::setStore($this->_data);
|
||||||
$this->reset();
|
$this->reset();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class ControllerWithDbTest extends ControllerTest
|
|||||||
mkdir($this->_path);
|
mkdir($this->_path);
|
||||||
}
|
}
|
||||||
$this->_options['dsn'] = 'sqlite:' . $this->_path . DIRECTORY_SEPARATOR . 'tst.sq3';
|
$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);
|
ServerSalt::setStore($this->_data);
|
||||||
TrafficLimiter::setStore($this->_data);
|
TrafficLimiter::setStore($this->_data);
|
||||||
$this->reset();
|
$this->reset();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class ControllerWithGcsTest extends ControllerTest
|
|||||||
'bucket' => self::$_bucket->name(),
|
'bucket' => self::$_bucket->name(),
|
||||||
'prefix' => 'pastes',
|
'prefix' => 'pastes',
|
||||||
);
|
);
|
||||||
$this->_data = GoogleCloudStorage::getInstance($this->_options);
|
$this->_data = new GoogleCloudStorage($this->_options);
|
||||||
ServerSalt::setStore($this->_data);
|
ServerSalt::setStore($this->_data);
|
||||||
TrafficLimiter::setStore($this->_data);
|
TrafficLimiter::setStore($this->_data);
|
||||||
$this->reset();
|
$this->reset();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
/* Setup Routine */
|
/* Setup Routine */
|
||||||
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
||||||
$this->_model = Database::getInstance($this->_options);
|
$this->_model = new Database($this->_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown()
|
public function tearDown()
|
||||||
@@ -35,7 +35,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testSaltMigration()
|
public function testSaltMigration()
|
||||||
{
|
{
|
||||||
ServerSalt::setStore(Filesystem::getInstance(array('dir' => 'data')));
|
ServerSalt::setStore(new Filesystem(array('dir' => 'data')));
|
||||||
$salt = ServerSalt::get();
|
$salt = ServerSalt::get();
|
||||||
$file = 'data' . DIRECTORY_SEPARATOR . 'salt.php';
|
$file = 'data' . DIRECTORY_SEPARATOR . 'salt.php';
|
||||||
$this->assertFileExists($file, 'ServerSalt got initialized and stored on disk');
|
$this->assertFileExists($file, 'ServerSalt got initialized and stored on disk');
|
||||||
@@ -141,7 +141,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetIbmInstance()
|
public function testGetIbmInstance()
|
||||||
{
|
{
|
||||||
Database::getInstance(array(
|
new Database(array(
|
||||||
'dsn' => 'ibm:', 'usr' => null, 'pwd' => null,
|
'dsn' => 'ibm:', 'usr' => null, 'pwd' => null,
|
||||||
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
||||||
));
|
));
|
||||||
@@ -152,7 +152,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetInformixInstance()
|
public function testGetInformixInstance()
|
||||||
{
|
{
|
||||||
Database::getInstance(array(
|
new Database(array(
|
||||||
'dsn' => 'informix:', 'usr' => null, 'pwd' => null,
|
'dsn' => 'informix:', 'usr' => null, 'pwd' => null,
|
||||||
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
||||||
));
|
));
|
||||||
@@ -163,7 +163,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetMssqlInstance()
|
public function testGetMssqlInstance()
|
||||||
{
|
{
|
||||||
Database::getInstance(array(
|
new Database(array(
|
||||||
'dsn' => 'mssql:', 'usr' => null, 'pwd' => null,
|
'dsn' => 'mssql:', 'usr' => null, 'pwd' => null,
|
||||||
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
||||||
));
|
));
|
||||||
@@ -174,7 +174,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetMysqlInstance()
|
public function testGetMysqlInstance()
|
||||||
{
|
{
|
||||||
Database::getInstance(array(
|
new Database(array(
|
||||||
'dsn' => 'mysql:', 'usr' => null, 'pwd' => null,
|
'dsn' => 'mysql:', 'usr' => null, 'pwd' => null,
|
||||||
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
||||||
));
|
));
|
||||||
@@ -185,7 +185,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetOciInstance()
|
public function testGetOciInstance()
|
||||||
{
|
{
|
||||||
Database::getInstance(array(
|
new Database(array(
|
||||||
'dsn' => 'oci:', 'usr' => null, 'pwd' => null,
|
'dsn' => 'oci:', 'usr' => null, 'pwd' => null,
|
||||||
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
||||||
));
|
));
|
||||||
@@ -196,7 +196,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetPgsqlInstance()
|
public function testGetPgsqlInstance()
|
||||||
{
|
{
|
||||||
Database::getInstance(array(
|
new Database(array(
|
||||||
'dsn' => 'pgsql:', 'usr' => null, 'pwd' => null,
|
'dsn' => 'pgsql:', 'usr' => null, 'pwd' => null,
|
||||||
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
|
||||||
));
|
));
|
||||||
@@ -208,7 +208,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetFooInstance()
|
public function testGetFooInstance()
|
||||||
{
|
{
|
||||||
Database::getInstance(array(
|
new Database(array(
|
||||||
'dsn' => 'foo:', 'usr' => null, 'pwd' => null, 'opt' => null,
|
'dsn' => 'foo:', 'usr' => null, 'pwd' => null, 'opt' => null,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$options = $this->_options;
|
$options = $this->_options;
|
||||||
unset($options['dsn']);
|
unset($options['dsn']);
|
||||||
Database::getInstance($options);
|
new Database($options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -232,7 +232,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$options = $this->_options;
|
$options = $this->_options;
|
||||||
unset($options['usr']);
|
unset($options['usr']);
|
||||||
Database::getInstance($options);
|
new Database($options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,7 +243,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$options = $this->_options;
|
$options = $this->_options;
|
||||||
unset($options['pwd']);
|
unset($options['pwd']);
|
||||||
Database::getInstance($options);
|
new Database($options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -254,7 +254,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$options = $this->_options;
|
$options = $this->_options;
|
||||||
unset($options['opt']);
|
unset($options['opt']);
|
||||||
Database::getInstance($options);
|
new Database($options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOldAttachments()
|
public function testOldAttachments()
|
||||||
@@ -266,7 +266,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
$this->_options['dsn'] = 'sqlite:' . $path;
|
$this->_options['dsn'] = 'sqlite:' . $path;
|
||||||
$this->_options['tbl'] = 'bar_';
|
$this->_options['tbl'] = 'bar_';
|
||||||
$model = Database::getInstance($this->_options);
|
$model = new Database($this->_options);
|
||||||
|
|
||||||
$original = $paste = Helper::getPasteWithAttachment(1, array('expire_date' => 1344803344));
|
$original = $paste = Helper::getPasteWithAttachment(1, array('expire_date' => 1344803344));
|
||||||
$meta = $paste['meta'];
|
$meta = $paste['meta'];
|
||||||
@@ -311,7 +311,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
$this->_options['dsn'] = 'sqlite:' . $path;
|
$this->_options['dsn'] = 'sqlite:' . $path;
|
||||||
$this->_options['tbl'] = 'baz_';
|
$this->_options['tbl'] = 'baz_';
|
||||||
$model = Database::getInstance($this->_options);
|
$model = new Database($this->_options);
|
||||||
$paste = Helper::getPaste(1, array('expire_date' => 1344803344));
|
$paste = Helper::getPaste(1, array('expire_date' => 1344803344));
|
||||||
unset($paste['meta']['formatter'], $paste['meta']['opendiscussion'], $paste['meta']['salt']);
|
unset($paste['meta']['formatter'], $paste['meta']['opendiscussion'], $paste['meta']['salt']);
|
||||||
$model->delete(Helper::getPasteId());
|
$model->delete(Helper::getPasteId());
|
||||||
@@ -378,7 +378,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||||||
'vizhash BLOB, ' .
|
'vizhash BLOB, ' .
|
||||||
'postdate INT );'
|
'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
|
// check if version number was upgraded in created configuration table
|
||||||
$statement = $db->prepare('SELECT value FROM foo_config WHERE id LIKE ?');
|
$statement = $db->prepare('SELECT value FROM foo_config WHERE id LIKE ?');
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
|
|||||||
/* Setup Routine */
|
/* Setup Routine */
|
||||||
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
||||||
$this->_invalidPath = $this->_path . DIRECTORY_SEPARATOR . 'bar';
|
$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)) {
|
if (!is_dir($this->_path)) {
|
||||||
mkdir($this->_path);
|
mkdir($this->_path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class GoogleCloudStorageTest extends PHPUnit_Framework_TestCase
|
|||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
ini_set('error_log', stream_get_meta_data(tmpfile())['uri']);
|
ini_set('error_log', stream_get_meta_data(tmpfile())['uri']);
|
||||||
$this->_model = GoogleCloudStorage::getInstance(array(
|
$this->_model = new GoogleCloudStorage(array(
|
||||||
'bucket' => self::$_bucket->name(),
|
'bucket' => self::$_bucket->name(),
|
||||||
'prefix' => 'pastes',
|
'prefix' => 'pastes',
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
|
|||||||
if (!is_dir($this->_path)) {
|
if (!is_dir($this->_path)) {
|
||||||
mkdir($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);
|
ServerSalt::setStore($this->_model);
|
||||||
|
|
||||||
$_POST = array();
|
$_POST = array();
|
||||||
@@ -272,7 +272,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json';
|
$mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json';
|
||||||
$options = parse_ini_file(CONF, true);
|
$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['main']['urlshortener'] = 'https://example.com/path/shortenviayourls?link=';
|
||||||
$options['yourls']['apiurl'] = $mock_yourls_service;
|
$options['yourls']['apiurl'] = $mock_yourls_service;
|
||||||
Helper::createIniFile(CONF, $options);
|
Helper::createIniFile(CONF, $options);
|
||||||
|
|||||||
85
tst/MigrateTest.php
Normal file
85
tst/MigrateTest.php
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
use PrivateBin\Data\Database;
|
||||||
|
use PrivateBin\Data\Filesystem;
|
||||||
|
|
||||||
|
class MigrateTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected $_model_1;
|
||||||
|
|
||||||
|
protected $_model_2;
|
||||||
|
|
||||||
|
protected $_path;
|
||||||
|
|
||||||
|
protected $_path_instance_1;
|
||||||
|
|
||||||
|
protected $_path_instance_2;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
/* Setup Routine */
|
||||||
|
$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)) {
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
|
||||||
|
// 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,7 +38,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
Helper::confBackup();
|
Helper::confBackup();
|
||||||
Helper::createIniFile(CONF, $options);
|
Helper::createIniFile(CONF, $options);
|
||||||
ServerSalt::setStore(Database::getInstance($options['model_options']));
|
ServerSalt::setStore(new Database($options['model_options']));
|
||||||
$this->_conf = new Configuration;
|
$this->_conf = new Configuration;
|
||||||
$this->_model = new Model($this->_conf);
|
$this->_model = new Model($this->_conf);
|
||||||
$_SERVER['REMOTE_ADDR'] = '::1';
|
$_SERVER['REMOTE_ADDR'] = '::1';
|
||||||
@@ -156,10 +156,10 @@ class ModelTest extends PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testCommentDefaults()
|
public function testCommentDefaults()
|
||||||
{
|
{
|
||||||
|
$class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model');
|
||||||
$comment = new Comment(
|
$comment = new Comment(
|
||||||
$this->_conf,
|
$this->_conf,
|
||||||
forward_static_call(
|
new $class(
|
||||||
'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model') . '::getInstance',
|
|
||||||
$this->_conf->getSection('model_options')
|
$this->_conf->getSection('model_options')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -259,7 +259,10 @@ class ModelTest extends PHPUnit_Framework_TestCase
|
|||||||
$paste = $model->getPaste();
|
$paste = $model->getPaste();
|
||||||
$paste->setData($pasteData);
|
$paste->setData($pasteData);
|
||||||
$paste->store();
|
$paste->store();
|
||||||
$paste->exists();
|
$this->assertTrue($paste->exists(), 'paste exists before creating comment');
|
||||||
|
|
||||||
|
$comment = $paste->getComment(Helper::getPasteId());
|
||||||
|
$comment->setData($commentData);
|
||||||
|
|
||||||
$db = new PDO(
|
$db = new PDO(
|
||||||
$options['model_options']['dsn'],
|
$options['model_options']['dsn'],
|
||||||
@@ -271,8 +274,9 @@ class ModelTest extends PHPUnit_Framework_TestCase
|
|||||||
$statement->execute();
|
$statement->execute();
|
||||||
$statement->closeCursor();
|
$statement->closeCursor();
|
||||||
|
|
||||||
$comment = $paste->getComment(Helper::getPasteId());
|
if (version_compare(PHP_VERSION, '7.2.0') < 0) {
|
||||||
$comment->setData($commentData);
|
throw new Exception('For some reason, this test stopped working in PHP < 7.2', 70);
|
||||||
|
}
|
||||||
$comment->store();
|
$comment->store();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +456,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
|
|||||||
public function testPurge()
|
public function testPurge()
|
||||||
{
|
{
|
||||||
$conf = new Configuration;
|
$conf = new Configuration;
|
||||||
$store = Database::getInstance($conf->getSection('model_options'));
|
$store = new Database($conf->getSection('model_options'));
|
||||||
$store->delete(Helper::getPasteId());
|
$store->delete(Helper::getPasteId());
|
||||||
$expired = Helper::getPaste(2, array('expire_date' => 1344803344));
|
$expired = Helper::getPaste(2, array('expire_date' => 1344803344));
|
||||||
$paste = Helper::getPaste(2, array('expire_date' => time() + 3600));
|
$paste = Helper::getPaste(2, array('expire_date' => time() + 3600));
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class PurgeLimiterTest extends PHPUnit_Framework_TestCase
|
|||||||
mkdir($this->_path);
|
mkdir($this->_path);
|
||||||
}
|
}
|
||||||
PurgeLimiter::setStore(
|
PurgeLimiter::setStore(
|
||||||
Filesystem::getInstance(array('dir' => $this->_path))
|
new Filesystem(array('dir' => $this->_path))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase
|
|||||||
mkdir($this->_path);
|
mkdir($this->_path);
|
||||||
}
|
}
|
||||||
ServerSalt::setStore(
|
ServerSalt::setStore(
|
||||||
Filesystem::getInstance(array('dir' => $this->_path))
|
new Filesystem(array('dir' => $this->_path))
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->_otherPath = $this->_path . DIRECTORY_SEPARATOR . 'foo';
|
$this->_otherPath = $this->_path . DIRECTORY_SEPARATOR . 'foo';
|
||||||
@@ -44,17 +44,17 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
// generating new salt
|
// generating new salt
|
||||||
ServerSalt::setStore(
|
ServerSalt::setStore(
|
||||||
Filesystem::getInstance(array('dir' => $this->_path))
|
new Filesystem(array('dir' => $this->_path))
|
||||||
);
|
);
|
||||||
$salt = ServerSalt::get();
|
$salt = ServerSalt::get();
|
||||||
|
|
||||||
// try setting a different path and resetting it
|
// try setting a different path and resetting it
|
||||||
ServerSalt::setStore(
|
ServerSalt::setStore(
|
||||||
Filesystem::getInstance(array('dir' => $this->_otherPath))
|
new Filesystem(array('dir' => $this->_otherPath))
|
||||||
);
|
);
|
||||||
$this->assertNotEquals($salt, ServerSalt::get());
|
$this->assertNotEquals($salt, ServerSalt::get());
|
||||||
ServerSalt::setStore(
|
ServerSalt::setStore(
|
||||||
Filesystem::getInstance(array('dir' => $this->_path))
|
new Filesystem(array('dir' => $this->_path))
|
||||||
);
|
);
|
||||||
$this->assertEquals($salt, ServerSalt::get());
|
$this->assertEquals($salt, ServerSalt::get());
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
// try setting an invalid path
|
// try setting an invalid path
|
||||||
chmod($this->_invalidPath, 0000);
|
chmod($this->_invalidPath, 0000);
|
||||||
$store = Filesystem::getInstance(array('dir' => $this->_invalidPath));
|
$store = new Filesystem(array('dir' => $this->_invalidPath));
|
||||||
ServerSalt::setStore($store);
|
ServerSalt::setStore($store);
|
||||||
$salt = ServerSalt::get();
|
$salt = ServerSalt::get();
|
||||||
ServerSalt::setStore($store);
|
ServerSalt::setStore($store);
|
||||||
@@ -76,7 +76,7 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase
|
|||||||
chmod($this->_invalidPath, 0700);
|
chmod($this->_invalidPath, 0700);
|
||||||
file_put_contents($this->_invalidFile, '');
|
file_put_contents($this->_invalidFile, '');
|
||||||
chmod($this->_invalidFile, 0000);
|
chmod($this->_invalidFile, 0000);
|
||||||
$store = Filesystem::getInstance(array('dir' => $this->_invalidPath));
|
$store = new Filesystem(array('dir' => $this->_invalidPath));
|
||||||
ServerSalt::setStore($store);
|
ServerSalt::setStore($store);
|
||||||
$salt = ServerSalt::get();
|
$salt = ServerSalt::get();
|
||||||
ServerSalt::setStore($store);
|
ServerSalt::setStore($store);
|
||||||
@@ -93,7 +93,7 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
file_put_contents($this->_invalidPath . DIRECTORY_SEPARATOR . '.htaccess', '');
|
file_put_contents($this->_invalidPath . DIRECTORY_SEPARATOR . '.htaccess', '');
|
||||||
chmod($this->_invalidPath, 0500);
|
chmod($this->_invalidPath, 0500);
|
||||||
$store = Filesystem::getInstance(array('dir' => $this->_invalidPath));
|
$store = new Filesystem(array('dir' => $this->_invalidPath));
|
||||||
ServerSalt::setStore($store);
|
ServerSalt::setStore($store);
|
||||||
$salt = ServerSalt::get();
|
$salt = ServerSalt::get();
|
||||||
ServerSalt::setStore($store);
|
ServerSalt::setStore($store);
|
||||||
@@ -105,9 +105,9 @@ class ServerSaltTest extends PHPUnit_Framework_TestCase
|
|||||||
// try creating an invalid path
|
// try creating an invalid path
|
||||||
chmod($this->_invalidPath, 0000);
|
chmod($this->_invalidPath, 0000);
|
||||||
ServerSalt::setStore(
|
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);
|
ServerSalt::setStore($store);
|
||||||
$salt = ServerSalt::get();
|
$salt = ServerSalt::get();
|
||||||
ServerSalt::setStore($store);
|
ServerSalt::setStore($store);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
/* Setup Routine */
|
/* Setup Routine */
|
||||||
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'trafficlimit';
|
$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);
|
ServerSalt::setStore($store);
|
||||||
TrafficLimiter::setStore($store);
|
TrafficLimiter::setStore($store);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class Vizhash16x16Test extends PHPUnit_Framework_TestCase
|
|||||||
mkdir($this->_path);
|
mkdir($this->_path);
|
||||||
}
|
}
|
||||||
$this->_file = $this->_path . DIRECTORY_SEPARATOR . 'vizhash.png';
|
$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()
|
public function tearDown()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class YourlsProxyTest extends PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
$this->_mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json';
|
$this->_mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json';
|
||||||
$options = parse_ini_file(CONF_SAMPLE, true);
|
$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['main']['urlshortener'] = 'https://example.com/shortenviayourls?link=';
|
||||||
$options['yourls']['apiurl'] = $this->_mock_yourls_service;
|
$options['yourls']['apiurl'] = $this->_mock_yourls_service;
|
||||||
Helper::confBackup();
|
Helper::confBackup();
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<phpunit bootstrap="Bootstrap.php" colors="true">
|
<phpunit bootstrap="Bootstrap.php" colors="true">
|
||||||
<testsuite name="PrivateBin Test Suite">
|
<testsuite name="PrivateBin Test Suite">
|
||||||
<directory suffix=".php">./</directory>
|
<directory suffix=".php">./</directory>
|
||||||
<exclude>ConfigurationTestGenerator.php</exclude>
|
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<filter>
|
<filter>
|
||||||
<whitelist>
|
<whitelist>
|
||||||
|
|||||||
157
vendor/composer/ClassLoader.php
vendored
157
vendor/composer/ClassLoader.php
vendored
@@ -37,130 +37,57 @@ 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 https://www.php-fig.org/psr/psr-0/
|
* @see http://www.php-fig.org/psr/psr-0/
|
||||||
* @see https://www.php-fig.org/psr/psr-4/
|
* @see http://www.php-fig.org/psr/psr-4/
|
||||||
*/
|
*/
|
||||||
class ClassLoader
|
class ClassLoader
|
||||||
{
|
{
|
||||||
/** @var ?string */
|
|
||||||
private $vendorDir;
|
|
||||||
|
|
||||||
// PSR-4
|
// PSR-4
|
||||||
/**
|
|
||||||
* @var array[]
|
|
||||||
* @psalm-var array<string, array<string, int>>
|
|
||||||
*/
|
|
||||||
private $prefixLengthsPsr4 = array();
|
private $prefixLengthsPsr4 = array();
|
||||||
/**
|
|
||||||
* @var array[]
|
|
||||||
* @psalm-var array<string, array<int, string>>
|
|
||||||
*/
|
|
||||||
private $prefixDirsPsr4 = array();
|
private $prefixDirsPsr4 = array();
|
||||||
/**
|
|
||||||
* @var array[]
|
|
||||||
* @psalm-var array<string, string>
|
|
||||||
*/
|
|
||||||
private $fallbackDirsPsr4 = array();
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
// PSR-0
|
// PSR-0
|
||||||
/**
|
|
||||||
* @var array[]
|
|
||||||
* @psalm-var array<string, array<string, string[]>>
|
|
||||||
*/
|
|
||||||
private $prefixesPsr0 = array();
|
private $prefixesPsr0 = array();
|
||||||
/**
|
|
||||||
* @var array[]
|
|
||||||
* @psalm-var array<string, string>
|
|
||||||
*/
|
|
||||||
private $fallbackDirsPsr0 = array();
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
private $useIncludePath = false;
|
private $useIncludePath = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string[]
|
|
||||||
* @psalm-var array<string, string>
|
|
||||||
*/
|
|
||||||
private $classMap = array();
|
private $classMap = array();
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
private $classMapAuthoritative = false;
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var bool[]
|
|
||||||
* @psalm-var array<string, bool>
|
|
||||||
*/
|
|
||||||
private $missingClasses = array();
|
private $missingClasses = array();
|
||||||
|
|
||||||
/** @var ?string */
|
|
||||||
private $apcuPrefix;
|
private $apcuPrefix;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var self[]
|
|
||||||
*/
|
|
||||||
private static $registeredLoaders = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ?string $vendorDir
|
|
||||||
*/
|
|
||||||
public function __construct($vendorDir = null)
|
|
||||||
{
|
|
||||||
$this->vendorDir = $vendorDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[]
|
|
||||||
*/
|
|
||||||
public function getPrefixes()
|
public function getPrefixes()
|
||||||
{
|
{
|
||||||
if (!empty($this->prefixesPsr0)) {
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array[]
|
|
||||||
* @psalm-return array<string, array<int, string>>
|
|
||||||
*/
|
|
||||||
public function getPrefixesPsr4()
|
public function getPrefixesPsr4()
|
||||||
{
|
{
|
||||||
return $this->prefixDirsPsr4;
|
return $this->prefixDirsPsr4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array[]
|
|
||||||
* @psalm-return array<string, string>
|
|
||||||
*/
|
|
||||||
public function getFallbackDirs()
|
public function getFallbackDirs()
|
||||||
{
|
{
|
||||||
return $this->fallbackDirsPsr0;
|
return $this->fallbackDirsPsr0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array[]
|
|
||||||
* @psalm-return array<string, string>
|
|
||||||
*/
|
|
||||||
public function getFallbackDirsPsr4()
|
public function getFallbackDirsPsr4()
|
||||||
{
|
{
|
||||||
return $this->fallbackDirsPsr4;
|
return $this->fallbackDirsPsr4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[] Array of classname => path
|
|
||||||
* @psalm-return array<string, string>
|
|
||||||
*/
|
|
||||||
public function getClassMap()
|
public function getClassMap()
|
||||||
{
|
{
|
||||||
return $this->classMap;
|
return $this->classMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $classMap Class to filename map
|
* @param array $classMap Class to filename map
|
||||||
* @psalm-param array<string, string> $classMap
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function addClassMap(array $classMap)
|
public function addClassMap(array $classMap)
|
||||||
{
|
{
|
||||||
@@ -175,11 +102,9 @@ class ClassLoader
|
|||||||
* Registers a set of PSR-0 directories for a given prefix, either
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
* appending or prepending to the ones previously set for this prefix.
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix
|
* @param string $prefix The prefix
|
||||||
* @param string[]|string $paths The PSR-0 root directories
|
* @param array|string $paths The PSR-0 root directories
|
||||||
* @param bool $prepend Whether to prepend the directories
|
* @param bool $prepend Whether to prepend the directories
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function add($prefix, $paths, $prepend = false)
|
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
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
* appending or prepending to the ones previously set for this namespace.
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
* @param string[]|string $paths The PSR-4 base directories
|
* @param array|string $paths The PSR-4 base directories
|
||||||
* @param bool $prepend Whether to prepend the directories
|
* @param bool $prepend Whether to prepend the directories
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function addPsr4($prefix, $paths, $prepend = false)
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
{
|
{
|
||||||
@@ -272,10 +195,8 @@ class ClassLoader
|
|||||||
* Registers a set of PSR-0 directories for a given prefix,
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
* replacing any others previously set for this prefix.
|
* replacing any others previously set for this prefix.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix
|
* @param string $prefix The prefix
|
||||||
* @param string[]|string $paths The PSR-0 base directories
|
* @param array|string $paths The PSR-0 base directories
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function set($prefix, $paths)
|
public function set($prefix, $paths)
|
||||||
{
|
{
|
||||||
@@ -290,12 +211,10 @@ class ClassLoader
|
|||||||
* Registers a set of PSR-4 directories for a given namespace,
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
* replacing any others previously set for this namespace.
|
* replacing any others previously set for this namespace.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
* @param string[]|string $paths The PSR-4 base directories
|
* @param array|string $paths The PSR-4 base directories
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function setPsr4($prefix, $paths)
|
public function setPsr4($prefix, $paths)
|
||||||
{
|
{
|
||||||
@@ -315,8 +234,6 @@ class ClassLoader
|
|||||||
* Turns on searching the include path for class files.
|
* Turns on searching the include path for class files.
|
||||||
*
|
*
|
||||||
* @param bool $useIncludePath
|
* @param bool $useIncludePath
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function setUseIncludePath($useIncludePath)
|
public function setUseIncludePath($useIncludePath)
|
||||||
{
|
{
|
||||||
@@ -339,8 +256,6 @@ class ClassLoader
|
|||||||
* that have not been registered with the class map.
|
* that have not been registered with the class map.
|
||||||
*
|
*
|
||||||
* @param bool $classMapAuthoritative
|
* @param bool $classMapAuthoritative
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
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.
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
*
|
*
|
||||||
* @param string|null $apcuPrefix
|
* @param string|null $apcuPrefix
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function setApcuPrefix($apcuPrefix)
|
public function setApcuPrefix($apcuPrefix)
|
||||||
{
|
{
|
||||||
@@ -383,44 +296,25 @@ class ClassLoader
|
|||||||
* Registers this instance as an autoloader.
|
* Registers this instance as an autoloader.
|
||||||
*
|
*
|
||||||
* @param bool $prepend Whether to prepend the autoloader or not
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters this instance as an autoloader.
|
* Unregisters this instance as an autoloader.
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the given class or interface.
|
* Loads the given class or interface.
|
||||||
*
|
*
|
||||||
* @param string $class The name of the class
|
* @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)
|
public function loadClass($class)
|
||||||
{
|
{
|
||||||
@@ -429,8 +323,6 @@ class ClassLoader
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -475,21 +367,6 @@ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $class
|
|
||||||
* @param string $ext
|
|
||||||
* @return string|false
|
|
||||||
*/
|
|
||||||
private function findFileWithExtension($class, $ext)
|
private function findFileWithExtension($class, $ext)
|
||||||
{
|
{
|
||||||
// PSR-4 lookup
|
// PSR-4 lookup
|
||||||
@@ -561,10 +438,6 @@ class ClassLoader
|
|||||||
* Scope isolated include.
|
* Scope isolated include.
|
||||||
*
|
*
|
||||||
* Prevents access to $this/self from included files.
|
* Prevents access to $this/self from included files.
|
||||||
*
|
|
||||||
* @param string $file
|
|
||||||
* @return void
|
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
function includeFile($file)
|
function includeFile($file)
|
||||||
{
|
{
|
||||||
|
|||||||
2
vendor/composer/autoload_classmap.php
vendored
2
vendor/composer/autoload_classmap.php
vendored
@@ -6,7 +6,6 @@ $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',
|
||||||
@@ -53,6 +52,7 @@ return array(
|
|||||||
'Jdenticon\\Rendering\\ColorTheme' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/ColorTheme.php',
|
'Jdenticon\\Rendering\\ColorTheme' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/ColorTheme.php',
|
||||||
'Jdenticon\\Rendering\\IconGenerator' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/IconGenerator.php',
|
'Jdenticon\\Rendering\\IconGenerator' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/IconGenerator.php',
|
||||||
'Jdenticon\\Rendering\\ImagickRenderer' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/ImagickRenderer.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\\InternalPngRenderer' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php',
|
||||||
'Jdenticon\\Rendering\\Point' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Point.php',
|
'Jdenticon\\Rendering\\Point' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Point.php',
|
||||||
'Jdenticon\\Rendering\\Rectangle' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Rectangle.php',
|
'Jdenticon\\Rendering\\Rectangle' => $vendorDir . '/jdenticon/jdenticon/src/Rendering/Rectangle.php',
|
||||||
|
|||||||
18
vendor/composer/autoload_real.php
vendored
18
vendor/composer/autoload_real.php
vendored
@@ -13,24 +13,19 @@ class ComposerAutoloaderInitDontChange
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \Composer\Autoload\ClassLoader
|
|
||||||
*/
|
|
||||||
public static function getLoader()
|
public static function getLoader()
|
||||||
{
|
{
|
||||||
if (null !== self::$loader) {
|
if (null !== self::$loader) {
|
||||||
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(\dirname(\dirname(__FILE__)));
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||||
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 __DIR__ . '/autoload_static.php';
|
require_once __DIR__ . '/autoload_static.php';
|
||||||
|
|
||||||
call_user_func(\Composer\Autoload\ComposerStaticInitDontChange::getInitializer($loader));
|
call_user_func(\Composer\Autoload\ComposerStaticInitDontChange::getInitializer($loader));
|
||||||
} else {
|
} else {
|
||||||
@@ -65,16 +60,11 @@ class ComposerAutoloaderInitDontChange
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $fileIdentifier
|
|
||||||
* @param string $file
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function composerRequireDontChange($fileIdentifier, $file)
|
function composerRequireDontChange($fileIdentifier, $file)
|
||||||
{
|
{
|
||||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
|
||||||
|
|
||||||
require $file;
|
require $file;
|
||||||
|
|
||||||
|
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/composer/autoload_static.php
vendored
2
vendor/composer/autoload_static.php
vendored
@@ -46,7 +46,6 @@ 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',
|
||||||
@@ -93,6 +92,7 @@ class ComposerStaticInitDontChange
|
|||||||
'Jdenticon\\Rendering\\ColorTheme' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/ColorTheme.php',
|
'Jdenticon\\Rendering\\ColorTheme' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/ColorTheme.php',
|
||||||
'Jdenticon\\Rendering\\IconGenerator' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/IconGenerator.php',
|
'Jdenticon\\Rendering\\IconGenerator' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/IconGenerator.php',
|
||||||
'Jdenticon\\Rendering\\ImagickRenderer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/ImagickRenderer.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\\InternalPngRenderer' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php',
|
||||||
'Jdenticon\\Rendering\\Point' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Point.php',
|
'Jdenticon\\Rendering\\Point' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Point.php',
|
||||||
'Jdenticon\\Rendering\\Rectangle' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Rectangle.php',
|
'Jdenticon\\Rendering\\Rectangle' => __DIR__ . '/..' . '/jdenticon/jdenticon/src/Rendering/Rectangle.php',
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ class SuperSampleBuffer
|
|||||||
const IDX_G = 3;
|
const IDX_G = 3;
|
||||||
const IDX_B = 4;
|
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
|
* Creates a color buffer keeping an average color out of several
|
||||||
* color samples per pixel.
|
* color samples per pixel.
|
||||||
|
|||||||
Reference in New Issue
Block a user