action = $params['action'] : FALSE; } } /** * Выдача контента в зависимости от места нахождения пользователя на сайте * * @return HTML */ public function getContent() { //Если действие существует - выполняем обработку, если нет - выдать главную if ($this->action && method_exists($this, "Action" . $this->action)) { return $this->{"Action" . $this->action}(); } //Если передан текст ошибки - приготовим его к показу $error = htmlspecialchars(strip_tags(urldecode(request("error", "")))); return $this->TMPL->template("upload", array( 'error' => $error )); } /** * Обработка запроса на загрузку пропатченного торента * */ public function ActionDownload() { //Если торент был пропатчен то его можно выдать. if (sizeof($_SESSION['torrent'])) { $this->Download(); } go2url("/"); } /** * Выдача torrent файла * */ private function Download() { //Возьмём файл из сессии $torrent = $_SESSION['torrent']; //Поствим флаг что мы его уже пропатчили $torrent['patched'] = 1; //Закодируем bencode $torrent = $this->BITE->encode_array($torrent); header('Content-Type: application/x-bittorrent; name="_' . $_SESSION['torrent_name'] . '"', TRUE); header('content-disposition: attachment; filename="_' . $_SESSION['torrent_name'] . '"', TRUE); header('Content-Length: ' . strlen($torrent)); while (@ob_end_clean()); die($torrent); } /** * Обработка меню настройки параметров * * @return HTML */ public function ActionConfig() { //Если не сохраняем то выдать то что есть if (!isset($_REQUEST['save'])) { $citys = $this->RETR->GetCitys(); $i = 0; $sorted = array(); foreach ($citys as $one) { $i++; $cur = &$sorted[]; $cur['num'] = $i; $cur['name'] = $one; } $sorted = ArraySortByField($sorted, "name"); return $this->TEMPL->template("config", array( "blacklist" => isset($_SESSION['info']['blacklist']) ? $_SESSION['info']['blacklist'] : array(), "mylist" => isset($_SESSION['info']['mylist']) ? $_SESSION['info']['mylist'] : array(), "citys" => $sorted, "isps" => isset($_SESSION['info']['stat']['city']) && $_SESSION['info']['stat']['city'] > 0 ? $this->RETR->GetProviders($_SESSION['info']['stat']['city']) : array() )); } $stat = (bool)request("stat", false); $local = (bool)request("local", false); $city = (int)request("city", ""); $isp = (int)request("isp", ""); //Настройки сохраним в сессии. $_SESSION['info'] = array(); $_SESSION['info']['stat'] = array(); if ($stat) { $_SESSION['info']['stat']['stat'] = TRUE; $_SESSION['info']['stat']['city'] = $city; $_SESSION['info']['stat']['isp'] = $isp; } else { unset($_SESSION['info']['stat']['stat']); } if ($local) { $_SESSION['info']['stat']['local'] = TRUE; } else { unset($_SESSION['info']['stat']['local']); } $blacklist = request("blacklist", ""); $blacklist = explode("\r\n", $blacklist); $mylist = request("mylist", ""); $mylist = explode("\r\n", $mylist); $_SESSION['info']['blacklist'] = (array)$blacklist; $_SESSION['info']['mylist'] = (array)$mylist; go2url("/settings/"); } /** * Обработка меню настройки редактирования торента * * @return HTML */ public function ActionEdit() { //Если торент файл был пропатчен ранее то не обрабатываем его. if (isset($_SESSION['torrent']['patched'])) { $_SESSION['torrent'] = array(); $_SESSION['torrent_name'] = ""; $_SESSION['compressed'] = array(); } //Обработка AJAX-а $js_req = (int)request("js_req", ""); if ($js_req > 0) { $out = ""; if ($js_req === 1) { //Сформируем список провайдеров в указанном городе $city = (int)request("isp_list", ""); $out .= ''; $i = 0; foreach ($this->RETR->GetProviders($city) as $isp) { $i++; $out .= ''; } while (@ob_end_clean()); die($out); } else if ($js_req === 2) { //Сформируем список ретрекеров по указанным городу и провайдеру $out = array(); $city = (int)request("city", ""); $isp = (int)request("isp", ""); $retrackers = request("retrackers", ""); if ($city > 0 && $isp > 0 && !$retrackers) { //Если ретрекеров не передано заранее то возьмём их из БД $retrackers = $city > 0 && $isp > 0 ? $this->RETR->GetRetrackersOld($city, $isp) : array(); $out += (array)isset($_SESSION['compressed']) ? $_SESSION['compressed'] : array(); } else { $retrackers = request("retrackers", ""); $retrackers = str_replace("\r\n", "\n", $retrackers); if (strpos($retrackers, "|||") !== FALSE) { $retrackers = explode("|||", $retrackers); } else { $retrackers = explode("\n", $retrackers); } } foreach ($retrackers as $retracker) { //Если список ретрекеров был из БД то каждая запись - массив параметорв ретрекера, нам же нужен только сам ретрекер if (is_array($retracker)) { if (isset($retracker['retracker']) && strlen($retracker['retracker']) && strpos($retracker['retracker'], "/retracker.local") === FALSE) { $out[] = $retracker['retracker']; } } else { if (strlen($retracker) && strpos($retracker, "/retracker.local") === FALSE) { $out[] = $retracker; } } } $out = implode("\r\n", $out); while (@ob_end_clean()); if (!isset($_REQUEST['json'])) { die($out); } die(json_encode($out)); } } //Сохранение параметорв, «патчинг» if (isset($_REQUEST['write'])) { $this->url = request("announce", ""); $this->list = request("retrackers", ""); $this->stat = (bool)request("stat", false); $this->local = (bool)request("local", false); $this->city = (int)request("city", ""); $this->isp = (int)request("isp", ""); $this->Patch(TRUE); go2url("/download/"); } $citys = $this->RETR->GetCitys(); $i = 0; $sorted = array(); //Сохранение номера города для совместимости со старыми версиями патчера foreach ($citys as $one) { $i++; $cur = &$sorted[]; $cur['num'] = $i; $cur['name'] = $one; } //Подготовим итоговый список ретрекеров который будет записан в торент $this->Prepare(); //Сортируем по-человечески $sorted = ArraySortByField($sorted, "name"); return $this->TEMPL->template("edit", array( "torrent" => $_SESSION['torrent'], "trackers" => $this->compressed, "citys" => $sorted, "isps" => isset($_SESSION['info']['stat']['city']) && $_SESSION['info']['stat']['city'] > 0 ? $this->RETR->GetProviders($_SESSION['info']['stat']['city']) : array() )); } /** * Первичная загрузка торента * */ public function ActionUpload() { $this->Upload(); go2url("/edit/"); } /** * Обработка торента по API * * @return HTML|torrent */ public function ActionPatch() { if (isset($_POST['patch'])) { //Если постипила команда на обработку - соберём все параметры $this->url = request("announce", ""); $this->use_settings = (bool)request("use_settings", TRUE); $this->list = request("retrackers", ""); $this->local = (bool)request("local", FALSE); $this->stat = (bool)request("stat", FALSE); $this->city = (int)request("city", ""); $this->isp = (int)request("isp", ""); //Если разрешено использовать настройки, хранящиеся на сайте if ($this->use_settings) { if (isset($_SESSION['info'])) { $this->local = isset($_SESSION['info']['stat']) && isset($_SESSION['info']['stat']['local']) ? (bool)$_SESSION['info']['stat']['local'] : $this->local; $this->stat = isset($_SESSION['info']['stat']) && isset($_SESSION['info']['stat']['stat']) ? (bool)$_SESSION['info']['stat']['stat'] : $this->stat; $this->city = isset($_SESSION['info']['stat']) && isset($_SESSION['info']['stat']['city']) ? (int)$_SESSION['info']['stat']['city'] : $this->city; $this->isp = isset($_SESSION['info']['stat']) && isset($_SESSION['info']['stat']['isp']) ? (int)$_SESSION['info']['stat']['isp'] : $this->isp; } } $this->Upload(FALSE); $this->Prepare(); $this->Patch(FALSE); $this->Download(); } else { return $this->TEMPL->template("patch", array()); } } /** * Подготовка списка ретрекеров для записи в торент в соответствиями с «чёрным списком» * * @return true */ private function Prepare() { $this->compressed = array(); if (isset($_SESSION['torrent']['announce-list']) && is_array($_SESSION['torrent']['announce-list']) && sizeof($_SESSION['torrent']['announce-list'])) { //Если в торенте уже есть какие-то ретрекеры - сохраним их foreach ($_SESSION['torrent']['announce-list'] as $group) { foreach ($group as $tracker) { $this->compressed[] = $tracker; } } } else { $_SESSION['torrent']['announce-list'] = array(); } $_SESSION['compressed'] = $this->compressed; //Если announce не задан - выберем первый ретрекер if ((!isset($_SESSION['torrent']['announce']) || !$_SESSION['torrent']['announce']) && sizeof($this->compressed)) { $_SESSION['torrent']['announce'] = current($this->compressed); } //Обработка «чёрного списка» $this->CheckBlackList(); return TRUE; } /** * Загрузка торента в сессию * * @param bool $show_errors Показывать ошибки в html или выдавать через die */ private function Upload($show_errors = true) { $link = request("url", ""); $_SESSION['torrent'] = array(); $_SESSION['torrent_name'] = array(); $_SESSION['compressed'] = array(); //Обработка ссылки или файла if ($link) { //Загрузка файла по указанной ссылке list($prefix, $host, ) = $this->URLS->explodeURL($link); $this->CURL->setReferer($prefix . "://" . $host); $this->CURL->_includeHeader = true; $this->CURL->_noBody = true; $this->CURL->createCurl($link); //Проверка заголовков, что попало не качаем $headers = $this->CURL->getHeaders(); if (!isset($headers['content_type']) || ($headers['content_type'] != "application/x-bittorrent" && $headers['content_type'] != "application/octet-stream")) { $this->Error("Некорректный заголовок Content-Type", $show_errors); } if (!isset($headers['download_content_length']) || $headers['download_content_length'] > 256 * 1024) { $this->Error("Файл, скачиваемый по указанной ссылке слишком большой, максимальный размер = 256Кб", $show_errors); } $this->CURL->_includeHeader = false; $this->CURL->_noBody = false; $this->CURL->createCurl($link); //Собственно загрузка $file = $this->CURL->__toString(); try { //Раскодирование торент файла $file = $this->BITD->decode($file); } catch (Exception $e) { $this->Error("Ошибка при декодировании файла: " . $e->getMessage(), $show_errors); } //Заполнение сессии $_SESSION['torrent'] = $file; $_SESSION['torrent_name'] = isset($file['info']['name']) ? $file['info']['name'] . ".torrent" : "Unk" . time() . ".torrent"; } else { if (!isset($_FILES['file'])) { $this->Error("Выберите файл", $show_errors); } if (!is_uploaded_file($_FILES['file']['tmp_name'])) { //На всякий случай @unlink($_FILES['file']['tmp_name']); $this->Error("Во время загрузки файла произошла ошибка.", $show_errors); } //После обработки файл больше не нужен register_shutdown_function("unlink", $_FILES['file']['tmp_name']); try { $this->BITD->decodeFile($_FILES['file']['tmp_name']); $_SESSION['torrent'] = $this->BITD->getDecoded(); $_SESSION['torrent_name'] = $_FILES['file']['name']; } catch (Exception $e) { $_SESSION['torrent'] = array(); $_SESSION['torrent_name'] = ""; $this->Error("Во время обработки файла произошла ошибка. Стоит заметить, что торенты, пропатченные программой TorrentPatcher не поддерживаются, т.к. не соответствуют спецификации протокола Bittorrent (нарушена внутренняя структура).", $show_errors); } } if (isset($_SESSION['torrent']['patched'])) { $_SESSION['torrent'] = array(); $_SESSION['torrent_name'] = ""; $_SESSION['compressed'] = array(); $this->Error("Данный файл уже был пропатчен.", $show_errors); } //Если список ретрекеров пуст - перенесём туда основной трекер чтобы не потерять трафик if (!isset($_SESSION['torrent']['announce-list']) || !sizeof($_SESSION['torrent']['announce-list'])) { $_SESSION['torrent']['announce-list'][] = array( $_SESSION['torrent']['announce'] ); } //Если в настройках заданы ретрекеры - добавим их в список if (isset($_SESSION['info']['mylist']) && sizeof($_SESSION['info']['mylist'])) { foreach ($_SESSION['info']['mylist'] as $one) { if (strlen($one)) { $_SESSION['torrent']['announce-list'][] = array( $one ); } } } return; } /** * Возврат текста ошибки * * @param string $text Текст ошибки * @param bool $show_error Выдать на главной или через die (для API) */ private function Error($text, $show_error = true) { $show_error ? go2url(path("/", "error=" . urlencode($text))) : _die("" . $text . "
Обновите страничку и попробуйте повторить операцию."); } /** * Обработка торента в соответствии с заданныими параметрами * * @param bool $clear_list Не использовать торенты из оригинального файла */ private function Patch($clear_list = true) { //Если задан список ретрекеров - проверим что это массив if (!is_array($this->list) && trim($this->list)) { $this->list = explode("\n", str_replace("\r\n", "\n", trim($this->list))); } else { $this->list = array(); } $satistic = array(); if ($this->stat) { //Подключение статистики на re-tracker.ru $satistic[] = "name=" . (isset($_SESSION['torrent']['info']['name']) ? urlencode($_SESSION['torrent']['info']['name']) : ""); $satistic[] = "comment=" . (isset($_SESSION['torrent']['comment']) ? urlencode($_SESSION['torrent']['comment']) : ""); if (isset($_SESSION['torrent']['info']['length'])) { $satistic[] = "size=" . (double)$_SESSION['torrent']['info']['length']; } else if (isset($_SESSION['torrent']['info']['files'])) { $size = 0; foreach ($_SESSION['torrent']['info']['files'] as $file) { $size += (double)$file['length']; } $satistic[] = "size=" . $size; } if ($this->city && $this->isp) { $satistic[] = "isp=" . $this->city . "+" . $this->isp . "&"; } //Сохраним парамерты в настройках $_SESSION['info']['stat']['stat'] = TRUE; $_SESSION['info']['stat']['city'] = $this->city; $_SESSION['info']['stat']['isp'] = $this->isp; } else { unset($_SESSION['info']['stat']['stat']); } $satistic = implode("&", $satistic); //Если нужно - заменяем основной annouce $this->url ? $_SESSION['torrent']['announce'] = $this->url : FALSE; //Обработка списков ретрекеров if (!$clear_list) { $this->list = is_array($this->list) ? $this->list : array(); $this->list += $this->compressed; } //Очистка списка $_SESSION['torrent']['announce-list'] = array(); //Если нужно подключить локальный ретрекер if ($this->local) { $_SESSION['info']['stat']['local'] = TRUE; array_unshift($_SESSION['torrent']['announce-list'], array( "http://retracker.local/announce" )); } else { unset($_SESSION['info']['stat']['local']); } //Если есть что записать в торент файл - обрабатываем его if (sizeof($this->list)) { foreach ($this->list as $url) { $url = trim($url); if (strlen($url) && strpos($url, "http://retracker.local") === FALSE && strpos($url, "http://re-tracker.ru") === FALSE) { $_SESSION['torrent']['announce-list'][] = array( $url ); } } //При необходимости добавим статистику if ($this->stat) { $_SESSION['torrent']['announce-list'][] = array( "http://re-tracker.ru/a?" . $satistic ); } //Проверка чёрного списка $this->CheckBlackList(); } else { unset($_SESSION['torrent']['announce-list']); } } /** * Проверка чёрного списка - удаление не нужных ретрекеров * */ private function CheckBlackList() { $_SESSION['info']['to_del'] = array(); //Если проверять не чего то ничего и не делаем if (!isset($_SESSION['torrent']['announce-list']) || !sizeof($_SESSION['torrent']['announce-list'])) { return TRUE; } if (isset($_SESSION['info']['blacklist']) && sizeof($_SESSION['info']['blacklist'])) { foreach ($_SESSION['torrent']['announce-list'] as $key1 => $row) { if (is_array($row)) { foreach ($row as $key2 => $one) { if (strlen($one)) { foreach ($_SESSION['info']['blacklist'] as $del) { if (!empty($del) && strpos($one, $del) !== FALSE) { unset($_SESSION['torrent']['announce-list'][$key1][$key2]); } } } } } else { if (strlen($row)) { foreach ($_SESSION['info']['blacklist'] as $del) { if (!empty($del) && strpos($row, $del) !== FALSE) { unset($_SESSION['torrent']['announce-list'][$key1]); } } } } } } return TRUE; } }