diff --git a/bt/announce.php b/bt/announce.php
index 8565c4aa3..ee70f9a2b 100644
--- a/bt/announce.php
+++ b/bt/announce.php
@@ -63,12 +63,22 @@ $passkey = ${$passkey_key} ?? null;
// Verify request
// Required params (info_hash, peer_id, port, uploaded, downloaded, left, passkey)
-if (!isset($info_hash) || strlen($info_hash) != 20) {
- msg_die('Invalid info_hash');
+if (!isset($info_hash)) {
+ msg_die('info_hash does not exists');
}
if (!isset($peer_id) || strlen($peer_id) != 20) {
msg_die('Invalid peer_id');
}
+
+// Check info_hash version
+if (strlen($info_hash) == 32) {
+ $is_bt_v2 = true;
+} elseif (strlen($info_hash) == 20) {
+ $is_bt_v2 = false;
+} else {
+ msg_die('Invalid info_hash');
+}
+
if (!isset($port) || $port < 0 || $port > 0xFFFF) {
msg_die('Invalid port');
}
@@ -178,13 +188,14 @@ if ($lp_info) {
} else {
// Verify if torrent registered on tracker and user authorized
$info_hash_sql = rtrim(DB()->escape($info_hash), ' ');
+ $info_hash_where = $is_bt_v2 ? "WHERE tor.info_hash_v2 = '$info_hash_sql'" : "WHERE tor.info_hash = '$info_hash_sql'";
$passkey_sql = DB()->escape($passkey);
$sql = "
SELECT tor.topic_id, tor.poster_id, tor.tor_type, u.*
FROM " . BB_BT_TORRENTS . " tor
LEFT JOIN " . BB_BT_USERS . " u ON u.auth_key = '$passkey_sql'
- WHERE tor.info_hash = '$info_hash_sql'
+ $info_hash_where
LIMIT 1
";
diff --git a/bt/scrape.php b/bt/scrape.php
index 81e7cbbce..af6128941 100644
--- a/bt/scrape.php
+++ b/bt/scrape.php
@@ -22,11 +22,21 @@ if (isset($_GET['?info_hash']) && !isset($_GET['info_hash'])) {
$_GET['info_hash'] = $_GET['?info_hash'];
}
-if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20) {
- msg_die('Invalid info_hash');
+$is_bt_v2 = null;
+$info_hash = isset($_GET['info_hash']) ? (string)$_GET['info_hash'] : null;
+
+if (!isset($info_hash)) {
+ msg_die('info_hash does not exists');
}
-$info_hash = $_GET['info_hash'];
+// Check info_hash version
+if (strlen($info_hash) == 32) {
+ $is_bt_v2 = true;
+} elseif (strlen($info_hash) == 20) {
+ $is_bt_v2 = false;
+} else {
+ msg_die('Invalid info_hash');
+}
function msg_die($msg)
{
@@ -42,15 +52,20 @@ function msg_die($msg)
require __DIR__ . '/includes/init_tr.php';
$info_hash_sql = rtrim(DB()->escape($info_hash), ' ');
+$info_hash_where = $is_bt_v2 ? "WHERE tor.info_hash_v2 = '$info_hash_sql'" : "WHERE tor.info_hash = '$info_hash_sql'";
$row = DB()->fetch_row("
SELECT tor.complete_count, snap.seeders, snap.leechers
FROM " . BB_BT_TORRENTS . " tor
LEFT JOIN " . BB_BT_TRACKER_SNAP . " snap ON (snap.topic_id = tor.topic_id)
- WHERE tor.info_hash = '$info_hash_sql'
+ $info_hash_where
LIMIT 1
");
+if (!$row) {
+ msg_die('Torrent not registered, info_hash = ' . bin2hex($info_hash_sql));
+}
+
$output['files'][$info_hash] = [
'complete' => (int)$row['seeders'],
'downloaded' => (int)$row['complete_count'],
diff --git a/install/sql/mysql.sql b/install/sql/mysql.sql
index cc4d91eea..d93b6dbab 100644
--- a/install/sql/mysql.sql
+++ b/install/sql/mysql.sql
@@ -274,6 +274,7 @@ DROP TABLE IF EXISTS `bb_bt_torrents`;
CREATE TABLE IF NOT EXISTS `bb_bt_torrents`
(
`info_hash` VARBINARY(20) NOT NULL DEFAULT '',
+ `info_hash_v2` VARBINARY(32) NOT NULL DEFAULT '',
`post_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0',
`poster_id` MEDIUMINT(9) NOT NULL DEFAULT '0',
`topic_id` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0',
diff --git a/install/upgrade/changes.txt b/install/upgrade/changes.txt
index c7aa1c8e7..e4cf6d56a 100644
--- a/install/upgrade/changes.txt
+++ b/install/upgrade/changes.txt
@@ -67,3 +67,4 @@ INSERT INTO `bb_cron` (`cron_active`, `cron_title`, `cron_script`, `schedule`, `
`disable_board`, `run_counter`) VALUES ('1', 'PM cleanup', 'clean_pm.php', 'daily', '', '05:00:00', '70', '', '', '', '1', '', '0', '1', '0');
ALTER TABLE `bb_posts_text` CHANGE `post_text` `post_text` MEDIUMTEXT NOT NULL;
ALTER TABLE `bb_privmsgs_text` CHANGE `privmsgs_text` `privmsgs_text` MEDIUMTEXT NOT NULL;
+ALTER TABLE `bb_bt_torrents` ADD COLUMN `info_hash_v2` VARBINARY(32) NOT NULL DEFAULT '';
diff --git a/library/attach_mod/displaying_torrent.php b/library/attach_mod/displaying_torrent.php
index ed08a4910..9ca1548dd 100644
--- a/library/attach_mod/displaying_torrent.php
+++ b/library/attach_mod/displaying_torrent.php
@@ -155,7 +155,7 @@ if ($tor_reged && $tor_info) {
$tor_type = $tor_info['tor_type'];
// Magnet link
- $tor_magnet = create_magnet($tor_info['info_hash'], $user_passkey);
+ $tor_magnet = create_magnet($tor_info['info_hash'], $tor_info['info_hash_v2'], $user_passkey);
// ratio limits
$min_ratio_dl = $bb_cfg['bt_min_ratio_allow_dl_tor'];
diff --git a/library/includes/functions.php b/library/includes/functions.php
index 91dab9e6b..451c7cb56 100644
--- a/library/includes/functions.php
+++ b/library/includes/functions.php
@@ -1760,11 +1760,12 @@ function decode_text_match($txt)
* Create magnet link
*
* @param string $infohash
+ * @param string $infohash_v2
* @param string|bool $auth_key
*
* @return string
*/
-function create_magnet($infohash, $auth_key): string
+function create_magnet(string $infohash, string $infohash_v2, $auth_key): string
{
global $bb_cfg, $images;
@@ -1778,7 +1779,7 @@ function create_magnet($infohash, $auth_key): string
return false;
}
- return '';
+ return '
';
}
function set_die_append_msg($forum_id = null, $topic_id = null, $group_id = null)
diff --git a/src/Legacy/Torrent.php b/src/Legacy/Torrent.php
index 43000b065..aeb956854 100644
--- a/src/Legacy/Torrent.php
+++ b/src/Legacy/Torrent.php
@@ -287,7 +287,8 @@ class Torrent
$topic_id = $torrent['topic_id'];
$forum_id = $torrent['forum_id'];
$poster_id = $torrent['poster_id'];
- $info_hash = null;
+ $info_hash = $info_hash_v2 = null;
+ $info_hash_sql = $info_hash_v2_sql = null;
if ($torrent['extension'] !== TORRENT_EXT) {
return self::torrent_error_exit($lang['NOT_TORRENT']);
@@ -345,10 +346,23 @@ class Torrent
return self::torrent_error_exit($lang['TORFILE_INVALID']);
}
+ // Check if torrent contains info_hash v2
+ $bt_v2 = false;
+ if (($info['meta version'] ?? null) == 2 && is_array($info['file tree'] ?? null)) {
+ $bt_v2 = true;
+ }
+
+ // Getting info_hash v1
$info_hash = pack('H*', sha1(\SandFox\Bencode\Bencode::encode($info)));
$info_hash_sql = rtrim(DB()->escape($info_hash), ' ');
$info_hash_md5 = md5($info_hash);
+ // Getting info_hash v2
+ if ($bt_v2) {
+ $info_hash_v2 = pack('H*', hash('sha256', \SandFox\Bencode\Bencode::encode($info)));
+ $info_hash_v2_sql = rtrim(DB()->escape($info_hash_v2), ' ');
+ }
+
// Ocelot
if ($bb_cfg['ocelot']['enabled']) {
self::ocelot_update_tracker('add_torrent', ['info_hash' => rawurlencode($info_hash), 'id' => $topic_id, 'freetorrent' => 0]);
@@ -366,7 +380,10 @@ class Torrent
$totallen = (float)$info['length'];
} elseif (isset($info['files']) && \is_array($info['files'])) {
foreach ($info['files'] as $fn => $f) {
- $totallen += (float)$f['length'];
+ // Exclude padding files
+ if (($f['attr'] ?? null) !== 'p') {
+ $totallen += (float)$f['length'];
+ }
}
} else {
return self::torrent_error_exit($lang['TORFILE_INVALID']);
@@ -374,8 +391,8 @@ class Torrent
$size = sprintf('%.0f', (float)$totallen);
- $columns = ' info_hash, post_id, poster_id, topic_id, forum_id, attach_id, size, reg_time, tor_status';
- $values = "'$info_hash_sql', $post_id, $poster_id, $topic_id, $forum_id, $attach_id, '$size', $reg_time, $tor_status";
+ $columns = 'info_hash, info_hash_v2, post_id, poster_id, topic_id, forum_id, attach_id, size, reg_time, tor_status';
+ $values = "'$info_hash_sql', '$info_hash_v2_sql', $post_id, $poster_id, $topic_id, $forum_id, $attach_id, '$size', $reg_time, $tor_status";
$sql = "INSERT INTO " . BB_BT_TORRENTS . " ($columns) VALUES ($values)";
diff --git a/src/Legacy/TorrentFileList.php b/src/Legacy/TorrentFileList.php
index c3b9d1bcc..b9bc54ac7 100644
--- a/src/Legacy/TorrentFileList.php
+++ b/src/Legacy/TorrentFileList.php
@@ -43,18 +43,45 @@ class TorrentFileList
{
global $html;
- $this->build_filelist_array();
+ if (($this->tor_decoded['info']['meta version'] ?? null) == 2 && is_array($this->tor_decoded['info']['file tree'] ?? null)) {
+ // v2
+ function fileTree($array, $name = '')
+ {
+ $folders = [];
+ $rootFiles = [];
- if ($this->multiple) {
- if ($this->files_ary['/'] !== '') {
- $this->files_ary = array_merge($this->files_ary, $this->files_ary['/']);
- unset($this->files_ary['/']);
+ foreach ($array as $key => $value) {
+ if (is_array($value) && !isset($value[''])) {
+ $html_v2 = fileTree($value);
+ $folders[] = "