Timeline — 2.4.1 (#1340)
|
@ -82,7 +82,7 @@ if (!isset($info_hash)) {
|
|||
$info_hash_hex = bin2hex($info_hash);
|
||||
|
||||
// Store peer id
|
||||
$peer_id_sql = rtrim(DB()->escape(preg_replace('/[^a-zA-Z0-9\-\_]/', '', $peer_id)), ' ');
|
||||
$peer_id_sql = preg_replace('/[^a-zA-Z0-9\-\_]/', '', $peer_id);
|
||||
|
||||
// Check info_hash length
|
||||
if (strlen($info_hash) !== 20) {
|
||||
|
@ -108,17 +108,15 @@ if (!isset($left) || $left < 0) {
|
|||
// IP
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
// 'ip' query handling
|
||||
if (!$bb_cfg['ignore_reported_ip'] && isset($_GET['ip']) && $ip !== $_GET['ip']) {
|
||||
if (!$bb_cfg['verify_reported_ip']) {
|
||||
$ip = $_GET['ip'];
|
||||
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
|
||||
foreach ($matches[0] as $x_ip) {
|
||||
if ($x_ip === $_GET['ip']) {
|
||||
if (!$bb_cfg['allow_internal_ip'] && preg_match("#(127\.([0-9]{1,3}\.){2}[0-9]{1,3}|10\.([0-9]{1,3}\.){2}[0-9]{1,3}|172\.[123][0-9]\.[0-9]{1,3}\.[0-9]{1,3}|192\.168\.[0-9]{1,3}\.[0-9]{1,3})#", $x_ip)) {
|
||||
break;
|
||||
}
|
||||
$ip = $x_ip;
|
||||
break;
|
||||
if (!$bb_cfg['verify_reported_ip'] && isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$x_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
|
||||
if ($x_ip === $_GET['ip']) {
|
||||
$filteredIp = filter_var($x_ip, FILTER_VALIDATE_IP);
|
||||
if ($filteredIp !== false && ($bb_cfg['allow_internal_ip'] || !filter_var($filteredIp, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))) {
|
||||
$ip = $filteredIp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +214,12 @@ if ($lp_info) {
|
|||
|
||||
// Check hybrid status
|
||||
if (!empty($row['info_hash']) && !empty($row['info_hash_v2'])) {
|
||||
if ($info_hash !== $row['info_hash']) { // Change this to substr($row['info_hash_v2'], 0, 20) in the future for updating statistics, in case of v2 torrents being prioritized.
|
||||
$stat_protocol = match($bb_cfg['tracker']['hybrid_stat_protocol']) {
|
||||
1 => $row['info_hash'],
|
||||
2 => substr($row['info_hash_v2'], 0, 20),
|
||||
default => $row['info_hash']
|
||||
};
|
||||
if ($info_hash !== $stat_protocol) {
|
||||
$hybrid_unrecord = true; // This allows us to announce only for one info-hash
|
||||
}
|
||||
}
|
||||
|
@ -450,7 +453,6 @@ if (!$output) {
|
|||
|
||||
$output = [
|
||||
'interval' => (int)$announce_interval,
|
||||
'min interval' => (int)$announce_interval,
|
||||
'complete' => (int)$seeders,
|
||||
'incomplete' => (int)$leechers,
|
||||
'downloaded' => (int)$client_completed,
|
||||
|
|
|
@ -44,7 +44,7 @@ date_default_timezone_set('UTC');
|
|||
// Set remote address
|
||||
$allowedCDNs = ['HTTP_X_FORWARDED_FOR', 'HTTP_FASTLY_CLIENT_IP', 'HTTP_CF_CONNECTING_IP'];
|
||||
foreach ($allowedCDNs as $allowedCDN) {
|
||||
if (isset($_SERVER[$allowedCDN]) && filter_var($_SERVER[$allowedCDN], FILTER_VALIDATE_IP)) {
|
||||
if (isset($_SERVER[$allowedCDN]) && filter_var($_SERVER[$allowedCDN], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||
$_SERVER['REMOTE_ADDR'] = $_SERVER[$allowedCDN];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"arokettu/bencode": "^4.1.0",
|
||||
"arokettu/torrent-file": "^5.2.1",
|
||||
"bugsnag/bugsnag": "^v3.29.1",
|
||||
"claviska/simpleimage": "^4.0",
|
||||
"egulias/email-validator": "^4.0.1",
|
||||
|
|
50
filelist.php
|
@ -35,9 +35,10 @@ if (empty($row) || empty($row['physical_filename'])) {
|
|||
bb_simple_die($lang['INVALID_TOPIC_ID_DB'], 404);
|
||||
}
|
||||
|
||||
if (empty($row['info_hash_v2'])) {
|
||||
bb_simple_die($lang['BT_V2_FLIST_ONLY'], 410);
|
||||
}
|
||||
// Method fields
|
||||
$t_version_field = !empty($row['info_hash_v2']) ? 'v2' : 'v1';
|
||||
$t_files_field = ($t_version_field === 'v2') ? 'getFileTree' : 'getFiles';
|
||||
$t_hash_field = ($t_version_field === 'v2') ? 'piecesRoot' : 'sha1';
|
||||
|
||||
$file_path = get_attachments_dir() . '/' . $row['physical_filename'];
|
||||
|
||||
|
@ -48,32 +49,44 @@ if (!is_file($file_path)) {
|
|||
$file_contents = file_get_contents($file_path);
|
||||
|
||||
if ($bb_cfg['flist_max_files']) {
|
||||
$filetree_pos = strpos($file_contents, '9:file tree');
|
||||
$filetree_pos = !empty($row['info_hash_v2']) ? strpos($file_contents, '9:file tree') : false;
|
||||
$files_pos = !empty($row['info_hash']) ? strpos($file_contents, '5:files', $filetree_pos) : false;
|
||||
$file_count = substr_count($file_contents, '6:length', $filetree_pos, ($files_pos ? ($files_pos - $filetree_pos) : null));
|
||||
|
||||
if ($filetree_pos) {
|
||||
$file_count = substr_count($file_contents, '6:length', $filetree_pos, ($files_pos ? ($files_pos - $filetree_pos) : null));
|
||||
}
|
||||
else {
|
||||
$file_count = substr_count($file_contents, '6:length', $files_pos);
|
||||
}
|
||||
|
||||
if ($file_count > $bb_cfg['flist_max_files']) {
|
||||
bb_simple_die(sprintf($lang['BT_V2_FLIST_LIMIT'], $bb_cfg['flist_max_files'], $file_count), 410);
|
||||
bb_simple_die(sprintf($lang['BT_FLIST_LIMIT'], $bb_cfg['flist_max_files'], $file_count), 410);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$torrent = \Arokettu\Bencode\Bencode::decode($file_contents, dictType: \Arokettu\Bencode\Bencode\Collection::ARRAY);
|
||||
$torrent = \Arokettu\Torrent\TorrentFile::loadFromString($file_contents);
|
||||
} catch (\Exception $e) {
|
||||
bb_simple_die(htmlCHR("{$lang['TORFILE_INVALID']}: {$e->getMessage()}"), 410);
|
||||
}
|
||||
|
||||
if (isset($torrent['info']['private']) && IS_GUEST) {
|
||||
if ($torrent->isPrivate() && IS_GUEST) {
|
||||
bb_simple_die($lang['BT_PRIVATE_TORRENT'], 403);
|
||||
}
|
||||
|
||||
$files = (new TorrentPier\Legacy\TorrentFileList($torrent))->fileTreeTable($torrent['info']['file tree']);
|
||||
$files = $torrent->$t_version_field()->$t_files_field();
|
||||
|
||||
$allFiles = '';
|
||||
foreach ($files as $file) {
|
||||
$allFiles .= '<tr><td>' . clean_tor_dirname(implode('/', $file->path)) . '</td><td>' . humn_size($file->length, 2) . '</td><td>' . ($t_hash_field === 'sha1' ? 'SHA1: ' : '') . $file->$t_hash_field . '</td></tr><tr>';
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => isset($torrent['info']['name']) ? htmlCHR(substr($torrent['info']['name'], 0, 255)) : 'undefined',
|
||||
'client' => isset($torrent['created by']) ? htmlCHR(substr($torrent['created by'], 0, 20)) : 'unknown client',
|
||||
'date' => (isset($torrent['creation date']) && is_numeric($torrent['creation date'])) ? date('d-M-Y H:i (e)', $torrent['creation date']) : 'unknown',
|
||||
'size' => humn_size($row['size']),
|
||||
'name' => !empty($t_name = $torrent->getName()) ? htmlCHR(substr($t_name, 0, 255)) : 'undefined',
|
||||
'client' => !empty($creator = $torrent->getCreatedBy()) ? htmlCHR(substr($creator, 0, 20)) : 'unknown client',
|
||||
'date' => (!empty($creation_date = $torrent->getCreationDate()->getTimestamp()) && is_numeric($creation_date)) ? date('d-M-Y H:i (e)', $creation_date) : 'unknown',
|
||||
'size' => humn_size($row['size'], 2),
|
||||
'file_count' => count($files),
|
||||
'site_url' => FULL_URL,
|
||||
'topic_url' => TOPIC_URL . $topic_id,
|
||||
];
|
||||
|
@ -174,7 +187,7 @@ sup {
|
|||
<hr>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Path ({$files['count']} files)</th>
|
||||
<th>Path ({$data['file_count']} files)</th>
|
||||
<th>Size</th>
|
||||
<th class="tooltip" style="width: auto;">
|
||||
BTMR hash
|
||||
|
@ -186,15 +199,12 @@ sup {
|
|||
</sup>
|
||||
</th>
|
||||
</tr>
|
||||
EOF;
|
||||
|
||||
echo $files['list'];
|
||||
|
||||
echo '
|
||||
$allFiles
|
||||
</table>
|
||||
<p style = "color: gray; font-family: Calibri Light">Generated by <a href = "https://github.com/torrentpier/torrentpier" target="_blank" title = "Bull-powered BitTorrent tracker engine">TorrentPier</a></p>
|
||||
</center>
|
||||
</body>
|
||||
</html>';
|
||||
</html>
|
||||
EOF;
|
||||
|
||||
die();
|
||||
|
|
|
@ -27,32 +27,41 @@ if (!$topic_id = (int)$this->request['topic_id']) {
|
|||
|
||||
switch ($mode) {
|
||||
case 'add':
|
||||
if (DB()->fetch_row('SELECT poster_id FROM ' . BB_BT_TORRENTS . " WHERE topic_id = $topic_id AND poster_id = " . $userdata['user_id'])) {
|
||||
$this->ajax_die($lang['LIKE_OWN_POST']);
|
||||
}
|
||||
if (!IS_GUEST) {
|
||||
if (DB()->fetch_row('SELECT poster_id FROM ' . BB_BT_TORRENTS . " WHERE topic_id = $topic_id AND poster_id = " . $userdata['user_id'])) {
|
||||
$this->ajax_die($lang['LIKE_OWN_POST']);
|
||||
}
|
||||
|
||||
if (DB()->fetch_row('SELECT topic_id FROM ' . BB_THX . " WHERE topic_id = $topic_id AND user_id = " . $userdata['user_id'])) {
|
||||
$this->ajax_die($lang['LIKE_ALREADY']);
|
||||
}
|
||||
if (DB()->fetch_row('SELECT topic_id FROM ' . BB_THX . " WHERE topic_id = $topic_id AND user_id = " . $userdata['user_id'])) {
|
||||
$this->ajax_die($lang['LIKE_ALREADY']);
|
||||
}
|
||||
|
||||
$columns = 'topic_id, user_id, time';
|
||||
$values = "$topic_id, {$userdata['user_id']}, " . TIMENOW;
|
||||
DB()->query('INSERT IGNORE INTO ' . BB_THX . " ($columns) VALUES ($values)");
|
||||
break;
|
||||
$columns = 'topic_id, user_id, time';
|
||||
$values = "$topic_id, {$userdata['user_id']}, " . TIMENOW;
|
||||
DB()->query('INSERT IGNORE INTO ' . BB_THX . " ($columns) VALUES ($values)");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
$this->ajax_die($lang['NEED_TO_LOGIN_FIRST']);
|
||||
}
|
||||
|
||||
case 'get':
|
||||
$sql = DB()->fetch_rowset('SELECT u.username, u.user_rank, u.user_id, t.* FROM ' . BB_THX . ' t, ' . BB_USERS . " u WHERE t.topic_id = $topic_id AND t.user_id = u.user_id");
|
||||
if (!IS_GUEST || $bb_cfg['tor_thanks_list_guests']) {
|
||||
$sql = DB()->fetch_rowset('SELECT u.username, u.user_rank, u.user_id, t.* FROM ' . BB_THX . ' t, ' . BB_USERS . " u WHERE t.topic_id = $topic_id AND t.user_id = u.user_id");
|
||||
|
||||
$user_list = [];
|
||||
foreach ($sql as $row) {
|
||||
$user_list[] = '<b>' . profile_url($row) . ' <i>(' . bb_date($row['time']) . ')</i></b>';
|
||||
$user_list = [];
|
||||
foreach ($sql as $row) {
|
||||
$user_list[] = '<b>' . profile_url($row) . ' <i>(' . bb_date($row['time']) . ')</i></b>';
|
||||
}
|
||||
|
||||
$this->response['html'] = join(', ', $user_list) ?: $lang['NO_LIKES'];
|
||||
break;
|
||||
}
|
||||
|
||||
$this->response['html'] = join(', ', $user_list) ?: $lang['NO_LIKES'];
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->ajax_die('Invalid mode: ' . $mode);
|
||||
else {
|
||||
$this->ajax_die($lang['NEED_TO_LOGIN_FIRST']);
|
||||
}
|
||||
default:
|
||||
$this->ajax_die('Invalid mode: ' . $mode);
|
||||
}
|
||||
|
||||
$this->response['mode'] = $mode;
|
||||
|
|
|
@ -217,10 +217,10 @@ if ($tor_reged && $tor_info) {
|
|||
'MAGNET' => $tor_magnet,
|
||||
'HASH' => !empty($tor_info['info_hash']) ? strtoupper(bin2hex($tor_info['info_hash'])) : false,
|
||||
'HASH_V2' => !empty($tor_info['info_hash_v2']) ? strtoupper(bin2hex($tor_info['info_hash_v2'])) : false,
|
||||
'FILELIST_LINK' => !empty($tor_info['info_hash_v2']) ? (FILELIST_URL . $tor_info['topic_id']) : false,
|
||||
'FILELIST_LINK' => FILELIST_URL . $tor_info['topic_id'],
|
||||
'REGED_TIME' => bb_date($tor_info['reg_time']),
|
||||
'REGED_DELTA' => delta_time($tor_info['reg_time']),
|
||||
'TORRENT_SIZE' => humn_size($tor_size),
|
||||
'TORRENT_SIZE' => humn_size($tor_size, 2),
|
||||
'DOWNLOAD_COUNT' => $download_count,
|
||||
'COMPLETED' => $tor_completed_count,
|
||||
]);
|
||||
|
@ -235,7 +235,7 @@ if ($tor_reged && $tor_info) {
|
|||
'SHOW_DL_LIST' => true,
|
||||
'SHOW_DL_LIST_TOR_INFO' => true,
|
||||
|
||||
'TOR_SIZE' => humn_size($tor_size),
|
||||
'TOR_SIZE' => humn_size($tor_size, 1),
|
||||
'TOR_LONGEVITY' => delta_time($tor_info['reg_time']),
|
||||
'TOR_DOWNLOAD_COUNT' => $download_count,
|
||||
'TOR_COMPLETED' => $tor_completed_count,
|
||||
|
@ -282,7 +282,7 @@ if ($tor_reged && $tor_info) {
|
|||
WHERE topic_id = $tor_id
|
||||
LIMIT 1";
|
||||
} elseif ($s_mode == 'names') {
|
||||
$sql = "SELECT tr.user_id, tr.ip, tr.port, tr.remain, tr.seeder, u.username, u.user_rank
|
||||
$sql = "SELECT tr.user_id, tr.ip, tr.ipv6, tr.port, tr.remain, tr.seeder, u.username, u.user_rank
|
||||
FROM " . BB_BT_TRACKER . " tr, " . BB_USERS . " u
|
||||
WHERE tr.topic_id = $tor_id
|
||||
AND u.user_id = tr.user_id
|
||||
|
@ -290,7 +290,7 @@ if ($tor_reged && $tor_info) {
|
|||
LIMIT $show_peers_limit";
|
||||
} else {
|
||||
$sql = "SELECT
|
||||
tr.user_id, tr.ip, tr.port, tr.peer_id, tr.uploaded, tr.downloaded, tr.remain,
|
||||
tr.user_id, tr.ip, tr.ipv6, tr.port, tr.peer_id, tr.uploaded, tr.downloaded, tr.remain,
|
||||
tr.seeder, tr.releaser, tr.speed_up, tr.speed_down, tr.update_time,
|
||||
tr.complete_percent, u.username, u.user_rank
|
||||
FROM " . BB_BT_TRACKER . " tr
|
||||
|
@ -373,7 +373,12 @@ if ($tor_reged && $tor_info) {
|
|||
|
||||
// Full details mode
|
||||
if ($s_mode == 'full') {
|
||||
$ip = bt_show_ip($peer['ip']);
|
||||
if (!empty($peer['ip']) && !empty($peer['ipv6'])) {
|
||||
$ip = bt_show_ip($peer['ipv6']) . ' (' . bt_show_ip($peer['ip']) . ')';
|
||||
}
|
||||
else {
|
||||
$ip = bt_show_ip(!empty($peer['ipv6']) ? $peer['ipv6'] : $peer['ip']);
|
||||
}
|
||||
$port = bt_show_port($peer['port']);
|
||||
|
||||
// peer max/current up/down
|
||||
|
|
|
@ -528,6 +528,7 @@ $bb_cfg['user_not_active_days_keep'] = 180; // After how many days should I dele
|
|||
|
||||
// Vote for torrents
|
||||
$bb_cfg['tor_thank'] = true;
|
||||
$bb_cfg['tor_thanks_list_guests'] = true; // Show voters to guests
|
||||
|
||||
// Groups
|
||||
$bb_cfg['group_members_per_page'] = 50; // How many groups will be displayed in a page
|
||||
|
@ -682,7 +683,8 @@ $bb_cfg['tracker'] = [
|
|||
'search_by_tor_status' => true,
|
||||
'freeleech' => false, // freeleech mode (If enabled, then disable "gold_silver_enabled")
|
||||
'gold_silver_enabled' => true, // golden / silver days mode (If enabled, then disable "freeleech")
|
||||
'disabled_v1_torrents' => false, // disallow registration of v1-only torrents, for future implementations where client will use v2 only and there won't be need for v1, relieving tracker
|
||||
'hybrid_stat_protocol' => 1, // For hybrid torrents there are two identical requests sent by clients, for counting stats we gotta choose one, you can change this to '2' in future, when v1 protocol is outdated
|
||||
'disabled_v1_torrents' => false, // disallow registration of v1-only torrents, for future implementations where client will use v2 only and there won't be need for v1, thus relieving tracker
|
||||
'disabled_v2_torrents' => false // disallow registration of v2-only torrents
|
||||
];
|
||||
|
||||
|
|
|
@ -1327,6 +1327,7 @@ function render_flag(string $code): string
|
|||
'GN' => 'Guinea',
|
||||
'GP' => 'Guadeloupe',
|
||||
'GQ' => 'Equatorial Guinea',
|
||||
'GR3' => 'German Reich (3rd)',
|
||||
'GR' => 'Greece',
|
||||
'GS' => 'South Georgia and the South Sandwich Islands',
|
||||
'GT' => 'Guatemala',
|
||||
|
|
|
@ -1075,8 +1075,7 @@ $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_V1_ONLY_DISALLOWED'] = 'v1-only torrents have been disabled by the administrator at the moment, allowed: v2 and hybrids';
|
||||
$lang['BT_V2_ONLY_DISALLOWED'] = 'v2-only torrents have been disabled by the administrator at the moment, allowed: v1 and hybrids';
|
||||
$lang['BT_V2_FLIST_ONLY'] = 'Currently, only torrents with BitTorrent version 2 support are enabled for separate file listing';
|
||||
$lang['BT_V2_FLIST_LIMIT'] = 'Tracker settings do not allow to process lists with more than %d files. Current number is: %d';
|
||||
$lang['BT_FLIST_LIMIT'] = 'Tracker settings do not allow to process lists with more than %d files. Current number is: %d';
|
||||
$lang['BT_UNREG_FROM_TRACKER'] = 'Remove from tracker';
|
||||
$lang['BT_UNREGISTERED'] = 'Torrent unregistered';
|
||||
$lang['BT_UNREGISTERED_ALREADY'] = 'Torrent already unregistered';
|
||||
|
|
|
@ -38,10 +38,10 @@ class Ajax
|
|||
'passkey' => ['user'],
|
||||
'change_torrent' => ['user'],
|
||||
'change_tor_status' => ['user'],
|
||||
'thx' => ['user'],
|
||||
'manage_group' => ['user'],
|
||||
'callseed' => ['user'],
|
||||
|
||||
'thx' => ['guest'],
|
||||
'view_post' => ['guest'],
|
||||
'view_torrent' => ['guest'],
|
||||
'user_register' => ['guest'],
|
||||
|
|
|
@ -569,6 +569,13 @@ class User
|
|||
return;
|
||||
} // prevent multiple calling
|
||||
|
||||
if (IS_GUEST && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { // Apply browser language
|
||||
$http_accept_language = locale_get_primary_language(locale_accept_from_http($_SERVER['HTTP_ACCEPT_LANGUAGE']));
|
||||
if (isset($bb_cfg['lang'][$http_accept_language])) {
|
||||
$bb_cfg['default_lang'] = $http_accept_language;
|
||||
}
|
||||
}
|
||||
|
||||
\define('DEFAULT_LANG_DIR', LANG_ROOT_DIR . '/' . $bb_cfg['default_lang'] . '/');
|
||||
\define('SOURCE_LANG_DIR', LANG_ROOT_DIR . '/source/');
|
||||
|
||||
|
|
|
@ -401,7 +401,7 @@ class Torrent
|
|||
} elseif (isset($bt_v1, $info['files']) && !isset($bt_v2) && \is_array($info['files'])) {
|
||||
foreach ($info['files'] as $fn => $f) {
|
||||
// Exclude padding files
|
||||
if (($f['attr'] ?? null) !== 'p') {
|
||||
if (!isset($f['attr']) || $f['attr'] !== 'p') {
|
||||
if (isset($f['length']) && is_numeric($f['length'])) {
|
||||
$totallen += $f['length'];
|
||||
} else {
|
||||
|
|
|
@ -80,7 +80,7 @@ class TorrentFileList
|
|||
}
|
||||
|
||||
if (isset($info['files']) && \is_array($info['files'])) {
|
||||
$this->root_dir = isset($info['name']) ? '../' . clean_tor_dirname($info['name']) : '...';
|
||||
$this->root_dir = isset($info['name']) ? clean_tor_dirname($info['name']) : '...';
|
||||
$this->multiple = true;
|
||||
|
||||
foreach ($info['files'] as $f) {
|
||||
|
@ -174,30 +174,4 @@ class TorrentFileList
|
|||
|
||||
return $allItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Table generation for BitTorrent v2 compatible torrents
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $parent
|
||||
* @return array
|
||||
*/
|
||||
public function fileTreeTable(array $array, string $parent = ''): array
|
||||
{
|
||||
static $filesList = ['list' => '', 'count' => 0];
|
||||
foreach ($array as $key => $value) {
|
||||
$key = clean_tor_dirname($key);
|
||||
$current = "$parent/$key";
|
||||
if (!isset($value[''])) {
|
||||
$this->fileTreeTable($value, $current);
|
||||
} else {
|
||||
$length = $value['']['length'];
|
||||
$root = bin2hex($value['']['pieces root'] ?? '');
|
||||
$filesList['list'] .= '<tr><td>' . $current . '</td><td>' . humn_size($length, 2) . '</td><td>' . $root . '</td></tr><tr>';
|
||||
$filesList['count']++;
|
||||
}
|
||||
}
|
||||
|
||||
return $filesList;
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 266 B |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 743 B After Width: | Height: | Size: 743 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 237 B After Width: | Height: | Size: 237 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 556 B After Width: | Height: | Size: 556 B |
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 501 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 628 B After Width: | Height: | Size: 628 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 302 B After Width: | Height: | Size: 302 B |
Before Width: | Height: | Size: 353 B After Width: | Height: | Size: 353 B |
Before Width: | Height: | Size: 283 B After Width: | Height: | Size: 283 B |
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 499 B After Width: | Height: | Size: 499 B |
Before Width: | Height: | Size: 231 B After Width: | Height: | Size: 231 B |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 557 B After Width: | Height: | Size: 557 B |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 582 B After Width: | Height: | Size: 582 B |
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 264 B |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 642 B |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 334 B |
Before Width: | Height: | Size: 910 B After Width: | Height: | Size: 910 B |
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 687 B |
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 470 B |
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 277 B After Width: | Height: | Size: 277 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 552 B After Width: | Height: | Size: 552 B |
Before Width: | Height: | Size: 840 B After Width: | Height: | Size: 840 B |
Before Width: | Height: | Size: 813 B After Width: | Height: | Size: 813 B |
Before Width: | Height: | Size: 286 B After Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 289 B |
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 610 B After Width: | Height: | Size: 610 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 687 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 225 B After Width: | Height: | Size: 225 B |
Before Width: | Height: | Size: 224 B After Width: | Height: | Size: 224 B |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 585 B After Width: | Height: | Size: 585 B |
Before Width: | Height: | Size: 236 B After Width: | Height: | Size: 236 B |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 294 B After Width: | Height: | Size: 294 B |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 333 B After Width: | Height: | Size: 333 B |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 804 B After Width: | Height: | Size: 804 B |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 446 B After Width: | Height: | Size: 446 B |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 234 B After Width: | Height: | Size: 234 B |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 771 B After Width: | Height: | Size: 771 B |
Before Width: | Height: | Size: 555 B After Width: | Height: | Size: 555 B |
Before Width: | Height: | Size: 231 B After Width: | Height: | Size: 231 B |
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |