0){ return true; } if(isset($data["path"]) and ($data["host"] == "anirena.com" or $data["host"] == "www.anirena.com") and preg_match("#^/dl/[0-9]+$#", $data["path"]) > 0){ return true; } if(isset($data["path"]) and ($data["host"] == "www.frozen-layer.com" or $data["host"] == "frozen-layer.com") and preg_match("#^/descargas/([0-9]+.*)$#", $data["path"], $matches) > 0){ $url = "https://www.frozen-layer.com/descargas/".$matches[1] .".torrent"; return true; } if(isset($data["path"]) and ($data["host"] == "anidex.info" or $data["host"] == "anidex.moe") and preg_match("#page=torrent&id=([0-9]+)$#", $data["path"], $matches) > 0){ $url = "https://anidex.info/dl/".$matches[1]; return true; } if(isset($data["path"]) and ($data["host"] == "anidex.info" or $data["host"] == "anidex.moe") and preg_match("#/torrent/([0-9]+)$#", $data["path"], $matches) > 0){ $url = "https://anidex.info/dl/".$matches[1]; return true; } //if(isset($data["path"]) and ($data["host"] == "nyaa.se" or $data["host"] == "www.nyaa.se") and preg_match("#page=download&tid=/.*$#", $data["path"]) > 0){ //return true; //} if(isset($data["path"]) and ($data["host"] == "nyaa.si" or $data["host"] == "www.nyaa.si") and preg_match("#view/[0-9]+/torrent$#", $data["path"]) > 0){ return true; } if(isset($data["path"]) and $data["host"] == "animebytes.tv" and preg_match("#torrent/[0-9]+/download#", $data["path"]) > 0){ return true; } if(isset($data["path"]) and ($data["host"] == "nyaa.se" or $data["host"] == "nyaa.eu" or $data["host"] == "www.nyaa.se") and preg_match("#page=(view|download)&tid=/.*$#", $data["path"], $matches) > 0){ $url = "https://nyaa.si/view/".$matches[1]."/torrent"; return true; } if(isset($data["path"]) and ($data["host"] == "nyaa.si" or $data["host"] == "www.nyaa.si") and preg_match("#view/([0-9]+)(|/torrent|\\.torrent)$#", $data["path"], $matches) > 0){ $url = "https://nyaa.si/view/".$matches[1]."/torrent"; return true; } return false; } public static function isPrivateTorrent($url){ $data = parse_url($url); if(!isset($data["host"])){ return false; } $domains = Database::getConfigKey("tracker.domain.private", []); return in_array($data["host"], $domains); } public static function getMagnetProperties($magnetUrl){ $data = parse_url($magnetUrl); if(!isset($data["query"]) or $data["scheme"] != "magnet"){ return []; } parse_str($data["query"], $query); return $query; } public static function getMagnetHash($magnetUrl){ $props = self::getMagnetProperties($magnetUrl); if(isset($props["xt"]) and preg_match('/urn:btih:[ ]*([A-Za-z0-9]{32,40})/', $props["xt"], $matches) > 0){ $hash = $matches[1]; if(strlen($hash) == 32){ $hash = bin2hex(Base32::decode($hash)); } $hash = strtoupper($hash); return $hash; } return null; } public static function queueMagnetTorrent($magnet, $cachePath = null){ if(!Database::getConfigKey("magnet.service.enable", false) or Database::getConfigKey("magnet.service.folder", "") === ""){ return false; } $hash = self::getMagnetHash($magnet); if($hash !== null and $cachePath !== null and file_exists($cachePath . "/". $hash . ".torrent")){ return true; } if($hash === null){ Downloader::log("Failed to magnet ".$hash." to MagnetService ($magnet)", "TORRENT"); return false; } file_put_contents(Database::getConfigKey("magnet.service.folder", "") . "/" . $hash . ".magnet", $magnet); #Downloader::log("Added magnet ".$hash." to MagnetService", "TORRENT"); return true; } public static function getTorrent($url, $cachePath = null){ $contents = null; if(strpos($url, "urn:btih:") !== false){ $hash = self::getMagnetHash($url); if($hash === null){ return ""; } $path = $cachePath . "/". $hash . ".torrent"; if($cachePath !== null and file_exists($path)){ $contents = file_get_contents($path); }else{ self::queueMagnetTorrent($url, $cachePath); return null; } }else{ $path = $cachePath . "/url_" . md5($url) . ".torrent"; if($cachePath !== null and file_exists($path)){ $contents = file_get_contents($path); } if(($contents === "" and !Database::getConfigKey("torrent.cache.addEmpty", false)) or $contents === null){ $contents = Request::getURL($url); if(self::isPrivateTorrent($url)){ sleep(Database::getConfigKey("tracker.private.fetchDelay", 5)); } if($cachePath !== null and strlen($contents) > 40){ file_put_contents($path, $contents); }elseif($cachePath !== null and Database::getConfigKey("torrent.cache.addEmpty", false)){ file_put_contents($path, ""); } } } return $contents; } public static function fromURL($url, $cachePath = null){ if(isset(self::$urls[$url])){ return self::$urls[$url]; } $contents = self::getTorrent($url, $cachePath); if($contents === null){ return null; } $t = new Torrent($contents); $hash = $t->getInfoHash(); if($contents != "" and $hash != null and $cachePath !== null and !file_exists($cachePath . "/" . $hash . ".torrent")){ file_put_contents($cachePath . "/" . $hash . ".torrent", $contents); } if($contents == ""){ return $t; } return self::$urls[$url] = $t; } public function __construct($contents){ $c = self::bdecode($contents); if(!is_array($c)){ return; } $this->announce = isset($c["announce-list"]) ? $c["announce-list"] : isset($c["announce"]) ? [[$c["announce"]]] : []; $this->creationDate = isset($c["creation-date"]) ? $c["creation-date"] : time(); if(isset($c["info"]["files"])){ foreach($c["info"]["files"] as $file){ //Damn padding files if(strpos($file["path"][0], "_____padding_file") === 0){ continue; } array_unshift($file["path"], $c["info"]["name"]); $this->files[] = [ "size" => $file["length"], "path" => $file["path"], "stringPath" => implode("/", $file["path"]), ]; } }else{ $this->files[] = [ "size" => $c["info"]["length"], "path" => [$c["info"]["name"]], "stringPath" => $c["info"]["name"], ]; } $this->info = $c["info"]; $this->info_hash = $c["info_hash"]; } public function getCreationDate(){ return $this->creationDate; } public function getFiles(){ return $this->files; } public function getInfoHash(){ return $this->info_hash; } private static function bdecode($s, &$pos = 0, $depth = 0) { if($pos>=strlen($s)) { return null; } switch($s[$pos]){ case 'd': $pos++; $retval=array(); while (isset($s[$pos]) and $s[$pos]!='e'){ $key=self::bdecode($s, $pos, $depth + 1); $origPos = $pos; $val=self::bdecode($s, $pos, $depth + 1); if ($key===null || $val===null) break; $retval[$key]=$val; if($key === "info" and $depth <= 1){ $retval["info_hash"] = strtoupper(sha1(substr($s, $origPos, $pos - $origPos))); } } $retval["isDct"]=true; $pos++; return $retval; case 'l': $pos++; $retval=array(); while ($s[$pos]!='e'){ $val=self::bdecode($s, $pos, $depth + 1); if ($val===null) break; $retval[]=$val; } $pos++; return $retval; case 'i': $pos++; $digits=strpos($s, 'e', $pos)-$pos; $val=round((float)substr($s, $pos, $digits)); $pos+=$digits+1; return $val; // case "0": case "1": case "2": case "3": case "4": // case "5": case "6": case "7": case "8": case "9": default: $digits=strpos($s, ':', $pos)-$pos; if ($digits<0 || $digits >20) return null; $len=(int)substr($s, $pos, $digits); $pos+=$digits+1; $str=substr($s, $pos, $len); $pos+=$len; //echo "pos: $pos str: [$str] len: $len digits: $digits\n"; return (string)$str; } return null; } }