BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

functions.php 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <?php
  2. #declare(strict_types=1);
  3. function get_group_info($GroupID, $Return = true, $RevisionID = 0, $PersonalProperties = true, $ApiCall = false)
  4. {
  5. global $Cache, $DB;
  6. if (!$RevisionID) {
  7. $TorrentCache = $Cache->get_value("torrents_details_$GroupID");
  8. }
  9. if ($RevisionID || !is_array($TorrentCache)) {
  10. // Fetch the group details
  11. $SQL = 'SELECT ';
  12. if (!$RevisionID) {
  13. $SQL .= '
  14. g.`description`,
  15. g.`picture`, ';
  16. } else {
  17. $SQL .= '
  18. w.`Body`,
  19. w.`Image`, ';
  20. }
  21. $SQL .= "
  22. g.`id`,
  23. g.`title`,
  24. g.`subject`,
  25. g.`object`,
  26. g.`year`,
  27. g.`workgroup`,
  28. g.`location`,
  29. g.`identifier`,
  30. g.`category_id`,
  31. g.`timestamp`,
  32. GROUP_CONCAT(DISTINCT tags.`Name` SEPARATOR '|'),
  33. GROUP_CONCAT(DISTINCT tags.`ID` SEPARATOR '|'),
  34. GROUP_CONCAT(tt.`UserID` SEPARATOR '|')
  35. FROM `torrents_group` AS g
  36. LEFT JOIN `torrents_tags` AS tt ON tt.`GroupID` = g.`id`
  37. LEFT JOIN `tags` ON tags.`ID` = tt.`TagID`";
  38. if ($RevisionID) {
  39. $SQL .= "
  40. LEFT JOIN `wiki_torrents` AS w ON w.`PageID` = '".db_string($GroupID)."'
  41. AND w.`RevisionID` = '".db_string($RevisionID)."' ";
  42. }
  43. $SQL .= "
  44. WHERE g.`id` = '".db_string($GroupID)."'
  45. GROUP BY NULL";
  46. $DB->query($SQL);
  47. $TorrentDetails = $DB->next_record(MYSQLI_ASSOC);
  48. $TorrentDetails['Screenshots'] = [];
  49. $TorrentDetails['Mirrors'] = [];
  50. # Screenshots (Publications)
  51. $DB->query("
  52. SELECT
  53. `id`,
  54. `user_id`,
  55. `timestamp`,
  56. `doi`
  57. FROM
  58. `literature`
  59. WHERE
  60. `group_id` = '$GroupID'
  61. ");
  62. if ($DB->has_results()) {
  63. while ($Screenshot = $DB->next_record(MYSQLI_ASSOC, true)) {
  64. $TorrentDetails['Screenshots'][] = $Screenshot;
  65. }
  66. }
  67. # Mirrors
  68. # todo: Fix $GroupID
  69. $DB->query("
  70. SELECT
  71. `id`,
  72. `user_id`,
  73. `timestamp`,
  74. `uri`
  75. FROM
  76. `torrents_mirrors`
  77. WHERE
  78. `torrent_id` = '$GroupID'
  79. ");
  80. if ($DB->has_results()) {
  81. while ($Mirror = $DB->next_record(MYSQLI_ASSOC, true)) {
  82. $TorrentDetails['Mirrors'][] = $Mirror;
  83. }
  84. }
  85. // Fetch the individual torrents
  86. $DB->query("
  87. SELECT
  88. t.ID,
  89. t.Media,
  90. t.Container,
  91. t.Codec,
  92. t.Resolution,
  93. t.Version,
  94. t.Censored,
  95. t.Anonymous,
  96. t.Archive,
  97. t.FileCount,
  98. t.Size,
  99. t.Seeders,
  100. t.Leechers,
  101. t.Snatched,
  102. t.FreeTorrent,
  103. t.FreeLeechType,
  104. t.Time,
  105. t.Description,
  106. t.FileList,
  107. t.FilePath,
  108. t.UserID,
  109. t.last_action,
  110. HEX(t.info_hash) AS InfoHash,
  111. tbt.TorrentID AS BadTags,
  112. tbf.TorrentID AS BadFolders,
  113. tfi.TorrentID AS BadFiles,
  114. t.LastReseedRequest,
  115. tln.TorrentID AS LogInDB,
  116. t.ID AS HasFile
  117. FROM torrents AS t
  118. LEFT JOIN torrents_bad_tags AS tbt ON tbt.TorrentID = t.ID
  119. LEFT JOIN torrents_bad_folders AS tbf ON tbf.TorrentID = t.ID
  120. LEFT JOIN torrents_bad_files AS tfi ON tfi.TorrentID = t.ID
  121. LEFT JOIN torrents_logs_new AS tln ON tln.TorrentID = t.ID
  122. WHERE t.GroupID = '".db_string($GroupID)."'
  123. GROUP BY t.ID
  124. ORDER BY
  125. t.Media ASC,
  126. t.ID");
  127. $TorrentList = $DB->to_array('ID', MYSQLI_ASSOC);
  128. if (count($TorrentList) === 0 && $ApiCall == false) {
  129. header('Location: log.php?search='.(empty($_GET['torrentid']) ? "Group+$GroupID" : "Torrent+$_GET[torrentid]"));
  130. error();
  131. } elseif (count($TorrentList) === 0 && $ApiCall == true) {
  132. return;
  133. }
  134. if (in_array(0, $DB->collect('Seeders'))) {
  135. $CacheTime = 600;
  136. } else {
  137. $CacheTime = 3600;
  138. }
  139. // Store it all in cache
  140. if (!$RevisionID) {
  141. $Cache->cache_value("torrents_details_$GroupID", array($TorrentDetails, $TorrentList), $CacheTime);
  142. }
  143. } else { // If we're reading from cache
  144. $TorrentDetails = $TorrentCache[0];
  145. $TorrentList = $TorrentCache[1];
  146. }
  147. if ($PersonalProperties) {
  148. // Fetch all user specific torrent and group properties
  149. $TorrentDetails['Flags'] = array('IsSnatched' => false, 'IsLeeching' => false, 'IsSeeding' => false);
  150. foreach ($TorrentList as &$Torrent) {
  151. Torrents::torrent_properties($Torrent, $TorrentDetails['Flags']);
  152. }
  153. }
  154. if ($Return) {
  155. return array($TorrentDetails, $TorrentList);
  156. }
  157. }
  158. function get_torrent_info($TorrentID, $Return = true, $RevisionID = 0, $PersonalProperties = true, $ApiCall = false)
  159. {
  160. global $Cache, $DB;
  161. $GroupID = (int)torrentid_to_groupid($TorrentID);
  162. $GroupInfo = get_group_info($GroupID, $Return, $RevisionID, $PersonalProperties, $ApiCall);
  163. if ($GroupInfo) {
  164. foreach ($GroupInfo[1] as &$Torrent) {
  165. // Remove unneeded entries
  166. if ($Torrent['ID'] !== $TorrentID) {
  167. unset($GroupInfo[1][$Torrent['ID']]);
  168. }
  169. if ($Return) {
  170. return $GroupInfo;
  171. }
  172. }
  173. } else {
  174. if ($Return) {
  175. return;
  176. }
  177. }
  178. }
  179. // Check if a givin string can be validated as a torrenthash
  180. function is_valid_torrenthash($Str)
  181. {
  182. // 6C19FF4C 6C1DD265 3B25832C 0F6228B2 52D743D5
  183. $Str = str_replace(' ', '', $Str);
  184. if (preg_match('/^[0-9a-fA-F]{40}$/', $Str)) {
  185. return $Str;
  186. }
  187. return false;
  188. }
  189. // Functionality for the API to resolve input into other data
  190. function torrenthash_to_torrentid($Str)
  191. {
  192. global $Cache, $DB;
  193. $DB->query("
  194. SELECT ID
  195. FROM torrents
  196. WHERE HEX(info_hash) = '".db_string($Str)."'");
  197. $TorrentID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
  198. if ($TorrentID) {
  199. return $TorrentID;
  200. }
  201. return;
  202. }
  203. function torrenthash_to_groupid($Str)
  204. {
  205. global $Cache, $DB;
  206. $DB->query("
  207. SELECT GroupID
  208. FROM torrents
  209. WHERE HEX(info_hash) = '".db_string($Str)."'");
  210. $GroupID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
  211. if ($GroupID) {
  212. return $GroupID;
  213. }
  214. return;
  215. }
  216. function torrentid_to_groupid($TorrentID)
  217. {
  218. global $Cache, $DB;
  219. $DB->query("
  220. SELECT GroupID
  221. FROM torrents
  222. WHERE ID = '".db_string($TorrentID)."'");
  223. $GroupID = (int)array_pop($DB->next_record(MYSQLI_ASSOC));
  224. if ($GroupID) {
  225. return $GroupID;
  226. }
  227. return;
  228. }
  229. // After adjusting / deleting logs, recalculate the score for the torrent
  230. function set_torrent_logscore($TorrentID)
  231. {
  232. global $DB;
  233. $DB->query("
  234. UPDATE torrents
  235. SET LogScore = (
  236. SELECT FLOOR(AVG(Score))
  237. FROM torrents_logs_new
  238. WHERE TorrentID = $TorrentID
  239. )
  240. WHERE ID = $TorrentID");
  241. }
  242. function get_group_requests($GroupID)
  243. {
  244. if (empty($GroupID) || !is_number($GroupID)) {
  245. return [];
  246. }
  247. global $DB, $Cache;
  248. $Requests = $Cache->get_value("requests_group_$GroupID");
  249. if ($Requests === false) {
  250. $DB->query("
  251. SELECT ID
  252. FROM requests
  253. WHERE GroupID = $GroupID
  254. AND TimeFilled IS NULL");
  255. $Requests = $DB->collect('ID');
  256. $Cache->cache_value("requests_group_$GroupID", $Requests, 0);
  257. }
  258. return Requests::get_requests($Requests);
  259. }
  260. // Used by both sections/torrents/details.php and sections/reportsv2/report.php
  261. function build_torrents_table($Cache, $DB, $LoggedUser, $GroupID, $GroupName, $GroupCategoryID, $TorrentList, $Types, $Username)
  262. {
  263. function filelist($Str)
  264. {
  265. return "</td>\n<td>" . Format::get_size($Str[1]) . "</td>\n</tr>";
  266. }
  267. $EditionID = 0;
  268. foreach ($TorrentList as $Torrent) {
  269. list($TorrentID, $Media, $Container, $Codec, $Resolution, $Version,
  270. $Censored, $Anonymous, $Archive, $FileCount, $Size, $Seeders, $Leechers, $Snatched,
  271. $FreeTorrent, $FreeLeechType, $TorrentTime, $Description, $FileList, $FilePath, $UserID,
  272. $LastActive, $InfoHash, $BadTags, $BadFolders, $BadFiles, $LastReseedRequest,
  273. $LogInDB, $HasFile, $PersonalFL, $IsSnatched, $IsSeeding, $IsLeeching) = array_values($Torrent);
  274. $Reported = false;
  275. $Reports = Torrents::get_reports($TorrentID);
  276. $NumReports = count($Reports);
  277. if ($NumReports > 0) {
  278. $Reported = true;
  279. include(SERVER_ROOT.'/sections/reportsv2/array.php');
  280. $ReportInfo = '
  281. <table class="reportinfo_table">
  282. <tr class="colhead_dark" style="font-weight: bold;">
  283. <td>This torrent has '.$NumReports.' active '.($NumReports === 1 ? 'report' : 'reports').":</td>
  284. </tr>";
  285. foreach ($Reports as $Report) {
  286. if (check_perms('admin_reports')) {
  287. $ReporterID = $Report['ReporterID'];
  288. $Reporter = Users::user_info($ReporterID);
  289. $ReporterName = $Reporter['Username'];
  290. $ReportLinks = "<a href=\"user.php?id=$ReporterID\">$ReporterName</a> <a href=\"reportsv2.php?view=report&amp;id=$Report[ID]\">reported it</a>";
  291. } else {
  292. $ReportLinks = 'Someone reported it';
  293. }
  294. if (isset($Types[$GroupCategoryID][$Report['Type']])) {
  295. $ReportType = $Types[$GroupCategoryID][$Report['Type']];
  296. } elseif (isset($Types['master'][$Report['Type']])) {
  297. $ReportType = $Types['master'][$Report['Type']];
  298. } else {
  299. // There was a type but it wasn't an option!
  300. $ReportType = $Types['master']['other'];
  301. }
  302. $ReportInfo .= "
  303. <tr>
  304. <td>$ReportLinks ".time_diff($Report['ReportedTime'], 2, true, true).' for the reason "'.$ReportType['title'].'":
  305. <blockquote>'.Text::full_format($Report['UserComment']).'</blockquote>
  306. </td>
  307. </tr>';
  308. }
  309. $ReportInfo .= "</table>";
  310. }
  311. $CanEdit = (check_perms('torrents_edit') || (($UserID == $LoggedUser['ID'] && !$LoggedUser['DisableWiki'])));
  312. $RegenLink = check_perms('users_mod') ? ' <a href="torrents.php?action=regen_filelist&amp;torrentid=' . $TorrentID . '" class="brackets">Regenerate</a>' : '';
  313. $FileTable = '
  314. <table class="filelist_table">
  315. <tr class="colhead_dark">
  316. <td>
  317. <div class="filelist_title float_left">File Names' . $RegenLink . '</div>
  318. <div class="filelist_path float_right">' . ($FilePath ? "/$FilePath/" : '') . '</div>
  319. </td>
  320. <td>
  321. <strong>Size</strong>
  322. </td>
  323. </tr>';
  324. if (substr($FileList, -3) == '}}}') { // Old style
  325. $FileListSplit = explode('|||', $FileList);
  326. foreach ($FileListSplit as $File) {
  327. $NameEnd = strrpos($File, '{{{');
  328. $Name = substr($File, 0, $NameEnd);
  329. if ($Spaces = strspn($Name, ' ')) {
  330. $Name = str_replace(' ', '&nbsp;', substr($Name, 0, $Spaces)) . substr($Name, $Spaces);
  331. }
  332. $FileSize = substr($File, $NameEnd + 3, -3);
  333. $FileTable .= sprintf("\n<tr class=\"row\"><td>%s</td><td class=\"number_column\">%s</td></tr>", $Name, Format::get_size($FileSize));
  334. }
  335. } else {
  336. $FileListSplit = explode("\n", $FileList);
  337. foreach ($FileListSplit as $File) {
  338. $FileInfo = Torrents::filelist_get_file($File);
  339. $FileTable .= sprintf("\n<tr class=\"row\"><td>%s</td><td class=\"number_column\">%s</td></tr>", $FileInfo['name'], Format::get_size($FileInfo['size']));
  340. }
  341. }
  342. $FileTable .= '</table>';
  343. $ExtraInfo = ''; // String that contains information on the torrent (e.g. format and encoding)
  344. $AddExtra = '&thinsp;|&thinsp;'; // Separator between torrent properties
  345. $TorrentUploader = $Username; // Save this for "Uploaded by:" below
  346. // Similar to Torrents::torrent_info()
  347. if (!$ExtraInfo) {
  348. $ExtraInfo = $GroupName;
  349. }
  350. if ($IsLeeching) {
  351. $ExtraInfo .= $AddExtra.Format::torrent_label('Leeching', 'important_text_semi');
  352. } elseif ($IsSeeding) {
  353. $ExtraInfo .= $AddExtra.Format::torrent_label('Seeding', 'important_text_alt');
  354. } elseif ($IsSnatched) {
  355. $ExtraInfo .= $AddExtra.Format::torrent_label('Snatched', 'bold');
  356. }
  357. if ($FreeTorrent === 1) {
  358. $ExtraInfo .= $AddExtra.Format::torrent_label('Freeleech', 'important_text_alt');
  359. }
  360. if ($FreeTorrent === 2) {
  361. $ExtraInfo .= $AddExtra.Format::torrent_label('Neutral Leech', 'bold');
  362. }
  363. if ($PersonalFL) {
  364. $ExtraInfo .= $AddExtra.Format::torrent_label('Personal Freeleech', 'important_text_alt');
  365. }
  366. if ($Reported) {
  367. $ExtraInfo .= $AddExtra.Format::torrent_label('Reported', 'tl_reported');
  368. }
  369. if (!empty($BadTags)) {
  370. $ExtraInfo .= $AddExtra.Format::torrent_label('Bad Tags', 'tl_reported');
  371. }
  372. if (!empty($BadFolders)) {
  373. $ExtraInfo .= $AddExtra.Format::torrent_label('Bad Folders', 'tl_reported');
  374. }
  375. if (!empty($BadFiles)) {
  376. $ExtraInfo .= $AddExtra.Format::torrent_label('Bad File Names', 'tl_reported');
  377. } ?>
  378. <tr class="torrent_row<?=(isset($ReleaseType)?' releases_'.$ReleaseType:'')?> groupid_<?=($GroupID)?> edition_<?=($EditionID)?> group_torrent<?=($IsSnatched ? ' snatched_torrent' : '')?>"
  379. style="font-weight: normal;" id="torrent<?=($TorrentID)?>">
  380. <td>
  381. <span>[ <a
  382. href="torrents.php?action=download&amp;id=<?=($TorrentID)?>&amp;authkey=<?=($LoggedUser['AuthKey'])?>&amp;torrent_pass=<?=($LoggedUser['torrent_pass'])?>"
  383. class="tooltip" title="Download"><?=($HasFile ? 'DL' : 'Missing')?></a>
  384. <?php if (Torrents::can_use_token($Torrent)) { ?>
  385. | <a href="torrents.php?action=download&amp;id=<?=($TorrentID)?>&amp;authkey=<?=($LoggedUser['AuthKey'])?>&amp;torrent_pass=<?=($LoggedUser['torrent_pass'])?>&amp;usetoken=1"
  386. class="tooltip" title="Use a FL Token"
  387. onclick="return confirm('Are you sure you want to use a freeleech token here?');">FL</a>
  388. <?php } ?>
  389. | <a href="reportsv2.php?action=report&amp;id=<?=($TorrentID)?>"
  390. class="tooltip" title="Report">RP</a>
  391. <?php if ($CanEdit) { ?>
  392. | <a href="torrents.php?action=edit&amp;id=<?=($TorrentID)?>"
  393. class="tooltip" title="Edit">ED</a>
  394. <?php }
  395. if (check_perms('torrents_delete') || $UserID == $LoggedUser['ID']) { ?>
  396. | <a href="torrents.php?action=delete&amp;torrentid=<?=($TorrentID)?>"
  397. class="tooltip" title="Remove">RM</a>
  398. <?php } ?>
  399. | <a href="torrents.php?torrentid=<?=($TorrentID)?>"
  400. class="tooltip" title="Permalink">PL</a>
  401. ]
  402. </span>
  403. <a data-toggle-target="#torrent_<?=($TorrentID)?>"><?=($ExtraInfo)?></a>
  404. </td>
  405. <td class="number_column nobr"><?=(Format::get_size($Size))?>
  406. </td>
  407. <td class="number_column"><?=(number_format($Snatched))?>
  408. </td>
  409. <td class="number_column"><?=(number_format($Seeders))?>
  410. </td>
  411. <td class="number_column"><?=(number_format($Leechers))?>
  412. </td>
  413. </tr>
  414. <tr class="<?=(isset($ReleaseType)?'releases_'.$ReleaseType:'')?> groupid_<?=($GroupID)?> edition_<?=($EditionID)?> torrentdetails pad<?php if (!isset($_GET['torrentid']) || $_GET['torrentid'] != $TorrentID) { ?> hidden<?php } ?>"
  415. id="torrent_<?=($TorrentID)?>">
  416. <td colspan="5">
  417. <blockquote>
  418. Uploaded by <?php
  419. if ($Anonymous) {
  420. if (check_perms('users_mod')) { ?>
  421. <em class="tooltip"
  422. title="<?=Users::user_info($UserID)['Username']?>">Anonymous</em>
  423. <?php } else {
  424. ?><em>Anonymous</em><?php
  425. }
  426. } else {
  427. print(Users::format_username($UserID, false, false, false));
  428. } ?> <?=time_diff($TorrentTime); ?>
  429. <?php if ($Seeders === 0) {
  430. if ($LastActive && time() - strtotime($LastActive) >= 1209600) { ?>
  431. <br /><strong>Last active: <?=time_diff($LastActive);?></strong>
  432. <?php } else { ?>
  433. <br />Last active: <?=time_diff($LastActive);?>
  434. <?php }
  435. if ($LastActive && time() - strtotime($LastActive) >= 345678 && time() - strtotime($LastReseedRequest) >= 864000) { ?>
  436. <br /><a
  437. href="torrents.php?action=reseed&amp;torrentid=<?=($TorrentID)?>&amp;groupid=<?=($GroupID)?>"
  438. class="brackets">Request re-seed</a>
  439. <?php }
  440. } ?>
  441. </blockquote>
  442. <?php if (check_perms('site_moderate_requests')) { ?>
  443. <div class="linkbox">
  444. <a href="torrents.php?action=masspm&amp;id=<?=($GroupID)?>&amp;torrentid=<?=($TorrentID)?>"
  445. class="brackets">Mass PM snatchers</a>
  446. </div>
  447. <?php } ?>
  448. <div class="linkbox">
  449. <a href="#" class="brackets"
  450. onclick="show_peers('<?=($TorrentID)?>', 0); return false;">View
  451. peer list</a>
  452. <?php if (check_perms('site_view_torrent_snatchlist')) { ?>
  453. <a href="#" class="brackets tooltip"
  454. onclick="show_downloads('<?=($TorrentID)?>', 0); return false;"
  455. title="View the list of users that have clicked the &quot;DL&quot; button.">View download list</a>
  456. <a href="#" class="brackets tooltip"
  457. onclick="show_snatches('<?=($TorrentID)?>', 0); return false;"
  458. title="View the list of users that have reported a snatch to the tracker.">View snatch list</a>
  459. <?php } ?>
  460. <a href="#" class="brackets"
  461. onclick="show_files('<?=($TorrentID)?>'); return false;">View
  462. file list</a>
  463. <?php if ($Reported) { ?>
  464. <a href="#" class="brackets"
  465. onclick="show_reported('<?=($TorrentID)?>'); return false;">View
  466. report information</a>
  467. <?php } ?>
  468. </div>
  469. <div id="peers_<?=($TorrentID)?>" class="hidden"></div>
  470. <div id="downloads_<?=($TorrentID)?>" class="hidden"></div>
  471. <div id="snatches_<?=($TorrentID)?>" class="hidden"></div>
  472. <div id="files_<?=($TorrentID)?>" class="hidden"><?=($FileTable)?>
  473. </div>
  474. <?php if ($Reported) { ?>
  475. <div id="reported_<?=($TorrentID)?>" class="hidden"><?=($ReportInfo)?>
  476. </div>
  477. <?php }
  478. if (!empty($Description)) {
  479. echo "<blockquote>" . Text::full_format($Description) . '</blockquote>';
  480. } ?>
  481. </td>
  482. </tr>
  483. <?php
  484. }
  485. }