| Current Path : /var/www/html/administrator/components/com_rsfirewall/helpers/ |
| Current File : /var/www/html/administrator/components/com_rsfirewall/helpers/log.php |
<?php
/*
* @package RSFirewall!
* @copyright (c) 2009 - 2024 RSJoomla!
* @link https://www.rsjoomla.com/joomla-extensions/joomla-security.html
* @license GNU General Public License https://www.gnu.org/licenses/gpl-3.0.en.html
*/
\defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Language\Text;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Mail\MailHelper;
class RSFirewallLogger {
protected $table;
protected $root;
protected $config;
protected $emails;
protected $mailfrom;
protected $fromname;
protected $bound = false;
protected $tz = true;
public function __construct() {
$config = Factory::getConfig();
$this->table = Table::getInstance('Logs', 'RsfirewallTable');
$cli = function_exists('php_sapi_name') && php_sapi_name() === 'cli';
if ($cli)
{
$uri = 'cli';
$root = 'cli';
}
else
{
try
{
$uri = Uri::getInstance()->toString();
$root = Uri::root();
}
catch (Exception $e)
{
$uri = $root = '-';
}
}
$this->table->bind(array(
'date' => Factory::getDate()->toSql(),
'ip' => $this->getIP(),
'user_id' => Factory::getUser()->get('id'),
'username' => Factory::getUser()->get('username'),
'page' => $uri,
'referer' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''
));
$this->root = $root;
$this->config = RSFirewallConfig::getInstance();
$this->emails = $this->config->get('log_emails', array(), true);
$this->mailfrom = $config->get('mailfrom');
$this->fromname = $config->get('fromname');
}
public static function getInstance() {
static $initialized = false;
if (!$initialized) {
// load language
Factory::getLanguage()->load('com_rsfirewall', JPATH_ADMINISTRATOR);
// set table path
Table::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_rsfirewall/tables');
// load config class if not already loaded
if (!class_exists('RSFirewallConfig')) {
require_once JPATH_ADMINISTRATOR.'/components/com_rsfirewall/helpers/config.php';
}
// don't call this again
$initialized = true;
}
// always create a new instance to allow subsequent calls to grab the correct details
$inst = new RSFirewallLogger();
return $inst;
}
protected function getIP() {
require_once __DIR__ . '/ip/ip.php';
return RSFirewallIP::get();
}
public function add($level='low', $code=1, $debug_variables=null) {
$this->table->bind(array(
'level' => $level,
'code' => $code,
'debug_variables' => $debug_variables
));
$this->bound = true;
return $this;
}
public function setTimezone($tz)
{
$this->tz = $tz;
}
protected function escape($string) {
$string = (string) $string;
return htmlentities($string, ENT_COMPAT, 'utf-8');
}
protected function showDate($date) {
return HTMLHelper::_('date', $date, 'Y-m-d H:i:s', $this->tz);
}
public function save() {
// save to db
if ($this->bound) {
$this->bound = false;
$this->table->store();
// if this level is higher or equal to the configured minimum level
if (in_array($this->table->level, $this->config->get('log_alert_level'))) {
// send the email alert
$this->sendAlert();
}
}
}
protected function sendAlert()
{
$lang = Factory::getLanguage();
// When SEF and Language Filter is enabled, the language could have untranslated strings
if (!$lang->hasKey('COM_RSFIREWALL_WEBSITE'))
{
// Load the backend language
$lang->load('com_rsfirewall', JPATH_ADMINISTRATOR);
}
$subject = Text::sprintf('COM_RSFIREWALL_LOG_EMAIL_SUBJECT',
Text::_('COM_RSFIREWALL_LEVEL_'.$this->table->level),
$this->escape($this->root),
$this->escape($this->table->ip)
);
$body = '<html>'."\n"
.'<body>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_WEBSITE').':</strong> <a href="'.$this->escape($this->root).'">'.$this->escape($this->root).'</a></p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_LOG_PAGE').':</strong> '.$this->escape($this->table->page).'</p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_LOG_REFERER').':</strong> '.($this->table->referer ? $this->escape($this->table->referer) : '<em>'.Text::_('COM_RSFIREWALL_NO_REFERER').'</em>').'</p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_LOG_DESCRIPTION').':</strong> '.Text::_('COM_RSFIREWALL_EVENT_'.$this->table->code).'</p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_LOG_DEBUG_VARIABLES').':</strong> '.nl2br($this->escape($this->table->debug_variables)).'</p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_ALERT_LEVEL').':</strong> '.Text::_('COM_RSFIREWALL_LEVEL_'.$this->table->level).'</p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_LOG_DATE_EVENT').':</strong> '.$this->showDate($this->table->date).'</p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_LOG_IP_ADDRESS').':</strong> '.$this->escape($this->table->ip).'</p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_LOG_USER_ID').':</strong> '.$this->escape($this->table->user_id).'</p>'."\n"
.'<p><strong>'.Text::_('COM_RSFIREWALL_LOG_USERNAME').':</strong> '.$this->escape($this->table->username).'</p>'."\n"
.'<small>'.Text::_('COM_RSFIREWALL_EMAIL_NOTICE').'</small>'."\n"
.'</body>'."\n"
.'</html>';
// sent so far
$sent = (int) $this->config->get('log_emails_count');
// limit per hour
$limit = $this->config->get('log_hour_limit');
// after the hour we're allowed to send
$after = $this->config->get('log_emails_send_after');
// now
$dateNow = Factory::getDate();
$now = $dateNow->toUnix();
// are we allowed to send?
if ($now > $after)
{
// do we have emails set?
if ($this->emails)
{
// loop through emails and attempt sending
foreach ($this->emails as $email)
{
$email = trim($email);
if (MailHelper::isEmailAddress($email) && $sent < $limit)
{
try
{
Factory::getMailer()->sendMail($this->mailfrom, $this->fromname, $email, $subject, $body, true);
// increment number of sent emails
$sent++;
}
catch (Exception $e)
{
Factory::getApplication()->enqueueMessage($e->getMessage(), 'warning');
}
}
}
// reached the limit?
if ($sent >= $limit)
{
// allow to send in the next hour
$nextDate = Factory::getDate()->setTime((int) $dateNow->hour + 1, 0);
$next_after = $nextDate->toUnix();
$this->config->set('log_emails_send_after', $next_after);
$this->config->set('log_emails_count', 0);
}
else
{
$this->config->set('log_emails_count', $sent);
}
}
}
}
}