Gazelle/classes/tools.class.php

325 lines
9.2 KiB
PHP
Raw Normal View History

2012-10-11 08:00:15 +00:00
<?
class Tools {
/**
* Returns true if given IP is banned.
*
* @param string $IP
*/
2013-04-19 08:00:55 +00:00
public static function site_ban_ip($IP) {
2013-08-28 23:08:41 +00:00
global $Debug;
2013-04-19 08:00:55 +00:00
$A = substr($IP, 0, strcspn($IP, '.'));
$IPNum = Tools::ip_to_unsigned($IP);
2013-08-28 23:08:41 +00:00
$IPBans = G::$Cache->get_value('ip_bans_'.$A);
2013-04-19 08:00:55 +00:00
if (!is_array($IPBans)) {
2013-05-28 08:01:02 +00:00
$SQL = sprintf("
SELECT ID, FromIP, ToIP
FROM ip_bans
WHERE FromIP BETWEEN %d << 24 AND (%d << 24) - 1", $A, $A + 1);
2013-08-28 23:08:41 +00:00
$QueryID = G::$DB->get_query_id();
G::$DB->query($SQL);
$IPBans = G::$DB->to_array(0, MYSQLI_NUM);
G::$DB->set_query_id($QueryID);
G::$Cache->cache_value('ip_bans_'.$A, $IPBans, 0);
2013-04-19 08:00:55 +00:00
}
foreach ($IPBans as $Index => $IPBan) {
list ($ID, $FromIP, $ToIP) = $IPBan;
if ($IPNum >= $FromIP && $IPNum <= $ToIP) {
return true;
}
2013-02-06 08:00:17 +00:00
}
2013-04-20 08:01:01 +00:00
2013-04-19 08:00:55 +00:00
return false;
2013-02-06 08:00:17 +00:00
}
2012-10-11 08:00:15 +00:00
/**
* Returns the unsigned form of an IP address.
*
* @param string $IP The IP address x.x.x.x
* @return string the long it represents.
*/
public static function ip_to_unsigned($IP) {
2013-04-19 08:00:55 +00:00
return sprintf('%u', ip2long($IP));
2012-10-11 08:00:15 +00:00
}
/**
* Geolocate an IP address using the database
*
* @param $IP the ip to fetch the country for
* @return the country of origin
*/
public static function geoip($IP) {
static $IPs = array();
if (isset($IPs[$IP])) {
return $IPs[$IP];
}
2013-02-10 08:00:29 +00:00
if (is_number($IP)) {
$Long = $IP;
} else {
$Long = Tools::ip_to_unsigned($IP);
}
2013-04-18 08:00:54 +00:00
if (!$Long || $Long == 2130706433) { // No need to check cc for 127.0.0.1
2012-10-11 08:00:15 +00:00
return false;
}
2013-08-28 23:08:41 +00:00
$QueryID = G::$DB->get_query_id();
G::$DB->query("
2013-05-28 08:01:02 +00:00
SELECT EndIP, Code
FROM geoip_country
WHERE $Long >= StartIP
ORDER BY StartIP DESC
LIMIT 1");
2013-08-28 23:08:41 +00:00
if ((!list($EndIP, $Country) = G::$DB->next_record()) || $EndIP < $Long) {
2012-10-11 08:00:15 +00:00
$Country = '?';
}
2013-08-28 23:08:41 +00:00
G::$DB->set_query_id($QueryID);
2012-10-11 08:00:15 +00:00
$IPs[$IP] = $Country;
return $Country;
}
/**
* Gets the hostname for an IP address
*
* @param $IP the IP to get the hostname for
* @return hostname fetched
*/
2013-04-19 08:00:55 +00:00
public static function get_host_by_ip($IP) {
2013-05-28 08:01:02 +00:00
$testar = explode('.', $IP);
2013-04-19 08:00:55 +00:00
if (count($testar) != 4) {
2012-10-11 08:00:15 +00:00
return $IP;
}
2013-04-19 08:00:55 +00:00
for ($i = 0; $i < 4; ++$i) {
2012-10-11 08:00:15 +00:00
if (!is_numeric($testar[$i])) {
return $IP;
}
}
$host = `host -W 1 $IP`;
2013-05-28 08:01:02 +00:00
return ($host ? end(explode(' ', $host)) : $IP);
2012-10-11 08:00:15 +00:00
}
/**
* Gets an hostname using AJAX
*
* @param $IP the IP to fetch
2013-06-17 08:01:02 +00:00
* @return a span with JavaScript code
2012-10-11 08:00:15 +00:00
*/
public static function get_host_by_ajax($IP) {
2015-01-28 08:00:26 +00:00
static $IPs = array();
$Class = strtr($IP, '.', '-');
$HTML = '<span class="host_'.$Class.'">Resolving host...';
if (!isset($IPs[$IP])) {
$HTML .= '<script type="text/javascript">' .
'$(document).ready(function() {' .
'$.get(\'tools.php?action=get_host&ip='.$IP.'\', function(host) {' .
'$(\'.host_'.$Class.'\').html(host);' .
'});' .
'});' .
'</script>';
}
$HTML .= '</span>';
$IPs[$IP] = 1;
return $HTML;
2012-10-11 08:00:15 +00:00
}
/**
* Looks up the full host of an IP address, by system call.
* Used as the server-side counterpart to get_host_by_ajax.
*
* @param string $IP The IP address to look up.
* @return string the host.
*/
public static function lookup_ip($IP) {
2013-08-28 23:08:41 +00:00
//TODO: use the G::$Cache
2012-10-11 08:00:15 +00:00
$Output = explode(' ',shell_exec('host -W 1 '.escapeshellarg($IP)));
2013-04-18 08:00:54 +00:00
if (count($Output) == 1 && empty($Output[0])) {
2012-10-11 08:00:15 +00:00
//No output at all implies the command failed
return '';
}
2013-04-18 08:00:54 +00:00
if (count($Output) != 5) {
2012-10-11 08:00:15 +00:00
return false;
} else {
2013-01-19 08:00:51 +00:00
return trim($Output[4]);
2012-10-11 08:00:15 +00:00
}
}
/**
* Format an IP address with links to IP history.
*
* @param string IP
* @return string The HTML
*/
public static function display_ip($IP) {
$Line = display_str($IP).' ('.Tools::get_country_code_by_ajax($IP).') ';
2013-10-26 08:00:58 +00:00
$Line .= '<a href="user.php?action=search&amp;ip_history=on&amp;ip='.display_str($IP).'&amp;matchtype=strict" title="Search" class="brackets tooltip">S</a>';
2013-05-16 16:15:57 +00:00
2012-10-11 08:00:15 +00:00
return $Line;
}
public static function get_country_code_by_ajax($IP) {
2015-01-28 08:00:26 +00:00
static $IPs = array();
$Class = strtr($IP, '.', '-');
$HTML = '<span class="cc_'.$Class.'">Resolving CC...';
if (!isset($IPs[$IP])) {
$HTML .= '<script type="text/javascript">' .
'$(document).ready(function() {' .
'$.get(\'tools.php?action=get_cc&ip='.$IP.'\', function(cc) {' .
'$(\'.cc_'.$Class.'\').html(cc);' .
'});' .
'});' .
'</script>';
}
$HTML .= '</span>';
$IPs[$IP] = 1;
return $HTML;
2012-10-11 08:00:15 +00:00
}
/**
* Disable an array of users.
*
* @param array $UserIDs (You can also send it one ID as an int, because fuck types)
* @param BanReason 0 - Unknown, 1 - Manual, 2 - Ratio, 3 - Inactive, 4 - Unused.
*/
public static function disable_users($UserIDs, $AdminComment, $BanReason = 1) {
2013-08-28 23:08:41 +00:00
$QueryID = G::$DB->get_query_id();
2013-04-18 08:00:54 +00:00
if (!is_array($UserIDs)) {
2012-10-11 08:00:15 +00:00
$UserIDs = array($UserIDs);
}
2013-08-28 23:08:41 +00:00
G::$DB->query("
2013-04-20 08:01:01 +00:00
UPDATE users_info AS i
2014-02-19 08:00:32 +00:00
JOIN users_main AS m ON m.ID = i.UserID
SET m.Enabled = '2',
m.can_leech = '0',
2013-04-20 08:01:01 +00:00
i.AdminComment = CONCAT('".sqltime()." - ".($AdminComment ? $AdminComment : 'Disabled by system')."\n\n', i.AdminComment),
2014-02-19 08:00:32 +00:00
i.BanDate = '".sqltime()."',
i.BanReason = '$BanReason',
i.RatioWatchDownload = ".($BanReason == 2 ? 'm.Downloaded' : "'0'")."
2013-06-18 08:00:48 +00:00
WHERE m.ID IN(".implode(',', $UserIDs).') ');
2013-08-28 23:08:41 +00:00
G::$Cache->decrement('stats_user_count', G::$DB->affected_rows());
2013-04-20 08:01:01 +00:00
foreach ($UserIDs as $UserID) {
2013-08-28 23:08:41 +00:00
G::$Cache->delete_value("enabled_$UserID");
G::$Cache->delete_value("user_info_$UserID");
G::$Cache->delete_value("user_info_heavy_$UserID");
G::$Cache->delete_value("user_stats_$UserID");
2012-10-11 08:00:15 +00:00
2013-08-28 23:08:41 +00:00
G::$DB->query("
2013-06-06 08:01:03 +00:00
SELECT SessionID
FROM users_sessions
2013-08-28 23:08:41 +00:00
WHERE UserID = '$UserID'
2013-06-06 08:01:03 +00:00
AND Active = 1");
2013-08-28 23:08:41 +00:00
while (list($SessionID) = G::$DB->next_record()) {
G::$Cache->delete_value("session_$UserID"."_$SessionID");
2012-10-11 08:00:15 +00:00
}
2013-08-28 23:08:41 +00:00
G::$Cache->delete_value("users_sessions_$UserID");
2013-05-16 16:15:57 +00:00
2013-08-28 23:08:41 +00:00
G::$DB->query("
2013-06-06 08:01:03 +00:00
DELETE FROM users_sessions
2013-08-28 23:08:41 +00:00
WHERE UserID = '$UserID'");
2013-05-16 16:15:57 +00:00
2012-10-11 08:00:15 +00:00
}
// Remove the users from the tracker.
2013-08-28 23:08:41 +00:00
G::$DB->query('
2013-06-06 08:01:03 +00:00
SELECT torrent_pass
FROM users_main
2013-08-28 23:08:41 +00:00
WHERE ID in ('.implode(', ', $UserIDs).')');
$PassKeys = G::$DB->collect('torrent_pass');
2013-04-18 08:00:54 +00:00
$Concat = '';
foreach ($PassKeys as $PassKey) {
if (strlen($Concat) > 3950) { // Ocelot's read buffer is 4 KiB and anything exceeding it is truncated
2012-10-11 08:00:15 +00:00
Tracker::update_tracker('remove_users', array('passkeys' => $Concat));
$Concat = $PassKey;
} else {
$Concat .= $PassKey;
}
}
Tracker::update_tracker('remove_users', array('passkeys' => $Concat));
2013-08-28 23:08:41 +00:00
G::$DB->set_query_id($QueryID);
2012-10-11 08:00:15 +00:00
}
/**
* Warn a user.
*
* @param int $UserID
* @param int $Duration length of warning in seconds
* @param string $reason
*/
public static function warn_user($UserID, $Duration, $Reason) {
2013-08-28 23:08:41 +00:00
global $Time;
2012-10-11 08:00:15 +00:00
2013-08-28 23:08:41 +00:00
$QueryID = G::$DB->get_query_id();
G::$DB->query("
2013-04-19 08:00:55 +00:00
SELECT Warned
FROM users_info
2013-08-28 23:08:41 +00:00
WHERE UserID = $UserID
2013-05-27 08:00:58 +00:00
AND Warned != '0000-00-00 00:00:00'");
2013-08-28 23:08:41 +00:00
if (G::$DB->has_results()) {
2012-10-11 08:00:15 +00:00
//User was already warned, appending new warning to old.
2013-08-28 23:08:41 +00:00
list($OldDate) = G::$DB->next_record();
2012-10-11 08:00:15 +00:00
$NewExpDate = date('Y-m-d H:i:s', strtotime($OldDate) + $Duration);
Misc::send_pm($UserID, 0,
2013-04-19 08:00:55 +00:00
'You have received multiple warnings.',
2013-08-28 23:08:41 +00:00
"When you received your latest warning (set to expire on ".date('Y-m-d', (time() + $Duration)).'), you already had a different warning (set to expire on '.date('Y-m-d', strtotime($OldDate)).").\n\n Due to this collision, your warning status will now expire at $NewExpDate.");
2012-10-11 08:00:15 +00:00
2013-08-28 23:08:41 +00:00
$AdminComment = date('Y-m-d')." - Warning (Clash) extended to expire at $NewExpDate by " . G::$LoggedUser['Username'] . "\nReason: $Reason\n\n";
2012-10-11 08:00:15 +00:00
2013-08-28 23:08:41 +00:00
G::$DB->query('
2013-05-16 16:15:57 +00:00
UPDATE users_info
SET
2013-08-28 23:08:41 +00:00
Warned = \''.db_string($NewExpDate).'\',
WarnedTimes = WarnedTimes + 1,
AdminComment = CONCAT(\''.db_string($AdminComment).'\', AdminComment)
WHERE UserID = \''.db_string($UserID).'\'');
2012-10-11 08:00:15 +00:00
} else {
//Not changing, user was not already warned
$WarnTime = time_plus($Duration);
2013-08-28 23:08:41 +00:00
G::$Cache->begin_transaction("user_info_$UserID");
G::$Cache->update_row(false, array('Warned' => $WarnTime));
G::$Cache->commit_transaction(0);
2012-10-11 08:00:15 +00:00
2013-08-28 23:08:41 +00:00
$AdminComment = date('Y-m-d')." - Warned until $WarnTime by " . G::$LoggedUser['Username'] . "\nReason: $Reason\n\n";
2012-10-11 08:00:15 +00:00
2013-08-28 23:08:41 +00:00
G::$DB->query('
2013-05-16 16:15:57 +00:00
UPDATE users_info
SET
2013-08-28 23:08:41 +00:00
Warned = \''.db_string($WarnTime).'\',
WarnedTimes = WarnedTimes + 1,
2014-02-19 08:00:32 +00:00
AdminComment = CONCAT(\''.db_string($AdminComment).'\', AdminComment)
2013-08-28 23:08:41 +00:00
WHERE UserID = \''.db_string($UserID).'\'');
2012-10-11 08:00:15 +00:00
}
2013-08-28 23:08:41 +00:00
G::$DB->set_query_id($QueryID);
2012-10-11 08:00:15 +00:00
}
2013-02-10 08:00:29 +00:00
2012-10-19 08:00:17 +00:00
/**
* Update the notes of a user
* @param unknown $UserID ID of user
* @param unknown $AdminComment Comment to update with
*/
public static function update_user_notes($UserID, $AdminComment) {
2013-08-28 23:08:41 +00:00
$QueryID = G::$DB->get_query_id();
G::$DB->query('
2013-05-16 16:15:57 +00:00
UPDATE users_info
2014-02-19 08:00:32 +00:00
SET AdminComment = CONCAT(\''.db_string($AdminComment).'\', AdminComment)
2013-08-28 23:08:41 +00:00
WHERE UserID = \''.db_string($UserID).'\'');
G::$DB->set_query_id($QueryID);
2012-10-19 08:00:17 +00:00
}
2014-08-11 08:00:26 +00:00
/**
2014-08-13 08:00:26 +00:00
* Check if an IP address is part of a given CIDR range.
* @param string $CheckIP the IP address to be looked up
2014-08-11 08:00:26 +00:00
* @param string $Subnet the CIDR subnet to be checked against
*/
public static function check_cidr_range($CheckIP, $Subnet) {
$IP = ip2long($CheckIP);
2014-08-13 08:00:26 +00:00
$CIDR = split('/', $Subnet);
2014-08-11 08:00:26 +00:00
$SubnetIP = ip2long($CIDR[0]);
$SubnetMaskBits = 32 - $CIDR[1];
return (($IP>>$SubnetMaskBits) == ($SubnetIP>>$SubnetMaskBits));
}
2012-10-11 08:00:15 +00:00
}
?>