59 lines
1.4 KiB
PHP
59 lines
1.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
namespace UploadLogger\Core\Services;
|
|
|
|
use UploadLogger\Core\Config;
|
|
|
|
final class FloodService
|
|
{
|
|
private Config $config;
|
|
|
|
public function __construct(?Config $config = null)
|
|
{
|
|
$this->config = $config ?? new Config(['modules' => []]);
|
|
}
|
|
|
|
public function check(string $ip): int
|
|
{
|
|
$window = (int)$this->config->get('limits.flood_window_sec', 60);
|
|
$stateDir = (string)$this->config->get('paths.state_dir', __DIR__ . '/../../state');
|
|
|
|
$key = rtrim($stateDir, '/\\') . '/upl_' . md5('v3|' . $ip);
|
|
|
|
$now = time();
|
|
$count = 0;
|
|
$start = $now;
|
|
|
|
$fh = @fopen($key, 'c+');
|
|
if ($fh === false) {
|
|
return 1;
|
|
}
|
|
|
|
if (flock($fh, LOCK_EX)) {
|
|
$raw = stream_get_contents($fh);
|
|
if ($raw !== false) {
|
|
if (preg_match('/^(\d+):(\d+)$/', trim($raw), $m)) {
|
|
$start = (int)$m[1];
|
|
$count = (int)$m[2];
|
|
}
|
|
}
|
|
|
|
if ((($now - $start) > $window)) {
|
|
$start = $now;
|
|
$count = 0;
|
|
}
|
|
|
|
$count++;
|
|
rewind($fh);
|
|
ftruncate($fh, 0);
|
|
fwrite($fh, $start . ':' . $count);
|
|
fflush($fh);
|
|
flock($fh, LOCK_UN);
|
|
}
|
|
|
|
fclose($fh);
|
|
|
|
return $count;
|
|
}
|
|
}
|