folding Persistance\TrafficLimiter into Data\Filesystem

This commit is contained in:
El RIDO 2021-06-08 07:49:22 +02:00
parent 3429d293d3
commit b5a6ce323e
No known key found for this signature in database
GPG key ID: 0F5C940A6BD81F92
8 changed files with 100 additions and 30 deletions

View file

@ -198,6 +198,7 @@ class Controller
try { try {
// Ensure last paste from visitors IP address was more than configured amount of seconds ago. // Ensure last paste from visitors IP address was more than configured amount of seconds ago.
TrafficLimiter::setConfiguration($this->_conf); TrafficLimiter::setConfiguration($this->_conf);
TrafficLimiter::setStore($this->_model->getStore());
if (!TrafficLimiter::canPass()) { if (!TrafficLimiter::canPass()) {
$this->_return_message( $this->_return_message(
1, I18n::_( 1, I18n::_(

View file

@ -130,6 +130,16 @@ abstract class AbstractData
*/ */
abstract public function existsComment($pasteid, $parentid, $commentid); abstract public function existsComment($pasteid, $parentid, $commentid);
/**
* Purge outdated entries.
*
* @access public
* @param string $namespace
* @param int $time
* @return void
*/
abstract public function purgeValues($namespace, $time);
/** /**
* Save a value. * Save a value.
* *

View file

@ -423,6 +423,23 @@ class Database extends AbstractData
); );
} }
/**
* Purge outdated entries.
*
* @access public
* @param string $namespace
* @param int $time
* @return void
*/
public function purgeValues($namespace, $time)
{
switch ($namespace) {
case 'traffic_limiter':
;
break;
}
}
/** /**
* Save a value. * Save a value.
* *

View file

@ -38,6 +38,15 @@ class Filesystem extends AbstractData
*/ */
private static $_path = 'data'; private static $_path = 'data';
/**
* cache for the traffic limiter
*
* @access private
* @static
* @var array
*/
private static $_traffic_limiter_cache = array();
/** /**
* get instance of singleton * get instance of singleton
* *
@ -240,6 +249,27 @@ class Filesystem extends AbstractData
); );
} }
/**
* Purge outdated entries.
*
* @access public
* @param string $namespace
* @param int $time
* @return void
*/
public function purgeValues($namespace, $time)
{
switch ($namespace) {
case 'traffic_limiter':
foreach (self::$_traffic_limiter_cache as $key => $last_access) {
if ($last_access <= $time) {
unset(self::$_traffic_limiter_cache[$key]);
}
}
break;
}
}
/** /**
* Save a value. * Save a value.
* *
@ -262,7 +292,11 @@ class Filesystem extends AbstractData
; ;
break; break;
case 'traffic_limiter': case 'traffic_limiter':
; self::$_traffic_limiter_cache[$key] = $value;
return self::_storeString(
self::$_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php',
'<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . var_export(self::$_traffic_limiter_cache, true) . ';'
);
break; break;
} }
return false; return false;
@ -290,7 +324,14 @@ class Filesystem extends AbstractData
; ;
break; break;
case 'traffic_limiter': case 'traffic_limiter':
; $file = self::$_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php';
if (is_file($file)) {
require $file;
self::$_traffic_limiter_cache = $GLOBALS['traffic_limiter'];
if (array_key_exists($key, self::$_traffic_limiter_cache)) {
return self::$_traffic_limiter_cache[$key];
}
}
break; break;
} }
return ''; return '';

View file

@ -217,6 +217,23 @@ class GoogleCloudStorage extends AbstractData
return $o->exists(); return $o->exists();
} }
/**
* Purge outdated entries.
*
* @access public
* @param string $namespace
* @param int $time
* @return void
*/
public function purgeValues($namespace, $time)
{
switch ($namespace) {
case 'traffic_limiter':
;
break;
}
}
/** /**
* This is the simplest thing that could possibly work. * This is the simplest thing that could possibly work.
* will be to tested for runtime performance. * will be to tested for runtime performance.

View file

@ -54,7 +54,7 @@ class Model
*/ */
public function getPaste($pasteId = null) public function getPaste($pasteId = null)
{ {
$paste = new Paste($this->_conf, $this->_getStore()); $paste = new Paste($this->_conf, $this->getStore());
if ($pasteId !== null) { if ($pasteId !== null) {
$paste->setId($pasteId); $paste->setId($pasteId);
} }
@ -67,9 +67,9 @@ class Model
public function purge() public function purge()
{ {
PurgeLimiter::setConfiguration($this->_conf); PurgeLimiter::setConfiguration($this->_conf);
PurgeLimiter::setStore($this->_getStore()); PurgeLimiter::setStore($this->getStore());
if (PurgeLimiter::canPurge()) { if (PurgeLimiter::canPurge()) {
$this->_getStore()->purge($this->_conf->getKey('batchsize', 'purge')); $this->getStore()->purge($this->_conf->getKey('batchsize', 'purge'));
} }
} }
@ -78,7 +78,7 @@ class Model
* *
* @return Data\AbstractData * @return Data\AbstractData
*/ */
private function _getStore() public function getStore()
{ {
if ($this->_store === null) { if ($this->_store === null) {
$this->_store = forward_static_call( $this->_store = forward_static_call(

View file

@ -169,35 +169,18 @@ class TrafficLimiter extends AbstractPersistence
} }
} }
$file = 'traffic_limiter.php';
if (self::_exists($file)) {
require self::getPath($file);
$tl = $GLOBALS['traffic_limiter'];
} else {
$tl = array();
}
// purge file of expired hashes to keep it small
$now = time();
foreach ($tl as $key => $time) {
if ($time + self::$_limit < $now) {
unset($tl[$key]);
}
}
// this hash is used as an array key, hence a shorter algo is used // this hash is used as an array key, hence a shorter algo is used
$hash = self::getHash('sha256'); $hash = self::getHash('sha256');
if (array_key_exists($hash, $tl) && ($tl[$hash] + self::$_limit >= $now)) { $now = time();
$tl = self::$_store->getValue('traffic_limiter', $hash);
self::$_store->purgeValues('traffic_limiter', $now - self::$_limit);
if ($tl > 0 && ($tl + self::$_limit >= $now)) {
$result = false; $result = false;
} else { } else {
$tl[$hash] = time(); $tl = time();
$result = true; $result = true;
} }
self::_store( self::$_store->setValue((string) $tl, 'traffic_limiter');
$file,
'<?php' . PHP_EOL .
'$GLOBALS[\'traffic_limiter\'] = ' . var_export($tl, true) . ';'
);
return $result; return $result;
} }
} }

View file

@ -17,6 +17,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 = Filesystem::getInstance(array('dir' => $this->_path));
TrafficLimiter::setStore($this->_data);
$this->reset(); $this->reset();
} }