$reason])); } if(empty($_GET)) die('There is nothing here.'); header('Content-Type: text/plain; charset=us-ascii'); header('X-Tracker-Version: Seria/' . SERIA_VERSION); if(!$sIsIPv4) announce_fail('Tracker is only supported over IPv4, please reset your DNS cache.'); //file_put_contents(SERIA_ERRORS, $_SERVER['REQUEST_URI'] . PHP_EOL, FILE_APPEND); $urlParts = explode('/', trim($_SERVER['PATH_INFO'], '/')); $cInfoHash = (string)filter_input(INPUT_GET, 'info_hash'); if(strlen($cInfoHash) !== 20) announce_fail('Invalid info hash.'); $cPeerId = (string)filter_input(INPUT_GET, 'peer_id'); if(strlen($cPeerId) !== 20) announce_fail('Invalid peer id format.'); $cPeerAddress = $_SERVER['REMOTE_ADDR']; $cPeerPort = (int)filter_input(INPUT_GET, 'port', FILTER_SANITIZE_NUMBER_INT); if($cPeerPort < 1 || $cPeerPort > 0xFFFF) announce_fail('Invalid port number.'); $cPeerKey = (string)filter_input(INPUT_GET, 'key'); if(strlen($cPeerKey) > 128) announce_fail('Key is ridiculous.'); $cPeerEvent = (string)filter_input(INPUT_GET, 'event'); if(strlen($cPeerEvent) > 128) announce_fail('Event is fucked up.'); $cPeerAgent = (string)filter_input(INPUT_SERVER, 'HTTP_USER_AGENT'); if(strlen($cPeerAgent) > 255) announce_fail('Agent is stupid.'); $cCompactPeers = !empty($_GET['compact']); $cNoPeerId = !empty($_GET['no_peer_id']); $cShortAnnounce = !empty($_GET['short']); $cBytesUploaded = (int)filter_input(INPUT_GET, 'uploaded', FILTER_SANITIZE_NUMBER_INT); $cBytesDownloaded = (int)filter_input(INPUT_GET, 'downloaded', FILTER_SANITIZE_NUMBER_INT); $cBytesRemaining = (int)filter_input(INPUT_GET, 'left', FILTER_SANITIZE_NUMBER_INT); $cPeerWant = (int)filter_input(INPUT_GET, 'numwant', FILTER_SANITIZE_NUMBER_INT); $cPassKey = $urlParts[0] ?? ''; if(!empty($cPassKey)) { try { $cUserInfo = SeriaUser::byPassKey($pdo, $cPassKey); } catch(SeriaUserNotFoundException $ex) { sleep(3); announce_fail('Authentication failed.'); } } else $cUserInfo = SeriaUser::anonymous(); $interval = SERIA_ANNOUNCE_INTERVAL; $minInterval = SERIA_ANNOUNCE_INTERVAL_MIN; if($cShortAnnounce && SERIA_ANNOUNCE_SHORT) { $interval = SERIA_ANNOUNCE_SHORT_INTERVAL; $minInterval = SERIA_ANNOUNCE_SHORT_INTERVAL_MIN; } try { $cTorrentInfo = SeriaTorrent::byHash($pdo, $cInfoHash); } catch(SeriaTorrentNotFoundException $ex) { announce_fail('Info hash not found.'); } $cCanDownload = $cTorrentInfo->canDownload($cUserInfo); if($cCanDownload !== '') switch($cCanDownload) { case 'inactive': announce_fail('This download is inactive.'); case 'private': announce_fail('You must be logged in for this download.'); case 'pending': announce_fail('This download is pending approval.'); default: announce_fail($cCanDownload); } $cPeerInfo = SeriaTorrentPeer::byPeerId($pdo, $cTorrentInfo, $cPeerId); if(empty($cPeerInfo)) { // could probably skip this is the event is 'stopped' $cPeerInfo = SeriaTorrentPeer::create( $pdo, $cTorrentInfo, $cUserInfo, $cPeerId, $cPeerAddress, $cPeerPort, $interval, $cPeerAgent, $cPeerKey, $cBytesUploaded, $cBytesDownloaded, $cBytesRemaining ); } else { if(!$cPeerInfo->verifyKey($cPeerKey)) { sleep(3); announce_fail('Peer verification failed.'); } if(!$cPeerInfo->verifyUser($cUserInfo)) { sleep(3); announce_fail('User verification failed.'); } $cUserInfo->incrementTransferCounts( $cBytesDownloaded - $cPeerInfo->getBytesDownloaded(), $cBytesUploaded - $cPeerInfo->getBytesUploaded() ); $cPeerInfo->update( $cUserInfo, $cPeerAddress, $cPeerPort, $interval, $cPeerAgent, $cBytesUploaded, $cBytesDownloaded, $cBytesRemaining ); } if($cPeerEvent === 'stopped') { $cPeerInfo->delete(); die(bencode(new SeriaAnnounceResponse)); } SeriaTorrentPeer::deleteExpired($pdo); $response = new SeriaAnnounceResponse( $interval + mt_rand(0, 10), $minInterval, $cTorrentInfo, $cNoPeerId && SERIA_ANNOUNCE_NO_PEER_ID, $cCompactPeers ); if(!$cPeerInfo->isSeed() || !SERIA_ANNOUNCE_NO_SEED_P2P) { $peers = $cTorrentInfo->getSeeds($cPeerInfo); foreach($peers as $peer) $response->addPeer($peer); } echo bencode($response);