Tracker client stats cache, more robust file list functions, permissions for file list access (#1069)

This commit is contained in:
Cønstantine Kovalensky 2023-11-09 18:55:46 +04:00 committed by GitHub
commit 33faad2355
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 47 deletions

View file

@ -82,29 +82,40 @@ $clients_percentage = [];
$numwant = !empty($_GET['client_numwant']) ? (int)$_GET['client_numwant'] : 100;
$client_full = !empty($_GET['client_length']) ? (int)$_GET['client_length'] : false;
$rowset = DB()->fetch_rowset('SELECT peer_id AS client FROM ' . TMP_TRACKER_TABLE);
if ($client_full || !$stats_cache = CACHE('tr_cache')->get('tracker_clients_stats')) {
if (!empty($rowset)) {
$rowset = DB()->fetch_rowset('SELECT peer_id AS client FROM ' . TMP_TRACKER_TABLE);
$client_count = 0;
if (!empty($rowset)) {
foreach ($rowset as $cnt => $row) {
$clientString = $client_full ? substr($row['client'], 0, $client_full) : substr($row['client'], 0, 3);
if (!isset($clients[$clientString])) {
$clients[$clientString] = 1;
$client_count = 0;
foreach ($rowset as $cnt => $row) {
$clientString = $client_full ? substr($row['client'], 0, $client_full) : substr($row['client'], 0, 3);
if (!isset($clients[$clientString])) {
$clients[$clientString] = 1;
}
else {
$clients[$clientString]++;
}
$client_count++;
}
else {
$clients[$clientString]++;
foreach ($clients as $client => $count) {
$percentage = number_format(($count / $client_count) * 100, 2);
$clients_percentage[$client] = "[$count] => $percentage%";
}
$client_count++;
}
foreach ($clients as $client => $count) {
$percentage = number_format(($count / $client_count) * 100, 2);
$clients_percentage[] = ($client_full ? $client : get_user_torrent_client($client)) . " [$count] => $percentage%";
if (!$client_full) {
CACHE('tr_cache')->set('tracker_clients_stats', $clients_percentage, 3600);
}
}
} else {
$clients_percentage = $stats_cache;
}
$client_list = implode('<br>', array_slice($clients_percentage, 0, $numwant));
foreach (array_slice($clients_percentage, 0, $numwant) as $client => $value) {
$client_list .= ($client_full) ? ("$client => $value<br>") : get_user_torrent_client($client) . " => $value<br>";
}
function commify_callback($matches)
@ -157,6 +168,7 @@ echo (count($clients_percentage) > $numwant) ? ('<a href="' . 'tracker.php?clien
echo $client_full ? '<br><b>Get more length and numbers via modifying the parameters in the url<b>' : (!empty($client_list) ? '<a href="tracker.php?client_length=6&client_numwant=10">Peer_ids with more length (version debugging)</a>': '');
echo '</td></tr>';
echo '</table>';
echo !$client_full ? '<p style = "text-align:right;">Simple stats for clients are being cached for one hour.</p>' : '';
echo '<div align="center"><pre>';
if ($l = sys('la')) {

View file

@ -6,7 +6,12 @@ if (!defined('BB_ROOT')) {
$user->session_start();
$topic_id = (int)$_GET['t'];
if ($bb_cfg['bt_disable_dht'] && IS_GUEST) {
http_response_code(403);
die($lang['BT_PRIVATE_TRACKER']);
}
$topic_id = !empty($_GET['t']) ? (int)$_GET['t'] : (http_response_code(404) && die($lang['INVALID_TOPIC_ID']));
$sql = 'SELECT t.attach_id, t.info_hash_v2, ad.physical_filename
FROM ' . BB_BT_TORRENTS . ' t
@ -24,13 +29,13 @@ if (empty($row) || empty($row['physical_filename'])) {
if (empty($row['info_hash_v2'])) {
http_response_code(404);
die('Currently torrents with BitTorrent v2 support are enabled for file listing');
die($lang['BT_V2_FILE_LIST_ONLY']);
}
$file_path = get_attachments_dir() . '/' . $row['physical_filename'];
if(!is_file($file_path)){
die($lang['INVALID_ATTACH_ID']);
die($lang['TOR_NOT_FOUND']);
}
$file_contents = file_get_contents($file_path);
@ -39,29 +44,35 @@ if (!$tor = \Arokettu\Bencode\Bencode::decode($file_contents, dictType: \Arokett
die($lang['TORFILE_INVALID']);
}
if (isset($tor['info']['private']) && IS_GUEST) {
die($lang['BT_PRIVATE_TORRENT']);
}
$torrent = new TorrentPier\Legacy\TorrentFileList($tor);
$file_list = $torrent->fileTreeTable($tor['info']['file tree']);
$files = $torrent->fileTreeTable($tor['info']['file tree']);
$data = [
'date' => '',
'name' => htmlCHR($tor['info']['name'] ?? ''),
'client' => htmlCHR(substr($tor['created by'] ?? 'unknown client', 0, 20)),
'size' => humn_size($file_list['size'])
'size' => humn_size($files['size']),
'hash' => bin2hex($row['info_hash_v2'])
];
if (isset($tor['creation date']) && is_numeric($tor['creation date'])) {
$data['date'] = date("d M Y | G:i:s T", $tor['creation date']);
}
echo "<html>
echo <<<EOF
<html>
<head>
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />
<meta name=\"robots\" content=\"index, follow\">
<meta name=\"description\" content=\"File list for topic - $topic_id\">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="robots" content="index, follow">
<meta name="description" content="File list for topic - $topic_id">
<title>File list {$data['name']} ({$data['size']})</title>
<title>File information listing | {$data['name']} ({$data['size']}) | {$data['hash']}</title>
</head>
<body style=\"background-color: #1f1f1f; color: #ffffff;\">
<body style="background-color: #1f1f1f; color: #ffffff;">
<style>
table {
@ -69,7 +80,7 @@ echo "<html>
border-collapse: collapse;
width: auto;
margin: 20px auto;
font-family: -apple-system,BlinkMacSystemFont,\"Segoe UI\",\"Noto Sans\",Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\";
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
background-color: #2c2c2c;
color: #ffffff;
}
@ -96,18 +107,19 @@ echo "<html>
</style>
<center>
<h2 style = \"color: #b3b3b3;font-family: Monospace\">Document name: {$data['name']} | Date: ({$data['date']}) | Size: {$data['size']}
<h2 style="color: #b3b3b3;font-family: Monospace">Document name: {$data['name']} | Date: ({$data['date']}) | Size: {$data['size']}
</h2>
<p><i>Created by: {$data['client']}</i></p>
<hr>
<table><tr><th>Path</th><th>Size</th><th title=\"BitTorrent Merkle Root — The hash of the file, which is embedded in torrents with BitTorrent v2 support, tracker users can extract, calculate them, also deduplicate torrents using desktop tools such as Torrent Merkle Root Reader.\">Hash <sup>?</sup></th></tr>";
<table><tr><th>Path</th><th>Size</th><th title="BitTorrent Merkle Root — The hash of the file, which is embedded in torrents with BitTorrent v2 support, tracker users can extract, calculate them, also deduplicate torrents using desktop tools such as Torrent Merkle Root Reader.">Hash <sup>?</sup></th></tr>
EOF;
echo implode('', $file_list['list']);
echo $files['list'];
echo '</center>
</table>
<p>Generated by <a href = "https://github.com/torrentpier/torrentpier" target="_blank">TorrentPier</a></p>
<p><i style = "color: gray">Generated by</i> <a href = "https://github.com/torrentpier/torrentpier" target="_blank">TorrentPier</a></p>
</body>
</html>';

View file

@ -1060,6 +1060,7 @@ $lang['BT_REG_ON_TRACKER'] = 'Register on tracker';
$lang['BT_REG_FAIL'] = 'Could not register torrent on tracker';
$lang['BT_REG_FAIL_SAME_HASH'] = 'Another torrent with same info_hash already <a href="%s"><b>registered</b></a>';
$lang['BT_V2_ONLY_DISALLOWED'] = 'v2-only torrents have been disabled by the administrator at the moment, allowed: v1 and hybrids';
$lang['BT_V2_FILE_LIST_ONLY'] = 'Currently, only torrents with BitTorrent version 2 support are enabled for separate file listing';
$lang['BT_UNREG_FROM_TRACKER'] = 'Remove from tracker';
$lang['BT_UNREGISTERED'] = 'Torrent unregistered';
$lang['BT_UNREGISTERED_ALREADY'] = 'Torrent already unregistered';
@ -2321,6 +2322,8 @@ $lang['BT_ANNOUNCE_URL'] = 'Announce url';
$lang['BT_ANNOUNCE_URL_EXPL'] = 'you can define additional allowed urls in "includes/torrent_announce_urls.php"';
$lang['BT_DISABLE_DHT'] = 'Disable DHT network';
$lang['BT_DISABLE_DHT_EXPL'] = 'Disable Peer Exchange and DHT (recommended for private networks, only url announce)';
$lang['BT_PRIVATE_TRACKER'] = 'This tracker is private: file listing (for guests), DHT | PEX are disabled';
$lang['BT_PRIVATE_TORRENT'] = 'The creator of this torrent made it private';
$lang['BT_CHECK_ANNOUNCE_URL'] = 'Verify announce url';
$lang['BT_CHECK_ANNOUNCE_URL_EXPL'] = 'register on tracker only allowed urls';
$lang['BT_REPLACE_ANN_URL'] = 'Replace announce url';

View file

@ -44,7 +44,7 @@ class TorrentFileList
global $html;
if (($this->tor_decoded['info']['meta version'] ?? 1) === 2) {
if (is_array($this->tor_decoded['info']['file tree'] ?? null)) {
return $this->fileTreeList($this->tor_decoded['info']['file tree']); //v2
return $this->fileTreeList($this->tor_decoded['info']['file tree'], $this->tor_decoded['info']['name'] ?? ''); //v2
}
}
@ -139,24 +139,21 @@ class TorrentFileList
*/
public function fileTreeList(array $array, string $name = ''): string
{
$folders = [];
$rootFiles = [];
$allItems = '';
foreach ($array as $key => $value) {
$key = htmlCHR($key);
if (!isset($value[''])) {
$html_v2 = $this->fileTreeList($value);
$folders[] = "<li><span class=\"b\">$key</span><ul>$html_v2</ul></li>";
$allItems .= "<li><span class=\"b\">$key</span><ul>$html_v2</ul></li>";
} else {
$length = (int)$value['']['length'];
$root = bin2hex($value['']['pieces root'] ?? '');
$rootFiles[] = "<li><span>$key<i>$length</i><p>$root</p></span></li>";
$allItems .= "<li><span>$key<i>$length</i><p>$root</p></span></li>";
}
}
$allFiles = implode('', [...$folders, ...$rootFiles]);
return '<div class="tor-root-dir">' . (empty($folders) ? '' : htmlCHR($name)) . '</div><ul class="tree-root">' . $allFiles . '</ul>';
return '<div class="tor-root-dir">' . (empty($allItems) ? '' : htmlCHR($name)) . '</div><ul class="tree-root">' . $allItems . '</ul>';
}
/**
@ -168,8 +165,7 @@ class TorrentFileList
*/
public function fileTreeTable(array $array, string $parent = ''): array
{
$filesList = [];
$size = 0;
static $filesList = ['list' => '', 'size' => 0];
foreach ($array as $key => $value) {
$key = htmlCHR($key);
$current = "$parent/$key";
@ -178,14 +174,11 @@ class TorrentFileList
} else {
$length = (int)$value['']['length'];
$root = bin2hex($value['']['pieces root'] ?? '');
$size += $length;
$filesList[] = '<tr><td>' . $current . '</td><td>' . humn_size($length, 2) . '</td><td>' . $root . '</td></tr><tr>';
$filesList['size'] += $length;
$filesList['list'] .= '<tr><td>' . $current . '</td><td>' . humn_size($length, 2) . '</td><td>' . $root . '</td></tr><tr>';
}
}
return [
'list' => $filesList,
'size' => $size
];
return $filesList;
}
}