* @license BSD */ //namespace Domframework; require_once ("domframework/lockfile.php"); require_once ("domframework/ratelimit.php"); /** 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; } }