Файл: library/XenForo/Model/Banning.php
Строк: 556
<?php
/**
* Model for banning.
*
* @package XenForo_Banning
*/
class XenForo_Model_Banning extends XenForo_Model
{
/**
* Gets banned users.
*
* @param array $conditions
* @param array $fetchOptions
*
* @return array Format: [user id] => info
*/
public function getBannedUsers(array $conditions = array(), array $fetchOptions = array())
{
$limitOptions = $this->prepareLimitFetchOptions($fetchOptions);
$whereConditions = $this->prepareUserBanConditions($conditions, $fetchOptions);
return $this->fetchAllKeyed($this->limitQueryResults(
'
SELECT user_ban.*,
user.username,
banning_user.username AS banning_username,
user.avatar_date, user.gravatar, user.gender
FROM xf_user_ban AS user_ban
LEFT JOIN xf_user AS user ON (user.user_id = user_ban.user_id)
LEFT JOIN xf_user AS banning_user ON (banning_user.user_id = user_ban.ban_user_id)
WHERE ' . $whereConditions . '
ORDER BY user_ban.ban_date DESC, user.username
', $limitOptions['limit'], $limitOptions['offset']
), 'user_id');
}
/**
* Counts the number of banned users.
*
* @return integer
*/
public function countBannedUsers(array $conditions = array())
{
$fetchOptions = array();
$whereConditions = $this->prepareUserBanConditions($conditions, $fetchOptions);
return $this->_getDb()->fetchOne('
SELECT COUNT(*)
FROM xf_user_ban AS user_ban
LEFT JOIN xf_user AS user ON (user.user_id = user_ban.user_id)
WHERE ' . $whereConditions . '
');
}
/**
* Gets the banned user record for the specified user ID.
*
* @param integer $userId
* @param array $fetchOptions
*
* @return array|false
*/
public function getBannedUserById($userId, array $fetchOptions = array())
{
return $this->_getDb()->fetchRow('
SELECT user_ban.*,
user.username,
banning_user.username AS banning_username
FROM xf_user_ban AS user_ban
LEFT JOIN xf_user AS user ON (user.user_id = user_ban.user_id)
LEFT JOIN xf_user AS banning_user ON (banning_user.user_id = user_ban.ban_user_id)
WHERE user_ban.user_id = ?
', $userId);
}
/**
* Gets all user ban records that have expired.
*
* @param integer|null $cutOff Cut-off date. Defaults to now.
*
* @return array Format: [user id] => info
*/
public function getExpiredUserBans($cutOff = null)
{
if ($cutOff === null)
{
$cutOff = XenForo_Application::$time;
}
return $this->fetchAllKeyed('
SELECT user_ban.*
FROM xf_user_ban AS user_ban
WHERE user_ban.end_date > 0
AND user_ban.end_date <= ?
', 'user_id', $cutOff);
}
/**
* Prepares a set of conditions against which to select prefixes.
*
* @param array $conditions List of conditions.
* @param array $fetchOptions The fetch options that have been provided. May be edited if criteria requires.
*
* @return string Criteria as SQL for where clause
*/
public function prepareUserBanConditions(array $conditions, array &$fetchOptions)
{
$sqlConditions = array();
$db = $this->_getDb();
if (!empty($conditions['username']))
{
if (is_array($conditions['username']))
{
$sqlConditions[] = 'user.username LIKE ' . XenForo_Db::quoteLike($conditions['username'][0], $conditions['username'][1], $db);
}
else
{
$sqlConditions[] = 'user.username LIKE ' . XenForo_Db::quoteLike($conditions['username'], 'lr', $db);
}
}
return $this->getConditionsForClause($sqlConditions);
}
/**
* Deletes all user ban records that have expired.
*
* @param integer|null $cutOff Cut-off date. Defaults to now.
*/
public function deleteExpiredUserBans($cutOff = null)
{
foreach ($this->getExpiredUserBans($cutOff) AS $ban)
{
$dw = XenForo_DataWriter::create('XenForo_DataWriter_UserBan');
$dw->setExistingData($ban, true);
$dw->delete();
}
}
/**
* Gets all banned IPs.
*
* @return array Format: [] => info
*/
public function getBannedIps()
{
return $this->_getDb()->fetchAll('
SELECT *
FROM xf_ip_match
WHERE match_type = ?
ORDER BY start_range
', 'banned');
}
/**
* Counts all banned IPs
*
* @return integer
*/
public function countBannedIps()
{
return $this->_getDb()->fetchOne('
SELECT COUNT(*)
FROM xf_ip_match
WHERE match_type = ?
', 'banned');
}
/**
* Bans the specified IP or IP range. Ranges may have wildcards but only at the end (10.*, 192.168.1.*).
* The wildcard is optional; 192.168 is equivalent to 192.168.*.
*
* Malformed input throws exceptions.
*
* @param string $ip
*
* @return boolean Returns true if the ban is inserted
*/
public function banIp($ip)
{
list($niceIp, $firstByte, $startRange, $endRange) = $this->_getIpRecord($ip);
$db = $this->_getDb();
XenForo_Db::beginTransaction($db);
$result = $this->_getDb()->query('
INSERT IGNORE INTO xf_ip_match
(ip, match_type, first_byte, start_range, end_range)
VALUES
(?, ?, ?, ?, ?)
', array($niceIp, 'banned', $startRange, $startRange, $endRange));
$inserted = ($result->rowCount() ? true : false);
if ($inserted)
{
$this->rebuildBannedIpCache();
}
XenForo_Db::commit($db);
return $inserted;
}
/**
* Deletes the specified banned IPs. Array values should be the "nice" IP address values
* (banned_ip column in the DB).
*
* @param array $ips
*/
public function deleteBannedIps(array $ips)
{
if (!$ips)
{
return;
}
$db = $this->_getDb();
XenForo_Db::beginTransaction($db);
$db->delete('xf_ip_match', 'ip IN (' . $db->quote($ips) . ') AND match_type = ' . $db->quote('banned'));
$this->rebuildBannedIpCache();
XenForo_Db::commit($db);
}
/**
* Rebuilds the cache of banned IPs.
*
* @return array Banned IP cache
*/
public function rebuildBannedIpCache()
{
$cache = array();
try
{
foreach ($this->getBannedIps() AS $bannedIp)
{
$cache[$bannedIp['first_byte']][] = array($bannedIp['start_range'], $bannedIp['end_range']);
}
}
catch (Zend_Db_Statement_Exception $e) {} // happens if table doesn't exist
$save = array(
'version' => XenForo_Application::$time,
'data' => $cache
);
$this->_getDataRegistryModel()->set('bannedIps', $save);
return $save;
}
/**
* Gets all discouraged IPs.
*
* @return array Format: [] => info
*/
public function getDiscouragedIps()
{
return $this->_getDb()->fetchAll('
SELECT *
FROM xf_ip_match
WHERE match_type = ?
ORDER BY start_range
', 'discouraged');
}
/**
* Counts all discouraged IPs
*
* @return integer
*/
public function countDiscouragedIps()
{
return $this->_getDb()->fetchOne('
SELECT COUNT(*)
FROM xf_ip_match
WHERE match_type = ?
', 'discouraged');
}
/**
* Discourages the specified IP or IP range. Ranges may have wildcards but only at the end (10.*, 192.168.1.*).
* The wildcard is optional; 192.168 is equivalent to 192.168.*.
*
* Malformed input throws exceptions.
*
* @param string $ip
*
* @return boolean Returns true if the ban is inserted
*/
public function discourageIp($ip)
{
list($niceIp, $firstByte, $startRange, $endRange) = $this->_getIpRecord($ip);
$db = $this->_getDb();
XenForo_Db::beginTransaction($db);
$result = $this->_getDb()->query('
INSERT IGNORE INTO xf_ip_match
(ip, match_type, first_byte, start_range, end_range)
VALUES
(?, ?, ?, ?, ?)
', array($niceIp, 'discouraged', $firstByte, $startRange, $endRange));
$inserted = ($result->rowCount() ? true : false);
if ($inserted)
{
$this->rebuildDiscouragedIpCache();
}
XenForo_Db::commit($db);
return $inserted;
}
/**
* Deletes the specified discouraged IPs. Array values should be the "nice" IP address values
* (discouraged_ip column in the DB).
*
* @param array $ips
*/
public function deleteDiscouragedIps(array $ips)
{
if (!$ips)
{
return;
}
$db = $this->_getDb();
XenForo_Db::beginTransaction($db);
$db->delete('xf_ip_match', 'ip IN (' . $db->quote($ips) . ') AND match_type = ' . $db->quote('discouraged'));
$this->rebuildDiscouragedIpCache();
XenForo_Db::commit($db);
}
/**
* Rebuilds the cache of discouraged IPs.
*
* @return array Discouraged IP cache
*/
public function rebuildDiscouragedIpCache()
{
$cache = array();
try
{
foreach ($this->getDiscouragedIps() AS $discouragedIp)
{
$cache[$discouragedIp['first_byte']][] = array($discouragedIp['start_range'], $discouragedIp['end_range']);
}
}
catch (Zend_Db_Statement_Exception $e) {} // happens if table doesn't exist
$save = array(
'version' => XenForo_Application::$time,
'data' => $cache
);
$this->_getDataRegistryModel()->set('discouragedIps', $save);
return $save;
}
protected function _getIpRecord($ip)
{
$results = XenForo_Helper_Ip::parseIpRangeString($ip);
if (!$results)
{
throw new XenForo_Exception(new XenForo_Phrase('please_enter_valid_ip_or_ip_range'), true);
}
return array(
$results['printable'],
$results['binary'][0],
$results['startRange'],
$results['endRange']
);
}
/**
* Gets all banned emails.
*
* @return array Format: [] => info
*/
public function getBannedEmails()
{
return $this->_getDb()->fetchAll('
SELECT *
FROM xf_ban_email
ORDER BY banned_email
');
}
/**
* Returns the total number of banned email addresses and address snippets
*
* @return integer
*/
public function countBannedEmails()
{
return $this->_getDb()->fetchOne('SELECT COUNT(*) FROM xf_ban_email');
}
/**
* Bans the specified email. Wildcards are allowed. If no wildcards are given, they are automatically
* added in logical places (no or leading @ gives wildcard prefix; no or trailing . gives wildcard suffix).
*
* Throws exceptions on malformed input.
*
* @param string $email
*
* @return boolean Returns true if the ban is inserted
*/
public function banEmail($email)
{
if ($email == '*' || $email === '')
{
throw new XenForo_Exception(new XenForo_Phrase('you_must_enter_at_least_one_non_wildcard_character'), true);
}
if (strpos($email, '*') === false)
{
if (strpos($email, '@') === false)
{
$email = '*' . $email;
}
if (strpos($email, '.') === false)
{
$email .= '*';
}
}
if ($email[0] == '@')
{
$email = '*' . $email;
}
$lastChar = substr($email, -1);
if ($lastChar == '.' || $lastChar == '@')
{
$email .= '*';
}
$atPos = strpos($email, '@');
if ($atPos !== false && strpos($email, '.', $atPos) === false && strpos($email, '*', $atPos) === false)
{
$email .= '*';
}
if ($email == '*@*' || $email == '*.*')
{
throw new XenForo_Exception(new XenForo_Phrase('this_would_ban_all_email_addresses'), true);
}
$email = preg_replace('/*{2,}/', '*', $email);
$db = $this->_getDb();
XenForo_Db::beginTransaction($db);
$result = $this->_getDb()->query('
INSERT IGNORE INTO xf_ban_email
(banned_email)
VALUES
(?)
', array($email));
$inserted = ($result->rowCount() ? true : false);
if ($inserted)
{
$this->rebuildBannedEmailCache();
}
XenForo_Db::commit($db);
return $inserted;
}
/**
* Deletes the specified banned emails. Array values should be the "nice" email address values
* (banned_email column in the DB).
*
* @param array $emails
*/
public function deleteBannedEmails(array $emails)
{
if (!$emails)
{
return;
}
$db = $this->_getDb();
XenForo_Db::beginTransaction($db);
$db->delete('xf_ban_email', 'banned_email IN (' . $db->quote($emails) . ')');
$this->rebuildBannedEmailCache();
XenForo_Db::commit($db);
}
/**
* Rebuilds the cache of banned emails.
*
* @return array Banned email cache
*/
public function rebuildBannedEmailCache()
{
$cache = array();
foreach ($this->getBannedEmails() AS $bannedEmail)
{
$cache[] = $bannedEmail['banned_email'];
}
$this->_getDataRegistryModel()->set('bannedEmails', $cache);
return $cache;
}
}