BitTorrent v2 support 🐸 (#230)

* BitTorrent v2 support 🐸

* Update scrape.php
This commit is contained in:
Roman Kelesidis 2023-08-27 23:26:05 +07:00 committed by GitHub
parent 2ededf453e
commit de00055c6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 112 additions and 23 deletions

View File

@ -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;
exit;

View File

@ -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;
exit;

View File

@ -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',

View File

@ -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 '';

View File

@ -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;

View File

@ -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']),

View File

@ -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 '<a href="magnet:?xt=urn:btih:'. bin2hex($infohash) .'&tr='. urlencode($bb_cfg['bt_announce_url'] . $passkey_url) .'"><img src="'. $images['icon_magnet'] .'" width="12" height="12" border="0" /></a>';
return '<a href="magnet:?xt=urn:btih:'. bin2hex($infohash) . (!empty($infohash_v2) ? '&xt=urn:btmh:1220' . bin2hex($infohash_v2) : '') .'&tr='. urlencode($bb_cfg['bt_announce_url'] . $passkey_url) .'"><img src="'. $images['icon_magnet'] .'" width="12" height="12" border="0" /></a>';
}
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']);
}

View File

@ -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)";

View File

@ -277,7 +277,7 @@ $(function(){
</div>
</fieldset>
<fieldset>
<legend><span class="a-hash bold" onclick="$(this).addClass('bold').next().removeClass('bold'); $('#title_search').attr('name','{TITLE_MATCH_NAME}');">{L_TITLE_MATCH}</span>&nbsp;&middot;&nbsp;<span class="a-hash" onclick="$(this).addClass('bold').prev().removeClass('bold'); $('#title_search').attr('name','hash');">{L_HASH_S}</span></legend>
<legend><span class="a-hash bold" onclick="$(this).addClass('bold').next().removeClass('bold'); $('#title_search').attr('name','{TITLE_MATCH_NAME}').attr('maxlength','{TITLE_MATCH_MAX}');">{L_TITLE_MATCH}</span>&nbsp;&middot;&nbsp;<span class="a-hash" onclick="$(this).addClass('bold').prev().removeClass('bold'); $('#title_search').attr('name','hash').attr('maxlength',64);">{L_HASH_S}</span></legend>
<div>
<p class="input">
<input id="title_search" style="width: 95%;" class="post" type="text" size="50" maxlength="{TITLE_MATCH_MAX}" name="{TITLE_MATCH_NAME}" value="{TITLE_MATCH_VAL}" />

View File

@ -160,7 +160,8 @@
<td width="70%">
{postrow.attach.tor_reged.TRACKER_LINK}
[ <span title="{postrow.attach.tor_reged.REGED_DELTA}">{postrow.attach.tor_reged.REGED_TIME}</span> ]
&#0183; {postrow.attach.tor_reged.HASH}
<br><br>info_hash: {postrow.attach.tor_reged.HASH}
<!-- IF postrow.attach.tor_reged.HASH_V2 --><br>info_hash v2: {postrow.attach.tor_reged.HASH_V2}<!-- ENDIF -->
</td>
<td width="15%" rowspan="4" class="tCenter pad_6">
<!-- IF postrow.attach.tor_reged.TOR_FROZEN -->
@ -366,4 +367,4 @@ $('#tor-filelist-btn').click(function(){
<!-- ENDIF -->
<!-- END tor_reged -->
<!-- END attach -->
<!-- END attach -->

View File

@ -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');
print_page('tracker.tpl');

View File

@ -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'],