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

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