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;
}
}