Install composer and run composer install
.
☕️ Quick install: Run php install.php
in CLI mode.');
}
require_once BB_PATH . '/vendor/autoload.php';
/**
* Gets the value of an environment variable.
*
* @param string $key
* @param mixed|null $default
* @return mixed
*/
function env(string $key, mixed $default = null): mixed
{
return \TorrentPier\Env::get($key, $default);
}
// Load ENV
try {
$dotenv = Dotenv\Dotenv::createMutable(BB_PATH);
$dotenv->load();
} catch (\Dotenv\Exception\InvalidPathException $pathException) {
die('🔩 Manual install: Rename from .env.example
to .env
, and configure it.
☕️ Quick install: Run php install.php
in CLI mode.');
}
// Load config
require_once BB_PATH . '/library/config.php';
// Local config
if (is_file(BB_PATH . '/library/config.local.php')) {
require_once BB_PATH . '/library/config.local.php';
}
/**
* Initialize debug
*/
define('APP_ENV', env('APP_ENV', 'production'));
if (APP_ENV === 'local') {
define('DBG_USER', true); // forced debug
} else {
define('DBG_USER', isset($_COOKIE[COOKIE_DBG]));
}
(new \TorrentPier\Dev());
/**
* Server variables initialize
*/
$server_protocol = $bb_cfg['cookie_secure'] ? 'https://' : 'http://';
$server_port = in_array((int)$bb_cfg['server_port'], [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);
/**
* Database
*/
$DBS = new TorrentPier\Legacy\Dbs($bb_cfg);
function DB(string $db_alias = 'db')
{
global $DBS;
return $DBS->get_db_obj($db_alias);
}
/**
* Cache
*/
$CACHES = new TorrentPier\Legacy\Caches($bb_cfg);
function CACHE(string $cache_name)
{
global $CACHES;
return $CACHES->get_cache_obj($cache_name);
}
/**
* Datastore
*/
switch ($bb_cfg['datastore_type']) {
case 'apcu':
$datastore = new TorrentPier\Legacy\Datastore\APCu($bb_cfg['cache']['prefix']);
break;
case 'memcached':
$datastore = new TorrentPier\Legacy\Datastore\Memcached($bb_cfg['cache']['memcached'], $bb_cfg['cache']['prefix']);
break;
case 'sqlite':
$datastore = new TorrentPier\Legacy\Datastore\Sqlite($bb_cfg['cache']['db_dir'] . 'datastore', $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']);
}
// Functions
function utime()
{
return array_sum(explode(' ', microtime()));
}
function bb_log($msg, $file_name = 'logs', $return_path = false)
{
if (is_array($msg)) {
$msg = implode(LOG_LF, $msg);
}
$file_name .= (LOG_EXT) ? '.' . LOG_EXT : '';
$path = (LOG_DIR . '/' . $file_name);
if ($return_path) {
return $path;
}
return file_write($msg, $path);
}
function file_write($str, $file, $max_size = LOG_MAX_SIZE, $lock = true, $replace_content = false)
{
$bytes_written = false;
clearstatcache();
if (is_file($file) && ($max_size && (filesize($file) >= $max_size))) {
$file_parts = pathinfo($file);
$new_name = ($file_parts['dirname'] . '/' . $file_parts['filename'] . '_[old]_' . date('Y-m-d_H-i-s_') . getmypid() . '.' . $file_parts['extension']);
clearstatcache();
if (!is_file($new_name)) {
rename($file, $new_name);
}
}
clearstatcache();
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): bool
{
if (is_dir($path)) {
return ($path !== '.' && $path !== '..') && is_writable($path);
}
return mkdir_rec(dirname($path), $mode) && mkdir($path, $mode);
}
function verify_id($id, $length): bool
{
return (is_string($id) && preg_match('#^[a-zA-Z0-9]{' . $length . '}$#', $id));
}
function clean_filename($fname)
{
static $s = ['\\', '/', ':', '*', '?', '"', '<', '>', '|', ' '];
return str_replace($s, '_', str_compact($fname));
}
/**
* Convert special characters to HTML entities
*
* @param $txt
* @param bool $double_encode
* @param int $quote_style
* @param ?string $charset
* @return string
*/
function htmlCHR($txt, bool $double_encode = false, int $quote_style = ENT_QUOTES, ?string $charset = DEFAULT_CHARSET): string
{
return (string)htmlspecialchars($txt ?? '', $quote_style, $charset, $double_encode);
}
/**
* @param string $str
* @return string
*/
function str_compact($str)
{
return preg_replace('/\s\s+/', ' ', trim($str ?? ''));
}
/**
* Generate a "random" alphanumeric string.
*
* Should not be considered sufficient for cryptography, etc.
*
* @param int $length
* @return string
* @throws Exception
*/
function make_rand_str(int $length = 10): string
{
$pool = str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $pool[random_int(0, 61)];
}
return $randomString;
}
/**
* Calculates user ratio
*
* @param array $btu
* @return float|null
*/
function get_bt_ratio(array $btu): ?float
{
return
(!empty($btu['u_down_total']) && $btu['u_down_total'] > MIN_DL_FOR_RATIO)
? round((($btu['u_up_total'] + $btu['u_up_release'] + $btu['u_up_bonus']) / $btu['u_down_total']), 2)
: null;
}
function array_deep(&$var, $fn, $one_dimensional = false, $array_only = false, $timeout = false)
{
if ($timeout) {
static $recursions = 0;
if (time() > (TIMENOW + $timeout)) {
return [
'timeout' => true,
'recs' => $recursions
];
}
$recursions++;
}
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, timeout: $timeout);
}
} elseif (!$array_only) {
$var[$k] = $fn($v);
}
}
} elseif (!$array_only) {
$var = $fn($var);
}
}
/**
* Hide BB_PATH
*
* @param string $path
* @return string
*/
function hide_bb_path(string $path): string
{
return ltrim(str_replace(BB_PATH, '', $path), '/\\');
}
/**
* Returns memory usage statistic
*
* @param string $param
* @return int|void
*/
function sys(string $param)
{
switch ($param) {
case 'mem':
return memory_get_usage();
case 'mem_peak':
return memory_get_peak_usage();
default:
trigger_error("invalid param: $param", E_USER_ERROR);
}
}
/**
* Some shared defines
*/
// Initialize demo mode
define('IN_DEMO_MODE', env('APP_DEMO_MODE', false));
// Ratio status
define('RATIO_ENABLED', TR_RATING_LIMITS && MIN_DL_FOR_RATIO > 0);
// Initialization
if (!defined('IN_TRACKER')) {
// Init board
require_once INC_DIR . '/init_bb.php';
} else {
define('DUMMY_PEER', pack('Nn', \TorrentPier\Helpers\IPHelper::ip2long($_SERVER['REMOTE_ADDR']), !empty($_GET['port']) ? (int)$_GET['port'] : random_int(1000, 65000)));
define('PEER_HASH_EXPIRE', round($bb_cfg['announce_interval'] * (0.85 * $bb_cfg['tracker']['expire_factor'])));
define('PEERS_LIST_EXPIRE', round($bb_cfg['announce_interval'] * 0.7));
define('SCRAPE_LIST_EXPIRE', round($bb_cfg['scrape_interval'] * 0.7));
define('PEER_HASH_PREFIX', 'peer_');
define('PEERS_LIST_PREFIX', 'peers_list_');
define('SCRAPE_LIST_PREFIX', 'scrape_list_');
// Init tracker
require_once BB_PATH . '/bt/includes/init_tr.php';
header('Content-Type: text/plain');
header('Pragma: no-cache');
if (!defined('IN_ADMIN')) {
// Exit if tracker is disabled via ON/OFF trigger
if (is_file(BB_DISABLED)) {
dummy_exit(random_int(60, 2400));
}
}
}