torrentsCtx->getTorrents()->getTorrent($torrentId); } catch(RuntimeException $ex) { $response->setStatusCode(404); return 'Download not found.'; } $canDownload = $this->torrentsCtx->canDownloadTorrent($torrentInfo, $this->authInfo->getUserInfo()); if($canDownload !== '') { $response->setStatusCode(403); return match($canDownload) { 'inactive' => 'This download is inactive.', 'private' => 'You must be logged in for this download.', 'pending' => 'This download is pending approval.', default => $canDownload, }; } $trackerUrl = ''; if($this->authInfo->isLoggedIn()) { $userInfo = $this->authInfo->getUserInfo(); $passKey = $userInfo->hasPassKey() ? $userInfo->getPassKey() : $this->usersCtx->getUsers()->updatePassKey($userInfo); $trackerUrl = sprintf($this->config->getString('url:user'), $passKey); } else $trackerUrl = $this->config->getString('url:anon'); $response->setContentType('application/x-bittorrent'); $response->setFileName(htmlspecialchars($torrentInfo->getName()) . '.torrent'); return $this->torrentsCtx->encodeTorrent($torrentInfo, $trackerUrl); } private function getTorrentInfo(string $torrentId): int { if($this->torrentInfo?->getId() === $torrentId) return 0; try { $this->torrentInfo = $this->torrentsCtx->getTorrents()->getTorrent($torrentId); } catch(RuntimeException $ex) { return 404; } $canDownload = $this->torrentsCtx->canDownloadTorrent($this->torrentInfo, $this->authInfo->getUserInfo()); if($canDownload !== '') return 403; return 0; } #[HttpGet('/info/([0-9]+)')] public function getInfo($response, $request, string $torrentId) { $error = $this->getTorrentInfo($torrentId); if($error > 0) return $error; if($this->torrentInfo->hasUser()) { $users = $this->usersCtx->getUsers(); $userInfo = $users->getUser($this->torrentInfo->getUserId(), 'id'); } else $userInfo = null; $peers = $this->torrentsCtx->getPeers(); $completePeers = $peers->countCompletePeers($this->torrentInfo); $incompletePeers = $peers->countIncompletePeers($this->torrentInfo); $files = $this->torrentsCtx->getFiles(); $totalFileSize = $files->countTotalSize($this->torrentInfo); $fileList = $files->getFiles($this->torrentInfo); return $this->templating->render('info', [ 'torrent_info' => $this->torrentInfo, 'torrent_user' => $userInfo, 'torrent_total_size' => $totalFileSize, 'torrent_complete_peers' => $completePeers, 'torrent_incomplete_peers' => $incompletePeers, 'torrent_files' => $fileList, ]); } #[HttpMiddleware('/info/([0-9]+)/rehash')] #[HttpMiddleware('/info/([0-9]+)/approve')] #[HttpMiddleware('/info/([0-9]+)/deny')] public function verifyRequest($response, $request, string $torrentId) { if(!$this->authInfo->isLoggedIn()) return 401; if(!$request->isFormContent()) return 400; $content = $request->getContent(); if(!$this->csrfp->verifyToken((string)$content->getParam('_csrfp'))) return 403; $error = $this->getTorrentInfo($torrentId); if($error > 0) return $error; } #[HttpPost('/info/([0-9]+)/rehash')] public function postRehash($response, $request, string $torrentId) { $error = $this->getTorrentInfo($torrentId); if($error > 0) return $error; if(!$this->authInfo->getUserInfo()->canRecalculateInfoHash()) return 403; $builder = TorrentBuilder::import( $this->torrentInfo, $this->torrentsCtx->getPieces()->getPieces($this->torrentInfo), $this->torrentsCtx->getFiles()->getFiles($this->torrentInfo) ); $infoHash = $builder->calculateInfoHash(); $this->torrentsCtx->getTorrents()->updateTorrentInfoHash($this->torrentInfo, $infoHash); return [ 'hash' => base64_encode($infoHash), ]; } #[HttpPost('/info/([0-9]+)/approve')] public function postApprove($response, $request, string $torrentId) { $error = $this->getTorrentInfo($torrentId); if($error > 0) return $error; if(!$this->authInfo->getUserInfo()->canApproveTorrents()) return 403; $this->torrentsCtx->getTorrents()->approveTorrent($this->torrentInfo); return 204; } #[HttpPost('/info/([0-9]+)/deny')] public function postDeny($response, $request, string $torrentId) { $error = $this->getTorrentInfo($torrentId); if($error > 0) return $error; if(!$this->authInfo->getUserInfo()->canApproveTorrents()) return 403; $this->torrentsCtx->getTorrents()->deleteTorrent($this->torrentInfo); return 204; } #[HttpGet('/info.php')] public function getInfoPHP($response, $request) { $torrentId = (int)$request->getParam('id', FILTER_SANITIZE_NUMBER_INT); if($torrentId < 1) return 404; $response->redirect(sprintf('/info/%d', $torrentId), true); } #[HttpGet('/download.php')] public function getDownloadPHP($response, $request) { $torrentId = (int)$request->getParam('id', FILTER_SANITIZE_NUMBER_INT); if($torrentId < 1) return 404; $response->redirect(sprintf('/download/%d', $torrentId), true); } }