torrentpier/common.php
Roman Kelesidis edab2300d3
Minor improments (#1719)
* Minor improments

* Update CHANGELOG.md

* Updated

* Update common.php
2024-12-20 20:29:06 +07:00

401 lines
11 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
if (isset($_REQUEST['GLOBALS'])) {
die();
}
define('TIMESTART', utime());
define('TIMENOW', time());
define('BB_PATH', __DIR__);
if (empty($_SERVER['REMOTE_ADDR'])) {
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
}
if (empty($_SERVER['HTTP_USER_AGENT'])) {
$_SERVER['HTTP_USER_AGENT'] = '';
}
if (empty($_SERVER['HTTP_REFERER'])) {
$_SERVER['HTTP_REFERER'] = '';
}
if (empty($_SERVER['SERVER_NAME'])) {
$_SERVER['SERVER_NAME'] = getenv('SERVER_NAME');
}
if (empty($_SERVER['SERVER_ADDR'])) {
$_SERVER['SERVER_ADDR'] = getenv('SERVER_ADDR');
}
if (!defined('BB_ROOT')) {
define('BB_ROOT', './');
}
if (!defined('BB_SCRIPT')) {
define('BB_SCRIPT', null);
}
header('X-Frame-Options: SAMEORIGIN');
date_default_timezone_set('UTC');
// Set remote address
$allowedCDNs = ['HTTP_X_FORWARDED_FOR', 'HTTP_FASTLY_CLIENT_IP', 'HTTP_CF_CONNECTING_IP'];
foreach ($allowedCDNs as $allowedCDN) {
if (isset($_SERVER[$allowedCDN]) && filter_var($_SERVER[$allowedCDN], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
$_SERVER['REMOTE_ADDR'] = $_SERVER[$allowedCDN];
}
}
// Get all constants
require_once BB_PATH . '/library/defines.php';
// Composer
if (!is_file(BB_PATH . '/vendor/autoload.php')) {
die('🔩 Manual install: <a href="https://getcomposer.org/download/" target="_blank" rel="noreferrer" style="color:#0a25bb;">Install composer</a> and run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">composer install</code>.<br/>☕️ Quick install: Run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">php install.php</code> 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 <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">.env.example</code> to <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">.env</code>, and configure it.<br/>☕️ Quick install: Run <code style="background:#222;color:#00e01f;padding:2px 6px;border-radius:3px;">php install.php</code> 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';
}
/**
* Error reporting
*/
if (env('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 = 'UTF-8'): 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);
}
}
/**
* Returns version code
*
* @param string $version
* @return int
*/
function version_code(string $version): int
{
return (int)trim(str_replace(['.', 'v'], '', $version));
}
/**
* Some shared defines
*/
// Initialize demo mode
define('IN_DEMO_MODE', env('APP_DEMO_MODE', false));
// Version code
define('VERSION_CODE', version_code($bb_cfg['tp_version']));
// 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));
}
}
}