Files
DomFramework/src/Ratelimitfile.php

171 lines
4.9 KiB
PHP

<?php
/**
* DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/**
* The rate limit with file storage
*/
class Ratelimitfile extends Ratelimit
{
/**
* The storage directory
*/
public $storageDir = "data/ratelimit/";
/**
* Debug the ratelimiting process to screen
*/
public $debug = false;
/**
* The function set a rate-limit
* @param string $name The rate-limit object to set
* @return bool true if the rate-limit is not overloaded
* false if the rate-limit is overloaded
*/
public function set($name)
{
$this->storageOK();
$nameFile = substr(rawurlencode($name), 0, 128);
$file = $this->storageDir . "/$nameFile";
// Add the current timestamp
$currentTimeStamp = microtime(true) . "\n";
if ($this->debug) {
echo "Add entry : $currentTimeStamp";
}
$user = posix_getpwuid(posix_getuid());
if (file_exists($file) && ! is_writeable($file)) {
throw new \Exception(sprintf(
dgettext(
"domframework",
"File '%s' not writeable for user '%s'"
),
$file,
$user["name"]
), 500);
}
file_put_contents($file, $currentTimeStamp, FILE_APPEND);
$lock = new Lockfile();
$lock->storagelock = $this->storageDir . "/lockfile.lock";
$lock->lockRW();
$contents = file($file);
// Look if there is deprecated entries in the file
foreach ($contents as $key => $content) {
$content = rtrim($content);
if ($content + $this->unittime < microtime(true)) {
if ($this->debug) {
echo "Remove deprecated entry : $content\n";
}
unset($contents[$key]);
} else {
if ($this->debug) {
echo "Active entry : $content\n";
}
}
}
file_put_contents($file, $contents);
$lock->unlockRW();
unset($lock);
$this->clean();
if (count($contents) > $this->maxEntries) {
if ($this->debug) {
echo "Ratelimiting for '$name'\n";
}
return false;
}
return true;
}
/**
* The function delete a rate-limit
* @param string $name The rate-limit object to del
* @return bool
*/
public function del($name)
{
$this->storageOK();
$nameFile = substr(rawurlencode($name), 0, 128);
$file = $this->storageDir . "/$nameFile";
if (file_exists($file)) {
if ($this->debug) {
echo "Removing the rate-limiting for '$name'\n";
}
unlink($file);
}
return true;
}
/**
* The function clean the storage with expired entries
* @return bool
*/
public function clean()
{
$this->storageOK();
$files = glob($this->storageDir . "/*");
foreach ($files as $file) {
if (filemtime($file) + $this->unittime < time()) {
if ($this->debug) {
echo "Removing the deprecated rate-limiting for '" .
rawurldecode(basename($file)) . "'\n";
}
unlink($file);
}
}
return true;
}
/**
* Check the storageDir state
*/
private function storageOK()
{
if (file_exists($this->storageDir)) {
if (! is_dir($this->storageDir)) {
throw new \Exception(sprintf(
dgettext(
"domframework",
"storageDir '%s' is not a directory"
),
$this->storageDir
), 500);
}
if (! is_readable($this->storageDir)) {
throw new \Exception(sprintf(
dgettext(
"domframework",
"storageDir '%s' is not readable"
),
$this->storageDir
), 500);
}
if (! is_writeable($this->storageDir)) {
throw new \Exception(sprintf(
dgettext(
"domframework",
"storageDir '%s' is not writeable"
),
$this->storageDir
), 500);
}
} else {
if (@mkdir($this->storageDir, 0777, true) === false) {
throw new \Exception(sprintf(
dgettext(
"domframework",
"Can't create '%s' storageDir"
),
$this->storageDir
), 500);
}
}
return true;
}
}