diff --git a/.bin/geoip2-csv-converter b/.bin/geoip2-csv-converter
new file mode 100755
index 0000000..957bd0f
Binary files /dev/null and b/.bin/geoip2-csv-converter differ
diff --git a/app/LoginWatch.php b/app/LoginWatch.php
index cf91e5a..386462a 100644
--- a/app/LoginWatch.php
+++ b/app/LoginWatch.php
@@ -200,7 +200,7 @@ class LoginWatch extends Base {
(ip.FromIP IS NOT NULL) AS banned
FROM login_attempts w
LEFT JOIN users_main um ON (um.ID = w.UserID)
- LEFT JOIN ip_bans ip ON (ip.FromIP = inet_aton(w.IP))
+ LEFT JOIN ip_bans ip ON (ip.FromIP = inet6_aton(w.IP))
WHERE (w.BannedUntil > now() OR w.LastAttempt > now() - INTERVAL 6 HOUR)
ORDER BY $orderBy $orderWay
");
@@ -219,9 +219,9 @@ class LoginWatch extends Base {
$reason = trim($reason);
$n = 0;
foreach ($list as $id) {
- $ipv4 = $this->db->scalar(
+ $ip = $this->db->scalar(
"
- SELECT inet_aton(IP) FROM login_attempts WHERE ID = ?
+ SELECT inet6_aton(IP) FROM login_attempts WHERE ID = ?
",
$id
);
@@ -233,8 +233,8 @@ class LoginWatch extends Base {
",
$userId,
$reason,
- $ipv4,
- $ipv4
+ $ip,
+ $ip
);
$n += $this->db->affected_rows();
}
diff --git a/app/Manager/IPv4.php b/app/Manager/IPv4.php
index cfe7073..0531445 100644
--- a/app/Manager/IPv4.php
+++ b/app/Manager/IPv4.php
@@ -2,55 +2,9 @@
namespace Gazelle\Manager;
-class IPv4 extends \Gazelle\Base {
+class IP extends \Gazelle\Base {
- const CACHE_KEY = 'ipv4_bans_';
-
- /**
- * Returns the unsigned 32bit form of an IPv4 address
- *
- * @param string $ipv4 The IP address x.x.x.x
- * @return string the long it represents.
- */
- public function ip2ulong(string $ipv4) {
- return sprintf('%u', ip2long($ipv4));
- }
-
- /**
- * Returns true if given IP is banned.
- * TODO: This looks really braindead. Why not compare the 32bit address
- * directly BETWEEN FromIP AND ToIP? Apart from dubious merits of
- * caching?
- *
- * @param string $IP
- * @return bool True if banned
- */
- public function isBanned(string $IP) {
- $A = substr($IP, 0, strcspn($IP, '.'));
- $key = self::CACHE_KEY . $A;
- $IPBans = $this->cache->get_value($key);
- if (!is_array($IPBans)) {
- $this->db->prepared_query(
- "
- SELECT FromIP, ToIP, ID
- FROM ip_bans
- WHERE FromIP BETWEEN ? << 24 AND (? << 24) - 1
- ",
- $A,
- $A + 1
- );
- $IPBans = $this->db->to_array(0, MYSQLI_NUM);
- $this->cache->cache_value($key, $IPBans, 0);
- }
- $IPNum = $this->ip2ulong($IP);
- foreach ($IPBans as $IPBan) {
- list($FromIP, $ToIP) = $IPBan;
- if ($IPNum >= $FromIP && $IPNum <= $ToIP) {
- return true;
- }
- }
- return false;
- }
+ const CACHE_KEY = 'ip_bans_';
/**
* Create an ip address ban over a range of addresses. Will append
@@ -61,16 +15,14 @@ class IPv4 extends \Gazelle\Base {
* @param string $to The last adddress in the range (may equal $from)
* @param string $reason Why ban?
*/
- public function createBan(int $userId, $ipv4From, string $ipv4To, string $reason) {
- $from = $this->ip2ulong($ipv4From);
- $to = $this->ip2ulong($ipv4To);
+ public function createBan(int $userId, $ipFrom, string $ipTo, string $reason) {
$current = $this->db->scalar(
'
SELECT Reason
FROM ip_bans
- WHERE ? BETWEEN FromIP AND ToIP
+ WHERE INET6_ATON(?) BETWEEN FromIP AND ToIP
',
- $from
+ $ipFrom
);
if ($current) {
@@ -81,13 +33,13 @@ class IPv4 extends \Gazelle\Base {
Reason = concat(?, ' AND ', Reason),
user_id = ?,
created = now()
- WHERE FromIP = ?
- AND ToIP = ?
+ WHERE FromIP = INET6_ATON(?)
+ AND ToIP = INET6_ATON(?)
",
$reason,
$userId,
- $from,
- $to
+ $ipFrom,
+ $ipTo
);
}
} else { // Not yet banned
@@ -95,15 +47,15 @@ class IPv4 extends \Gazelle\Base {
"
INSERT INTO ip_bans
(Reason, FromIP, ToIP, user_id)
- VALUES (?, ?, ?, ?)
+ VALUES (?, ?, INET6_ATON(?), INET6_ATON(?))
",
$reason,
- $from,
- $to,
+ $ipFrom,
+ $ipTo,
$userId
);
$this->cache->delete_value(
- self::CACHE_KEY . substr($ipv4From, 0, strcspn($ipv4From, '.'))
+ self::CACHE_KEY . substr($ipFrom, 0, strcspn($ipFrom, '.'))
);
}
}
@@ -116,7 +68,7 @@ class IPv4 extends \Gazelle\Base {
public function removeBan(int $id) {
$fromClassA = $this->db->scalar(
"
- SELECT FromIP >> 24 FROM ip_bans WHERE ID = ?
+ SELECT INET6_NTOA(FromIP) FROM ip_bans WHERE ID = ?
",
$id
);
diff --git a/classes/donationsview.class.php b/classes/donationsview.class.php
index 2b862e4..bb21a41 100644
--- a/classes/donationsview.class.php
+++ b/classes/donationsview.class.php
@@ -32,10 +32,10 @@ class DonationsView {
-
- if ($IsDonor) {
+ if ($IsDonor) { ?>
+
if (check_perms('users_mod') || $OwnProfile) {
- ?>
+ ?>
@@ -56,11 +56,13 @@ class DonationsView {
- } else { ?>
+ } else {
+ ?>
- } ?>
+
+ } ?>
diff --git a/classes/invite_tree.class.php b/classes/invite_tree.class.php
index 55f2bb9..a4298f8 100644
--- a/classes/invite_tree.class.php
+++ b/classes/invite_tree.class.php
@@ -24,7 +24,7 @@ class INVITE_TREE {
$UserID = $this->UserID;
?>
-
+
G::$DB->query("
SELECT TreePosition, TreeID, TreeLevel
@@ -113,11 +113,14 @@ class INVITE_TREE {
if ($Donor) {
$DonorCount++;
}
-
// Manage tree depth
if ($TreeLevel > $PreviousTreeLevel) {
for ($i = 0; $i < $TreeLevel - $PreviousTreeLevel; $i++) {
- echo "\n\n
\n\t\n";
+ if ($TreeLevel == 2) {
+ echo "\n\n
+
+ = $Tree ?>
G::$DB->set_query_id($QueryID);
diff --git a/classes/tools.class.php b/classes/tools.class.php
index b460f8a..55de4f7 100644
--- a/classes/tools.class.php
+++ b/classes/tools.class.php
@@ -6,41 +6,13 @@ class Tools {
* @param string $IP
*/
public static function site_ban_ip($IP) {
- global $Debug;
- $A = substr($IP, 0, strcspn($IP, '.'));
- $IPNum = Tools::ip_to_unsigned($IP);
- $IPBans = G::$Cache->get_value('ip_bans_' . $A);
- if (!is_array($IPBans)) {
- $SQL = sprintf("
- SELECT ID, FromIP, ToIP
- FROM ip_bans
- WHERE FromIP BETWEEN %d << 24 AND (%d << 24) - 1", $A, $A + 1);
- $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);
+ G::$DB->prepared_query('SELECT ID FROM ip_bans WHERE INET6_ATON(?) BETWEEN FromIP and ToIP', $IP);
+ if (G::$DB->has_results() > 0) {
+ return true;
}
- foreach ($IPBans as $Index => $IPBan) {
- list($ID, $FromIP, $ToIP) = $IPBan;
- if ($IPNum >= $FromIP && $IPNum <= $ToIP) {
- return true;
- }
- }
-
return false;
}
- /**
- * 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) {
- return sprintf('%u', ip2long($IP));
- }
-
/**
* Geolocate an IP address using the database
*
@@ -52,22 +24,14 @@ class Tools {
if (isset($IPs[$IP])) {
return $IPs[$IP];
}
- if (is_number($IP)) {
- $Long = $IP;
- } else {
- $Long = Tools::ip_to_unsigned($IP);
- }
- if (!$Long || $Long == 2130706433) { // No need to check cc for 127.0.0.1
- return false;
- }
$QueryID = G::$DB->get_query_id();
G::$DB->query("
- SELECT EndIP, Code
+ SELECT Code
FROM geoip_country
- WHERE $Long >= StartIP
+ WHERE INET6_ATON('$IP')>= StartIP and INET6_ATON('$IP') < EndIP
ORDER BY StartIP DESC
LIMIT 1");
- if ((!list($EndIP, $Country) = G::$DB->next_record()) || $EndIP < $Long) {
+ if ((!list($Country) = G::$DB->next_record())) {
$Country = '?';
}
G::$DB->set_query_id($QueryID);
@@ -151,7 +115,7 @@ class Tools {
*/
public static function display_ip($IP) {
$Line = display_str($IP) . ' (' . Tools::get_country_code_by_ajax($IP) . ') ';
- $Line .= '
' . t('server.common.search') . ' ';
+ $Line .= '
' . S . ' ';
return $Line;
}
@@ -299,18 +263,4 @@ class Tools {
WHERE UserID = \'' . db_string($UserID) . '\'');
G::$DB->set_query_id($QueryID);
}
-
- /**
- * Check if an IP address is part of a given CIDR range.
- * @param string $CheckIP the IP address to be looked up
- * @param string $Subnet the CIDR subnet to be checked against
- */
- public static function check_cidr_range($CheckIP, $Subnet) {
- $IP = ip2long($CheckIP);
- $CIDR = split('/', $Subnet);
- $SubnetIP = ip2long($CIDR[0]);
- $SubnetMaskBits = 32 - $CIDR[1];
-
- return (($IP >> $SubnetMaskBits) == ($SubnetIP >> $SubnetMaskBits));
- }
}
diff --git a/db/migrations/20221205120723_ipv6.php b/db/migrations/20221205120723_ipv6.php
new file mode 100644
index 0000000..c8631c1
--- /dev/null
+++ b/db/migrations/20221205120723_ipv6.php
@@ -0,0 +1,85 @@
+table('ip_bans')
+ ->renameColumn('FromIP', 'FromIP_Old')
+ ->renameColumn('ToIP', 'ToIP_Old')
+ ->addColumn('FromIP', 'varbinary', ['length' => 16])
+ ->addColumn('ToIP', 'varbinary', ['length' => 16])
+ ->save();
+ $this->execute('UPDATE ip_bans SET FromIP=INET6_ATON(INET_NTOA(FromIP_Old)), ToIP=INET6_ATON(INET_NTOA(ToIP_Old));');
+
+ $this->table('geoip_country')
+ ->renameColumn('StartIP', 'StartIP_Old')
+ ->renameColumn('EndIP', 'EndIP_Old')
+ ->addColumn('StartIP', 'varbinary', ['length' => 16])
+ ->addColumn('EndIP', 'varbinary', ['length' => 16])
+ ->save();
+ $this->execute('UPDATE geoip_country SET StartIP=INET6_ATON(INET_NTOA(StartIP_Old)), EndIP=INET6_ATON(INET_NTOA(EndIP_Old));');
+
+ $this->table('login_attempts')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ $this->table('users_history_ips')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ $this->table('users_main')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ $this->table('users_history_ips')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ $this->table('users_history_emails')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ $this->table('users_history_passkeys')
+ ->changeColumn('ChangerIP', 'string', ['length' => 45])
+ ->save();
+ $this->table('users_history_passkeys')
+ ->changeColumn('ChangerIP', 'string', ['length' => 45])
+ ->save();
+ $this->table('users_sessions')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ $this->table('apply_user')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ $this->table('ip_lock')
+ ->changeColumn('IPs', 'string', ['length' => 255])
+ ->save();
+ $this->table('register_apply_link')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ $this->table('users_enable_requests')
+ ->changeColumn('IP', 'string', ['length' => 45])
+ ->save();
+ }
+}
diff --git a/db/migrations/20221205144841_ipv6_index.php b/db/migrations/20221205144841_ipv6_index.php
new file mode 100644
index 0000000..e3ead4c
--- /dev/null
+++ b/db/migrations/20221205144841_ipv6_index.php
@@ -0,0 +1,35 @@
+table('ip_bans')->removeIndexByName('FromIP_2')->removeIndexByName('ToIP')->addIndex(['FromIP', 'ToIP'], ['unique' => true])->save();
+ $this->table('geoip_country')->changePrimaryKey(['StartIP', 'EndIP'])->save();
+ }
+}
diff --git a/public/static/functions/reports.js b/public/static/functions/reports.js
index e7377ee..6092dec 100644
--- a/public/static/functions/reports.js
+++ b/public/static/functions/reports.js
@@ -33,8 +33,9 @@ function claim(id) {
}
if (json['status'] == 'success') {
var username = json['username']
- $('#claim_' + id).raw().innerHTML =
- '
Claimed by ' + username + ' '
+ $('#claim_' + id).ghide()
+ $('#unclaim_' + id).gshow()
+ $('#claimer_' + id).raw().innerHTML = username
}
})
}
@@ -46,12 +47,9 @@ function unClaim(id) {
ajax.post('reports.php?action=unclaim', post, function (response) {
var json = JSON.parse(response)
if (json['status'] == 'success') {
- $('#claimed_' + id).raw().innerHTML =
- '
Claim '
+ $('#claim_' + id).gshow()
+ $('#unclaim_' + id).ghide()
+ $('#claimer_' + id).raw().innerHTML = ''
}
})
}
@@ -60,26 +58,20 @@ function resolve(id, claimer) {
var answer = true
if (!claimer) {
if ($('#claimed_' + id).raw()) {
- var answer = confirm(
- 'This is a claimed report. Are you sure you want to resolve it?'
- )
+ var answer = confirm('This is a claimed report. Are you sure you want to resolve it?')
if (answer) answer = true
else answer = false
}
}
if (answer) {
- ajax.post(
- 'reports.php?action=resolve',
- 'report_form_' + id,
- function (response) {
- var json = JSON.parse(response)
- if (json['status'] == 'success') {
- $('#report_' + id).remove()
- } else {
- alert(json['status'])
- }
+ ajax.post('reports.php?action=resolve', 'report_form_' + id, function (response) {
+ var json = JSON.parse(response)
+ if (json['status'] == 'success') {
+ $('#report_' + id).remove()
+ } else {
+ alert(json['status'])
}
- )
+ })
}
return false
}
diff --git a/sections/bonus/bprates.php b/sections/bonus/bprates.php
index 4f1e17c..575bf12 100644
--- a/sections/bonus/bprates.php
+++ b/sections/bonus/bprates.php
@@ -64,7 +64,42 @@ $TotalMonthlyPoints = $TotalDailyPoints * 30.436875;
$TotalYearlyPoints = $TotalDailyPoints * 365.2425;
$Pages = Format::get_pages($Page, $TotalTorrents, CONFIG['TORRENTS_PER_PAGE']);
+if ($TotalTorrents > 0) {
+ $DB->prepared_query("
+ SELECT
+ t.ID,
+ t.GroupID,
+ t.Size,
+ t.Size / (1024 * 1024 * 1024) as CorrectSize,
+ t.Codec,
+ t.Source,
+ t.Processing,
+ t.Container,
+ t.Resolution,
+ t.Scene,
+ t.RemasterYear,
+ t.RemasterTitle,
+ t.Slot,
+ GREATEST(t.Seeders, 1) AS Seeders,
+ xfh.seedtime AS Seedtime,
+ (t.Size / (1024 * 1024 * 1024) * 1 *(
+ 0.025 + (
+ (0.06 * LN(1 + (xfh.seedtime / (24)))) / (POW(GREATEST(t.Seeders, 1), 0.6))
+ )
+ )) AS HourlyPoints
+ FROM
+ (SELECT DISTINCT uid,fid FROM xbt_files_users WHERE active=1 AND remaining=0 AND mtime > unix_timestamp(NOW() - INTERVAL 1 HOUR) AND uid = ?) AS xfu
+ JOIN xbt_files_history AS xfh ON xfh.uid = xfu.uid AND xfh.fid = xfu.fid
+ JOIN torrents AS t ON t.ID = xfu.fid
+ WHERE
+ xfu.uid = ?
+ $OrderBy
+ LIMIT ?
+ OFFSET ?", $UserID, $UserID, $Limit, $Offset);
+ $GroupIDs = $DB->collect('GroupID');
+ $Groups = Torrents::get_groups($GroupIDs, true, true, false);
+}
?>
@@ -134,59 +169,26 @@ $Pages = Format::get_pages($Page, $TotalTorrents, CONFIG['TORRENTS_PER_PAGE']);
$LinkTail = "&order_way=" . ($OrderWay == "asc" ? "desc" : "asc") . ($Page != 1 ? "&page=$Page" : "");
?>
-
-
-
-
-
-
- 0) {
- $DB->prepared_query("
- SELECT
- t.ID,
- t.GroupID,
- t.Size,
- t.Size / (1024 * 1024 * 1024) as CorrectSize,
- t.Codec,
- t.Source,
- t.Processing,
- t.Container,
- t.Resolution,
- t.Scene,
- t.RemasterYear,
- t.RemasterTitle,
- t.Slot,
- GREATEST(t.Seeders, 1) AS Seeders,
- xfh.seedtime AS Seedtime,
- (t.Size / (1024 * 1024 * 1024) * 1 *(
- 0.025 + (
- (0.06 * LN(1 + (xfh.seedtime / (24)))) / (POW(GREATEST(t.Seeders, 1), 0.6))
- )
- )) AS HourlyPoints
- FROM
- (SELECT DISTINCT uid,fid FROM xbt_files_users WHERE active=1 AND remaining=0 AND mtime > unix_timestamp(NOW() - INTERVAL 1 HOUR) AND uid = ?) AS xfu
- JOIN xbt_files_history AS xfh ON xfh.uid = xfu.uid AND xfh.fid = xfu.fid
- JOIN torrents AS t ON t.ID = xfu.fid
- WHERE
- xfu.uid = ?
- $OrderBy
- LIMIT ?
- OFFSET ?", $UserID, $UserID, $Limit, $Offset);
-
- $GroupIDs = $DB->collect('GroupID');
- $Groups = Torrents::get_groups($GroupIDs, true, true, false);
+
+ if ($TotalTorrents > 0) {
+ ?>
+
+
+
+
+
+
+
while ($Torrent = $DB->next_record(MYSQLI_ASSOC)) {
$Size = intval($Torrent['Size']);
$CorrectSize = $Torrent['CorrectSize'];
@@ -201,7 +203,7 @@ $Pages = Format::get_pages($Page, $TotalTorrents, CONFIG['TORRENTS_PER_PAGE']);
'SettingTorrentTitle' => G::$LoggedUser['SettingTorrentTitle'],
]);
$DisplayName = '' . $Name . ' ';
- ?>
+ ?>
= $DisplayName ?>
= Format::get_size($Torrent['Size']) ?>
@@ -213,22 +215,12 @@ $Pages = Format::get_pages($Page, $TotalTorrents, CONFIG['TORRENTS_PER_PAGE']);
= number_format($MonthlyPoints) ?>
= number_format($YearlyPoints) ?>
-
-
- = t('server.bonus.no_torrent_seeded_currently') ?>
-
-
-
-
-
-
+ } ?>
+
+
+
+ } ?>
-
\ No newline at end of file
diff --git a/sections/bonus/index.php b/sections/bonus/index.php
index 6396723..b4173ce 100644
--- a/sections/bonus/index.php
+++ b/sections/bonus/index.php
@@ -13,6 +13,7 @@ if (isset($_GET['action'])) {
switch ($_GET['action']) {
case 'purchase':
/* handle validity and cost as early as possible */
+
if (isset($_REQUEST['label']) && preg_match('/^[a-z]{1,15}(-\w{1,15}){0,4}/', $_REQUEST['label'])) {
$Label = $_REQUEST['label'];
$Item = $Bonus->getItem($Label);
diff --git a/sections/bonus/store.php b/sections/bonus/store.php
index b48351f..472c216 100644
--- a/sections/bonus/store.php
+++ b/sections/bonus/store.php
@@ -5,12 +5,12 @@ View::show_header('积分商城', 'bonus', 'PageBonusStore');
if (isset($_GET['complete'])) {
$label = $_GET['complete'];
$item = $Bonus->getItem($label);
+ $Items = $Bonus->getList();
?>
-
- "= t("server.bonus.${item['Label']}") ?>" = t('server.bonus.purchased') ?>
-
+
}
+$Items = $Bonus->getList();
?>
@@ -24,66 +24,74 @@ if (isset($_GET['complete'])) {
-
-
-
-
-
-
-
+ "= t("server.bonus.${item['Label']}") ?>" = t('server.bonus.purchased') ?>
+
+ if (count($Items) > 0) { ?>
+
+
+
+
+
+
+ getList();
+ $Cnt = 0;
- foreach ($Items as $Label => $Item) {
- /*
+ foreach ($Items as $Label => $Item) {
+ /*
if ($Item['MinClass'] > G::$LoggedUser['EffectiveClass']) {
continue;
}
*/
- $Cnt++;
- $Price = $Bonus->getEffectivePrice($Label, G::$LoggedUser['EffectiveClass']);
- $FormattedPrice = number_format($Price);
- ?>
-
- = $Cnt ?>
- = t("server.bonus.${Item['Label']}") ?>
- = $FormattedPrice ?>
-
-
- if ($Item['MinClass'] > $LoggedUser['EffectiveClass']) {
- ?>
- = t('server.bonus.need_higher_user_class') ?>
+ $Cnt++;
+ $Price = $Bonus->getEffectivePrice($Label, G::$LoggedUser['EffectiveClass']);
+ $FormattedPrice = number_format($Price);
+ ?>
+
+ = $Cnt ?>
+ = t("server.bonus.${Item['Label']}") ?>
+ = $FormattedPrice ?>
+
- } else {
- if (G::$LoggedUser['BonusPoints'] >= $Price) {
- $NextFunction = preg_match('/^other-\d$/', $Label) ? 'ConfirmOther' : 'null';
- $OnClick = preg_match('/^title-bbcode-[yn]$/', $Label) ? "NoOp" : "ConfirmPurchase";
+ if ($Item['MinClass'] > $LoggedUser['EffectiveClass']) {
?>
- = t('server.bonus.purchase') ?>
-
+ = t('server.bonus.need_higher_user_class') ?>
+
} else {
- ?>
- = t('server.bonus.too_expensive') ?>
-
+ if (G::$LoggedUser['BonusPoints'] >= $Price) {
+ $NextFunction = preg_match('/^other-\d$/', $Label) ? 'ConfirmOther' : 'null';
+ $OnClick = preg_match('/^title-bbcode-[yn]$/', $Label) ? "NoOp" : "ConfirmPurchase";
+ ?>
+ = t('server.bonus.purchase') ?>
+
+ } else {
+ ?>
+ = t('server.bonus.too_expensive') ?>
+
+ }
}
- }
- print <<
HTML;
- }
- ?>
-
-
-
+ }
+ ?>
+
+
+
+ } else {
+ VIew::line(t('server.common.no_results'));
+ }
+ ?>
+
channel('Gazelle Change Log', 'RSS feed for Gazelle\'s changelog.');
if (!$Changelog = $Cache->get_value('changelog')) {
require(CONFIG['SERVER_ROOT'] . '/classes/mysql.class.php');
- require(CONFIG['SERVER_ROOT'] . '/classes/misc.class.php');
$DB = new DB_MYSQL;
$DB->query("
diff --git a/sections/forums/search.php b/sections/forums/search.php
index 5c84ef0..3c2caf6 100644
--- a/sections/forums/search.php
+++ b/sections/forums/search.php
@@ -93,126 +93,128 @@ View::show_header(t('server.forums.forums_greater_than_search'), 'bbcode,forum_s
diff --git a/sections/log/index.php b/sections/log/index.php
index e50e44f..08404f3 100644
--- a/sections/log/index.php
+++ b/sections/log/index.php
@@ -1,6 +1,9 @@
enforce_login();
+if (!check_perms('site_view_full_log')) {
+ error(403);
+}
View::show_header(t('server.log.site_log'), '', 'PageLogHome');
include(CONFIG['SERVER_ROOT'] . '/sections/log/sphinx.php');
diff --git a/sections/login/index.php b/sections/login/index.php
index def3d5e..d0a0187 100644
--- a/sections/login/index.php
+++ b/sections/login/index.php
@@ -5,6 +5,67 @@ use Gazelle\Util\Crypto;
/*-- TODO ---------------------------//
Add the JavaScript validation into the display page using the class
//-----------------------------------*/
+// Function to log a user's login attempt
+function log_attempt($UserID) {
+ global $DB, $Cache, $AttemptID, $Attempts, $Bans, $BannedUntil;
+ $IPStr = $_SERVER['REMOTE_ADDR'];
+ if ($AttemptID) { // User has attempted to log in recently
+ $Attempts++;
+ if ($Attempts > 5) { // Only 6 allowed login attempts, ban user's IP
+ $BannedUntil = time_plus(60 * 60 * 6);
+ $DB->query("
+ UPDATE login_attempts
+ SET
+ LastAttempt = '" . sqltime() . "',
+ Attempts = '" . db_string($Attempts) . "',
+ BannedUntil = '" . db_string($BannedUntil) . "',
+ Bans = Bans + 1
+ WHERE ID = '" . db_string($AttemptID) . "'");
+
+ if ($Bans > 9) { // Automated bruteforce prevention
+ $DB->query("
+ SELECT Reason
+ FROM ip_bans
+ WHERE INET6_ATON('$IPStr') BETWEEN FromIP AND ToIP");
+ if ($DB->has_results()) {
+ //Ban exists already, only add new entry if not for same reason
+ list($Reason) = $DB->next_record(MYSQLI_BOTH, false);
+ if ($Reason != 'Automated ban per >60 failed login attempts') {
+ $DB->query("
+ UPDATE ip_bans
+ SET Reason = CONCAT('Automated ban per >60 failed login attempts AND ', Reason)
+ WHERE FromIP < INET6_ATON('$IPStr')
+ AND ToIP > INET6_ATON('$IPStr')");
+ }
+ } else {
+ //No ban
+ $DB->query("
+ INSERT IGNORE INTO ip_bans
+ (FromIP, ToIP, Reason)
+ VALUES
+ (INET6_ATON('$IPStr'),INET6_ATON('$IPStr'), 'Automated ban per >60 failed login attempts')");
+ $Cache->delete_value("ip_bans_$IPStr");
+ }
+ }
+ } else {
+ // User has attempted fewer than 6 logins
+ $DB->query("
+ UPDATE login_attempts
+ SET
+ LastAttempt = '" . sqltime() . "',
+ Attempts = '" . db_string($Attempts) . "',
+ BannedUntil = '0000-00-00 00:00:00'
+ WHERE ID = '" . db_string($AttemptID) . "'");
+ }
+ } else { // User has not attempted to log in recently
+ $Attempts = 1;
+ $DB->query("
+ INSERT INTO login_attempts
+ (UserID, IP, LastAttempt, Attempts)
+ VALUES
+ ('" . db_string($UserID) . "', '" . db_string($IPStr) . "', '" . sqltime() . "', 1)");
+ }
+} // end log_attempt function
function checkLoginKey($Key) {
$Key = db_string($Key);
@@ -249,69 +310,7 @@ elseif (isset($_REQUEST['act']) && $_REQUEST['act'] === '2fa_recovery') {
WHERE IP = '" . db_string($_SERVER['REMOTE_ADDR']) . "'");
list($AttemptID, $Attempts, $Bans, $BannedUntil) = $DB->next_record();
- // Function to log a user's login attempt
- function log_attempt($UserID) {
- global $DB, $Cache, $AttemptID, $Attempts, $Bans, $BannedUntil;
- $IPStr = $_SERVER['REMOTE_ADDR'];
- $IPA = substr($IPStr, 0, strcspn($IPStr, '.'));
- $IP = Tools::ip_to_unsigned($IPStr);
- if ($AttemptID) { // User has attempted to log in recently
- $Attempts++;
- if ($Attempts > 5) { // Only 6 allowed login attempts, ban user's IP
- $BannedUntil = time_plus(60 * 60 * 6);
- $DB->query("
- UPDATE login_attempts
- SET
- LastAttempt = '" . sqltime() . "',
- Attempts = '" . db_string($Attempts) . "',
- BannedUntil = '" . db_string($BannedUntil) . "',
- Bans = Bans + 1
- WHERE ID = '" . db_string($AttemptID) . "'");
- if ($Bans > 9) { // Automated bruteforce prevention
- $DB->query("
- SELECT Reason
- FROM ip_bans
- WHERE $IP BETWEEN FromIP AND ToIP");
- if ($DB->has_results()) {
- //Ban exists already, only add new entry if not for same reason
- list($Reason) = $DB->next_record(MYSQLI_BOTH, false);
- if ($Reason != 'Automated ban per >60 failed login attempts') {
- $DB->query("
- UPDATE ip_bans
- SET Reason = CONCAT('Automated ban per >60 failed login attempts AND ', Reason)
- WHERE FromIP = $IP
- AND ToIP = $IP");
- }
- } else {
- //No ban
- $DB->query("
- INSERT IGNORE INTO ip_bans
- (FromIP, ToIP, Reason)
- VALUES
- ('$IP','$IP', 'Automated ban per >60 failed login attempts')");
- $Cache->delete_value("ip_bans_$IPA");
- }
- }
- } else {
- // User has attempted fewer than 6 logins
- $DB->query("
- UPDATE login_attempts
- SET
- LastAttempt = '" . sqltime() . "',
- Attempts = '" . db_string($Attempts) . "',
- BannedUntil = '0000-00-00 00:00:00'
- WHERE ID = '" . db_string($AttemptID) . "'");
- }
- } else { // User has not attempted to log in recently
- $Attempts = 1;
- $DB->query("
- INSERT INTO login_attempts
- (UserID, IP, LastAttempt, Attempts)
- VALUES
- ('" . db_string($UserID) . "', '" . db_string($IPStr) . "', '" . sqltime() . "', 1)");
- }
- } // end log_attempt function
log_attempt($UserID);
unset($_SESSION['temp_stay_logged'], $_SESSION['temp_user_data']);
header('Location: login.php');
@@ -413,70 +412,6 @@ else {
WHERE IP = '" . db_string($_SERVER['REMOTE_ADDR']) . "'");
list($AttemptID, $Attempts, $Bans, $BannedUntil) = $DB->next_record();
- // Function to log a user's login attempt
- function log_attempt($UserID) {
- global $DB, $Cache, $AttemptID, $Attempts, $Bans, $BannedUntil;
- $IPStr = $_SERVER['REMOTE_ADDR'];
- $IPA = substr($IPStr, 0, strcspn($IPStr, '.'));
- $IP = Tools::ip_to_unsigned($IPStr);
- if ($AttemptID) { // User has attempted to log in recently
- $Attempts++;
- if ($Attempts > 5) { // Only 6 allowed login attempts, ban user's IP
- $BannedUntil = time_plus(60 * 60 * 6);
- $DB->query("
- UPDATE login_attempts
- SET
- LastAttempt = '" . sqltime() . "',
- Attempts = '" . db_string($Attempts) . "',
- BannedUntil = '" . db_string($BannedUntil) . "',
- Bans = Bans + 1
- WHERE ID = '" . db_string($AttemptID) . "'");
-
- if ($Bans > 9) { // Automated bruteforce prevention
- $DB->query("
- SELECT Reason
- FROM ip_bans
- WHERE $IP BETWEEN FromIP AND ToIP");
- if ($DB->has_results()) {
- //Ban exists already, only add new entry if not for same reason
- list($Reason) = $DB->next_record(MYSQLI_BOTH, false);
- if ($Reason != 'Automated ban per >60 failed login attempts') {
- $DB->query("
- UPDATE ip_bans
- SET Reason = CONCAT('Automated ban per >60 failed login attempts AND ', Reason)
- WHERE FromIP = $IP
- AND ToIP = $IP");
- }
- } else {
- //No ban
- $DB->query("
- INSERT IGNORE INTO ip_bans
- (FromIP, ToIP, Reason)
- VALUES
- ('$IP','$IP', 'Automated ban per >60 failed login attempts')");
- $Cache->delete_value("ip_bans_$IPA");
- }
- }
- } else {
- // User has attempted fewer than 6 logins
- $DB->query("
- UPDATE login_attempts
- SET
- LastAttempt = '" . sqltime() . "',
- Attempts = '" . db_string($Attempts) . "',
- BannedUntil = '0000-00-00 00:00:00'
- WHERE ID = '" . db_string($AttemptID) . "'");
- }
- } else { // User has not attempted to log in recently
- $Attempts = 1;
- $DB->query("
- INSERT INTO login_attempts
- (UserID, IP, LastAttempt, Attempts)
- VALUES
- ('" . db_string($UserID) . "', '" . db_string($IPStr) . "', '" . sqltime() . "', 1)");
- }
- } // end log_attempt function
-
// If user has submitted form
if (isset($_POST['username']) && !empty($_POST['username']) && isset($_POST['password']) && !empty($_POST['password'])) {
if ($CloseLogin) {
diff --git a/sections/reports/reports.php b/sections/reports/reports.php
index 8e5397f..20655f0 100644
--- a/sections/reports/reports.php
+++ b/sections/reports/reports.php
@@ -93,81 +93,94 @@ $DB->set_query_id($Reports);
$Type = $Types[$Short];
$Reference = "reports.php?id=$ReportID#report$ReportID";
?>
-