install composer and run composer install'); } require_once __DIR__ . '/vendor/autoload.php'; /** * Gets the value of an environment variable. Supports boolean, empty and null. * * @param string $key * @param mixed $default * @return mixed */ function env($key, $default = null) { $value = getenv($key); if (!$value) return value($default); switch (strtolower($value)) { case 'true': case '(true)': return true; case 'false': case '(false)': return false; case '(null)': return null; case '(empty)': return ''; } return $value; } /** * Return the default value of the given value. * * @param mixed $value * @return mixed */ function value($value) { return $value instanceof Closure ? $value() : $value; } // Get initial config if (!getenv('APP_DEBUG') && file_exists(__DIR__ . '/.env')) { (new Symfony\Component\Dotenv\Dotenv())->load(__DIR__ . '/.env'); } require_once __DIR__ . '/library/config.php'; // Local config if (file_exists(__DIR__ . '/library/config.local.php')) { require_once __DIR__ . '/library/config.local.php'; } $server_protocol = $bb_cfg['cookie_secure'] ? 'https://' : 'http://'; $server_port = in_array((int)$bb_cfg['server_port'], array(80, 443), true) ? '' : ':' . $bb_cfg['server_port']; define('FORUM_PATH', $bb_cfg['script_path']); define('FULL_URL', $server_protocol . $bb_cfg['server_name'] . $server_port . $bb_cfg['script_path']); unset($server_protocol, $server_port); // Debug options define('DBG_USER', (isset($_COOKIE[COOKIE_DBG]))); // Board / tracker shared constants and functions define('BB_BT_TORRENTS', 'bb_bt_torrents'); define('BB_BT_TRACKER', 'bb_bt_tracker'); define('BB_BT_TRACKER_SNAP', 'bb_bt_tracker_snap'); define('BB_BT_USERS', 'bb_bt_users'); define('BT_AUTH_KEY_LENGTH', 10); define('PEER_HASH_PREFIX', 'peer_'); define('PEERS_LIST_PREFIX', 'peers_list_'); define('PEER_HASH_EXPIRE', round($bb_cfg['announce_interval'] * (0.85 * $bb_cfg['tracker']['expire_factor']))); // sec define('PEERS_LIST_EXPIRE', round($bb_cfg['announce_interval'] * 0.7)); // sec define('DL_STATUS_RELEASER', -1); define('DL_STATUS_DOWN', 0); define('DL_STATUS_COMPLETE', 1); define('DL_STATUS_CANCEL', 3); define('DL_STATUS_WILL', 4); define('TOR_TYPE_GOLD', 1); define('TOR_TYPE_SILVER', 2); define('GUEST_UID', -1); define('BOT_UID', -746); /** * Progressive error reporting */ if ($bb_cfg['bugsnag']['enabled']) { if (env('APP_ENV', 'production') !== 'local') { /** @var Bugsnag\Handler $bugsnag */ $bugsnag = Bugsnag\Client::make($bb_cfg['bugsnag']['api_key']); Bugsnag\Handler::register($bugsnag); } } else { if (DBG_USER) { /** @var Whoops\Run $whoops */ $whoops = new \Whoops\Run; $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler); $whoops->register(); } } /** * Database */ $DBS = new TorrentPier\Legacy\Dbs($bb_cfg); function DB($db_alias = 'db') { global $DBS; return $DBS->get_db_obj($db_alias); } /** * Cache */ $CACHES = new TorrentPier\Legacy\Caches($bb_cfg); function CACHE($cache_name) { global $CACHES; return $CACHES->get_cache_obj($cache_name); } /** * Datastore */ switch ($bb_cfg['datastore_type']) { case 'memcache': $datastore = new TorrentPier\Legacy\Datastore\Memcache($bb_cfg['cache']['memcache'], $bb_cfg['cache']['prefix']); break; case 'sqlite': $default_cfg = array( 'db_file_path' => $bb_cfg['cache']['db_dir'] . 'datastore.sqlite.db', 'pconnect' => true, 'con_required' => true, ); $datastore = new TorrentPier\Legacy\Datastore\Sqlite($default_cfg, $bb_cfg['cache']['prefix']); break; case 'redis': $datastore = new TorrentPier\Legacy\Datastore\Redis($bb_cfg['cache']['redis'], $bb_cfg['cache']['prefix']); break; case 'filecache': default: $datastore = new TorrentPier\Legacy\Datastore\File($bb_cfg['cache']['db_dir'] . 'datastore/', $bb_cfg['cache']['prefix']); } function is_ajax(): bool { return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); } function sql_dbg_enabled() { return (SQL_DEBUG && DBG_USER && !empty($_COOKIE['sql_log'])); } function short_query($sql, $esc_html = false) { $max_len = 100; $sql = str_compact($sql); if (!empty($_COOKIE['sql_log_full'])) { if (mb_strlen($sql, 'UTF-8') > $max_len) { $sql = mb_substr($sql, 0, 50) . ' [...cut...] ' . mb_substr($sql, -50); } } return $esc_html ? htmlCHR($sql, true) : $sql; } // Functions function utime() { return array_sum(explode(' ', microtime())); } function bb_log($msg, $file_name) { if (is_array($msg)) { $msg = implode(LOG_LF, $msg); } $file_name .= (LOG_EXT) ? '.' . LOG_EXT : ''; return file_write($msg, LOG_DIR . '/' . $file_name); } function file_write($str, $file, $max_size = LOG_MAX_SIZE, $lock = true, $replace_content = false) { $bytes_written = false; if ($max_size && file_exists($file) && filesize($file) >= $max_size) { $old_name = $file; $ext = ''; if (preg_match('#^(.+)(\.[^\\\/]+)$#', $file, $matches)) { [$old_name, $ext] = $matches; } $new_name = $old_name . '_[old]_' . date('Y-m-d_H-i-s_') . getmypid() . $ext; clearstatcache(); if (!file_exists($new_name)) { rename($file, $new_name); } } if (bb_mkdir(dirname($file))) { if ($fp = fopen($file, 'ab+')) { if ($lock) { flock($fp, LOCK_EX); } if ($replace_content) { ftruncate($fp, 0); fseek($fp, 0, SEEK_SET); } $bytes_written = fwrite($fp, $str); fclose($fp); } } return $bytes_written; } function bb_mkdir($path, $mode = 0777) { $old_um = umask(0); $dir = mkdir_rec($path, $mode); umask($old_um); return $dir; } function mkdir_rec($path, $mode) { if (is_dir($path)) { return ($path !== '.' && $path !== '..') ? is_writable($path) : false; } return mkdir_rec(dirname($path), $mode) ? mkdir($path, $mode) : false; } function verify_id($id, $length) { return (is_string($id) && preg_match('#^[a-zA-Z0-9]{' . $length . '}$#', $id)); } function clean_filename($fname) { static $s = array('\\', '/', ':', '*', '?', '"', '<', '>', '|', ' '); return str_replace($s, '_', str_compact($fname)); } /** * Декодирование оригинального IP * @param $ip * @return string */ function encode_ip($ip) { return Longman\IPTools\Ip::ip2long($ip); } /** * Восстановление декодированного IP * @param $ip * @return string */ function decode_ip($ip) { return Longman\IPTools\Ip::long2ip($ip); } /** * Проверка IP на валидность * * @param $ip * @return bool */ function verify_ip($ip) { return Longman\IPTools\Ip::isValid($ip); } function bb_crc32($str) { return (float)sprintf('%u', crc32($str)); } function hexhex($value) { return dechex(hexdec($value)); } /** * @param string $str * @return string */ function str_compact($str) { return preg_replace('#\s+#u', ' ', trim($str)); } /** * Generate a "random" alphanumeric string. * * Should not be considered sufficient for cryptography, etc. * * @param int|string $length * @return string */ function make_rand_str($length = 10): string { $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; return substr(str_shuffle(str_repeat($pool, (int)$length)), 0, $length); } function array_deep(&$var, $fn, $one_dimensional = false, $array_only = false) { if (is_array($var)) { foreach ($var as $k => $v) { if (is_array($v)) { if ($one_dimensional) { unset($var[$k]); } elseif ($array_only) { $var[$k] = $fn($v); } else { array_deep($var[$k], $fn); } } elseif (!$array_only) { $var[$k] = $fn($v); } } } elseif (!$array_only) { $var = $fn($var); } } function hide_bb_path($path) { return ltrim(str_replace(BB_PATH, '', $path), '/\\'); } function sys($param) { switch ($param) { case 'la': return function_exists('sys_getloadavg') ? implode(' ', sys_getloadavg()) : 0; break; case 'mem': return memory_get_usage(); break; case 'mem_peak': return memory_get_peak_usage(); break; default: trigger_error("invalid param: $param", E_USER_ERROR); } } function ver_compare($version1, $operator, $version2) { return version_compare($version1, $version2, $operator); } function dbg_log($str, $file) { $dir = LOG_DIR . (defined('IN_TRACKER') ? '/dbg_tr/' : '/dbg_bb/') . date('m-d_H') . '/'; return file_write($str, $dir . $file, false, false); } function log_get($file = '', $prepend_str = false) { log_request($file, $prepend_str, false); } function log_post($file = '', $prepend_str = false) { log_request($file, $prepend_str, true); } function log_request($file = '', $prepend_str = false, $add_post = true) { global $user; $file = $file ?: 'req/' . date('m-d'); $str = array(); $str[] = date('m-d H:i:s'); if ($prepend_str !== false) { $str[] = $prepend_str; } if (!empty($user->data)) { $str[] = $user->id . "\t" . html_entity_decode($user->name); } $str[] = sprintf('%-15s', $_SERVER['REMOTE_ADDR']); if (isset($_SERVER['REQUEST_URI'])) { $str[] = $_SERVER['REQUEST_URI']; } if (isset($_SERVER['HTTP_USER_AGENT'])) { $str[] = $_SERVER['HTTP_USER_AGENT']; } if (isset($_SERVER['HTTP_REFERER'])) { $str[] = $_SERVER['HTTP_REFERER']; } if (!empty($_POST) && $add_post) { $str[] = "post: " . str_compact(urldecode(http_build_query($_POST))); } $str = implode("\t", $str) . "\n"; bb_log($str, $file); } // Board or tracker init if (!defined('IN_TRACKER')) { require INC_DIR . '/init_bb.php'; } else { define('DUMMY_PEER', pack('Nn', ip2long($_SERVER['REMOTE_ADDR']), !empty($_GET['port']) ? (int)$_GET['port'] : random_int(1000, 65000))); function dummy_exit($interval = 1800) { $output = \Rych\Bencode\Bencode::encode([ 'interval' => (int)$interval, 'min interval' => (int)$interval, 'peers' => (string)DUMMY_PEER, ]); die($output); } header('Content-Type: text/plain'); header('Pragma: no-cache'); if (!defined('IN_ADMIN')) { // Exit if tracker is disabled via ON/OFF trigger if (file_exists(BB_DISABLED)) { dummy_exit(random_int(60, 2400)); } } }