', $text);
}
function generate_user_info($row, bool $have_auth = IS_ADMIN): array
{
global $userdata, $lang, $images, $bb_cfg;
$from = !empty($row['user_from']) ? $row['user_from'] : $lang['NOSELECT'];
$joined = bb_date($row['user_regdate'], 'Y-m-d H:i', false);
$user_time = !empty($row['user_time']) ? sprintf('%s (%s)', bb_date($row['user_time']), delta_time($row['user_time'])) : $lang['NOSELECT'];
$posts = '' . $row['user_posts'] ?: 0 . '';
$pm = $bb_cfg['text_buttons'] ? '' . $lang['SEND_PM_TXTB'] . '' : '
';
$avatar = get_avatar($row['user_id'], $row['avatar_ext_id'], !bf($row['user_opt'], 'user_opt', 'dis_avatar'), 50, 50);
if (bf($row['user_opt'], 'user_opt', 'user_viewemail') || $have_auth || ($row['user_id'] == $userdata['user_id'])) {
$email_uri = ($bb_cfg['board_email_form']) ? ("profile.php?mode=email&" . POST_USERS_URL . "=" . $row['user_id']) : 'mailto:' . $row['user_email'];
$email = '' . $row['user_email'] . '';
} else {
$email = $lang['HIDDEN_USER'];
}
if ($row['user_website']) {
$www = $bb_cfg['text_buttons'] ? '' . $lang['VISIT_WEBSITE_TXTB'] . '' : '
';
} else {
$www = $lang['NOSELECT'];
}
return [
'from' => $from,
'joined' => $joined,
'joined_raw' => $row['user_regdate'],
'posts' => $posts,
'pm' => $pm,
'avatar' => $avatar,
'user_time' => $user_time,
'user_time_raw' => ($row['user_time'] ?? ''),
'email' => $email,
'www' => $www
];
}
function get_bt_userdata($user_id)
{
if (!$btu = CACHE('bb_cache')->get('btu_' . $user_id)) {
$btu = DB()->fetch_row("
SELECT bt.*, SUM(tr.speed_up) AS speed_up, SUM(tr.speed_down) AS speed_down
FROM " . BB_BT_USERS . " bt
LEFT JOIN " . BB_BT_TRACKER . " tr ON (bt.user_id = tr.user_id)
WHERE bt.user_id = " . (int)$user_id . "
GROUP BY bt.user_id
LIMIT 1
");
CACHE('bb_cache')->set('btu_' . $user_id, $btu, 300);
}
return $btu;
}
function get_bt_ratio($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 show_bt_userdata($user_id): void
{
global $template;
if (!$btu = get_bt_userdata($user_id)) {
return;
}
$template->assign_vars([
'SHOW_BT_USERDATA' => true,
'UP_TOTAL' => humn_size($btu['u_up_total']),
'UP_BONUS' => humn_size($btu['u_up_bonus']),
'RELEASED' => humn_size($btu['u_up_release']),
'DOWN_TOTAL' => humn_size($btu['u_down_total']),
'DOWN_TOTAL_BYTES' => $btu['u_down_total'],
'USER_RATIO' => get_bt_ratio($btu),
'MIN_DL_FOR_RATIO' => humn_size(MIN_DL_FOR_RATIO),
'MIN_DL_BYTES' => MIN_DL_FOR_RATIO,
'AUTH_KEY' => $btu['auth_key'],
'TD_DL' => humn_size($btu['down_today']),
'TD_UL' => humn_size($btu['up_today']),
'TD_REL' => humn_size($btu['up_release_today']),
'TD_BONUS' => humn_size($btu['up_bonus_today']),
'TD_POINTS' => $btu['auth_key'] ? $btu['points_today'] : '0.00',
'YS_DL' => humn_size($btu['down_yesterday']),
'YS_UL' => humn_size($btu['up_yesterday']),
'YS_REL' => humn_size($btu['up_release_yesterday']),
'YS_BONUS' => humn_size($btu['up_bonus_yesterday']),
'YS_POINTS' => $btu['auth_key'] ? $btu['points_yesterday'] : '0.00',
'SPEED_UP' => humn_size($btu['speed_up'], 0, 'KB') . '/s',
'SPEED_DOWN' => humn_size($btu['speed_down'], 0, 'KB') . '/s',
]);
}
function get_attachments_dir($cfg = null)
{
if (!$cfg and !$cfg = $GLOBALS['attach_config']) {
$cfg = bb_get_config(BB_ATTACH_CONFIG, true, false);
}
if ($cfg['upload_dir'][0] == '/' || ($cfg['upload_dir'][0] != '/' && $cfg['upload_dir'][1] == ':')) {
return $cfg['upload_dir'];
}
return BB_ROOT . $cfg['upload_dir'];
}
function bb_get_config($table, $from_db = false, $update_cache = true)
{
if ($from_db or !$cfg = CACHE('bb_config')->get("config_{$table}")) {
$cfg = [];
foreach (DB()->fetch_rowset("SELECT * FROM $table") as $row) {
$cfg[$row['config_name']] = $row['config_value'];
}
if ($update_cache) {
CACHE('bb_config')->set("config_{$table}", $cfg);
}
}
return $cfg;
}
function bb_update_config($params, $table = BB_CONFIG)
{
$updates = [];
foreach ($params as $name => $val) {
$updates[] = [
'config_name' => $name,
'config_value' => $val
];
}
$updates = DB()->build_array('MULTI_INSERT', $updates);
DB()->query("REPLACE INTO $table $updates");
// Update cache
bb_get_config($table, true, true);
}
function clean_username($username)
{
$username = mb_substr(htmlspecialchars(str_replace("\'", "'", trim($username))), 0, 25, 'UTF-8');
$username = rtrim($username, "\\");
$username = str_replace("'", "\'", $username);
return $username;
}
/**
* Get Userdata
*
* @param int|string $u
* @param bool $is_name
* @param bool $allow_guest
* @return mixed
*/
function get_userdata(int|string $u, bool $is_name = false, bool $allow_guest = false, bool $profile_view = false)
{
if (empty($u)) {
return false;
}
if (!$is_name) {
$u = (int)$u;
if ($u === GUEST_UID && $allow_guest) {
if ($u_data = CACHE('bb_cache')->get('guest_userdata')) {
return $u_data;
}
}
$where_sql = "WHERE user_id = " . $u;
} else {
$where_sql = "WHERE username = '" . DB()->escape(clean_username($u)) . "'";
}
if ($profile_view) {
$where_sql = "WHERE user_id = " . (int)$u . " OR username = '" . DB()->escape(clean_username($u)) . "'";
}
$exclude_anon_sql = (!$allow_guest) ? "AND user_id != " . GUEST_UID : '';
$sql = "SELECT * FROM " . BB_USERS . " $where_sql $exclude_anon_sql LIMIT 1";
if (!$u_data = DB()->fetch_row($sql)) {
return false;
}
if ((int)$u_data['user_id'] === GUEST_UID) {
CACHE('bb_cache')->set('guest_userdata', $u_data);
}
return $u_data;
}
function make_jumpbox(): void
{
global $datastore, $template, $bb_cfg;
if (!$bb_cfg['show_jumpbox']) {
return;
}
if (!$jumpbox = $datastore->get('jumpbox')) {
$datastore->update('jumpbox');
$jumpbox = $datastore->get('jumpbox');
}
$template->assign_vars(['JUMPBOX' => IS_GUEST ? DB()->escape($jumpbox['guest']) : DB()->escape($jumpbox['user'])]);
}
// $mode: array(not_auth_forum1,not_auth_forum2,..) or (string) 'mode'
function get_forum_select($mode = 'guest', $name = POST_FORUM_URL, $selected = null, $max_length = HTML_SELECT_MAX_LENGTH, $multiple_size = null, $js = '', $all_forums_option = null)
{
global $lang, $datastore;
if (is_array($mode)) {
$not_auth_forums_fary = array_flip($mode);
$mode = 'not_auth_forums';
}
if (null === $max_length) {
$max_length = HTML_SELECT_MAX_LENGTH;
}
$select = null === $all_forums_option ? [] : [$lang['ALL_AVAILABLE'] => $all_forums_option];
if (!$forums = $datastore->get('cat_forums')) {
$datastore->update('cat_forums');
$forums = $datastore->get('cat_forums');
}
foreach ($forums['f'] as $fid => $f) {
switch ($mode) {
case 'guest':
if ($f['auth_view'] != AUTH_ALL) {
continue 2;
}
break;
case 'user':
if ($f['auth_view'] != AUTH_ALL && $f['auth_view'] != AUTH_REG) {
continue 2;
}
break;
case 'not_auth_forums':
if (isset($not_auth_forums_fary[$f['forum_id']])) {
continue 2;
}
break;
case 'admin':
break;
default:
trigger_error(__FUNCTION__ . ": invalid mode '$mode'", E_USER_ERROR);
}
$cat_title = $forums['c'][$f['cat_id']]['cat_title'];
$f_name = ($f['forum_parent']) ? ' |- ' : '';
$f_name .= $f['forum_name'];
while (isset($select[$cat_title][$f_name])) {
$f_name .= ' ';
}
$select[$cat_title][$f_name] = $fid;
if (!$f['forum_parent']) {
$class = 'root_forum';
$class .= isset($f['subforums']) ? ' has_sf' : '';
$select['__attributes'][$cat_title][$f_name]['class'] = $class;
}
}
return build_select($name, $select, $selected, $max_length, $multiple_size, $js);
}
function setup_style()
{
global $bb_cfg, $template, $userdata;
// AdminCP works only with default template
$tpl_dir_name = defined('IN_ADMIN') ? 'default' : basename($bb_cfg['tpl_name']);
$stylesheet = defined('IN_ADMIN') ? 'main.css' : basename($bb_cfg['stylesheet']);
if (!IS_GUEST && !empty($userdata['tpl_name'])) {
foreach ($bb_cfg['templates'] as $folder => $name) {
if ($userdata['tpl_name'] == $folder) {
$tpl_dir_name = basename($userdata['tpl_name']);
}
}
}
$template = new TorrentPier\Legacy\Template(TEMPLATES_DIR . '/' . $tpl_dir_name);
$css_dir = 'styles/' . basename(TEMPLATES_DIR) . '/' . $tpl_dir_name . '/css/';
$template->assign_vars([
'SPACER' => make_url('styles/images/spacer.gif'),
'STYLESHEET' => make_url($css_dir . $stylesheet),
'EXT_LINK_NEW_WIN' => $bb_cfg['ext_link_new_win'],
'TPL_DIR' => make_url($css_dir),
'SITE_URL' => make_url('/')
]);
require_once TEMPLATES_DIR . '/' . $tpl_dir_name . '/tpl_config.php';
return ['template_name' => $tpl_dir_name];
}
// Create date / time with format and friendly date
function bb_date($gmepoch, $format = false, $friendly_date = true)
{
global $bb_cfg, $lang, $userdata;
$gmepoch = (int)$gmepoch;
if (!$format) {
$format = $bb_cfg['default_dateformat'];
}
if (empty($lang)) {
require_once($bb_cfg['default_lang_dir'] . 'main.php');
}
if (empty($userdata['session_logged_in'])) {
$tz = $bb_cfg['board_timezone'];
} else {
$tz = $userdata['user_timezone'];
}
$date = gmdate($format, $gmepoch + (3600 * $tz));
if ($friendly_date) {
$time_format = ' H:i';
$today = gmdate('d', TIMENOW + (3600 * $tz));
$month = gmdate('m', TIMENOW + (3600 * $tz));
$year = gmdate('Y', TIMENOW + (3600 * $tz));
$date_today = gmdate('d', $gmepoch + (3600 * $tz));
$date_month = gmdate('m', $gmepoch + (3600 * $tz));
$date_year = gmdate('Y', $gmepoch + (3600 * $tz));
if ($date_today == $today && $date_month == $month && $date_year == $year) {
$date = 'today' . gmdate($time_format, $gmepoch + (3600 * $tz));
} elseif ($today != 1 && $date_today == ($today - 1) && $date_month == $month && $date_year == $year) {
$date = 'yesterday' . gmdate($time_format, $gmepoch + (3600 * $tz));
} elseif ($today == 1 && $month != 1) {
$yesterday = date('t', mktime(0, 0, 0, ($month - 1), 1, $year));
if ($date_today == $yesterday && $date_month == ($month - 1) && $date_year == $year) {
$date = 'yesterday' . gmdate($time_format, $gmepoch + (3600 * $tz));
}
} elseif ($today == 1 && $month == 1) {
$yesterday = date('t', mktime(0, 0, 0, 12, 1, ($year - 1)));
if ($date_today == $yesterday && $date_month == 12 && $date_year == ($year - 1)) {
$date = 'yesterday' . gmdate($time_format, $gmepoch + (3600 * $tz));
}
}
}
return ($bb_cfg['translate_dates']) ? strtr(strtoupper($date), $lang['DATETIME']) : $date;
}
/**
* Get user's torrent client string
*
* @param string $peer_id
* @return string
*/
function get_user_torrent_client(string $peer_id): string
{
static $clients = [
'-AG' => 'Ares', '-AZ' => 'Vuze', '-A~' => 'Ares', '-BC' => 'BitComet',
'-BE' => 'BitTorrent SDK', '-BI' => 'BiglyBT', '-BL' => 'BitLord', '-BT' => 'BitTorrent',
'-CT' => 'CTorrent', '-DE' => 'Deluge', '-FD' => 'Free Download Manager', 'FD6' => 'Free Download Manager',
'-FG' => 'FlashGet', '-FL' => 'Folx', '-HL' => 'Halite', '-KG' => 'KGet',
'-KT' => 'KTorrent', '-LT' => 'libTorrent', '-Lr' => 'LibreTorrent',
'-TR' => 'Transmission', '-tT' => 'tTorrent', '-UM' => "uTorrent Mac", '-UT' => 'uTorrent',
'-UW' => 'uTorrent Web', '-WW' => 'WebTorrent', '-WD' => 'WebTorrent', '-XL' => 'Xunlei',
'-PI' => 'PicoTorrent', '-qB' => 'qBittorrent', 'M' => 'BitTorrent', 'MG' => 'MediaGet',
'-MG' => 'MediaGet', 'OP' => 'Opera', 'TIX' => 'Tixati', 'aria2-' => 'Aria2', 'A2' => 'Aria2',
/**
* ================================ Other ================================
* '-BB' => 'BitBuddy', '-AR' => 'Arctic', '-AT' => 'Artemis', '-AV' => 'Avicora',
* '-AX' => 'BitPump', '-BB' => 'BitBuddy', '-AD' => 'Advanced Download Manager', '-BF' => 'BitFlu',
* '-BG' => 'BTGetit', '-BH' => 'BitZilla', '-BM' => 'BitMagnet', '-BN' => 'Baidu Netdisk',
* '-BOW' => 'Bits on Wheels', '-BP' => 'BitTorrent Pro (Azureus + Spyware)', '-BR' => 'BitRocket', '-BS' => 'BTSlave',
* '-BW' => 'BitTorrent Web', '-BX' => 'BittorrentX', '-CD' => 'Enhanced CTorrent', '-DP' => 'Propagate Data Client',
* '-EB' => 'EBit', '-ES' => 'Electric Sheep', '-FC' => 'FileCroc', '-HN' => 'Hydranode',
* '-FT' => 'FoxTorrent/RedSwoosh', '-FW' => 'FrostWire', '-FX' => 'Freebox', '-G3' => 'G3 Torrent',
* '-GR' => 'GetRight', '-GS' => 'GSTorrent', '-HK' => 'Hekate', '-LW' => 'LimeWire',
* '-LC' => 'LeechCraft', '-LH' => 'LH-ABC', '-LP' => 'Lphant', '-UE' => "uTorrent Embedded",
* '-UL' => 'uLeecher!', '-TS' => 'Torrentstorm', '-TT' => 'TuoTu', '-MK' => 'Meerkat',
* '-ML' => 'MLDonkey', '-MO' => 'MonoTorrent', '-MP' => 'MooPolice', '-MR' => 'Miro',
* '-MT' => 'Moonlight', '-NE' => 'BT Next Evolution', '-NX' => 'Net Transport', '-OS' => 'OneSwarm', '-OT' => 'OmegaTorrent',
* '-PD' => 'Pando', '-PI' => 'PicoTorrent', '-QD' => 'QQDownload', '-QT' => 'QT 4 Torrent example',
* '-RS' => 'Rufus', '-RT' => 'Retriever', '-RZ' => 'RezTorrent', '-SB' => 'Swiftbit',
* '-SD' => 'Thunder', '-SM' => 'SoMud', '-SP' => 'BitSpirit', '-SS' => 'SwarmScope',
* '-ST' => 'SymTorrent', '-SZ' => 'Shareaza', '-S~' => 'Shareaza', '-TB' => 'Torch Browser',
* '-TN' => 'Torrent .NET', '-WY' => 'FireTorrent', '-XC' => 'Xtorrent', '-XF' => 'Xfplay',
* '-VG' => 'Vagaa', '-WS' => 'HTTP Seed', '-WT' => 'BitLet', '-WT-' => 'BitLet',
* '-XS' => 'XSwifter', '-XT' => 'XanTorrent', '-XX' => 'Xtorrent', '-ZO' => 'Zona',
* '-ZT' => 'Zip Torrent', '-bk' => 'BitKitten (libtorrent)', '-lt' => 'libTorrent (Rakshasa)', '-pb' => 'pbTorrent', 'Mbrst' => 'burst!',
* '-st' => 'SharkTorrent', '346-' => 'TorrentTopia', 'AZ2500BT' => 'BitTyrant (Azureus Mod)', 'BLZ' => 'Blizzard Downloader',
* 'DNA' => 'BitTorrent DNA', 'FD6' => 'Free Download Manager 6', 'LIME' => 'Limewire', 'Pando' => 'Pando',
* 'Plus' => 'Plus!', 'Q' => 'Queen Bee', 'QVOD' => 'QVOD', 'S3' => 'Amazon S3',
* 'btpd' => 'BT Protocol Daemon', 'eX' => 'eXeem', 'martini' => 'Martini Man',
* =======================================================================
**/
];
static $iconExtension = '.png';
$bestMatch = null;
$bestMatchLength = 0;
foreach ($clients as $key => $clientName) {
if (str_starts_with($peer_id, $key) !== false && strlen($key) > $bestMatchLength) {
$bestMatch = $clientName;
$bestMatchLength = strlen($key);
}
}
if (!empty($bestMatch)) {
return '
';
}
return $peer_id;
}
/**
* Returns country flag by country code
*
* @param string $code
* @return string
*/
function render_flag(string $code): string
{
static $iconExtension = '.svg';
static $country_codes = [
'AD' => 'Andorra',
'AE' => 'United Arab Emirates',
'AF' => 'Afghanistan',
'AG' => 'Antigua and Barbuda',
'AI' => 'Anguilla',
'AL' => 'Albania',
'AM' => 'Armenia',
'AO' => 'Angola',
'AQ' => 'Antarctica',
'AR' => 'Argentina',
'AS' => 'American Samoa',
'AT' => 'Austria',
'AU' => 'Australia',
'AW' => 'Aruba',
'AX' => 'Aland Islands',
'AZ' => 'Azerbaijan',
'BA' => 'Bosnia and Herzegovina',
'BB' => 'Barbados',
'BD' => 'Bangladesh',
'BE' => 'Belgium',
'BF' => 'Burkina Faso',
'BG' => 'Bulgaria',
'BH' => 'Bahrain',
'BI' => 'Burundi',
'BJ' => 'Benin',
'BL' => 'Saint Barthélemy',
'BM' => 'Bermuda',
'BN' => 'Brunei Darussalam',
'BO' => 'Bolivia, Plurinational State of',
'BQ' => 'Caribbean Netherlands',
'BR' => 'Brazil',
'BS' => 'Bahamas',
'BT' => 'Bhutan',
'BV' => 'Bouvet Island',
'BW' => 'Botswana',
'BY' => 'Belarus',
'BZ' => 'Belize',
'CA' => 'Canada',
'CC' => 'Cocos (Keeling) Islands',
'CD' => 'Congo, the Democratic Republic of the',
'CF' => 'Central African Republic',
'CG' => 'Republic of the Congo',
'CH' => 'Switzerland',
'CI' => 'Republic of Cote d\'Ivoire',
'CK' => 'Cook Islands',
'CL' => 'Chile',
'CM' => 'Cameroon',
'CN' => 'China (People\'s Republic of China)',
'CO' => 'Colombia',
'CR' => 'Costa Rica',
'CU' => 'Cuba',
'CV' => 'Cape Verde',
'CW' => 'Country of Curaçao',
'CX' => 'Christmas Island',
'CY' => 'Cyprus',
'CZ' => 'Czech Republic',
'DE' => 'Germany',
'DJ' => 'Djibouti',
'DK' => 'Denmark',
'DM' => 'Dominica',
'DO' => 'Dominican Republic',
'DZ' => 'Algeria',
'EC' => 'Ecuador',
'EE' => 'Estonia',
'EG' => 'Egypt',
'EH' => 'Western Sahara',
'ER' => 'Eritrea',
'ES' => 'Spain',
'ET' => 'Ethiopia',
'EU' => 'Europe',
'FI' => 'Finland',
'FJ' => 'Fiji',
'FK' => 'Falkland Islands (Malvinas)',
'FM' => 'Micronesia, Federated States of',
'FO' => 'Faroe Islands',
'FR' => 'France',
'GA' => 'Gabon',
'GB-ENG' => 'England',
'GB-NIR' => 'Northern Ireland',
'GB-SCT' => 'Scotland',
'GB-WLS' => 'Wales',
'GB' => 'United Kingdom',
'GD' => 'Grenada',
'GE' => 'Georgia',
'GF' => 'French Guiana',
'GG' => 'Guernsey',
'GH' => 'Ghana',
'GI' => 'Gibraltar',
'GL' => 'Greenland',
'GM' => 'Gambia',
'GN' => 'Guinea',
'GP' => 'Guadeloupe',
'GQ' => 'Equatorial Guinea',
'GR3' => 'German Reich (3rd)',
'GR' => 'Greece',
'GS' => 'South Georgia and the South Sandwich Islands',
'GT' => 'Guatemala',
'GU' => 'Guam',
'GW' => 'Guinea-Bissau',
'GY' => 'Guyana',
'HK' => 'Hong Kong',
'HM' => 'Heard Island and McDonald Islands',
'HN' => 'Honduras',
'HR' => 'Croatia',
'HT' => 'Haiti',
'HU' => 'Hungary',
'ID' => 'Indonesia',
'IE' => 'Ireland',
'IL' => 'Israel',
'IM' => 'Isle of Man',
'IN' => 'India',
'IO' => 'British Indian Ocean Territory',
'IQ' => 'Iraq',
'IR' => 'Iran, Islamic Republic of',
'IS' => 'Iceland',
'IT' => 'Italy',
'JE' => 'Jersey',
'JM' => 'Jamaica',
'JO' => 'Jordan',
'JP' => 'Japan',
'KE' => 'Kenya',
'KG' => 'Kyrgyzstan',
'KH' => 'Cambodia',
'KI' => 'Kiribati',
'KM' => 'Comoros',
'KN' => 'Saint Kitts and Nevis',
'KP' => 'Korea, Democratic People\'s Republic of',
'KR' => 'Korea, Republic of',
'KW' => 'Kuwait',
'KY' => 'Cayman Islands',
'KZ' => 'Kazakhstan',
'LA' => 'Laos (Lao People\'s Democratic Republic)',
'LB' => 'Lebanon',
'LC' => 'Saint Lucia',
'LI' => 'Liechtenstein',
'LK' => 'Sri Lanka',
'LR' => 'Liberia',
'LS' => 'Lesotho',
'LT' => 'Lithuania',
'LU' => 'Luxembourg',
'LV' => 'Latvia',
'LY' => 'Libya',
'MA' => 'Morocco',
'MC' => 'Monaco',
'MD' => 'Moldova, Republic of',
'ME' => 'Montenegro',
'MF' => 'Saint Martin',
'MG' => 'Madagascar',
'MH' => 'Marshall Islands',
'MK' => 'North Macedonia',
'ML' => 'Mali',
'MM' => 'Myanmar',
'MN' => 'Mongolia',
'MO' => 'Macao',
'MP' => 'Northern Mariana Islands',
'MQ' => 'Martinique',
'MR' => 'Mauritania',
'MS' => 'Montserrat',
'MT' => 'Malta',
'MU' => 'Mauritius',
'MV' => 'Maldives',
'MW' => 'Malawi',
'MX' => 'Mexico',
'MY' => 'Malaysia',
'MZ' => 'Mozambique',
'NA' => 'Namibia',
'NC' => 'New Caledonia',
'NE' => 'Niger',
'NF' => 'Norfolk Island',
'NG' => 'Nigeria',
'NI' => 'Nicaragua',
'NL' => 'Netherlands',
'NO' => 'Norway',
'NP' => 'Nepal',
'NR' => 'Nauru',
'NU' => 'Niue',
'NZ' => 'New Zealand',
'OM' => 'Oman',
'PA' => 'Panama',
'PE' => 'Peru',
'PF' => 'French Polynesia',
'PG' => 'Papua New Guinea',
'PH' => 'Philippines',
'PK' => 'Pakistan',
'PL' => 'Poland',
'PM' => 'Saint Pierre and Miquelon',
'PN' => 'Pitcairn',
'PR' => 'Puerto Rico',
'PS' => 'Palestine',
'PT' => 'Portugal',
'PW' => 'Palau',
'PY' => 'Paraguay',
'QA' => 'Qatar',
'RE' => 'Réunion',
'RO' => 'Romania',
'RS' => 'Serbia',
'RU' => 'Russian Federation',
'RW' => 'Rwanda',
'SA' => 'Saudi Arabia',
'SB' => 'Solomon Islands',
'SC' => 'Seychelles',
'SD' => 'Sudan',
'SE' => 'Sweden',
'SG' => 'Singapore',
'SH' => 'Saint Helena, Ascension and Tristan da Cunha',
'SI' => 'Slovenia',
'SJ' => 'Svalbard and Jan Mayen Islands',
'SK' => 'Slovakia',
'SL' => 'Sierra Leone',
'SM' => 'San Marino',
'SN' => 'Senegal',
'SO' => 'Somalia',
'SR' => 'Suriname',
'SS' => 'South Sudan',
'SU' => 'Soviet Union',
'ST' => 'Sao Tome and Principe',
'SV' => 'El Salvador',
'SX' => 'Sint Maarten (Dutch part)',
'SY' => 'Syrian Arab Republic',
'SZ' => 'Swaziland',
'TC' => 'Turks and Caicos Islands',
'TD' => 'Chad',
'TF' => 'French Southern Territories',
'TG' => 'Togo',
'TH' => 'Thailand',
'TJ' => 'Tajikistan',
'TK' => 'Tokelau',
'TL' => 'Timor-Leste',
'TM' => 'Turkmenistan',
'TN' => 'Tunisia',
'TO' => 'Tonga',
'TR' => 'Turkey',
'TT' => 'Trinidad and Tobago',
'TV' => 'Tuvalu',
'TW' => 'Taiwan (Republic of China)',
'TZ' => 'Tanzania, United Republic of',
'UA' => 'Ukraine',
'UG' => 'Uganda',
'UM' => 'US Minor Outlying Islands',
'US' => 'United States',
'UY' => 'Uruguay',
'UZ' => 'Uzbekistan',
'VA' => 'Holy See (Vatican City State)',
'VC' => 'Saint Vincent and the Grenadines',
'VE' => 'Venezuela, Bolivarian Republic of',
'VG' => 'Virgin Islands, British',
'VI' => 'Virgin Islands, U.S.',
'VN' => 'Vietnam',
'VU' => 'Vanuatu',
'WBW' => 'Wonderful Russia of the Future 🕊',
'WF' => 'Wallis and Futuna Islands',
'WS' => 'Samoa',
'XK' => 'Kosovo',
'YE' => 'Yemen',
'YU' => 'Yugoslavia',
'YT' => 'Mayotte',
'ZA' => 'South Africa',
'ZM' => 'Zambia',
'ZW' => 'Zimbabwe'
];
if (isset($country_codes[$code])) {
return '
';
}
return $code;
}
function birthday_age($date)
{
global $bb_cfg;
if (!$date) {
return '';
}
$tz = TIMENOW + (3600 * $bb_cfg['board_timezone']);
return delta_time(strtotime($date, $tz));
}
//
// Pagination routine, generates
// page number sequence
//
function generate_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = true)
{
global $lang, $template;
$begin_end = 3;
$from_middle = 1;
$total_pages = ceil($num_items / $per_page);
$on_page = floor($start_item / $per_page) + 1;
$page_string = '';
if ($total_pages > ((2 * ($begin_end + $from_middle)) + 2)) {
$init_page_max = ($total_pages > $begin_end) ? $begin_end : $total_pages;
for ($i = 1; $i < $init_page_max + 1; $i++) {
$page_string .= ($i == $on_page) ? '' . $i . '' : '' . $i . '';
if ($i < $init_page_max) {
$page_string .= ", ";
}
}
if ($total_pages > $begin_end) {
if ($on_page > 1 && $on_page < $total_pages) {
$page_string .= ($on_page > ($begin_end + $from_middle + 1)) ? ' ... ' : ', ';
$init_page_min = ($on_page > ($begin_end + $from_middle)) ? $on_page : ($begin_end + $from_middle + 1);
$init_page_max = ($on_page < $total_pages - ($begin_end + $from_middle)) ? $on_page : $total_pages - ($begin_end + $from_middle);
for ($i = $init_page_min - $from_middle; $i < $init_page_max + ($from_middle + 1); $i++) {
$page_string .= ($i == $on_page) ? '' . $i . '' : '' . $i . '';
if ($i < $init_page_max + $from_middle) {
$page_string .= ', ';
}
}
$page_string .= ($on_page < $total_pages - ($begin_end + $from_middle)) ? ' ... ' : ', ';
} else {
$page_string .= ' ... ';
}
for ($i = $total_pages - ($begin_end - 1); $i < $total_pages + 1; $i++) {
$page_string .= ($i == $on_page) ? '' . $i . '' : '' . $i . '';
if ($i < $total_pages) {
$page_string .= ", ";
}
}
}
} else {
for ($i = 1; $i < $total_pages + 1; $i++) {
$page_string .= ($i == $on_page) ? '' . $i . '' : '' . $i . '';
if ($i < $total_pages) {
$page_string .= ', ';
}
}
}
if ($add_prevnext_text) {
if ($on_page > 1) {
$page_string = ' ' . $lang['PREVIOUS_PAGE'] . ' ' . $page_string;
}
if ($on_page < $total_pages) {
$page_string .= ' ' . $lang['NEXT_PAGE'] . '';
}
}
$pagination = false;
if ($page_string && $total_pages > 1) {
$pagination = ' : ' . $page_string;
$pagination = str_replace('&start=0', '', $pagination);
}
$template->assign_vars([
'PAGINATION' => $pagination,
'PAGE_NUMBER' => sprintf($lang['PAGE_OF'], (floor($start_item / $per_page) + 1), ceil($num_items / $per_page)),
'PG_BASE_URL' => $base_url,
'PG_PER_PAGE' => $per_page
]);
return $pagination;
}
//
// This does exactly what preg_quote() does in PHP 4-ish
// If you just need the 1-parameter preg_quote call, then don't bother using this.
//
function bb_preg_quote($str, $delimiter)
{
$text = preg_quote($str);
$text = str_replace($delimiter, '\\' . $delimiter, $text);
return $text;
}
//
// Obtain list of naughty words and build preg style replacement arrays for use by the
// calling script, note that the vars are passed as references this just makes it easier
// to return both sets of arrays
//
function obtain_word_list(&$orig_word, &$replacement_word)
{
global $bb_cfg;
if (!$bb_cfg['use_word_censor']) {
return false;
}
if (!$sql = CACHE('bb_cache')->get('censored')) {
$sql = DB()->fetch_rowset("SELECT word, replacement FROM " . BB_WORDS);
if (!$sql) {
$sql = [['word' => 1, 'replacement' => 1]];
}
CACHE('bb_cache')->set('censored', $sql, 7200);
}
foreach ($sql as $row) {
//$orig_word[] = '#(?ajax_die($msg_text);
}
// Check
if (defined('HAS_DIED')) {
trigger_error(__FUNCTION__ . ' was called multiple times', E_USER_ERROR);
}
define('HAS_DIED', 1);
define('DISABLE_CACHING_OUTPUT', true);
// If empty lang
if (empty($lang)) {
require($bb_cfg['default_lang_dir'] . 'main.php');
}
// If empty session
if (empty($userdata)) {
$userdata = $user->session_start();
}
// If the header hasn't been output then do it
if (!defined('PAGE_HEADER_SENT')) {
if (empty($template)) {
$template = new TorrentPier\Legacy\Template(BB_ROOT . "templates/{$bb_cfg['tpl_name']}");
}
if (empty($theme)) {
$theme = setup_style();
}
require(PAGE_HEADER);
}
// Check for lang variable
if (!empty($lang[$msg_text])) {
$msg_text = $lang[$msg_text];
}
$template->assign_vars([
'TPL_BB_DIE' => true,
'MESSAGE_TEXT' => $msg_text
]);
$template->set_filenames(['bb_die' => 'common.tpl']);
$template->pparse('bb_die');
require(PAGE_FOOTER);
exit;
}
function bb_simple_die($txt, $status_code = null)
{
global $bb_cfg;
header('Content-Type: text/plain; charset=' . $bb_cfg['charset']);
if (isset($status_code)) {
http_response_code($status_code);
}
if (!empty($_COOKIE['explain'])) {
bb_die("bb_simple_die:
$txt");
}
die($txt);
}
function login_redirect($url = '')
{
redirect(LOGIN_URL . '?redirect=' . (($url) ?: ($_SERVER['REQUEST_URI'] ?? '/')));
}
function meta_refresh($url, $time = 5)
{
global $template;
$template->assign_var('META', '');
}
function redirect($url)
{
global $bb_cfg;
if (headers_sent($filename, $linenum)) {
trigger_error("Headers already sent in $filename($linenum)", E_USER_ERROR);
}
if (str_contains(urldecode($url), "\n") || str_contains(urldecode($url), "\r") || str_contains(urldecode($url), ';url')) {
bb_die('Tried to redirect to potentially insecure url');
}
$url = trim($url);
$server_protocol = ($bb_cfg['cookie_secure']) ? 'https://' : 'http://';
$server_name = preg_replace('#^\/?(.*?)\/?$#', '\1', trim($bb_cfg['server_name']));
$server_port = ($bb_cfg['server_port'] <> 80) ? ':' . trim($bb_cfg['server_port']) : '';
$script_name = preg_replace('#^\/?(.*?)\/?$#', '\1', trim($bb_cfg['script_path']));
if ($script_name) {
$script_name = "/$script_name";
$url = preg_replace("#^$script_name#", '', $url);
}
$redirect_url = $server_protocol . $server_name . $server_port . $script_name . preg_replace('#^\/?(.*?)\/?$#', '/\1', $url);
// Behave as per HTTP/1.1 spec for others
header('Location: ' . $redirect_url, response_code: 301);
exit;
}
// build a list of the sortable fields or return field name
function get_forum_display_sort_option($selected_row = 0, $action = 'list', $list = 'sort')
{
global $lang;
$forum_display_sort = [
'lang_key' => ['LASTPOST', 'SORT_TOPIC_TITLE', 'SORT_TIME'],
'fields' => ['t.topic_last_post_time', 't.topic_title', 't.topic_time']
];
$forum_display_order = [
'lang_key' => ['DESC', 'ASC'],
'fields' => ['DESC', 'ASC']
];
// get the good list
$list_name = 'forum_display_' . $list;
$listrow = ${$list_name};
// init the result
$res = '';
if ($selected_row > count($listrow['lang_key'])) {
$selected_row = 0;
}
// build list
if ($action == 'list') {
foreach ($listrow['lang_key'] as $i => $iValue) {
$selected = ($i == $selected_row) ? ' selected' : '';
$l_value = $lang[$listrow['lang_key'][$i]] ?? $iValue;
$res .= '';
}
} else {
// field
$res = $listrow['fields'][$selected_row];
}
return $res;
}
function topic_attachment_image($switch_attachment)
{
global $is_auth;
if (!$switch_attachment || !($is_auth['auth_download'] && $is_auth['auth_view'])) {
return '';
}
return '
';
}
function clear_dl_list($topics_csv)
{
DB()->query("DELETE FROM " . BB_BT_DLSTATUS . " WHERE topic_id IN($topics_csv)");
DB()->query("DELETE FROM " . BB_BT_DLSTATUS_SNAP . " WHERE topic_id IN($topics_csv)");
}
// $ids - array(id1,id2,..) or (string) id
function get_id_csv($ids)
{
$ids = array_values((array)$ids);
array_deep($ids, 'intval', 'one-dimensional');
return (string)implode(',', $ids);
}
// $ids - array(id1,id2,..) or (string) id1,id2,..
function get_id_ary($ids)
{
$ids = is_string($ids) ? explode(',', $ids) : array_values((array)$ids);
array_deep($ids, 'intval', 'one-dimensional');
return (array)$ids;
}
function get_topic_title($topic_id)
{
$row = DB()->fetch_row("
SELECT topic_title FROM " . BB_TOPICS . " WHERE topic_id = " . (int)$topic_id . "
");
return $row['topic_title'];
}
function forum_exists($forum_id = null): bool
{
if (!isset($forum_id)) {
return (bool)DB()->fetch_row("SELECT * FROM " . BB_FORUMS . " LIMIT 1");
}
return (bool)DB()->fetch_row("SELECT forum_id FROM " . BB_FORUMS . " WHERE forum_id = $forum_id LIMIT 1");
}
function cat_exists($cat_id): bool
{
return (bool)DB()->fetch_row("SELECT cat_id FROM " . BB_CATEGORIES . " WHERE cat_id = $cat_id LIMIT 1");
}
function get_topic_icon($topic, $is_unread = null)
{
global $bb_cfg, $images;
$t_hot = ($topic['topic_replies'] >= $bb_cfg['hot_threshold']);
$is_unread ??= is_unread($topic['topic_last_post_time'], $topic['topic_id'], $topic['forum_id']);
if ($topic['topic_status'] == TOPIC_MOVED) {
$folder_image = $images['folder'];
} else {
$folder = ($t_hot) ? $images['folder_hot'] : $images['folder'];
$folder_new = ($t_hot) ? $images['folder_hot_new'] : $images['folder_new'];
if ($topic['topic_type'] == POST_ANNOUNCE) {
$folder = $images['folder_announce'];
$folder_new = $images['folder_announce_new'];
} elseif ($topic['topic_type'] == POST_STICKY) {
$folder = $images['folder_sticky'];
$folder_new = $images['folder_sticky_new'];
} elseif ($topic['topic_status'] == TOPIC_LOCKED) {
$folder = $images['folder_locked'];
$folder_new = $images['folder_locked_new'];
} elseif ($topic['topic_dl_type'] == TOPIC_DL_TYPE_DL) {
$folder = ($t_hot) ? $images['folder_dl_hot'] : $images['folder_dl'];
$folder_new = ($t_hot) ? $images['folder_dl_hot_new'] : $images['folder_dl_new'];
}
$folder_image = ($is_unread) ? $folder_new : $folder;
}
return $folder_image;
}
function build_topic_pagination($url, $replies, $per_page)
{
$pg = '';
if (++$replies > $per_page) {
$total_pages = ceil($replies / $per_page);
for ($j = 0, $page = 1; $j < $replies; $j += $per_page, $page++) {
$href = ($j) ? "$url&start=$j" : $url;
$pg .= '' . $page . '';
if ($page == 1 && $total_pages > 3) {
$pg .= ' .. ';
$page = $total_pages - 2;
$j += ($total_pages - 3) * $per_page;
} elseif ($page < $total_pages) {
$pg .= ', ';
}
}
}
return $pg;
}
function print_confirmation($tpl_vars)
{
global $template, $lang;
$template->assign_vars([
'TPL_CONFIRM' => true,
'CONFIRM_TITLE' => $lang['CONFIRM'],
'FORM_METHOD' => 'post'
]);
if (!isset($tpl_vars['QUESTION'])) {
$tpl_vars['QUESTION'] = $lang['QUESTION'];
}
$template->assign_vars($tpl_vars);
print_page('common.tpl');
}
/**
* $args = array(
* 'tpl' => 'template file name',
* 'simple' => $gen_simple_header,
* );
* OR (string) 'template_file_name'
*
* $type = '' (common forum page)
* 'admin' (adminCP page)
* 'simple' (simple page without common header)
*
* $mode = 'no_header'
* 'no_footer'
*/
function print_page($args, $type = '', $mode = '')
{
global $template, $gen_simple_header;
$tpl = (is_array($args) && !empty($args['tpl'])) ? $args['tpl'] : $args;
$tpl = ($type === 'admin') ? ADMIN_TPL_DIR . $tpl : $tpl;
$gen_simple_header = (is_array($args) && !empty($args['simple']) or $type === 'simple') ? true : $gen_simple_header;
if ($mode !== 'no_header') {
require(PAGE_HEADER);
}
$template->set_filenames(['body' => $tpl]);
$template->pparse('body');
if ($mode !== 'no_footer') {
require(PAGE_FOOTER);
}
}
function caching_output($enabled, $mode, $cache_var_name, $ttl = 300)
{
if (!$enabled || !CACHE('bb_cache')->used) {
return;
}
if ($mode == 'send') {
if ($cached_contents = CACHE('bb_cache')->get($cache_var_name)) {
exit($cached_contents);
}
} elseif ($mode == 'store') {
if ($output = ob_get_contents()) {
CACHE('bb_cache')->set($cache_var_name, $output, $ttl);
}
}
}
function clean_title($str, $replace_underscore = false)
{
$str = ($replace_underscore) ? str_replace('_', ' ', $str) : $str;
$str = htmlCHR(str_compact($str));
return $str;
}
function clean_text_match($text, $ltrim_star = true, $die_if_empty = false)
{
global $bb_cfg, $lang;
$text = str_compact($text);
$ltrim_chars = ($ltrim_star) ? ' *-!' : ' ';
$wrap_with_quotes = preg_match('#^"[^"]+"$#', $text);
$text = ' ' . str_compact(ltrim($text, $ltrim_chars)) . ' ';
if ($bb_cfg['search_engine_type'] == 'sphinx') {
$text = preg_replace('#(?<=\S)\-#u', ' ', $text); // "1-2-3" -> "1 2 3"
$text = preg_replace('#[^0-9a-zA-Zа-яА-ЯёЁ\-_*|]#u', ' ', $text); // допустимые символы (кроме " которые отдельно)
$text = str_replace(['-', '*'], [' -', '* '], $text); // только в начале / конце слова
$text = preg_replace('#\s*\|\s*#u', '|', $text); // "| " -> "|"
$text = preg_replace('#\|+#u', ' | ', $text); // "||" -> "|"
$text = preg_replace('#(?<=\s)[\-*]+\s#u', ' ', $text); // одиночные " - ", " * "
$text = trim($text, ' -|');
$text = str_compact($text);
$text_match_sql = ($wrap_with_quotes && $text != '') ? '"' . $text . '"' : $text;
} else {
$text_match_sql = DB()->escape(trim($text));
}
if (!$text_match_sql && $die_if_empty) {
bb_die($lang['NO_SEARCH_MATCH']);
}
return $text_match_sql;
}
function init_sphinx()
{
global $sphinx;
if (!isset($sphinx)) {
$sphinx = \Sphinx\SphinxClient::create();
$sphinx->setConnectTimeout(5);
$sphinx->setRankingMode($sphinx::SPH_RANK_NONE);
$sphinx->setMatchMode($sphinx::SPH_MATCH_BOOLEAN);
}
return $sphinx;
}
function log_sphinx_error($err_type, $err_msg, $query = '')
{
$ignore_err_txt = [
'negation on top level',
'Query word length is less than min prefix length'
];
if (!count($ignore_err_txt) || !preg_match('#' . implode('|', $ignore_err_txt) . '#i', $err_msg)) {
$orig_query = strtr($_REQUEST['nm'], ["\n" => '\n']);
bb_log(date('m-d H:i:s') . " | $err_type | $err_msg | $orig_query | $query" . LOG_LF, 'sphinx_error');
}
}
function get_title_match_topics($title_match_sql, array $forum_ids = [])
{
global $bb_cfg, $sphinx, $userdata, $title_match, $lang;
$where_ids = [];
if ($forum_ids) {
$forum_ids = array_diff($forum_ids, [0 => 0]);
}
$title_match_sql = encode_text_match($title_match_sql);
if ($bb_cfg['search_engine_type'] == 'sphinx') {
$sphinx = init_sphinx();
$where = $title_match ? 'topics' : 'posts';
$sphinx->setServer($bb_cfg['sphinx_topic_titles_host'], $bb_cfg['sphinx_topic_titles_port']);
if ($forum_ids) {
$sphinx->setFilter('forum_id', $forum_ids, false);
}
if (preg_match('#^"[^"]+"$#u', $title_match_sql)) {
$sphinx->setMatchMode($sphinx::SPH_MATCH_PHRASE);
}
if ($result = $sphinx->query($title_match_sql, $where, $userdata['username'] . ' (' . CLIENT_IP . ')')) {
if (!empty($result['matches'])) {
$where_ids = array_keys($result['matches']);
}
} elseif ($error = $sphinx->getLastError()) {
if (strpos($error, 'errno=110')) {
bb_die($lang['SEARCH_ERROR']);
}
log_sphinx_error('ERR', $error, $title_match_sql);
}
if ($warning = $sphinx->getLastWarning()) {
log_sphinx_error('wrn', $warning, $title_match_sql);
}
} elseif ($bb_cfg['search_engine_type'] == 'mysql') {
$where_forum = ($forum_ids) ? "AND forum_id IN(" . implode(',', $forum_ids) . ")" : '';
$search_bool_mode = ($bb_cfg['allow_search_in_bool_mode']) ? ' IN BOOLEAN MODE' : '';
if ($title_match) {
$where_id = 'topic_id';
$sql = "SELECT topic_id FROM " . BB_TOPICS . "
WHERE MATCH (topic_title) AGAINST ('$title_match_sql'$search_bool_mode)
$where_forum";
} else {
$where_id = 'post_id';
$sql = "SELECT p.post_id FROM " . BB_POSTS . " p, " . BB_POSTS_SEARCH . " ps
WHERE ps.post_id = p.post_id
AND MATCH (ps.search_words) AGAINST ('$title_match_sql'$search_bool_mode)
$where_forum";
}
foreach (DB()->fetch_rowset($sql) as $row) {
$where_ids[] = $row[$where_id];
}
} else {
bb_die($lang['SEARCH_OFF']);
}
return $where_ids;
}
// для более корректного поиска по словам содержащим одиночную кавычку
function encode_text_match($txt)
{
return str_replace("'", ''', $txt);
}
function decode_text_match($txt)
{
return str_replace(''', "'", $txt);
}
/**
* Create magnet link
*
* @param string $infohash
* @param string $infohash_v2
* @param string $auth_key
* @param string $name
*
* @return string
*/
function create_magnet(string $infohash, string $infohash_v2, string $auth_key, string $name): string
{
global $bb_cfg, $images, $lang;
if (!$bb_cfg['magnet_links_enabled']) {
return false;
}
// Only for registered users
if (IS_GUEST && $bb_cfg['bt_tor_browse_only_reg']) {
return false;
}
$v1_support = !empty($infohash);
$v2_support = !empty($infohash_v2);
$magnet = 'magnet:?';
if ($v1_support) {
$magnet .= 'xt=urn:btih:' . bin2hex($infohash);
}
if ($v2_support) {
if ($v1_support) {
$magnet .= '&';
}
$magnet .= 'xt=urn:btmh:1220' . bin2hex($infohash_v2);
}
return '
';
}
function set_die_append_msg($forum_id = null, $topic_id = null, $group_id = null)
{
global $lang, $template;
$msg = '';
$msg .= $topic_id ? '' . $lang['TOPIC_RETURN'] . '
' : '';
$msg .= $forum_id ? '' . $lang['FORUM_RETURN'] . '
' : '';
$msg .= $group_id ? '' . $lang['GROUP_RETURN'] . '
' : '';
$msg .= '' . $lang['INDEX_RETURN'] . '
';
$template->assign_var('BB_DIE_APPEND_MSG', $msg);
}
function set_pr_die_append_msg($pr_uid)
{
global $lang, $template;
$template->assign_var('BB_DIE_APPEND_MSG', '
' . $lang['PROFILE_RETURN'] . '
' . $lang['PROFILE_EDIT_RETURN'] . '
' . $lang['INDEX_RETURN'] . '
');
}
function send_pm($user_id, $subject, $message, $poster_id = BOT_UID)
{
global $userdata;
$subject = DB()->escape($subject);
$message = DB()->escape($message);
if ($poster_id == BOT_UID) {
$poster_ip = '7f000001';
} elseif ($row = DB()->fetch_row("SELECT user_reg_ip FROM " . BB_USERS . " WHERE user_id = $poster_id")) {
$poster_ip = $row['user_reg_ip'];
} else {
$poster_id = $userdata['user_id'];
$poster_ip = USER_IP;
}
DB()->query("INSERT INTO " . BB_PRIVMSGS . " (privmsgs_type, privmsgs_subject, privmsgs_from_userid, privmsgs_to_userid, privmsgs_date, privmsgs_ip) VALUES (" . PRIVMSGS_NEW_MAIL . ", '$subject', {$poster_id}, $user_id, " . TIMENOW . ", '$poster_ip')");
$pm_id = DB()->sql_nextid();
DB()->query("INSERT INTO " . BB_PRIVMSGS_TEXT . " (privmsgs_text_id, privmsgs_text) VALUES ($pm_id, '$message')");
DB()->query("UPDATE " . BB_USERS . " SET user_new_privmsg = user_new_privmsg + 1, user_last_privmsg = " . TIMENOW . ", user_newest_pm_id = $pm_id WHERE user_id = $user_id");
}
function profile_url($data, $target_blank = false)
{
global $bb_cfg, $lang, $datastore;
if (!$ranks = $datastore->get('ranks')) {
$datastore->update('ranks');
$ranks = $datastore->get('ranks');
}
$user_rank = !empty($data['user_rank']) ? $data['user_rank'] : 0;
if (isset($ranks[$user_rank])) {
$title = $ranks[$user_rank]['rank_title'];
$style = $ranks[$user_rank]['rank_style'];
}
if (empty($title)) {
$title = $lang['USER'];
}
if (empty($style)) {
$style = 'colorUser';
}
if (!$bb_cfg['color_nick']) {
$style = '';
}
$username = !empty($data['username']) ? $data['username'] : $lang['GUEST'];
$user_id = (!empty($data['user_id']) && $username != $lang['GUEST']) ? $data['user_id'] : GUEST_UID;
$profile = '' . $username . '';
if (!in_array($user_id, explode(',', EXCLUDED_USERS)) && $username) {
$target_blank = $target_blank ? ' target="_blank" ' : '';
$profile = '' . $profile . '';
if (getBanInfo((int)$user_id)) {
return '' . $profile . '';
}
}
return $profile;
}
function get_avatar($user_id, $ext_id, $allow_avatar = true, $height = '', $width = '')
{
global $bb_cfg;
$height = $height ? 'height="' . $height . '"' : '';
$width = $width ? 'width="' . $width . '"' : '';
$user_avatar = '
';
if ($user_id == BOT_UID && $bb_cfg['avatars']['bot_avatar']) {
$user_avatar = '
';
} elseif ($allow_avatar && $ext_id) {
if (is_file(get_avatar_path($user_id, $ext_id))) {
$user_avatar = '
';
}
}
return $user_avatar;
}
/**
* Returns gender image
*
* @param int $gender
* @return string|null
*/
function genderImage(int $gender): ?string
{
global $bb_cfg, $lang, $images;
if (!$bb_cfg['gender']) {
return false;
}
return match ($gender) {
MALE => '
',
FEMALE => '
',
default => '
',
};
}
function is_gold($type): string
{
global $lang, $bb_cfg, $images;
$type = (int)$type;
$is_gold = '';
if (!$bb_cfg['tracker']['gold_silver_enabled']) {
return $is_gold;
}
switch ($type) {
case TOR_TYPE_GOLD:
$is_gold = '
';
break;
case TOR_TYPE_SILVER:
$is_gold = '
';
break;
default:
break;
}
return $is_gold;
}
function update_atom($type, $id)
{
switch ($type) {
case 'user':
\TorrentPier\Legacy\Atom::update_user_feed($id, get_username($id));
break;
case 'topic':
$topic_poster = (int)DB()->fetch_row("SELECT topic_poster FROM " . BB_TOPICS . " WHERE topic_id = $id LIMIT 1", 'topic_poster');
\TorrentPier\Legacy\Atom::update_user_feed($topic_poster, get_username($topic_poster));
break;
}
}
function hash_search($hash)
{
global $lang;
$hash = htmlCHR(trim($hash));
$info_hash_where = null;
if (!isset($hash) || !ctype_xdigit($hash)) {
bb_die(sprintf($lang['HASH_INVALID'], $hash));
}
$info_hash = DB()->escape(pack('H*', $hash));
// Check info_hash version
if (mb_strlen($hash, 'UTF-8') == 40) {
$info_hash_where = "WHERE info_hash = '$info_hash'";
} elseif (mb_strlen($hash, 'UTF-8') == 64) {
$info_hash_where = "WHERE info_hash_v2 = '$info_hash'";
} else {
bb_die(sprintf($lang['HASH_INVALID'], $hash));
}
if ($row = DB()->fetch_row("SELECT topic_id FROM " . BB_BT_TORRENTS . " $info_hash_where")) {
redirect(TOPIC_URL . $row['topic_id']);
} else {
bb_die(sprintf($lang['HASH_NOT_FOUND'], $hash));
}
}
/**
* Функция для получения и проверки правильности ответа от Google ReCaptcha.
*
* @param $mode
* @param string $callback
*
* @return bool|string
*/
function bb_captcha($mode, $callback = '')
{
global $bb_cfg, $lang;
$secret = $bb_cfg['captcha']['secret_key'];
$public = $bb_cfg['captcha']['public_key'];
$cp_theme = $bb_cfg['captcha']['theme'] ?? 'light';
if (!$bb_cfg['captcha']['disabled'] && (!$public || !$secret)) {
bb_die($lang['CAPTCHA_SETTINGS']);
}
$reCaptcha = new \ReCaptcha\ReCaptcha($secret);
switch ($mode) {
case 'get':
return "
";
break;
case 'check':
$resp = $reCaptcha->verify(
request_var('g-recaptcha-response', ''),
$_SERVER["REMOTE_ADDR"]
);
if ($resp->isSuccess()) {
return true;
}
break;
default:
bb_simple_die(__FUNCTION__ . ": invalid mode '$mode'");
}
return false;
}
function clean_tor_dirname($dirname)
{
return str_replace(['[', ']', '<', '>', "'"], ['[', ']', '<', '>', '''], $dirname);
}
/**
* Get birthday icon
*
* @param $user_birthday
* @param $user_id
* @return string
*/
function user_birthday_icon($user_birthday, $user_id): string
{
global $bb_cfg, $images, $lang;
$current_date = bb_date(TIMENOW, 'md', false);
$user_birthday = ($user_id != GUEST_UID && !empty($user_birthday) && $user_birthday != '1900-01-01')
? bb_date(strtotime($user_birthday), 'md', false) : false;
return ($bb_cfg['birthday_enabled'] && $current_date == $user_birthday) ? '
' : '';
}
/**
* Returns information about user ban
*
* @param int|null $userId
* @return array|null
*/
function getBanInfo(int $userId = null): ?array
{
global $datastore;
// Get bans info from datastore
if (!$bans = $datastore->get('ban_list')) {
$datastore->update('ban_list');
$bans = $datastore->get('ban_list');
}
if (!isset($userId)) {
return $bans;
}
return $bans[$userId] ?? [];
}