php-mpos/public/include/classes/memcache_ad.class.php
2014-01-28 07:26:08 -05:00

73 lines
2.6 KiB
PHP

<?php
$defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1;
class MemcacheAntiDos
{
public $cache;
public static $key = 'mcad_';
public static $request_model = array(
'ident' => '',
'last_hit' => 0,
'last_flush' => 0,
'hits_since_flush' => 0
);
public $rate_limit_this_request = false;
public function __construct($config, $userORip, $request, $mcSettings) {
if (PHP_OS == 'WINNT') {
require_once('memcached.class.php');
}
$this->cache = new Memcached();
$this->cache->addServer($mcSettings['host'], $mcSettings['port']);
// set our config options
$per_page = $config['per_page'];
$flush_sec = $config['flush_seconds'];
$rate_limit = $config['rate_limit'];
unset($config);
// prep stuff we need to check this request
$key_md5 = substr(md5($userORip), 0, 4);
$request_md5 = substr(md5($request), 0, 4);
$request_key = $mcSettings['keyprefix'].self::$key.$key_md5."_".$request_md5."_".$per_page;
$request_data = $this->cache->get($request_key);
$now = time();
// check the request
if (is_array($request_data)) {
// this request key already exists, update it
$request_data['ident'] = $key_md5;
$request_data['last_hit'] = $now;
$request_data['hits_since_flush'] += 1;
// not rate limited yet, update the rest of the object
if ($request_data['hits_since_flush'] < $rate_limit) {
if (($request_data['last_flush'] + $flush_sec) <= $now || ($request_data['last_hit'] + $flush_sec) <= $now) {
// needs to be flushed
$request_data['hits_since_flush'] = 0;
$request_data['last_hit'] = 0;
$request_data['last_flush'] = $now;
// update the object
$this->cache->set($request_key, $request_data, $flush_sec);
$this->rate_limit_this_request = false;
} else {
// no flush, just update
$this->cache->set($request_key, $request_data, $flush_sec);
$this->rate_limit_this_request = false;
}
} else {
// too many hits, we should rate limit this
$this->rate_limit_this_request = true;
}
} else {
// doesn't exist for this request_key, create one
$new_data = self::$request_model;
$new_data['ident'] = $key_md5;
$new_data['last_hit'] = time();
$new_data['hits_since_flush'] = 1;
$new_data['last_flush'] = $now;
$this->cache->set($request_key, $new_data, $flush_sec);
$this->rate_limit_this_request = false;
}
}
public function rateLimitRequest() {
return $this->rate_limit_this_request;
}
}
?>