From de00055c6ac3ebefcbe7f81d6bdcb6f7f067c006 Mon Sep 17 00:00:00 2001 From: Roman Kelesidis Date: Sun, 27 Aug 2023 23:26:05 +0700 Subject: [PATCH] =?UTF-8?q?BitTorrent=20v2=20support=20=F0=9F=90=B8=20(#23?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * BitTorrent v2 support 🐸 * Update scrape.php --- bt/announce.php | 22 +++++++++++-- bt/scrape.php | 33 +++++++++++++++++-- install/sql/mysql.sql | 1 + install/upgrade/changes.txt | 3 ++ library/ajax/view_torrent.php | 5 +++ library/attach_mod/displaying_torrent.php | 3 +- library/includes/functions.php | 23 ++++++++++--- library/includes/functions_torrent.php | 28 +++++++++++++--- styles/templates/default/tracker.tpl | 2 +- styles/templates/default/viewtopic_attach.tpl | 5 +-- tracker.php | 6 ++-- viewforum.php | 4 +-- 12 files changed, 112 insertions(+), 23 deletions(-) diff --git a/bt/announce.php b/bt/announce.php index 6848b65a..f6d10fc5 100644 --- a/bt/announce.php +++ b/bt/announce.php @@ -74,10 +74,25 @@ $passkey = isset($$passkey_key) ? $$passkey_key : null; // Verify request // Required params (info_hash, peer_id, port, uploaded, downloaded, left, passkey) -if (!isset($info_hash) || strlen($info_hash) != 20) +if (!isset($info_hash)) +{ + msg_die('info_hash does not exist'); +} + +// 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($peer_id) || strlen($peer_id) != 20) { msg_die('Invalid peer_id'); @@ -225,13 +240,14 @@ 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 "; @@ -508,4 +524,4 @@ if (!$output) echo bencode($output); tracker_exit(); -exit; \ No newline at end of file +exit; diff --git a/bt/scrape.php b/bt/scrape.php index e09ebbb9..ce28a875 100644 --- a/bt/scrape.php +++ b/bt/scrape.php @@ -17,7 +17,28 @@ if (!isset($_GET['info_hash']) || strlen($_GET['info_hash']) != 20) msg_die('Invalid info_hash'); } -$info_hash = $_GET['info_hash']; +$is_bt_v2 = null; +$info_hash = isset($_GET['info_hash']) ? (string)$_GET['info_hash'] : null; + +// Verify info_hash +if (!isset($info_hash)) +{ + msg_die('info_hash does not exist'); +} + +// 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) { @@ -36,15 +57,21 @@ define('TR_ROOT', './'); require(TR_ROOT . '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] = array( 'complete' => (int) $row['seeders'], 'downloaded' => (int) $row['complete_count'], @@ -54,4 +81,4 @@ $output['files'][$info_hash] = array( echo bencode($output); tracker_exit(); -exit; \ No newline at end of file +exit; diff --git a/install/sql/mysql.sql b/install/sql/mysql.sql index 7ddbb546..ce36ddb8 100644 --- a/install/sql/mysql.sql +++ b/install/sql/mysql.sql @@ -255,6 +255,7 @@ CREATE TABLE IF NOT EXISTS `bb_bt_torhelp` ( 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 35c5442a..cfaa0616 100644 --- a/install/upgrade/changes.txt +++ b/install/upgrade/changes.txt @@ -99,3 +99,6 @@ DELETE FROM `bb_smilies` WHERE `code` = ':ad:'; INSERT INTO `bb_smilies` (`code`, `smile_url`, `emoticon`) VALUES (':cd:', 'cd.gif', 'cd'); 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; + +// 2.1.5 (LTS 2023.08) +ALTER TABLE `bb_bt_torrents` ADD COLUMN `info_hash_v2` VARBINARY(32) NOT NULL DEFAULT ''; diff --git a/library/ajax/view_torrent.php b/library/ajax/view_torrent.php index 0a045021..afa68f32 100644 --- a/library/ajax/view_torrent.php +++ b/library/ajax/view_torrent.php @@ -103,6 +103,11 @@ class torrent { continue; } + // Exclude padding files + if (($f['attr'] ?? null) === 'p') + { + continue; + } array_deep($f['path'], 'clean_tor_dirname'); $length = isset($f['length']) ? (float) $f['length'] : 0; diff --git a/library/attach_mod/displaying_torrent.php b/library/attach_mod/displaying_torrent.php index 1ad72c4e..a812482a 100644 --- a/library/attach_mod/displaying_torrent.php +++ b/library/attach_mod/displaying_torrent.php @@ -154,7 +154,7 @@ if ($tor_reged && $tor_info) // Magnet link $passkey = DB()->fetch_row("SELECT auth_key FROM ". BB_BT_USERS ." WHERE user_id = ". (int) $bt_user_id ." LIMIT 1"); - $tor_magnet = create_magnet($tor_info['info_hash'], $passkey['auth_key']); + $tor_magnet = create_magnet($tor_info['info_hash'], $tor_info['info_hash_v2'], $passkey['auth_key']); // ratio limits $min_ratio_dl = $bb_cfg['bt_min_ratio_allow_dl_tor']; @@ -231,6 +231,7 @@ if ($tor_reged && $tor_info) 'FILESIZE' => $tor_file_size, 'MAGNET' => $tor_magnet, 'HASH' => strtoupper(bin2hex($tor_info['info_hash'])), + 'HASH_V2' => !empty($tor_info['info_hash_v2']) ? strtoupper(bin2hex($tor_info['info_hash_v2'])) : false, 'DOWNLOAD_COUNT' => sprintf($lang['DOWNLOAD_NUMBER'], $download_count), 'REGED_TIME' => bb_date($tor_info['reg_time']), 'REGED_DELTA' => delta_time($tor_info['reg_time']), diff --git a/library/includes/functions.php b/library/includes/functions.php index e4e0aabc..9601c321 100644 --- a/library/includes/functions.php +++ b/library/includes/functions.php @@ -2574,7 +2574,7 @@ function pad_with_space ($str) return ($str) ? " $str " : $str; } -function create_magnet ($infohash, $auth_key) +function create_magnet ($infohash, $infohash_v2, $auth_key) { global $bb_cfg, $images, $lang, $userdata; @@ -2597,7 +2597,7 @@ function create_magnet ($infohash, $auth_key) } $passkey_url = $passkey ? "?{$bb_cfg['passkey_key']}=$auth_key" : ''; - return ''; + return ''; } function set_die_append_msg ($forum_id = null, $topic_id = null, $group_id = null) @@ -2795,15 +2795,30 @@ function hash_search ($hash) global $lang; $hash = htmlCHR(trim($hash)); + $info_hash_where = null; - if (!isset($hash) || mb_strlen($hash, 'UTF-8') != 40) + if (!isset($hash)) { bb_die(sprintf($lang['HASH_INVALID'], $hash)); } $info_hash = DB()->escape(pack("H*", $hash)); - if ($row = DB()->fetch_row("SELECT topic_id FROM " . BB_BT_TORRENTS . " WHERE info_hash = '$info_hash'")) + // Check info_hash version + if (mb_strlen($hash, 'UTF-8') == 40) + { + $info_hash_where = "WHERE info_hash = '$info_hash'"; + } + elseif (mb_strlen($hash, 'UTF-8') == 64) + { + $info_hash_where = "WHERE info_hash_v2 = '$info_hash'"; + } + else + { + bb_die(sprintf($lang['HASH_INVALID'], $hash)); + } + + if ($row = DB()->fetch_row("SELECT topic_id FROM " . BB_BT_TORRENTS . " $info_hash_where")) { redirect(TOPIC_URL . $row['topic_id']); } diff --git a/library/includes/functions_torrent.php b/library/includes/functions_torrent.php index 7c391262..e0b041de 100644 --- a/library/includes/functions_torrent.php +++ b/library/includes/functions_torrent.php @@ -249,7 +249,8 @@ function tracker_register ($attach_id, $mode = '', $tor_status = TOR_NOT_APPROVE $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 torrent_error_exit($lang['NOT_TORRENT']); if (!$torrent['allow_reg_tracker']) return torrent_error_exit($lang['REG_NOT_ALLOWED_IN_THIS_FORUM']); @@ -294,10 +295,25 @@ function tracker_register ($attach_id, $mode = '', $tor_status = TOR_NOT_APPROVE return 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(bencode($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', bencode($info))); + $info_hash_v2_sql = rtrim(DB()->escape($info_hash_v2), ' '); + } + // Ocelot if ($bb_cfg['ocelot']['enabled']) { @@ -321,7 +337,11 @@ function tracker_register ($attach_id, $mode = '', $tor_status = TOR_NOT_APPROVE { foreach ($info['files'] as $fn => $f) { - $totallen += (float) $f['length']; + // Exclude padding files + if (($f['attr'] ?? null) !== 'p') + { + $totallen += (float) $f['length']; + } } } else @@ -331,8 +351,8 @@ function tracker_register ($attach_id, $mode = '', $tor_status = TOR_NOT_APPROVE $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, post_id, poster_id, topic_id, forum_id, attach_id, size, reg_time, tor_status, info_hash_v2'; + $values = "'$info_hash_sql', $post_id, $poster_id, $topic_id, $forum_id, $attach_id, '$size', $reg_time, $tor_status, '$info_hash_v2_sql'"; $sql = "INSERT INTO ". BB_BT_TORRENTS ." ($columns) VALUES ($values)"; diff --git a/styles/templates/default/tracker.tpl b/styles/templates/default/tracker.tpl index 09fbf791..283e8df7 100644 --- a/styles/templates/default/tracker.tpl +++ b/styles/templates/default/tracker.tpl @@ -277,7 +277,7 @@ $(function(){
- {L_TITLE_MATCH} · {L_HASH_S} + {L_TITLE_MATCH} · {L_HASH_S}

diff --git a/styles/templates/default/viewtopic_attach.tpl b/styles/templates/default/viewtopic_attach.tpl index 153b6339..64ace279 100644 --- a/styles/templates/default/viewtopic_attach.tpl +++ b/styles/templates/default/viewtopic_attach.tpl @@ -160,7 +160,8 @@ {postrow.attach.tor_reged.TRACKER_LINK} [ {postrow.attach.tor_reged.REGED_TIME} ] - · {postrow.attach.tor_reged.HASH} +

info_hash: {postrow.attach.tor_reged.HASH} +
info_hash v2: {postrow.attach.tor_reged.HASH_V2} @@ -366,4 +367,4 @@ $('#tor-filelist-btn').click(function(){ - \ No newline at end of file + diff --git a/tracker.php b/tracker.php index 7195bab3..22a43f45 100644 --- a/tracker.php +++ b/tracker.php @@ -728,7 +728,7 @@ if ($allowed_forums) $select = " SELECT tor.topic_id, tor.post_id, tor.attach_id, tor.size, tor.reg_time, tor.complete_count, tor.seeder_last_seen, tor.tor_status, tor.tor_type, - t.topic_title, t.topic_time, t.topic_replies, t.topic_views, sn.seeders, sn.leechers, tor.info_hash + t.topic_title, t.topic_time, t.topic_replies, t.topic_views, sn.seeders, sn.leechers, tor.info_hash, tor.info_hash_v2 "; $select .= (!$hide_speed) ? ", sn.speed_up, sn.speed_down" : ''; $select .= (!$hide_forum) ? ", tor.forum_id" : ''; @@ -787,7 +787,7 @@ if ($allowed_forums) $s_last = $tor['seeder_last_seen']; $att_id = $tor['attach_id']; $size = $tor['size']; - $tor_magnet = create_magnet($tor['info_hash'], $passkey['auth_key']); + $tor_magnet = create_magnet($tor['info_hash'], $tor['info_hash_v2'], $passkey['auth_key']); $compl = $tor['complete_count']; $dl_sp = ($dl) ? humn_size($dl, 0, 'KB') .'/s' : '0 KB/s'; $ul_sp = ($ul) ? humn_size($ul, 0, 'KB') .'/s' : '0 KB/s'; @@ -993,4 +993,4 @@ $template->assign_vars(array( 'TR_POSTER_URL' => "$tracker_url?$poster_id_key=", )); -print_page('tracker.tpl'); \ No newline at end of file +print_page('tracker.tpl'); diff --git a/viewforum.php b/viewforum.php index 98a3978b..9139af57 100644 --- a/viewforum.php +++ b/viewforum.php @@ -311,7 +311,7 @@ if ($forum_data['allow_reg_tracker']) } $select_tor_sql = ', - bt.auth_key, tor.info_hash, tor.size AS tor_size, tor.reg_time, tor.complete_count, tor.seeder_last_seen, tor.attach_id, tor.tor_status, tor.tor_type, + bt.auth_key, tor.info_hash, tor.info_hash_v2, tor.size AS tor_size, tor.reg_time, tor.complete_count, tor.seeder_last_seen, tor.attach_id, tor.tor_status, tor.tor_type, sn.seeders, sn.leechers '; $select_tor_sql .= ($join_dl) ? ', dl.user_status AS dl_status' : ''; @@ -512,7 +512,7 @@ foreach ($topic_rowset as $topic) if (isset($topic['tor_size'])) { - $tor_magnet = create_magnet($topic['info_hash'], $topic['auth_key']); + $tor_magnet = create_magnet($topic['info_hash'], $topic['info_hash_v2'], $topic['auth_key']); $template->assign_block_vars('t.tor', array( 'SEEDERS' => (int) $topic['seeders'],