<?php

/*
 * @name        JMY CMS
 * @link        https://jmy.su/
 * @copyright   Copyright (C) 2012-2025 JMY LTD
 * @license     LICENSE.txt (see attached file)
 * @version     VERSION.txt (see attached file)
 * @author      Komarov Ivan
 * @edited      Orlov Alexsey
 */

if (!defined('ACCESS')) {
    header('Location: /');
    exit;
}
global $lang;
if (isset($lang['today'])) return;
function parseBB($text, $id = false, $html = false): string
{
    $bb = new bb;
    return $bb->parse($text, $id, $html);
}

function html2bb($text): array|string|null
{
    $bb = new bb;
    return $bb->htmltobb($text);
}

function processText($str): string
{
    if (function_exists("get_magic_quotes_gpc")) $str = stripslashes($str);
    return addslashes($str);
}

function prepareTitle($title): array|string
{
    $title = htmlspecialchars(stripslashes($title), ENT_QUOTES);
    return str_replace("&amp;", "&", $title);
}

function get_exgroup($points, $exgroup)
{
    global $core;
    if ($exgroup > 0 && isset($core->auth->groups_array[$exgroup])) {
        return is_array($exgroup) ? $core->auth->groups_array[$exgroup] : '';
    } elseif ($points > 0 && $exgroup == 0) {
        foreach ($core->auth->groups_array as $id => $arr) {
            if ($arr['special'] == 1 && $points >= $arr['points'] && $arr['points'] > 0) return $arr;
        }
    }
}

function user_points($uid, $conf): void
{
    global $core, $user;
    if ($user['count_points'] == 1) {
        require_once(ROOT . 'etc/points.config.php');
        $where = is_numeric($uid) ? "WHERE `id`='" . intval($uid) . "'" : "WHERE `nick`='" . filter($uid, 'nick') . "'";
        if (isset($points_conf[$conf])) $core->upd_data('users', 'points = points+"' . intval($points_conf[$conf]) . '"', $where);
    }
}

function clearcache(): void
{
    if (checkAdmControl()) {
        ajaxInit();
        full_rmdir(ROOT . 'tmp/mysql');
        full_rmdir(ROOT . 'tmp/cache');
        @mkdir(ROOT . 'tmp/mysql');
        @mkdir(ROOT . 'tmp/cache');
    }
}

function clear_cache(): void
{
    ajaxInit();
    full_rmdir(ROOT . 'tmp/cache');
    @mkdir(ROOT . 'tmp/cache', 0777);
}

function engine_encode($str = ''): string
{
    global $config;
    $result = '';
    for ($i = 0, $len = strlen($str); $i < $len; $i++) {
        $result .= '#' . strtr(ord($str[$i]), $config['uniqKey'], strrev($config['uniqKey']));
    }
    return $result;
}

function counts_error($id): int
{
    $errors = 0;
    foreach (glob(ROOT . 'tmp/' . $id . '.log') as $file) {
        $errors = count(file($file));
    }
    return $errors;
}

function engine_decode($str = ''): string
{
    global $config;
    $result = '';
    $str = explode('#', $str);
    for ($i = 0, $len = count_($str); $i < $len; $i++) {
        if (empty($str[$i])) continue;
        $result .= chr((int)strtr($str[$i], strrev($config['uniqKey']), $config['uniqKey']));
    }
    return $result;
}

function fwrite_stream($fp, $string): int
{
    for ($written = 0; $written < strlen($string); $written += $fwrite) {
        $fwrite = fwrite($fp, substr($string, $written));
        if ($fwrite === false) {
            return $written;
        }
    }
    return $written;
}

/*
      * Сохраняем кэш
      * $file - файл(без разрещения .cache) который находится в tmp/cache
      * $data - то что запишем в кэш
      */
function setcache($file, $data, $conf = false)
{
    global $allowCahce;
    if (isset($allowCahce[$file]) && $allowCahce[$file] == 0) return true;
    if (isset($allowCahce[$conf]) && $allowCahce[$conf] == 0) return true;
    if ($data) {
        $data = int_Serialize('ser', $data);
        $fp = @fopen(ROOT . 'tmp/cache/' . trim($file) . '.cache', 'w');
        fwrite_stream($fp, $data);
        fclose($fp);
        @chmod(ROOT . 'tmp/cache/' . trim($file) . '.cache', 0777);
        return true;
    }
}

function is_cache($file): bool
{
    return file_exists(ROOT . 'tmp/cache/' . trim($file) . '.cache');
}

/*
      * Получаем кэш из файла
      * $file - файл(без разрещения .cache) который находится в tmp/cache
      */
function getcache($file)
{
    global $core;
    if (empty($core->cacheContent[md5($file)])) {
        $path = ROOT . 'tmp/cache/' . trim($file) . '.cache';
        if ($core->cacheContent[md5($file)] = int_Serialize('uns', @file_get_contents($path))) return $core->cacheContent[md5($file)];
    } else {
        return $core->cacheContent[md5($file)];
    }
}

function delcache($file): void
{
    $path = ROOT . 'tmp/cache/' . trim($file) . '.cache';
    @unlink($path);
}

function removeDirectory($id, $module = false): void
{
    $dir = !isset($module) ? ROOT . 'files/' . $id : ROOT . 'files/' . $module . '/' . $id;
    if ($objs = glob($dir . "/*")) {
        foreach ($objs as $obj) {
            is_dir($obj) ? removeDirectory($obj) : unlink($obj);
        }
    }
    rmdir($dir);
}

function clearDirectory($dir, $id): void
{
    if (isset($id)) {
        $paths = ROOT . 'files/' . $dir . '/' . $id;
        @unlink($paths);
    } else {
        /*********************************/
        $paths = ROOT . 'files/' . $dir . '/';
        $idir = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($paths, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($idir as $v) {
            if ($v->isDir() and $v->isWritable()) {
                $f = glob($idir->key() . '/*.*');
                if (empty($f)) rmdir($idir->key());
            }
        }
        /*********************************/
    }
}

/*
      * Сжимаем файлики
      * $scr - полный адресс к файлу( ROOT.'/')
      */
function compress($src): void
{
    global $log_conf;
    if (file_exists($src) && filesize($src) > $log_conf['compressSize']) {
        $fp = fopen($src, "r");
        $data = fread($fp, filesize($src));
        fclose($fp);
        $name = explode('.', basename($src));
        $dst = ROOT . 'tmp/archives/' . $name[0] . '_' . time() . '.gz';
        $zp = gzopen($dst, "w9");
        if (gzwrite($zp, $data)) unlink($src);
        gzclose($zp);
    }
}

function GZunpack($file_name): void
{
// Raising this value may increase performance
    $buffer_size = 4096; // read 4kb at a time
    $out_file_name = str_replace('.gz', '', $file_name);
// Open our files (in binary mode)
    $file = gzopen($file_name, 'rb');
    $out_file = fopen($out_file_name, 'wb');
// Keep repeating until the end of the input file
    while (!gzeof($file)) {
        // Read buffer-size bytes
        // Both fwrite and gzread and binary-safe
        fwrite($out_file, gzread($file, $buffer_size));
    }
// Files are done, close files
    fclose($out_file);
    gzclose($file);
}

function checkType($type, $obj = 'all'): void
{
    global $files_conf;
    switch ($obj) {
        case 'all':
            $parseStr = $files_conf['imgFormats'] . ',' . $files_conf['attachFormats'];
            $typeArr = explode(',', $parseStr);
            foreach ($typeArr as $type) {
                if (trim($type) != '') $types[] = $type;
            }
            if (in_array($type, $types)) echo 'ok';
            break;
        case 'image':
            $parseStr = $files_conf['imgFormats'];
            $typeArr = explode(',', $parseStr);
            foreach ($typeArr as $type) {
                if (trim($type) != '') $types[] = $type;
            }
            if (in_array($type, $types)) echo 'ok';
            break;
        case 'attach':
            $parseStr = $files_conf['attachFormats'];
            $typeArr = explode(',', $parseStr);
            foreach ($typeArr as $type) {
                if (trim($type) != '') $types[] = $type;
            }
            if (in_array($type, $types)) echo 'ok';
            break;
    }
}

/*
      * Красиво выводим массивы
      * $var - переменную которую будем обрабатывать
      */
function prt($var): void
{
    echo '<pre>';
    print_r($var);
    echo '</pre>';
}

function getTime($startTime)
{
    global $lang;
    $result = '';
    $time = time() - $startTime;
    $s = $time % 60;
    $m = $time / 60 % 60;
    $h = $time / 3600 % 24;
    $d = $time / 86400 % 30;
    if ($m > 0) {
        $result = $m . $lang['minute_ago'];
        if ($m < 1) $result = $lang['now'];
    }
    if ($h > 0) $result = $h . $lang['hour_ago'];
    if ($d > 0) $result = $d . $lang['day_ago'];
    if (empty($result)) {
        $result = $m == 0 ? $lang['now'] : $s . $lang['sec_ago'];
    }
    return $result;
}

/*
      * Преобразовываем время в нормальный вид
      * $date - это время в юникс формате(time();)
      * $norm - если true(Января),а если false(янв)
      */
function formatDate($date, $norm = false)
{
    global $lang;
    $str_time = date("Y-m-d H:i:sP", $date);
    $time = strtotime($str_time);
    try {
        $d = new DateTime($str_time);
    } catch (Exception $e) {
    }
    $min_diff = floor((strtotime('now') - $time) / 60);
    $hour_diff = floor((strtotime('now') - $time) / (60 * 60));
    $weekDays = ['mon', 'tue', 'wed', 'thur', 'fri', 'sat', 'sun'];
    $months = $norm ? ['januarys', 'februarys', 'marchs', 'aprils', 'mays', 'junes', 'julys', 'augusts', 'septembers', 'octobers', 'novembers', 'decembers'] : ['mjan', 'mfeb', 'mmar', 'mapr', 'mmay', 'mjun', 'mjul', 'maug', 'msep', 'moct', 'mnov', 'mdec'];
    if ($time > strtotime('-1 minutes')) {
        return $lang['now'];
    } elseif ($time > strtotime('-2 minutes')) {
        return $min_diff . $lang['minutes4'] . $lang['time_ago'];
    } elseif ($time > strtotime('-59 minutes')) {
        return declension($min_diff, array($lang['minutes1'], $lang['minutes2'], $lang['minutes3'])) . $lang['time_ago'];
    } elseif ($time > strtotime('-23 hours')) {
        return declension($hour_diff, array($lang['hours1'], $lang['hours2'], $lang['hours3'])) . $lang['time_ago'];
    } elseif ($time > strtotime('today')) {
        return $d->format('G:i');
    } elseif ($time > strtotime('yesterday')) {
        return $lang['yesterday_in'] . $d->format('G:i');
    } elseif ($time > strtotime('this week')) {
        return $lang[$weekDays[$d->format('N') - 1]] . $lang['in'] . $d->format('G:i');
    } else {
        return $d->format('j') . '&nbsp;' . $lang[$months[$d->format('n') - 1]] . (($d->format('Y') != date("Y")) ? $d->format(' Y') : "") . $lang['in'] . $d->format('G:i');
    }
}

/*
      * Обрезаем текст
      * $text - это собственно текст который режем
      * $max - максимальное кол-во символов
      */
function str($text, $max)
{
    return mb_strlen($text, 'UTF-8') > $max ? mb_substr($text, 0, $max, 'utf-8') . '...' : $text;
}

/*
      * Ситаем  количество введённых символов
      * $text - это собственно текст который ситаем
      */
function jmy_strlen($text)
{
    if (isset($text)) return mb_strlen($text, 'utf-8');
}

/*
      * Функция транслита текста
      * $text - это собственно текст который будем преобразовывать
      */
function translit($string, $tochka = ''): string
{
    $string = filter($string, 'a');
    $arr = array('ж' => 'zh', 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'shh', 'э' => 'je', 'ю' => 'ju', 'я' => 'ja', 'ъ' => '', 'ь' => '', '.' => $tochka);
    $str = array("а", "б", "в", "г", "д", "е", "з", "и", "к", "л", "м", "н", "о", "п", "р", "с", "т", "у", "ф", "ц", "ъ", "ы", "ь");
    $str_to = array("a", "b", "v", "g", "d", "e", "z", "i", "k", "l", "m", "n", "o", "p", "r", "s", "t", "u", "f", "с", "", "y", "");
    $result = mb_strtolower(trim(strip_tags($string)), 'UTF-8');
    $result = preg_replace('/\s+/ms', '-', $result);
    $result = str_replace($str, $str_to, $result);
    $result = str_replace(array_keys($arr), array_values($arr), $result);
    $result = preg_replace('/[^a-z0-9\_\-.]+/mi', '', $result);
    $result = preg_replace('#[\-]+#i', '-', $result);
    return mb_substr($result, 0, 40);
}

/*
      * Отображаем обратный отчет типа 2 года 6 месяцев 3 дня 2 часа 25 минут 54 секунды
       diff($d, $format = "Y-m-d H:i:s")
      */
function decl($n, $f): string
{
    $c = '[2, 0, 1, 1, 1, 2]';
    return $n . '&nbsp;' . $f[($n % 100 > 4 && $n % 100 < 20) ? 2 : $c[min($n % 10, 5)]] . ' ';
}

function f($n, $s): string
{
    return $n > 0 ? decl($n, $s) : '';
}

function diff($d, $format = "Y-m-d H:i:s"): string
{
    //			  1,		  2-4,		5-20...
    static $a = '[["год", "года", "лет"],
              ["месяц", "месяца", "месяцев"],
              ["день", "дня", "дней"],
              ["час", "часа", "часов"],
              ["минута", "минуты", "минут"],
              ["секунда", "секунды", "секунд"],
          ]';
    $dt = DateTime::createFromFormat($format, $d);
    $now = new DateTime();
    $diff = $dt->diff($now);
    $result = f($diff->y, $a[0]);
    $result .= f($diff->m, $a[1]);
    $result .= f($diff->d, $a[2]);
    $result .= f($diff->h, $a[3]);
    $result .= f($diff->i, $a[4]);
    $result .= f($diff->s, $a[5]);
    return rtrim($result);
}

function secToArray($secs): array
{
    $res = array();
    $res['days'] = floor($secs / 86400);
    $secs = $secs % 86400;
    $res['hours'] = floor($secs / 3600);
    $secs = $secs % 3600;
    $res['minutes'] = floor($secs / 60);
    $res['secs'] = $secs % 60;
    return $res;
}

function num_word($value, $words, $show = true): string
{
    $num = $value % 100;
    if ($num > 19) $num = $num % 10;
    $out = ($show) ? $value . ' ' : '';
    $out .= match ($num) {
        1 => $words[0],
        2, 3, 4 => $words[1],
        default => $words[2],
    };
    return $out;
}

function secToStr($secs, $full = false): string
{
    $res = '';
    if ($full) {
        $days = floor($secs / 86400);
        $secs = $secs % 86400;
        $res .= num_word($days, array('день', 'дня', 'дней')) . ', ';
        $hours = floor($secs / 3600);
        $secs = $secs % 3600;
        $res .= num_word($hours, array('час', 'часа', 'часов')) . ', ';
    }
    $minutes = floor($secs / 60);
    $secs = $secs % 60;
    $res .= num_word($minutes, array('минута', 'минуты', 'минут')) . ', ';
    $res .= num_word($secs, array('секунда', 'секунды', 'секунд'));
    return $res;
}


/**
 * Счетчик обратного отсчета
 *
 * @param mixed $date
 * @return
 */
function downcounter($date): false|string
{
    global $lang;
    $check_time = $date - time();
    if ($check_time <= 0) return false;
    $days = floor($check_time / 86400);
    $hours = floor(($check_time % 86400) / 3600);
    $minutes = floor(($check_time % 3600) / 60);
    $seconds = $check_time % 60;
    $str = '';
    if ($days > 0) $str .= declension($days, array($lang['days1'], $lang['days2'], $lang['days3'])) . ' ';
    if ($hours > 0) $str .= declension($hours, array($lang['hours1'], $lang['hours2'], $lang['hours3'])) . ' ';
    if ($minutes > 0) $str .= declension($minutes, array($lang['minutes1'], $lang['minutes2'], $lang['minutes3'])) . ' ';
    if ($seconds > 0) $str .= declension($seconds, array($lang['seconds1'], $lang['seconds2'], $lang['seconds3']));
    return $str;
}

/**
 * Функция склонения слов
 *
 * @param mixed $digit
 * @param mixed $expr
 * @param bool $onlyword
 * @return
 */
function declension($digit, $expr, $onlyword = false): string
{
    if (!is_array($expr)) $expr = array_filter(explode(' ', $expr));
    if (empty($expr[2])) $expr[2] = $expr[1];
    $i = preg_replace('/[^0-9]+/s', '', $digit) % 100;
    if ($onlyword) $digit = '';
    if ($i >= 5 && $i <= 20) {
        $res = $digit . '&nbsp;' . $expr[2];
    } else {
        $i %= 10;
        if ($i == 1) {
            $res = $digit . '&nbsp;' . $expr[0];
        } elseif ($i >= 2 && $i <= 4) {
            $res = $digit . '&nbsp;' . $expr[1];
        } else {
            $res = $digit . '&nbsp;' . $expr[2];
        }
    }
    return trim($res);
}

/*
      * Отображаем превью картинки
      */
function img_preview($img, $type)
{
    if ($type == 'box') return $img;
}

/*
* Парсер шаблона bb редактора
* $name - имя формы например: <textarea name='этот параметр'.....
* $val - возможно в форму чтото нада пихнуть это будет <textarea>тут</textarea>
* $rows - количество строк в форме
* $class - возможно захотите задать уникальный css класс
* $onlick - дополнительное поле на разнообразные нужды
*/
/**
 * @param $name
 * @param null $val
 * @param int $rows
 * @param string $class
 * @param null $onclick
 * @param bool|bool $return
 * @param bool|bool $html
 * @return string
 */
function bb_area($name, $val = null, int $rows = 5, string $class = 'textarea', $onclick = null, bool $return = false, bool $html = false): string
{
    global $core, $config, $smileList, $smiles, $user, $url, $lang;
    static $initArea;
    $id = $name;
    $core->tpl->headerIncludes['bb'] = '<script type="text/javascript" src="usr/plugins/js/bb_editor.js"></script><script type="text/javascript">var textareaName = \'' . $name . '\';</script>';
    if (($core->auth->isUser && $core->auth->group_info['addComment'] == 1) || $core->auth->isUser && $core->auth->group_info['addPost'] == 1 || ($core->auth->isModer || $core->auth->isAdmin)) {
        $core->tpl->headerIncludes['htmleditor'] = '<script type="text/javascript" src="/usr/plugins/tinymce/tinymce.min.js"></script>
         <script>
  tinymce.init({
      theme: \'modern\',
      skin: \'custom\',
      selector: \'textarea\',
      language: "' . $config['lang'] . '",
      height: 300,
      menubar:false,
      statusbar: false,
      convert_urls: false,
      relative_urls: false,
      plugins: [
          \'advlist autolink lists link codesample hr image charmap print preview anchor\',
          \'searchreplace visualblocks code fullscreen imagetools textcolor colorpicker textpattern\',
          \'insertdatetime media table contextmenu paste spellchecker responsivefilemanager code youtube jmybutton emoticons\'
      ],
      toolbar1: \'undo redo | styleselect | fontsizeselect | fontselect | bold italic underline strikethrough | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent table hr  | subscript superscript \',
      toolbar2: \'link image jmythumb responsivefilemanager | jmymusic media youtube jmyflash jmyemo | jmymail jmyquote jmyhide codesample jmyspoiler | spellchecker removeformat searchreplace code \',
      image_advtab: true,
      imagetools_cors_hosts: [\'www.tinymce.com\', \'codepen.io\'],
      spellchecker_language : "' . $config['lang'] . '",
      spellchecker_languages : "Russian=ru,Ukrainian=uk,English=en",
      spellchecker_rpc_url : "//speller.yandex.net/services/tinyspell",
      external_filemanager_path: "/usr/plugins/filemanager/",
      external_plugins: { "filemanager" : "/usr/plugins/filemanager/plugin.min.js"},
      filemanager_title: "' . $lang['files_config'] . '",
  });
</script>';
    } else {
        $core->tpl->headerIncludes['htmleditor'] = '<script type="text/javascript" src="/usr/plugins/tinymce/tinymce.min.js"></script>
             <script>
  tinymce.init({
      theme: \'modern\',
      skin: \'custom\',
      selector: \'textarea\',
      language: "' . $config['lang'] . '",
      height: 300,
      menubar:false,
      statusbar: false,
      convert_urls: false,
      relative_urls: false,
      plugins: [
          \'advlist autolink lists link codesample hr image charmap print preview anchor\',
          \'searchreplace visualblocks code fullscreen imagetools textcolor colorpicker textpattern\',
          \'insertdatetime media table contextmenu paste spellchecker responsivefilemanager code youtube jmybutton  \'
      ],
      toolbar1: \' styleselect |  bold italic underline strikethrough | alignleft aligncenter alignright alignjustify  forecolor \',
      toolbar2: \'jmyemo | jmymail jmyquote jmyhide codesample jmyspoiler | spellchecker  \',
      image_advtab: true,
      imagetools_cors_hosts: [\'www.tinymce.com\', \'codepen.io\'],
      spellchecker_language : "' . $config['lang'] . '",
      spellchecker_languages : "Russian=ru,Ukrainian=uk,English=en",
      spellchecker_rpc_url : "//speller.yandex.net/services/tinyspell",
      external_filemanager_path: "/usr/plugins/filemanager/",
      external_plugins: { "filemanager" : "/usr/plugins/filemanager/plugin.min.js"},
      filemanager_title: "' . $lang['files_config'] . '"
  });
</script>';
    }
    return '<textarea id="' . $id . '" name="' . $name . '" rows="' . $rows . '" cols="90" class="' . $class . '" onclick="mainArea(\'' . $name . '\')">' . $val . '</textarea>';
}

function edit_area($name, $val = null, $rows = 5, $class = 'textarea', $onclick = null, $return = false, $html = false)
{
    global $core, $smileList, $smiles, $user, $url;
    $core->tpl->headerIncludes['htmleditor'] = '<script type="text/javascript" src="/usr/plugins/tinymce/tinymce.min.js"></script>';
    if ($name) {
        $i_smile = 0;
        foreach ($smiles as $smile => $info) {
            if ($url[0] == ADMIN) {
                if ($i_smile % 4 == 0) $smileList .= '<li>';
                $smileList .= '<img src="' . $info['url'] . '" border="0" title="' . $info['title'] . '" onclick="javascript:insertBB(\'' . $smile . '\', \'smile\');" class="_pointer" alt=""/>';
                if ($i_smile <> 0) {
                    if (($i_smile + 1) % 4 == 0) $smileList .= '</li>';
                }
                $i_smile = $i_smile + 1;
            } else {
                $smileList .= '<span><img src="' . $info['url'] . '" style="border:0;" title="' . $info['title'] . '" onclick="javascript:insertBB(\'' . $smile . '\', \'smile\');" class="_pointer" alt=""/></span>';
            }
        }
        if ($return) ob_start();
        $core->tpl->loadFile('bb_area');
        $core->tpl->setVar('NAME', $name);
        $core->tpl->setVar('TEXT', $core->bbDecode(parseBB($val)));
        $core->tpl->setVar('ROWS', $rows);
        $core->tpl->setVar('CLASS', $class);
        $core->tpl->setVar('ONCLICK', $onclick);
        $core->tpl->setVar('SMILE_LIST', $smileList);
        $core->tpl->sources = preg_replace_callback("#\\[loadAttach](.*?)\\[/loadAttach]#is", 'isLoadAttach', $core->tpl->sources);
        $core->tpl->sources = if_sets("#\\[activeFlash](.*?)\\[/activeFlash]#is", $core->tpl->sources, isset($user['activeFlash']) && $user['activeFlash'] == 1);
        $core->tpl->sources = if_sets("#\\[activeVideo](.*?)\\[/activeVideo]#is", $core->tpl->sources, isset($user['activeVideo']) && $user['activeVideo'] == 1);
        $core->tpl->sources = if_sets("#\\[activeAudio](.*?)\\[/activeAudio]#is", $core->tpl->sources, isset($user['activeAudio']) && $user['activeAudio'] == 1);
        $core->tpl->sources = if_sets("#\\[activeHTML](.*?)\\[/activeHTML]#is", $core->tpl->sources, (bool)$html);
        $core->tpl->sources = if_sets("#\\[initArea](.*?)\\[/initArea]#is", $core->tpl->sources, !isset($initArea));
        if (!isset($initArea)) $initArea = true;
        $core->tpl->end();
        if ($return) {
            $contents = ob_get_contents();
            ob_end_clean();
            return $contents;
        }
    }
}

function bb_areaADM($name, $val = null, $rows = 5, $class = 'textarea', $onclick = null, $return = false, $html = false)
{
    global $core, $smileList, $smiles, $user;
    static $initArea;
    if ($name) {
        $i_smile = 0;
        foreach ($smiles as $smile => $info) {
            if ($i_smile % 4 == 0) $smileList .= '<li>';
            $smileList .= '<img src="' . $info['url'] . '" border="0" title="' . $info['title'] . '" onclick="javascript:insertBB(\'' . $smile . '\', \'smile\');" class="_pointer" alt=""/>';
            if ($i_smile <> 0) {
                if (($i_smile + 1) % 4 == 0) $smileList .= '</li>';
            }
            $i_smile = $i_smile + 1;
        }
        if ($return) ob_start();
        $core->tpl->loadFile('bb_area');
        $core->tpl->setVar('NAME', $name);
        $core->tpl->setVar('TEXT', $val);
        $core->tpl->setVar('ROWS', $rows);
        $core->tpl->setVar('CLASS', $class);
        $core->tpl->setVar('ONCLICK', $onclick);
        $core->tpl->setVar('SMILE_LIST', $smileList);
        $core->tpl->sources = preg_replace_callback("#\\[loadAttach](.*?)\\[/loadAttach]#is", 'isLoadAttach', $core->tpl->sources);
        $core->tpl->sources = if_sets("#\\[activeFlash](.*?)\\[/activeFlash]#is", $core->tpl->sources, isset($user['activeFlash']) && $user['activeFlash'] == 1);
        $core->tpl->sources = if_sets("#\\[activeVideo](.*?)\\[/activeVideo]#is", $core->tpl->sources, isset($user['activeVideo']) && $user['activeVideo'] == 1);
        $core->tpl->sources = if_sets("#\\[activeAudio](.*?)\\[/activeAudio]#is", $core->tpl->sources, isset($user['activeAudio']) && $user['activeAudio'] == 1);
        $core->tpl->sources = if_sets("#\\[activeHTML](.*?)\\[/activeHTML]#is", $core->tpl->sources, (bool)$html);
        $core->tpl->sources = if_sets("#\\[initArea](.*?)\\[/initArea]#is", $core->tpl->sources, !isset($initArea));
        if (!isset($initArea)) $initArea = true;
        $core->tpl->end();
        if ($return) {
            $contents = ob_get_contents();
            ob_end_clean();
            return $contents;
        }
    }
}

function getUrlData($url, $raw = false): false|array // $raw - enable for raw display
{
    $result = false;
    $contents = getUrlContents($url);
    if (isset($contents) && is_string($contents)) {
        $title = null;
        $metaTags = null;
        $metaProperties = null;
        preg_match('/<title>([^>]*)<\/title>/si', $contents, $match);
        if (isset($match) && is_array($match) && count_($match) > 0) $title = strip_tags($match[1]);
        preg_match_all('/<[\s]*meta[\s]*(name|property)="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si', $contents, $match);
        if (isset($match) && is_array($match) && count_($match) == 4) {
            $originals = $match[0];
            $names = $match[2];
            $values = $match[3];
            if (count_($originals) == count_($names) && count_($names) == count_($values)) {
                $metaTags = array();
                $metaProperties = $metaTags;
                if ($raw) $flags = version_compare(PHP_VERSION, '5.4.0') == -1 ? ENT_COMPAT : ENT_COMPAT | ENT_HTML401;
                for ($i = 0, $limiti = count_($names); $i < $limiti; $i++) {
                    $meta_type = $match[1][$i] == 'name' ? 'metaTags' : 'metaProperties';
                    if ($raw) {
                        ${$meta_type}[$names[$i]] = array(
                            'html' => htmlentities($originals[$i], $flags, 'UTF-8'),
                            'value' => $values[$i]
                        );
                    } else {
                        ${$meta_type}[$names[$i]] = array(
                            'html' => $originals[$i],
                            'value' => $values[$i]
                        );
                    }
                }
            }
        }
        $result = array(
            'title' => $title,
            'metaTags' => $metaTags,
            'metaProperties' => $metaProperties,
        );
    }
    return $result;
}

function getUrlContents($url, $maximumRedirections = null, $currentRedirection = 0): false|string
{
    $result = false;
    $contents = @file_get_contents($url);
    // Check if we need to go somewhere else
    if (isset($contents) && is_string($contents)) {
        preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' . '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' . '[\s]*[\/]?[\s]*>/si', $contents, $match);
        if (isset($match) && is_array($match) && count_($match) == 2 && count_($match[1]) == 1) {
            if (!isset($maximumRedirections) || $currentRedirection < $maximumRedirections) return getUrlContents($match[1][0], $maximumRedirections, ++$currentRedirection);
            $result = false;
        } else {
            $result = $contents;
        }
    }
    return $result;
}

function unser_base($obj): string
{
    $string = base64_encode(serialize($obj));
    unserialize(base64_decode($string));
    return $string;
}

function int_Serialize($choice, $obj)
{

    if ($choice == 'ser') {
        return base64_encode(@gzcompress(serialize($obj)));
    } elseif ($choice == 'uns') {
        return unserialize(@gzuncompress(base64_decode($obj)));
    }
}

function file_get_contents_utf8($fn): bool|array|string
{
    $content = false;
    if (stripos($fn, "http://") !== 0 and stripos($fn, "https://") !== 0) return false;
    if (function_exists('curl_init')) {
        $ch = curl_init($fn);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_URL, $fn);
        curl_setopt($ch, CURLOPT_REFERER, $fn);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $content = curl_exec($ch);
        curl_close($ch);
    } else {
        $content = @file_get_contents($fn);
        return mb_convert_encoding($content, 'UTF-8', mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true));
    }
    return $content ?? false;

}

function send_url($url, $sitemap): bool|string
{
    $data = false;
    $file = $url . urlencode($sitemap);
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        $timeout = 30;
        curl_setopt($ch, CURLOPT_URL, $file);
        curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_REFERER, $file);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    } else {
        return file_get_contents($file);
    }
}

function get_url_contents($url): bool|array|string
{
    if (function_exists('file_get_contents')) $result = @file_get_contents_utf8($url);
    if ($result == '') {
        $ch = curl_init($url);
        $timeout = 30;
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_REFERER, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        $result = curl_exec($ch);
        curl_close($ch);
    }
    return $result;
}

function ContOptions($url)
{
    global $adminTpl, $db, $core, $lang;
    if (isset($url)) {
        $arrContextOptions = array(
            "ssl" => array(
                "verify_peer" => false,
                "verify_peer_name" => false,
            ),
        );
        $content = file_get_contents_utf8($url, false, stream_context_create($arrContextOptions));
    }
    if (isset($content)) return $content;
}

function search_tags($dir, $text): bool
{
    $file = file_get_contents($dir);
    $search = substr_count($file, $text);
    return $search > 0;
}

function simple($content): SimpleXMLElement
{
    try {
        return new SimpleXmlElement($content);
    } catch (Exception $e) {
    }
}

function getFeeds($url): void
{
    $content = file_get_contents($url);
    $items = simple($content);
    print '<ul>';
    foreach ($items->channel->item as $item) {
        print '<li><a href = ‘{$item->link}’ title = ‘$item->title’>' .
            $item->title . '</a> - ' . $item->description . '</li>';
    }
    print '</ul>';
}

function getFeed($url, $nmax, $tmax, $dmax, $date_format)
{
    $content = ContOptions($url);
    if ($content) {
        $items = simple($content);
        $count = 0;
        $html = '<p>';
        if ($items->channel->item) {
            foreach ($items->channel->item as $item) {
                $count++;
                if ($item->title) $title = (string)$item->title;
                if ($item->description) $description = (string)$item->description;
                if ($item->link) $link = (string)$item->link;
                if ($item->pubDate) $pubDate = (string)$item->pubDate;
                if ($item->category) $category = (string)$item->category;
                if ($item->content) $content = (string)$item->content;
                if ($count > $nmax) break;
                if (!isset($description)) {
                    if ($count > 1) break;
                    if ($url) $html .= check_netz($url);
                } else {
                    $html .= '<p><a href="' . $link . '"  title = ' . utf8_convert($title, "") . '><i>' . internoetics_mb_strimwidthd(utf8_convert($title, ""), 0, $tmax, $trimmarker = '...') . '</i></a></p>';
                }
            }
        } else {
            $atom = $items->children('http://www.w3.org/2005/Atom');
            foreach ($atom->entry as $item) {
                $count++;
                if ($item->title) $title = (string)$item->title;
                if ($item->summary) $description = (string)$item->summary;
                if ($item->link) $link = (string)$item->link->attributes()->href;
                if ($item->published) $date = (string)$item->published;
                if ($item->updated) $date = (string)$item->updated;
                if ($item->category) $category = (string)$item->category;
                $content = str_replace(array(']]>', '</content>', '#<content[^>]*>#', '&lt;', '&gt;', '&amp;'), array('', '', '', '<', '>', '&'), $description);
                if ($count > $nmax) break;
                if (!isset($description)) {
                    if ($count > 1) break;
                    if ($url) $html .= check_netz($url);
                } else {
                    $html .= '<p><a href="' . $link . '"  title = ' . utf8_convert($title, "") . '><i>' . internoetics_mb_strimwidthd(utf8_convert($title, ""), 0, $tmax, $trimmarker = '...') . '</i></a></p>';
                }
            }
        }
        $html .= '</p>';
    } else {
        return;
    }
    return $html;
}

function check_netz($url): string
{
    $massiv[] = $url;
    foreach ($massiv as $key => $value) {
        $cont = ContOptions($url);
        $textcod = str_replace(array(']]>'), array(''), $cont);
        return '<div class="alert alert-component">
						<span>' . $textcod . '</span>
						</div>';
    }
}

function utf8_convert($str, $type)
{
    static $conv = '';
    if (!is_array($conv)) {
        $conv = array();
        for ($x = 128; $x <= 143; $x++) {
            $conv['utf'][] = chr(209) . chr($x);
            $conv['win'][] = chr($x + 112);
        }
        for ($x = 144; $x <= 191; $x++) {
            $conv['utf'][] = chr(208) . chr($x);
            $conv['win'][] = chr($x + 48);
        }
        $conv['utf'][] = chr(208) . chr(129);
        $conv['win'][] = chr(168);
        $conv['utf'][] = chr(209) . chr(145);
        $conv['win'][] = chr(184);
    }
    if ($type == 'w') {
        return str_replace($conv['utf'], $conv['win'], $str);
    } elseif ($type == 'u') {
        return str_replace($conv['win'], $conv['utf'], $str);
    } else {
        return $str;
    }
}

function convertEncoding($str): false|string
{
    return iconv(mb_detect_encoding($str), "UTF-8", $str);
}

function rss_forms($url)
{
    global $lang;
    $content = ContOptions($url);
    if (strripos($content, $lang['feed_atom'])) {
        $rss_forms = $lang['feed_atomd'];
    } elseif (strripos($content, $lang['feed_turbo_yandex1']) || strripos($content, $lang['feed_turbo_yandex2']) || strripos($content, $lang['feed_turbo_yandex3'])) {
        $rss_forms = $lang['feed_turbo_yandexd'];
    } elseif (strripos($content, $lang['feed_rss'])) {
        $rss_forms = $lang['feed_rssd'];
    } else {
        $rss_forms = $lang['feed_not_identified'];
    }
    return $rss_forms;
}

function isLoadAttach($content)
{
    global $core, $user;
    if ($core->auth->user_info['loadAttach'] == 1 && $user['activeAttach'] == 1) return stripslashes($content);
}

/*
 * Устанавливаем титл <title></title> страницы сайта
 * $array - массив из титлов (array('Главная', 'Новости'))
 */
function set_title($array): void
{
    global $core, $config;
    if (is_array($array)) {
        $title_massiv = array_reverse($array);
        $core->tpl->title = false;
        foreach ($title_massiv as $title) {
            if ($title) $core->tpl->title .= filter($title) . $config['divider'];
        }
    }
}

/*
 * Укорачиваем текст
 * $title - текст для сокращения
 * $quantity - значения
 */
function trimtitle($title, $quantity = '20')
{
    global $lang;
    if ($title) {
        $trimtitle = $quantity ? (mb_strlen($title, 'utf-8') <= $quantity ? $title : mb_strimwidth($title, 0, $quantity, $trimmarker = '...')) : ($title > 20 ? $title : mb_strimwidth($title, 0, 20, $trimmarker = '...'));
    } else {
        return $lang['error_conclusion'];
    }
    return $trimtitle;
}

/*
 * Форматируем размер файла в байтах
 * $size - размер в байтах
 */
function formatfilesize($size, $short = false)
{
    global $lang;
    if (is_numeric($size)) {
        $filesizename = $short ? array(" b", " kb", " mb", " gb", " tb", " pb", " eb", " zb", " yb") : array($lang['byte'], $lang['kbyte'], $lang['mbyte'], $lang['gbyte'], $lang['tbyte'], $lang['pbyte'], $lang['ebyte'], $lang['zbyte'], $lang['ybyte']);
        return $size ? round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . $filesizename[$i] : '0 ' . $lang['byte'];
    } else {
        return $size;
    }
}

/*
 * Альтернативная функция Форматирования размера файла в байтах
 * $bytes - размер в байтах
 */
function formatBytes($bytes): int|string
{
    if ($bytes > 0) {
        $i = floor(($bytes ? log($bytes) : 0) / log(1024));
        $sizes = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
        return sprintf('%.02F', round($bytes / pow(1024, $i), 1)) * 1 . '&nbsp;' . @$sizes[$i];
    } else {
        return 0;
    }
}

/*
 * Размер файла в кило/мега/гига/тера/пета байтах
 * @param int $sum — первичное значение
 * @return string — возвращаем форматируемое первичное значение в К, М, Г или Т
 */
function formatCounter($sum): string
{
    $formats = array('', 'К', 'М', 'Г', 'Т');// варианты размера
    $format = 0;// формат размера по-умолчанию
    // прогоняем цикл
    while ($sum > 1000 && count_($formats) != ++$format) {
        $sum = round(intval($sum) / 1000, 1);
    }
    // если число большое, мы выходим из цикла с
    // форматом превышающим максимальное значение
    // поэтому нужно добавить последний возможный
    // размер файла в массив еще раз
    $formats[] = 'Т';
    return $sum . $formats[$format];
}

/*
      * Инитилизируем странички ищем в массивах совпадения если таковы есть выводим
      */
function init_page($pref = 'page'): int
{
    global $url;
    if (is_array($url) && !array_key_exists($pref, $url) && !array_search($pref, $url)) {
        return 1;
    } else {
        $prepage = is_array($url) && !array_key_exists($pref, $url) ? array_search($pref, $url) : '';
        return isset($url[$prepage + 1]) && $url[$prepage] > 0 ? intval((string)$url[(int)$prepage + 1]) : 1;
        unset($url[$prepage]);
        unset($url[$prepage + 1]);
    }
}

function init_count_text(): void
{
    echo '<style>
    span{
        text-align:right;
}
</style>
 <script language="javascript" type="text/javascript">
var count = 1;
do {
    function count_down(obj, count, limit){
    let element = document.getElementById(\'char_\'+ count);
    let counter = limit - obj.value.length;
    element.innerHTML = counter + \'/\'+ limit;
    if (counter <0) {
     element.innerHTML = 0 + \'/\'+ limit;
  } else if  (counter <5) {
     element.style.color = "red";
  } else if (counter  <20) {
     element.style.color = "orange";
  } else {
     element.style.color = "green";
  }
}
count++;
} while (count <20);
</script>';
    // init_count_text();
    // <div align="right" class="text-right">
    //    <span id="char_id"></span>
    // </div>
}

function init_complexity_pass(): void
{
    global $lang;
    echo '<script type = "text/javascript">
    function passwordChanged()
    {
        var
        strength = document . getElementById(\'strength\');
        var strongRegex = new RegExp("^(?=.{14,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$", "g");
        var mediumRegex = new RegExp("^(?=.{10,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$", "g");
        var enoughRegex = new RegExp("(?=.{8,}).*", "g");
        var pwd = document.getElementById("password");
        if (pwd.value.length === 0) {
            strength.innerHTML = "' . $lang['do_type_password'] . '";
        } else if (false === enoughRegex.test(pwd.value)) {
            strength.innerHTML =  "' . $lang['do_too_short'] . '";
        } else if (strongRegex.test(pwd.value)) {
            strength.innerHTML = "' . $lang['do_hard'] . '";
        } else if (mediumRegex.test(pwd.value)) {
            strength.innerHTML = "' . $lang['do_medium'] . '";
        } else {
            strength.innerHTML = "' . $lang['do_easy'] . '";
        }
    }
</script>';
}

/*
      * Обработка фатальных ошибок
      * $title - титл ошибки
      * $error - текст ошибки
      */
function fatal_error($title, $error): void
{
    global $config, $lang;
    include_once ROOT . 'langs/' . $config['lang'] . '/' . $config['lang'] . '.site.lng';
    if ($title && $error) {
        die(' <!DOCTYPE html>
      			<html lang = "en">
      			<head >
      				<meta charset = "utf-8">
      				<base href = "' . $config['url'] . '/">
      				<meta name = "viewport" content = "width=device-width, user-scalable=1, initial-scale=1, maximum-scale=1">
      				<title > ' . $lang['error'] . ' </title>
      				<!--Stylesheets-->
      				<link rel = "stylesheet" type = "text/css" href = "//fonts.googleapis.com/css?family=Lato:300,400,600,700%7CMontserrat:400,700">
      				<link rel = "stylesheet" type = "text/css" href = "/usr/tpl/admin/assets/css/theme.css" >
      				<!--Favicon-->
      				<link rel = "icon" href = "/usr/tpl/admin/assets/images/favicon.ico" type = "image/x-icon" >
      			 </head >
      			 <body class="error-page external-page external-alt sb-l-c sb-r-c">
      				<div id = "main">
      					<section id = "content_wrapper">
      						<section id = "content" class="pn animated fadeIn">
      							<div class="center-block mt50 mw800">
      								<h1 class="error-title"> error</h1>
      								<h3 class="error-subtitle"><div class="mg-b-lg"> ' . $title . '</div ></h3 >
      								<p style = "margin-top:-50px;" class="text-center"> ' . $error . '<br > ' . $lang['error_sorry'] . ' </p>
      								<p class="text-center mt10" ><a target = "_blank" href = "' . $lang['jmycms_core'] . '" >&copy; 2012 - <span id = "year" class="mg-r-xs" ></span > JMY CORE </a ></p>
      							</div>
      							<script type = "text/javascript" >var el = document . getElementById("year"),year = (new Date().getFullYear());el . innerHTML = year;</script>
      						</section>
      				  </section>
      				</div>
      			  </body>
      			</html> ');
    }
}

function error_news(): void
{
    global $core, $config;
    @header("HTTP/1.1 404 Not Found");
    if ($config['off'] <> 0 && file_get_contents($config['url'] . '/404')) {
        @header("Content-type: text/html; charset=" . $config['charset']);
        location('404');
    } else {
        $core->tpl->info('Внимание!Обнаружена ошибка </br > К сожалению, данная страница для Вас недоступна, возможно был изменён её адрес или она была удалена . Пожалуйста, воспользуйтесь поиском . ');
    }
}

/*
      * Редиукреты
      * $path - куда редикретим
      */
function location($path = '/'): void
{
    global $config, $url, $core;
    if ($path != '/' && mb_substr($path, 0, 1) != '/' && !eregStrt('http', $path)) {
        if ($core->lang != $config['lang'] && $url[0] != ADMIN) $path = $config['lang'] . '/' . $path;
        $path = $config['url'] . '/' . $path;
    }
    $initFullAjax = (isset($_SERVER['HTTP_AJAX_ENGINE']) || isset($_REQUEST['fullajax']));
    if ($initFullAjax) {
        if (eregStrt('#', $path)) {
            $pathMass = explode('#', $path);
            header('Location: ' . $pathMass[0] . '&fullajax=ok');
        } else {
            header('Location: ' . $path . '&fullajax=ok');
        }
//	header('Location: ' . str_replace('#', ':@', $path) . '; FULL_AJAX');
    } else {
        header('Location: ' . str_replace('#', ':@', $path) . $initFullAjax);
    }
}

function _nTitle($mod, $id)
{
    global $core;
    $content = $core->row_data($mod, 'id = "' . $id . '"', false, 'c.*, l.*', 'as c  LEFT JOIN ' . DB_PREFIX . '_langs as l on(l.postId=c.id and l.module="' . $mod . '")');
    $catInfo = $content['cat'] !== ',0,' ? $core->getCat($mod, $content['cat'], 'development') : '';
    $altname = isset($catInfo) ? ($content['altname'] ?? $content['translate']) : '';
    $url_link = $catInfo ? $catInfo . '/' . $altname . '.html' : $altname . '.html';
    $linked = array('profile' => 'profile/{id}', 'news' => 'news/' . $url_link, 'content' => 'content/' . $url_link, 'blog' => 'blog/read/{id}', 'gallery' => 'gallery/photo/{id}');
    return isset($linked[$mod]) ? '<a target="_blank" href="' . str_replace('{id}', $id, $linked[$mod]) . '">' . $content['title'] . '</a>' : $content['title'];
}

function _nLink($mod, $id)
{
    global $core;
    $content = $core->row_data($mod, 'id = "' . $id . '"');
    $catInfo = $content['cat'] !== ',0,' ? $core->getCat($mod, $content['cat'], 'development') : '';
    $altname = isset($catInfo) ? ($content['altname'] ?? $content['translate']) : '';
    $url_link = $catInfo ? $catInfo . '/' . $altname . '.html' : $altname . '.html';
    $linked = array('profile' => 'profile/{id}', 'news' => 'news/' . $url_link, 'content' => 'content/' . $url_link, 'blog' => 'blog/read/{id}', 'gallery' => 'gallery/photo/{id}');
    if (isset($linked[$mod])) return str_replace('{id}', $id, $linked[$mod]);
}

function LatKir($word): void
{
    echo preg_match('/[a-z]/i', $word) ? 'латиница' : 'кириллица';
}

function Gtranslate($text, $old, $new)
{
    $res = file_get_contents("https://translate.googleapis.com/translate_a/single?client=gtx&ie=UTF-8&oe=UTF-8&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at&sl=" . $old . "&tl=" . $new . "&hl=hl&q=" . urlencode($text), $_SERVER['DOCUMENT_ROOT'] . "/transes.html");
    $res = json_decode($res);
    return $res[0][0][0] ?? null;
}

function commentLink($mod, $id, $full = true)
{
    global $core;
    $content = $core->row_data($mod, 'id = "' . $id . '"');
    $catInfo = is_array($content) && $content['cat'] !== ',0,' ? $core->getCat($mod, $content['cat'], 'development') : '';
    $altname = $content['altname'] ?? $content['translate'];
    $url_link = $catInfo ? $catInfo . '/' . $altname . '.html' : $altname . '.html';
    $linked = array('profile' => 'profile/{id}', 'news' => 'news/' . $url_link, 'content' => 'content/' . $url_link, 'blog' => 'blog/read/{id}', 'gallery' => 'gallery/photo/{id}');
    if (isset($linked[$mod])) {
        if ($full) {
            return '<a target="_blank" href="' . str_replace('{id}', $id, $linked[$mod]) . '">' . _mName($mod) . '</a>';
        } else {
            return str_replace('{id}', $id, $linked[$mod]);
        }
    } else {
        return _mName($mod);
    }
}

function InitCountLines(): void
{
    echo '<script type="text/javascript">
         // функция подсчета количества строк
         function countLines(strtocount, cols) {
         	var hard_lines = 1;
         	var last = 0;
         	while ( true ) {
         		last = strtocount.indexOf("\n", last+1);
         		hard_lines ++;
         		/* if ( hard_lines == 35) break; */
         		if ( last === -1 ) break;
         		}
         	var soft_lines = Math.ceil(strtocount.length/(cols-1));
         	var hard = eval("hard_lines " + unescape("%3e") + "soft_lines;");
         	if ( hard ) soft_lines = hard_lines;
         	return soft_lines;
         }
         // функция вызывается при каждом нажатии клавиши в области ввода текста
         function ResizeTextArea(the_form,min_rows) {
         	the_form.rows = Math.max(min_rows,countLines(the_form.value,the_form.cols) +1);
         }
      </Script>';
}

/*
      * Шлём письмо
      * $to - кому
      * $title - тема письма
      * $msg - текст
      */
function sendMail($to, $title, $msg, $for_header = '', $content_type = 'text/html; charset=utf-8;'): bool
{
    global $config;
    $headers = 'From: ' . $config['name'] . ' Mail Robot <robot@' . $_SERVER['HTTP_HOST'] . '>' . "\r\n";
    $headers .= "Content-Type: " . $content_type . " \r\n";
    $headers .= 'Reply-To: noreply@' . $_SERVER['HTTP_HOST'] . "\r\n";
    $headers .= 'X-Mailer: ' . $config['name'] . ' Mail Robot' . "\r\n";
    $headers .= $for_header;
    return mail($to, $title, $msg, $headers);
}

function validationInit($type): void
{
    global $config, $adminTpl;
    $rules = 'rules: {';
    $massege = 'messages: {';
    if (isset($type)) {
        foreach ($type as $fieldName => $parametr) {
            $rules .= $fieldName . ': {';
            $massege .= $fieldName . ': {';
            if (is_array($parametr)) {
                foreach ($parametr as $pname => $atrb) {
                    $rules .= $pname == 'remote' ? $pname . ': {url: "' . $atrb[0] . '", type: "post"}, ' : $pname . ': ' . $atrb[0] . ', ';
                    $massege .= $pname . ': \'' . $atrb[1] . '\', ';
                }
            }
            $rules .= '}, ';
            $massege .= '}, ';
        }
    }
    $rules .= '}, ';
    $massege .= '}, ';
    $script = '$("#admin-form").validate({
      		  errorClass: "state-error",
      		  validClass: "state-success",
      		  errorElement: "em", ' . $rules . $massege . 'highlight: function (element, errorClass, validClass) {
      			$(element).closest(\'.field\').addClass(errorClass).removeClass(validClass);
      		  },
      		  unhighlight: function (element, errorClass, validClass) {
      			$(element).closest(\'.field\').removeClass(errorClass).addClass(validClass);
      		  },
      		  errorPlacement: function (error, element) {
      			if (element.is(":radio") || element.is(":checkbox")) {
      			  element.closest(\'.option-group\').after(error);
      			} else {
      			  error.insertAfter(element.parent());
      			}
      		  }
      		});';
    $adminTpl->footIncludes['validation'] = '<script src="' . $config['url'] . '/usr/plugins/js/jquery.validate.min.js"></script>
      	                                     <script src="' . $config['url'] . '/usr/plugins/js/additional-methods.min.js"></script>';
    $adminTpl->js_code[] = $script;
    $adminTpl->body_class[] = 'admin-validation-page';
}

function InitCheckPass(): void
{
    global $lang;
    echo '<script language="javascript">
    function passwordChanged() {
        var strength = document.getElementById(\'strength\');
        var strongRegex = new RegExp("^(?=.{14,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$", "g");
        var mediumRegex = new RegExp("^(?=.{10,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$", "g");
        var enoughRegex = new RegExp("(?=.{8,}).*", "g");
        var pwd = document.getElementById("password");
        if (pwd.value.length === 0) {
            strength.innerHTML =  \'<span style="color:grey">' . $lang['type_password'] . '</span>\';
        } else if (false === enoughRegex.test(pwd.value)) {
            strength.innerHTML =  \'<span style="color:blue">' . $lang['more_characters'] . '</span>\';
        } else if (strongRegex.test(pwd.value)) {
            strength.innerHTML = \'<span style="color:green">' . $lang['pass_strong'] . '</span>\';
        } else if (mediumRegex.test(pwd.value)) {
            strength.innerHTML =   \'<span style="color:orange">' . $lang['pass_medium'] . '</span>\';
        } else {
            strength.innerHTML =\'<span style="color:red">' . $lang['pass_weak'] . '</span>\';
        }
    }
</script>';
}

/*
      * Инициализируем Ajax
      */
function ajaxInit(): void
{
    header('Content-type: text/html; charset=utf-8');
}

/*
      * Получаем адресс без http и www
      * $uri - полный адресс
      */
function getHost($uri): string
{
    $url = str_replace(array('http://', 'https://', 'www.'), array('', '', ''), $uri);
    $url = explode('/', $url);
    return mb_strtolower($url[0]);
}

/*
      * Подсвечиваем слова поиска)
      * $textShort = highlightSearch('php ajax', $news['short']);
      * $words - слова разделить пробелом пример "php ajax css"
      * $text - то что обработаем
      */
function highlightSearch($words, $text)
{
    $searchWords = explode(' ', $words);
    foreach ($searchWords as $word) {
        if (!preg_match('/[\||\'|\<|\>|\"|\!|\?|\$|\@|\/|\\\|\&\~\*\+]/', $word)) $text = str_ireplace($word, "<span class=\"highlightSearch\">$word</span>", $text);
    }
    return $text;
}

function editor_area($name, $value, $rows, $add = '', $class = 'textarea', $return = false): void
{
    bb_area($name, $value, $rows, $class, $add, $return);
}

function windowOpen(): void
{
    echo '<style>body{background:#ffffff;}</style>';
}

function fileInit($module, $id, $type = 'dir', $content = '', $what = 'temp')
{
    global $core, $db;
    $temp = 'files/' . $module . '/' . $what;
    $new = 'files/' . $module . '/' . $id;
    switch ($type) {
        case 'dir':
            if (is_dir($temp)) {
                rename($temp, $new);
                $q = $core->select_data('attach', 'pub_id = 0 OR pub_id = "' . $what . '"');
                while ($rows = $db->getRow($q)) {
                    $core->upd_data('attach', 'url = "' . $db->safesql(str_replace($temp, $new, $rows['url'])) . '", pub_id = "' . $id . '"', 'id = "' . $rows['id'] . '"');
                }
            }
            break;
        case 'content':
            return str_replace($temp, $new, $content);
            break;
    }
}

function mjsEnd($array)
{
    $page = array_search('page', $array);
    return $page ? $array[$page - 1] : end($array);
}

/** @noinspection PhpStatementHasEmptyBodyInspection */
function ftp_DC($dir): void
{
    global $config;
    $ftp_server = $config['ftp_server'] ?? '';
    $ftp_user = $config['ftp_user'] ?? '';
    $ftp_pass = $config['ftp_pass'] ?? '';//-- ftp сервер; логин; pass
// Установка соединения
    if ($ftp_server && $ftp_user && $ftp_pass) {
        $ftp_conn = ftp_connect($ftp_server) or die("Could not connect to $ftp_server");
        $login = ftp_login($ftp_conn, $ftp_user, $ftp_pass);
        ftp_pasv($ftp_conn, true);
        $file_size = ftp_size($ftp_conn, $dir);
        // Создание директории
        if ($file_size != -1) {
            //echo 'Файл существует';
        } else {
            ftp_mkdir($ftp_conn, $dir);
        }

// Закрытие соединения
        ftp_close($ftp_conn);
    }
}

function ftp_del_Dir($dir): void
{
    global $config;
    $ftp_server = $config['ftp_server'] ?? '';
    $ftp_user = $config['ftp_user'] ?? '';
    $ftp_pass = $config['ftp_pass'] ?? '';//-- ftp сервер; логин; pass
// Установка соединения
    if ($ftp_server && $ftp_user && $ftp_pass) {
        $ftp_conn = ftp_connect($ftp_server) or die("Could not connect to $ftp_server");
        $login = ftp_login($ftp_conn, $ftp_user, $ftp_pass);
        ftp_pasv($ftp_conn, true);

// попытка удалить файл
        echo ftp_delete($ftp_conn, $dir) ? "Файл $dir удалён\n" : "Не удалось удалить $dir\n";
// Закрытие соединения
        ftp_close($ftp_conn);
    }
}


function initDir($module, $dir1 = false, $dir2 = false, $dir3 = false)
{
    $dir1 = $dir1 ? '/' . $dir1 : '/temp';
    $dir2 = $dir2 ? '/' . $dir2 : '';
    $dir3 = $dir3 ? '/' . $dir3 : '';
    $path = 'files/' . $module . $dir1 . $dir2 . $dir3;
    if (!file_exists($path)) mkdir(ROOT . $path, 0777, true);
    ftp_DC($path);
    $_SESSION["RF"]["fff"] = 'files/' . $module . $dir1 . $dir2 . $dir3 . '/';
    return $_SESSION["RF"]["fff"];
}

function initDC($directory, $module, $users, $altname): string
{
    if ($module && $users) {
        $dir = ROOT . 'files/' . $directory . '/' . $module . '/' . $users . '/' . translit($altname);
        if (!file_exists($dir)) mkdir($dir);
        return 'files/' . $directory . '/' . $module . '/' . $users . '/' . translit($altname);
    } else {
        $dir = ROOT . 'files/' . $directory . '/' . translit($altname);
        if (!file_exists($dir)) mkdir($dir);
        return 'files/' . $directory . '/' . translit($altname);
    }
}

function GetDirectorySize($path)
{
    $bytestotal = 0;
    $path = realpath($path);
    if ($path !== false && $path != '' && file_exists($path)) {
        foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object) {
            $bytestotal += $object->getSize();
        }
    }
    return $bytestotal;
}

function keep_no_glop($line): bool
{
    global $bad_words;
    foreach ($bad_words as $bad_word) {
        if (str_contains($line, $bad_word)) return false;
    }
    return true;
}

function configMatch($reg): array|string
{
    return str_replace(array(' * ', ' % '), array(' . +', ' . +'), $reg);
}

function modAccess($mod): bool|string
{
    global $core;
    if (isset($core->tpl->modules[$mod])) {
        $groups = explode(',', $core->tpl->modules[$mod]['groups']);
        return empty($groups[0]);
    }
    return 'nonMod';
}

function writeInLog($msg, $type): void
{
    $logPath = ROOT . 'tmp/' . $type . '.log';
    if (file_exists($logPath)) $data = int_Serialize('uns', @file_get_contents($logPath));
    $data[] = array('msg' => $msg,
        'ip' => $_SERVER['REMOTE_ADDR'],
        'url' => isset($_REQUEST['url']) ? filter($_REQUEST['url']) : '',
        'agent' => filter($_SERVER['HTTP_USER_AGENT']),
        'time' => time(),
    );
    $data = int_Serialize('ser', $data);
    $fp = @fopen($logPath, 'w');
    fwrite($fp, $data);
    fclose($fp);
}

function set_error_php_log(): void
{
    global $log_conf;
    if ($log_conf['display_php_errors'] && !$log_conf["phpError"]) {
        @ini_set('display_errors', '1');
        @ini_set('display_startup_errors', '1');
        @ini_set('html_errors', '0');
    } elseif ($log_conf['display_php_errors'] && $log_conf["phpError"]) {
        $logPath = ROOT . 'tmp/phpError.log';
        @error_reporting(E_ALL);
        @ini_set('error_log', $logPath);
        @error_log('Запись в лог', '1');
        @ini_set('display_errors', '1');
        @ini_set('display_startup_errors', '1');
        @ini_set('html_errors', '0');
    } elseif ($log_conf["phpError"]) {
        $logPath = ROOT . 'tmp/phpError.log';
        @error_reporting(E_ALL);
        @ini_set('error_log', $logPath);
        @error_log('Запись в лог', '1');
        @ini_set('display_errors', '0');
        @ini_set('display_startup_errors', '0');
    } else {
        @ini_set('display_errors', '0');
        @ini_set('display_startup_errors', '0');
    }
}

/**
 * Error handler, passes flow over the exception logger with new ErrorException.
 */
function log_error($num, $str, $file, $line): ?string
{
    return log_exception(new ErrorException($str, 0, $num, $file, $line));
}

/**
 * Uncaught exception handler.
 */
function log_exception(Exception $e): ?string
{
    global $config, $log_conf, $lang;
    $types = get_class($e);
    $messages = htmlspecialchars(str_replace('"', '\"', stripslashes(Gtranslate($e->getMessage(), 'en', $config['lang']))), ENT_QUOTES);/*Это содержит сообщение об ошибке, которое обычно более значимо, чем код ошибки. В приведенном выше примере это был первый параметр, переданный при возникновении исключения.*/
    $files = $e->getFile();/*Здесь содержится имя файла, в котором возникло исключение. Это (или любой другой элемент ниже) может быть отправлен по электронной почте, зарегистрирован в файле и т.д. В этих примерах я повторю их.*/
    $lines = $e->getLine();/*Здесь указан номер строки, в которой произошло исключение.*/
    $code = $e->getCode();/*Это содержит код ошибки. В приведенном выше примере это был второй параметр, переданный при вызове "throw new Exception". Значение кода будет зависеть от генерируемого исключения.*/
    $trace = $e->getTrace(); /*getTrace возвращает обратную трассировку, чтобы показать порядок вызовов функций, которые привели к исключению, в обратном порядке с самым последним вызовом функции первым. */
    $traceAsStrin = $e->getTraceAsString();/*Альтернативой методу getTrace является getTraceAsString(), который возвращает информацию того же типа, что и debug_print_backtrace(), но в виде строки, а не в стандартный вывод. Это более сжатая версия, чем getTrace.*/
    $toString = $e->__toString();/*__toString() возвращает строку, содержащую сообщение об ошибке, номер файла и строки, а также обратную трассировку, возвращенную из getTraceAsString().*/
    $logPath = ROOT . 'tmp/phpError.log';
    $data = file_exists($logPath) ? int_Serialize('uns', @file_get_contents($logPath)) : '';
    $message = '';
    if ($log_conf["display_php_errors"] && !$log_conf["phpError"]) {
        $message .= " < div style = 'text-align: center;' > ";
        $message .= "<h2 style = 'color: rgb(190, 50, 50);' > " . $lang['log_debugging'] . " </h2 > ";
        $message .= "<table style = 'width: 800px; display: inline-block;' > ";
        $message .= "<tr style = 'background-color:rgb(230,230,230);' ><th style = 'width: 80px;' > " . $lang['log_type'] . ":  </th ><td > " . $types . " </td ></tr > ";
        $message .= "<tr style = 'background-color:rgb(240,240,240);' ><th > " . $lang['log_code'] . "KOD6I </th ><td > " . $code . " </td ></tr > ";
        $message .= "<tr style = 'background-color:rgb(240,240,240);' ><th > " . $lang['log_message'] . " </th ><td > " . $messages . " </td ></tr > ";
        $message .= "<tr style = 'background-color:rgb(230,230,230);' ><th > " . $lang['log_file'] . ":  </th ><td > " . $files . " </td ></tr > ";
        $message .= "<tr style = 'background-color:rgb(240,240,240);' ><th > " . $lang['log_line'] . ":   </th ><td > " . $lines . " </td ></tr > ";
        $message .= "</table ></div > ";
    } else {
        $message .= $lang['log_type'] . ": " . $types . ";\n";
        $message .= $lang['log_message'] . ": $messages;\n";
        $message .= $lang['log_file'] . ": $files;\n";
        $message .= $lang['log_line'] . ": $toString;";
    }
    return $log_conf["phpError"] ? ((!str_contains($data, $messages)) ? writeInLog($message, 'phpError') : '') : $message;
}

/**
 * Checks for a fatal error, work around for set_error_handler not working on fatal errors.
 */
function check_for_fatal(): void
{
    $error = error_get_last();
    if ($error !== NULL) log_error($error["type"], $error["message"], $error["file"], $error["line"]);
}

function mysqlFatalError($title, $text, $query): void
{
    global $log_conf;
    loadConfig('log');
    if ($log_conf['dbError'] == 1) writeInLog('[Ошибка в базе данных] - запрос: ' . $query, 'db_query');
    //if(file_exists(ROOT.'install.php') && !file_exists(ROOT.'install/lock.install'))
    //{
    //	header('Location: install.php');
    //}
    //else
    //{
    fatal_error($title, $text);
    //}
}

function pmNew(): void
{
    global $core, $db, $lang;
    if (!empty($core->auth->newPms)) {
        $pms = '';
        $message = '';
        $info = array();
        foreach ($core->auth->newPms as $num => $info) {
            if ($num == 1) $pms .= '<hr/><strong>' . $lang['pmalso'] . ':</strong><br/>';
            $pms .= $num == 0 ? '<i><a href="pm/view/' . $info['id'] . '" onclick="clearModal_box(\'newPm\');">' . formatDate($info['time'], true) . '</a> (От: <a href="profile/' . $info['nick'] . '">' . $info['nick'] . '</a>)</i> [ <a href="pm/write/' . $info['nick'] . '">' . $lang['pmreply'] . '</a> | <a href="pm/view/' . $info['id'] . '" onclick="clearModal_box(\'newPm\');">' . $lang['pmread'] . '</a> ]<hr/>' . str($core->bbDecode($info['message']), 200) : '<a href="pm/view/' . $info['id'] . '" onclick="clearModal_box(\'newPm\');">' . formatDate($info['time'], true) . '</a> (От: <a href="profile/' . $info['nick'] . '">' . $info['nick'] . '</a>) [ <a href="pm/write/' . $info['nick'] . '">' . $lang['pmreply'] . '</a> | <a href="pm/view/' . $info['id'] . '" onclick="clearModal_box(\'newPm\');">' . $lang['pmread'] . '</a> ]<br/>';
        }
        if (count_($core->auth->newPms)) {
            list($inbox) = $db->fetchRow($db->query("SELECT COUNT(*) FROM `" . DB_PREFIX . "_pm` as pm LEFT JOIN `" . USER_DB . "`.`" . USER_PREFIX . "_users` as u on (pm.fromid = u.id) WHERE pm.toid = '" . $core->auth->user_id . "' AND pm.status !='2' AND pm.status !='3' AND pm.status !='4' ORDER BY time DESC"));
            $inboxviews = '<a href="pm/view/" title ="' . $lang['go_to_views'] . '" onclick="clearModal_box(\'newPm\');">' . $inbox . '</a>';
            $message = declension($inboxviews, array($lang['message1'], $lang['message2'], $lang['message3']));
        }
        require_once(ROOT . 'usr/plugins/modal_box/init.php');
        ob_start();
        modal_box($lang['pmnew'], str_replace('[num]', $message, $lang['pminfo']), $pms, 'newPm');
        $c = ob_get_contents();
        ob_end_clean();
        $core->tpl->bodyIncludes = $c . '<script>modal_box(\'newPm\');</script>';
    }
}

function getExt($file): string
{
    $arr = explode('.', $file);
    return mb_strtolower(end($arr));
}

function getUserFriends($uid, $limit = 9999): array
{
    loadConfig('user');
    global $db, $user, $lang, $core;
    $friends = '';
    $fq = $core->select_data('users', '(f.who_invite = "' . $uid . '" OR f.whom_invite = "' . $uid . '") AND u.id != "' . $uid . '" AND f.confirmed = 1', false, 'u.id as uuid, u.nick, u.last_visit, f.*', 'as u LEFT JOIN `' . DB_PREFIX . '_user_friends` as f on(u.id = f.who_invite OR u.id = f.whom_invite)');
    $yourFriends = array();
    if ($db->numRows($fq) > 0) {
        while ($frows = $db->getRow($fq)) {
            $friends .= '<span class="_userfriends"><a href="profile/' . $frows['nick'] . '" title="' . $lang['page_friends'] . '">' . $frows['nick'] . '</a></span>';
            $yourFriends[] = $frows['uuid'];
        }
    }
    return array($friends, $yourFriends);
}

function createThumb($fname, $thumb_fname, $max_x = 99, $max_y = 99, $resp = false)
{
    $ext = getExt($thumb_fname);
    switch ($ext) {
        case 'jpg':
        case 'jpeg':
            $im = imagecreatefromjpeg($fname);
            break;
        case 'gif':
            $im = imagecreatefromgif($fname);
            break;
        case 'png':
            $im = imagecreatefrompng($fname);
            break;
        default:
            return false;
    }
    if (@$im) {
        list($width, $height, $type, $attr) = getimagesize($fname);
        if (($width > $max_x) or ($height > $max_y)) {
            if ($width > $height) {
                $nw = $max_x;
                $nh = ($max_x / $width) * $height;
            } else {
                $nw = ($max_y / $height) * $width;
                $nh = $max_y;
            }
            $thumb = imagecreatetruecolor((int)$nw, (int)$nh);
            imagecopyresampled($thumb, $im, 0, 0, 0, 0, (int)$nw, (int)$nh, (int)$width, (int)$height);
            imagejpeg($thumb, $thumb_fname, 90);
            imagedestroy($thumb);
        } else {
            if ($resp) {
                return 'orig';
            } else {
                copy($fname, $thumb_fname);
            }
        }
    } else {
        return false;
    }
}

function catsicon($icon)
{
    static $catsicon = array();
    if (empty($catsicon[$icon])) {
        if (glob(ROOT . '/media/cats/.*')) {
            foreach (glob(ROOT . '/media/cats/' . $icon) as $ico)
                $catsicon[$icon] = '/media/cats/' . basename($ico);
        } else {
            $catsicon[$icon] = '/media/cats/no_image.png';
        }
    }
    return $catsicon[$icon];
}

function arr2str(&$arr, $depth = 0): string
{
    $ret = array();
    if (is_array($arr) && sizeof($arr) > 0) {
        foreach ($arr as $key => $value) {
            $key = str_replace("'", "\'", $key);
            if (is_array($value)) $ret[] = "'{$key}'=>" . arr2str($value, $depth + 1);
            elseif (is_int($value)) $ret[] = "'{$key}'=>$value";
            else {
                if (is_string($value)) $value = str_replace("'", '"', $value);
                $ret[] = "'{$key}'=>'" . strval($value) . "'";
            }
        }
    }
    return 'array(' . implode(',', $ret) . ')';
}

function avatar($uid)
{
    static $avatar = array();
    global $core, $config, $user;
    require ROOT . 'etc/user.config.php';
    $rows = $core->row_data('users', 'id = "' . $uid . '"');
    if (empty($avatar[$uid])) {
        if (glob(ROOT . 'files/avatars/users/av' . $uid . '.*')) {
            foreach (glob(ROOT . 'files/avatars/users/av' . $uid . '.*') as $av) $avatar[$uid] = 'files/avatars/users/' . basename($av);
        } elseif (isset($rows['avatar_auth']) && $rows['avatar_auth']) {
            $avatar[$uid] = $rows['avatar_auth'];
        } else {
            $avatar[$uid] = $uid == 0 ? $config['url'] . '/' . $user['avatarGuest'] : $config['url'] . '/' . $user['noAvatar'];
        }
    }
    return $avatar[$uid];
}

function tplDir(): string
{
    global $config;
    $tplDir = $config['tpl'] ?? 'error';
    return '/usr/tpl/' . $tplDir;
}

function get_folder($folder = 'langs'): array
{
    $allowed_folder = array('langs');
    $list = array();
    if (!in_array($folder, $allowed_folder)) return $list;
    if (!$handle = opendir(ROOT . "/" . $folder)) {
        $list[]['name'] = 'Невозможно открыть папку ' . $folder;
        return $list;
    }
    while (false !== ($file = readdir($handle))) {
        if (is_dir(ROOT . '/' . $folder . '/' . $file) and ($file != "." and $file != '..')) {
            if (is_file(ROOT . '/' . $folder . '/' . $file . '/info.json')) {
                $data = json_decode(trim(file_get_contents(ROOT . '/' . $folder . '/' . $file . '/info.json')), true);
                if (isset($data['name']) and $data['name']) {
                    $list[$file] = $data;
                    continue;
                }
            }
            $list[$file]['name'] = $file;
        }
    }
    closedir($handle);
    ksort($list);
    return $list;
}

function stristrarray($array, $str): array
{
    //This array will hold the indexes of every
    //element that contains our substring.
    $indexes = array();
    foreach ($array as $k => $v) {
        //If stristr, add the index to our
        //$indexes array.
        if (stristr($v, $str)) $indexes[] = $k;
    }
    return $indexes;
}

function ConfigMod($module): void
{
    require ROOT . 'etc/' . $module . '.config.php';
}

function related_images($module, $module_conf, $related): string
{
    global $core;
    require ROOT . 'etc/' . $module . '.config.php';
    $rel_images = '';
    $patch = !$module_conf['related_' . $module . '_img_thumbs'] ? 'files/' . $module . '/' . $related['id'] . '/' : 'files/thumbs/files/' . $module . '/' . $related['id'] . '/';
    $related_cache = '';
    $rel_link = $related['cat'] !== ',0,' ? $module . '/' . $core->getCat($module, $related['cat'], 'development') : $module;
    $altname = isset($related['altname']) ? '/' . $related['altname'] : '/' . $related['translate'];
    $dir = news_image($patch);
    $images = array();
    $all_files = is_dir($dir) ? scandir($dir) : '';
    for ($i = 0; $i < count_($all_files); $i++) {
        if (is_array($all_files) && (!str_contains($all_files[$i], ".png") && !str_contains($all_files[$i], ".jpg") && !str_contains($all_files[$i], ".gif"))) continue;
        $images[] = $all_files[$i];
    }
    $files = glob($dir . '*.*');
    if ($files) {
        $img_random = $images[rand(0, sizeof($images) - 1)];
        $img_src = $dir . $img_random;
    } else {
        $img_src = tplDir() . '/assest/images/no_image.jpg';
    }
    list($width, $height, $type, $attr) = @is_array(getimagesize($img_src)) ? getimagesize($img_src) : '';
    if ($module_conf['related_' . $module . '_img_height'] && $module_conf['related_' . $module . '_img_widtht']) {
        $style = 'style="width:' . $module_conf['related_' . $module . '_img_widtht'] . 'px; height:' . $module_conf['related_' . $module . '_img_height'] . 'px;"';
    } elseif ($module_conf['related_' . $module . '_img_height'] == 0 && $module_conf['related_' . $module . '_img_widtht']) {
        $style = 'style="width:' . $module_conf['related_' . $module . '_img_widtht'] . 'px; height:' . $height . 'px;"';
    } elseif ($module_conf['related_' . $module . '_img_height'] && $module_conf['related_' . $module . '_img_widtht'] == 0) {
        $style = 'style="width:' . $width . 'px; height:' . $module_conf['related_' . $module . '_img_height'] . 'px;"';
    } else {
        $style = 'style="width:' . $width . 'px; height:' . $height . 'px;"';
    }
    if ($module_conf['related'] == 1) {
        $cat_id = str_replace(',', '', $related['cat']);
        $related_cache = $module_conf['related_' . $module . '_img'] == 1 ? $related_cache . '<li>
    <div class="post-media"><a href="' . $rel_link . $altname . '.html"><img src="' . $img_src . '"  ' . $style . ' alt=""></a></div>
    <h3 class="post-title"><a href="' . $rel_link . $altname . '.html">' . $related['title'] . ' (' . formatdate($related['date'], true) . ')</a></h3>
    <div class="post-info"><a href="' . $rel_link . $altname . '.html"><i class="icon icon-bubbles"></i>' . $related['comments'] . ' Комметрариев</a></div>
 </li>' : $related_cache . '<li><a href="' . $rel_link . $altname . '.html">' . $related['title'] . ' (' . formatdate($related['date'], true) . ')</a></li>';
    } else {
        $related_cache .= '';
    }
    return $related_cache;
}

function deleteAvatar($uid): void
{
    if (glob(ROOT . 'files/avatars/users/av' . $uid . '.*')) foreach (glob(ROOT . 'files/avatars/users/av' . $uid . '.*') as $av) @unlink($av);
}

function news_image($patch)
{
    $image = array();
    $v = false;
    if (empty($image[$v])) {
        if (glob(ROOT . $patch)) {
            foreach (glob(ROOT . $patch) as $v)
                $image[$v] = $patch;
        } else {
            $image[$v] = 0;
        }
    }
    return $image[$v];
}

function pimage($uid)
{
    static $pimage = array();
    global $config, $user;
    require ROOT . 'etc/user.config.php';
    if (empty($pimage[$uid])) {
        if (glob(ROOT . 'files/avatars/profile_image/pi' . $uid . '.*')) {
            foreach (glob(ROOT . 'files/avatars/profile_image/pi' . $uid . '.*') as $pi) $pimage[$uid] = 'files/avatars/profile_image/' . basename($pi);
        } else {
            $pimage[$uid] = $config['url'] . '/' . $user['noPimage'];
        }
    }
    return $pimage[$uid];
}

function deletePimage($uid): void
{
    if (glob(ROOT . 'files/avatars/profile_image/pi' . $uid . '.*')) foreach (glob(ROOT . 'files/avatars/profile_image/pi' . $uid . '.*') as $pi) @unlink($pi);
}

function _mName($mod)
{
    global $core;
    return isset($core->tpl->modules[$mod]) ? $core->tpl->modules[$mod]['content'] : $mod;
}

function groupName($gid = -1)
{
    global $core;
    static $groupNames = array();
    if ($gid == -1) $gid = $core->auth->group;
    if (empty($groupNames[$gid])) $groupNames[$gid] = $core->auth->group_info['color'] != '' ? colorSpan($core->auth->group_info['color'], $core->auth->group_info['gname']) : $core->auth->group_info['gname'];
    return $groupNames[$gid];
}

/* Helper functions */
function validateURL($str): false|int
{
    return preg_match('/(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:\/~\+#]*[\w\-\@?^=%&amp;\/~\+#])?/i', $str);
}

function ftp_image($str)
{
    global $config;
    $ftp_server = $config['ftp_server'] ?? '';
    $ftp_user = $config['ftp_user'] ?? '';
    $ftp_pass = $config['ftp_pass'] ?? '';//-- ftp сервер; логин; pass
    if ($ftp_server && $ftp_user && $ftp_pass) {
        $conn_id = ftp_connect($ftp_server) or die("Не удалось установить соединение с $ftp_server");
        $img_src = '';
        if (@ftp_login($conn_id, $ftp_user, $ftp_pass)) {
            $type = 'jpg';
            $img = file_get_contents('ftp://' . $ftp_user . ':' . $ftp_pass . '@' . $str);//--логин:pass@ftp сервер/путь
            $base64 = 'data:image/' . $type . ';base64,' . base64_encode($img);
            $img_src = '<img src="' . $base64 . '">';
        } else {
            $img_src = 'Не удалось войти \n';
        }
        return $img_src;
        ftp_close($conn_id);
    }
}

function get_ftp_mode($file): int
{
    $path_parts = pathinfo($file);

    if (!isset($path_parts['extension'])) return FTP_BINARY;
    return match (strtolower($path_parts['extension'])) {
        'am', 'asp', 'bat', 'c', 'cfm', 'cgi', 'conf', 'cpp', 'css', 'dhtml', 'diz', 'h', 'hpp', 'htm', 'html', 'in', 'inc', 'js', 'm4', 'mak', 'nfs', 'nsi', 'pas', 'patch', 'php', 'php3', 'php4', 'php5', 'phtml', 'pl', 'po', 'py', 'qmail', 'sh', 'shtml', 'sql', 'tcl', 'tpl', 'txt', 'vbs', 'xml', 'xrc' => FTP_ASCII,
        default => FTP_BINARY,
    };
}

function url_name($url): string
{
    return basename($url);
}

function ftp_down($file)
{
    global $config;
    $ftp_server = $config['ftp_server'] ?? '';
    $ftp_user = $config['ftp_user'] ?? '';
    $ftp_pass = $config['ftp_pass'] ?? '';//-- ftp сервер; логин; pass
    $conn_id = ftp_connect($ftp_server) or die("Не удалось установить соединение с $ftp_server");
    if ($ftp_server && $ftp_user && $ftp_pass) {
        if (@ftp_login($conn_id, $ftp_user, $ftp_pass)) {
// Скачать файл
            return ftp_fget($conn_id, $file, $file, FTP_ASCII, 0) ? 'Файл успешно скачен' : 'Ошибка';
        }
// Закрытие файла и соединения
        ftp_close($conn_id);
    }
}

function ftp_link($string): string
{
    //return preg_replace('@((https ?://)?([-\w]+\.[-\w\.]+)+\w(:\d+)?(/([-\w/_\.\,]*(\?\S+)?)?)*)@', '<a href="$1">$1</a>', $string);
    /* Вызываем функцию, которая все совпадения помещает в массив $matches */
    preg_match_all("/<[Aa][\s]{1}[^>]*[Hh][Rr][Ee][Ff][^=]*=[ '\"\s]*([^ \"'>\s#]+)[^>]*>/", $string, $matches);
    $urls = $matches[1]; // Берём то место, где сама ссылка (благодаря группирующим скобкам в регулярном выражении)
    $href = '';
    /* Выводим все ссылки */
    for ($i = 0; $i < count($urls); $i++) {
        $href .= $urls[$i] . "<br/>";
    }
    return $href . "<br/>";
}

function ftp_str($str, $scet = false): string
{
    $str_ = '';
    preg_match_all('#<img[^>]+src=[\'"]([^\s>]*)[\'"][^>]*>#i', $str, $images, PREG_SET_ORDER);
    foreach ($images as $image) {
        $content = str_replace(array('http://', 'https://', 'www.'), array('', '', ''), $image[1]);
        $str_ .= $scet ? $content : ftp_image($content);
    }
    return $str_;
}

function ftp_preg($content): array|string|null
{
    return preg_replace('#<img[^>]+src=[\'"]([^\s>]*)[\'"][^>]*>#i', ftp_str($content), $content);
    //return ftp_link($content);
    //return ftp_str($content);

    // $file = ftp_link($content);
    // echo ftp_down($file);
    // echo url_name($file);
}

function replace_img_src($img_tag): false|string
{
    $old_src = '';
    $ftp_user = "ftp";
    $ftp_pass = "52445225";//-- ftp сервер; логин; pass
    $doc = new DOMDocument();
    $doc->loadHTML($img_tag);
    $tags = $doc->getElementsByTagName('img');
    foreach ($tags as $tag) {
        $old_src .= $tag->getAttribute('src');
        $old_src = ftp_image(str_replace(array('http://', 'https://', 'www.'), array('', '', ''), $old_src));
        $new_src_url = 'ftp://' . $ftp_user . ':' . $ftp_pass . '@' . $old_src;
        $tag->setAttribute('src', $new_src_url);
    }
    return $doc->saveHTML();
}

function sanitize($str): string
{
    if (ini_get('magic_quotes_gpc'))
        $str = stripslashes($str);
    $str = strip_tags($str);
    $str = trim($str);
    $str = htmlspecialchars($str);
    return mysqli_real_escape_string($str);
}

// Defining fallback functions for mb_substr and
// mb_strlen if the mb extension is not installed:
if (!function_exists('mb_substr')) {
    function mb_substr($str, $start, $length, $encoding): string
    {
        return substr($str, $start, $length);
    }
}
if (!function_exists('mb_strlen')) {
    function mb_strlen($str, $encoding): int
    {
        return strlen($str);
    }
}

function ddraw_rat($id = false, $rrating = false, $summ = false, $close = false)
{
    global $core, $url, $lang;
    $mod = $url[0] == 'news' ? '' : $url[0] . '_';
    $array_replace = array(
        "#\\[rating_plus\\](.*?)\\[/rating_plus\\]#is" => (!$close ? '' : (($core->auth->user_id) ? "\${1}" : '')),
        "#\\[rating_minus\\](.*?)\\[/rating_minus\\]#is" => (!$close ? '' : (($core->auth->user_id) ? "\${1}" : '')),
        "#\\[rating_num\\](.*?)\\[/rating_num\\]#is" => (!$close && !$summ ? '' : (($core->auth->user_id) ? "\${1}" : '')),
    );
    $core->tpl->sources = preg_replace(array_keys($array_replace), array_values($array_replace), $core->tpl->sources);
    $core->tpl->setVar('rating_plus', !$close ? '' : '<a  onclick="' . $mod . 'do_carma(' . $id . ', 1)" alt="' . $lang['plus_carma'] . '" title="' . $lang['plus_carma'] . '" href="javascript:void(0)">');
    $core->tpl->setVar('rating_minus', !$close ? '' : '<a  onclick="' . $mod . 'do_carma(' . $id . ', 2)" alt="' . $lang['minus_carma'] . '" title="' . $lang['minus_carma'] . '" href="javascript:void(0)">');
    $core->tpl->setVar('rating_num', !$close && !$summ ? '' : $summ);
    $core->tpl->setVar('rrating', !$close && !$rrating ? '' : $rrating);
    return $rrating;
}

function draw_rating($id, $module, $score, $votes, $blocked = null)
{
    global $core, $user, $config, $lang;
    $mod = $module == 'news' ? '' : $module . '_';
    $rating = '';
    $summ = !$core->auth->isUser ? ($user['carma_summ'] ? ((intval($score) - $votes) > 0 ? '<span class="rating_plus">+' . (intval($score) - $votes) . '</span>' : ((intval($score) - $votes) == 0 ? '<span class="rating_zero">0</span>' : '<span class="rating_minus">' . (intval($score) - $votes) . '</span>')) : ((intval($score) - $votes) > 0 ? '<span class="rating_plus">+' . (intval($score) - $votes) . '</span>' : ((intval($score) - $votes) == 0 ? '<span class="rating_zero">0</span>' : '<span class="rating_minus">' . (intval($score) - $votes) . '</span>'))) : ($user['carma_summ'] ? ((intval($score) - $votes) > 0 ? '<span class="rating_plus">+' . (intval($score) - $votes) . '</span>' : ((intval($score) - $votes) == 0 ? '<span class="rating_zero">0</span>' : '<span class="rating_minus">' . (intval($score) - $votes) . '</span>')) : (($score + $votes) > 0 ? '<span class="rating_plus">' . ($score > 0 ? '+' . intval($score) : intval($score)) . '</span> <span class="rating_minus">' . ($votes > 0 ? '-' . $votes : $votes) . '</span>' : '<span class="rating_zero">0</span>'));
    $Theme = $config['tpl'] ?? $core->tpl->tplDir;
    if ($core->auth->group_info) {
        if ($core->auth->group_info['allowRating'] == 0) ddraw_rat($id, false, $summ);
    }
    if (isset($user['carma_rate']) && $user['carma_rate'] == 1) {
        $button_plus = !defined('AJAX') ? '' : '<img src="usr/tpl/' . $Theme . '/assest/images/engine/up.gif" border="0" alt="' . $lang['plus_carma'] . '" title="' . $lang['plus_carma'] . '" align="middle" class="_pointer" onclick="' . $mod . 'do_carma(' . $id . ', 1)"/>';
        $button_minus = !defined('AJAX') ? '' : '<img src="usr/tpl/' . $Theme . '/assest/images/engine/down.gif" border="0" alt="' . $lang['minus_carma'] . '" title="' . $lang['minus_carma'] . '" align="middle" class="_pointer" onclick="' . $mod . 'do_carma(' . $id . ', 2)"/>';
        $srating = '<div id="rating' . $id . '" class="mains-info">
                    <div class="main-info-item">' . $button_plus . '</div>
                    <div class="main-info-item">' . $lang['rrating'] . $summ . '</div>
                    <div class="main-info-item ">' . $button_minus . '</div>
                    </div>';/*rating_layer*/
        $rrating = '<div id="rating' . $id . '" class="rating_layer"></div>';
        if ($user['carma_newrate'] == 1) ddraw_rat($id, $rrating, $summ, true); else ddraw_rat($id, $srating);
    } else {
        static $limitStar, $starStyle;
        if (empty($limitStar) && empty($starStyle)) {
            if (file_exists(ROOT . 'etc/' . mb_strtolower($module) . '.config.php')) {
                require ROOT . 'etc/' . mb_strtolower($module) . '.config.php';
                $confName = mb_strtolower($module) . '_conf';
                if (isset($$confName)) $subArray = $$confName;
            }
            $limitStar = isset($subArray['limitStar']) && $subArray['limitStar'] > 3 ? intval($subArray['limitStar']) : 5;
            $starStyle = !empty($subArray['starStyle']) ? $subArray['starStyle'] : 'star-rating';
        }
        $starWidth = $core->tpl->starWidth;
        $sc_vot = mb_substr(($votes == 0) ? 0 : ($score / $votes), 0, 3);
        if (defined('AJAX')) {
            $rating .= '<div id="rating' . $id . '"></div>';
            if ($blocked == 0) echo '<div id="rat' . $id . '" style="display:none;"></div>';
            $rating .= "<script type=\"text/javascript\">genRating('" . $starStyle . "','" . $starWidth . "','" . $limitStar . "','" . $score . "','" . $votes . "','" . $blocked . "','" . $id . "','" . $module . "', '" . $lang['rating'] . ': ' . $sc_vot . ' ' . $lang['votes'] . ': ' . $votes . "')</script>";
        } else {
            $rating .= "'" . $starStyle . "','" . $starWidth . "','" . $limitStar . "','" . $score . "','" . $votes . "','" . $blocked . "','" . $id . "','" . $module . "', '" . $lang['rating'] . ': ' . $sc_vot . ' ' . $lang['votes'] . ': ' . $votes . "'";
        }
        return $rating;
    }
}

/*
      function bb_edition($text){
          global $user;
          $bb = new bb;
           if($user['editor']){
         $bb = bb_area('message', html2bb($text), 5, 'textarea', null, true);
      } else{
         $bb = edit_area('message', html2bb($text), 5, 'textarea', null, true);
      }
          return $bb;
      }
      */
function show_comments($module, $id, $comment_num = 10, $ajax = false, $newPage = false, $warning = false, $langPref = '', $adminUid = false)
{
    global $db, $core, $config, $user, $page, $email_conf, $url, $lang;
    if ($config['comments'] == 0) return;
    require_once ROOT . '/etc/email.config.php';
    $bb = new bb;
    $captcha = captcha_image();
    $id = intval($id);
    $page = $newPage ? intval($newPage) : init_page();
    $cut = ($page - 1) * $comment_num;
    $query = $db->query("SELECT c .*, u.nick, u.group, u.last_visit, u.signature, u.user_comments, u.user_news  FROM " . DB_PREFIX . "_comments as c LEFT JOIN `" . USER_DB . "` . `" . USER_PREFIX . "_users` as u on(c.uid = u.id) WHERE c.post_id = '" . intval($id) . "' AND c.module = '" . filter($module, 'module') . "' AND c.status = '1' ORDER BY date DESC " . ($user['commentTree'] == 0 ? "LIMIT " . $cut . ", " . $comment_num : ''));
    $i = 0;
    if ($user['commentSubscribe'] == 1) {
        list($all, $isSubscribe) = $db->fetchRow($db->query("SELECT Count(id), (SELECT COUNT(*) FROM " . DB_PREFIX . "_com_subscribe WHERE id = '" . intval($id) . "' AND module = '" . filter($module, 'module') . "' AND uid = '" . $core->auth->user_id . "') as isSubscribe FROM " . DB_PREFIX . "_comments WHERE post_id = '" . $id . "' AND module = '" . filter($module, 'module') . "' AND status = '1'"));
    } else {
        list($all) = $db->fetchRow($db->query("SELECT Count(id) FROM " . DB_PREFIX . "_comments WHERE post_id = '" . $id . "' AND module = '" . filter($module) . "' AND status = '1'"));
    }
    echo '<div id="commentError"></div>';
    echo '<div id="hideCommNum" style="display:none;">' . $comment_num . '</div>';
    echo '<div id="commentBox">' . "\n";
    $nowNumber = $all - $cut;
    if ($db->numRows($query) > 0) {
        $core->tpl->loadFile('comments/comments.view.top');
        $core->tpl->end('comments/comments.view.top');
        while ($rows = $db->getRow($query)) {
            $comment_array[$rows['parent']][] = $rows;
        }
        if (!empty($comment_array[0])) {
            foreach ($comment_array[0] as $comment) {
                $i++;
                build_comment($comment, '', $nowNumber);
                if ($user['commentTree'] == 1) {
                    $newNumber = build_tree($comment['id'], $comment_array, 3, $nowNumber);
                    $nowNumber = ($newNumber > 0 ? $newNumber : $nowNumber);
                }
                $nowNumber--;
            }
        }
        if ($user['commentTree'] == 0) $core->tpl->pages($page, $comment_num, $all, 'javascript:void(0)', 'onclick="commentPage(\'news\', ' . $id . ', {num});"');
        $core->tpl->loadFile('comments/comments.view.down');
        $core->tpl->end('comments/comments.view.down');
    } else {
        $core->tpl->info($lang['no_comment']);
    }
    if ($core->auth->group_info['addComment'] == 1) {
        $text = '';
        if (is_array($warning)) {
            $text = isset($_REQUEST['text']) ? filter(utf_decode($_REQUEST['text'], 'html')) : false;
        } elseif ($warning) {
            $text = '';
            if ($email_conf['new_comments'] == 1) {
                $query = $core->select_data('email', false, 'id ASC');
                list($uid, $post_id, $text) = $core->fetch_data('comments', false, 'uid, post_id, text');
                $news = $core->row_data('news', 'id = "' . $id . '"');
                $news_link = $news['cat'] !== ',0,' ? 'news/' . $core->getCat('news', $news['cat'], 'development') . '/' : 'news/';
                $link = $config['url'] . '/' . $news_link . $news['altname'] . '.html';
                $email = ($config['support_mail']);
                while ($result = $db->getRow($query)) {
                    if (!empty($email)) {
                        $message = $result['new_comments_text'] > 0 ? str_replace(array('&lt;', '&gt;', '{%username%}', '{%username_to%}', '{%date%}', '{%text%}', '{%link%}', '{%url%}'), array('<', '>', $news['author'], 'Администратор', formatDate(time(), true), strip_tags(($text), 'html'), $link, $config['url']), $result['new_comments_text']) : str_replace(array('\p', '\n', '\r', '<br>', '<br/>', '&nbsp;', '{%username%}', '{%username_to%}', '{%date%}', '{%text%}', '{%link%}', '{%url%}'), array('""', '""', '""', '\n', '\n', '\n', $news['author'], 'Администратор', formatDate(time(), true), strip_tags(($text), 'html'), $link, $config['url']), $result['new_comments_text']);
                        mailSMTP($email, $result['new_comments_text'], $lang['mail_comments'], $message);
                    } else {
                        $core->tpl->info($lang['sendfalse'] . '<strong><a href="javascript:history.go(-1)"><b>' . $lang['go_back'] . '</b></a></strong>');
                    }
                }
            }
            $core->tpl->info($lang['comment_added']);
        }
        if ($url[1] <> 'addPost' || $url[1] <> 'editshort') initDir('comments', 'users_' . ($core->auth->user_info['id'] ?? 0), $id);
        $bb_area = $user['editor'] == "htmlEditor" ? 'bb_area' : 'edit_area';
        $bb = $bb_area('text', stripslashes($core->bbDecode(html2bb(parseBB($text)))), 6, 'textarea', false, true);
        $core->tpl->loadFile('comments/comments.add');
        $core->tpl->setVar('ID', $id);
        $core->tpl->setVar('COOKIE_NAME', (isset($_COOKIE['commentator']) && !$core->auth->isUser) ? $_COOKIE['commentator'] : ($core->auth->user_info['nick'] ?? ''));
        $core->tpl->setVar('COOKIE_MAIL', (isset($_COOKIE['email']) && !$core->auth->isUser) ? $_COOKIE['email'] : (isset($core->auth->user_info['nick']) ? $core->auth->user_info['email'] : ''));
        $core->tpl->setvar('BB_AREA', $bb);
        $core->tpl->setVar('CAPTCHA', $captcha);
        $core->tpl->sources = preg_replace_callback("#\\[noSubscribe\\](.*?)\\[/noSubscribe\\]#is", function ($matches) use ($user, $core, $isSubscribe) {
            if ($user['commentSubscribe'] == 1 && $core->auth->isUser && $isSubscribe == 0) return $matches[1];
        }, $core->tpl->sources);
        $core->tpl->sources = preg_replace_callback("#\\[yesSubscribe\\](.*?)\\[/yesSubscribe\\]#is", function ($matches) use ($user, $core, $isSubscribe) {
            if ($user['commentSubscribe'] == 1 && $core->auth->isUser && $isSubscribe == 1) return $matches[1];
        }, $core->tpl->sources);
        $core->tpl->setVar('MOD', $module);
        $core->tpl->end();
        if ($warning) {
            $contents = ob_get_contents();
            ob_end_clean();
            return $contents;
        }
    }
    access_delcache();
    echo '</div>' . "\n";
}

function access_delcache(): void
{
    global $core, $db;
    $access = $core->row_data('users', 'nick = "' . $db->safesql($core->auth->user_info['nick'] ?? '') . '"', false, 'id');
    if (isset($access['id'])) delcache('userInfo_' . $access['id']);
}


function show_user_wall($module, $id, $comment_num = 10, $ajax = false, $newPage = false, $warning = false, $langPref = '', $adminUid = false): void
{
    global $db, $core, $config, $user, $page, $email_conf, $url, $lang;
    if ($config['comments'] == 0) return;
    $bb = new bb;
    $captcha = captcha_image();
    $id = intval($id);
    $page = $newPage ? intval($newPage) : init_page();
    $cut = ($page - 1) * $comment_num;
    $query = $db->query("SELECT c.*, u.nick, u.group, u.last_visit, u.signature, u.user_comments, u.user_news FROM " . DB_PREFIX . "_comments as c LEFT JOIN `" . USER_DB . "`.`" . USER_PREFIX . "_users` as u on (c.uid=u.id) WHERE c.post_id='" . intval($id) . "' AND c.module='" . filter($module, 'module') . "' AND c.status='1' ORDER BY date DESC " . ($user['commentTree'] == 0 ? "LIMIT " . $cut . ", " . $comment_num : ''));
    $i = 0;
    if ($user['commentSubscribe'] == 1) {
        list($all, $isSubscribe) = $db->fetchRow($db->query("SELECT Count(id), (SELECT COUNT(*) FROM " . DB_PREFIX . "_com_subscribe WHERE id='" . intval($id) . "' AND module='" . filter($module, 'module') . "' AND uid='" . $core->auth->user_id . "') as isSubscribe FROM " . DB_PREFIX . "_comments WHERE post_id='" . $id . "' AND module='" . filter($module, 'module') . "' AND status='1'"));
    } else {
        list($all) = $db->fetchRow($db->query("SELECT Count(id) FROM " . DB_PREFIX . "_comments WHERE post_id='" . $id . "' AND module='" . filter($module) . "' AND status='1'"));
    }
    echo '<div id="commentError"></div>';
    echo '<div id="hideCommNum" style="display:none;">' . $comment_num . '</div>';
    echo '<div id="commentBox">' . "\n";
    $nowNumber = $all - $cut;
    if ($db->numRows($query) > 0) {
        $core->tpl->loadFile('profile/wall.view.top');
        $core->tpl->end('profile/wall.view.top');
        while ($rows = $db->getRow($query)) {
            $comment_array[$rows['parent']][] = $rows;
        }
        if (!empty($comment_array[0])) {
            foreach ($comment_array[0] as $comment) {
                $i++;
                build_comment($comment, '', $nowNumber);
                if ($user['commentTree'] == 1) {
                    $newNumber = build_tree($comment['id'], $comment_array, 3, $nowNumber);
                    $nowNumber = ($newNumber > 0 ? $newNumber : $nowNumber);
                }
                $nowNumber--;
            }
        }
        if ($user['commentTree'] == 0) $core->tpl->pages($page, $comment_num, $all, 'javascript:void(0)', 'onclick="wallPage(\'profile\', ' . $id . ', {num});"');
        $core->tpl->loadFile('profile/wall.view.down');
        $core->tpl->end('profile/wall.view.down');
    } else {
        $core->tpl->info($lang['empty_wall']);
    }
    if ($core->auth->group_info['addComment'] == 1) {
        $text = '';
        if (is_array($warning)) {
            $text = filter(utf_decode($_REQUEST['text'], 'html'));
        } elseif ($warning) {
            $text = '';
            if ($email_conf['new_comments'] == 1) {
                $query = $core->select_data('email', false, 'id ASC');
                list($uid, $post_id, $text) = $core->fetch_data('comments', false, 'uid, post_id, text');
                $news = $core->row_data('news', 'id = "' . $id . '"');
                $news_link = $news['cat'] !== ',0,' ? 'news/' . $core->getCat('news', $news['cat'], 'development') . '/' : 'news/';
                $link = $config['url'] . '/' . $news_link . $news['altname'] . '.html';
                $email = ($config['support_mail']);
                while ($result = $db->getRow($query)) {
                    if (!empty($email)) {
                        $message = $result['new_comments_text'] > 0 ? str_replace(array('&lt;', '&gt;', '{%username%}', '{%username_to%}', '{%date%}', '{%text%}', '{%link%}', '{%url%}'), array('<', '>', $news['author'], 'Администратор', formatDate(time(), true), strip_tags(($text), 'html'), $link, $config['url']), $result['new_comments_text']) : str_replace(array('\p', '\n', '\r', '<br>', '<br/>', '&nbsp;', '{%username%}', '{%username_to%}', '{%date%}', '{%text%}', '{%link%}', '{%url%}'), array('""', '""', '""', '\n', '\n', '\n', $news['author'], 'Администратор', formatDate(time(), true), strip_tags(($text), 'html'), $link, $config['url']), $result['new_comments_text']);
                        mailSMTP($email, $result['new_comments_text'], $lang['mail_comments'], $message);
                    } else {
                        $core->tpl->info($lang['sendfalse'] . '   <strong><a href="javascript:history.go(-1)"><b>' . $lang['go_back'] . '</b></a></strong>');
                    }
                }
            }
            $core->tpl->info($lang['wall_added']);
        }
        if (isset($url[1]) && ($url[1] <> 'addPost' || $url[1] <> 'editshort')) initDir('comments', 'users_' . ($core->auth->user_info['id'] ?? 0), $id);
        $bb_area = $user['editor'] == "htmlEditor" ? 'bb_area' : 'edit_area';
        $bb = $bb_area('text', stripslashes($core->bbDecode(html2bb(parseBB($text)))), 6, 'textarea', false, true);
        $core->tpl->loadFile('profile/wall.add');
        $core->tpl->setVar('ID', $id);
        $core->tpl->setVar('COOKIE_NAME', isset($_COOKIE['commentator']) && !$core->auth->isUser ? $_COOKIE['commentator'] : $core->auth->user_info['nick']);
        $core->tpl->setVar('COOKIE_MAIL', isset($_COOKIE['email']) && !$core->auth->isUser ? $_COOKIE['email'] : $core->auth->user_info['email']);
        $core->tpl->setvar('BB_AREA', $bb);
        $core->tpl->setVar('CAPTCHA', $captcha);
        $core->tpl->sources = preg_replace_callback("#\\[noSubscribe\\](.*?)\\[/noSubscribe\\]#is", function ($matches) use ($user, $core, $isSubscribe) {
            if ($user['commentSubscribe'] == 1 && $core->auth->isUser && $isSubscribe == 0) return $matches[1];
        }, $core->tpl->sources);
        $core->tpl->sources = preg_replace_callback("#\\[yesSubscribe\\](.*?)\\[/yesSubscribe\\]#is", function ($matches) use ($user, $core, $isSubscribe) {
            if ($user['commentSubscribe'] == 1 && $core->auth->isUser && $isSubscribe == 1) return $matches[1];
        }, $core->tpl->sources);
        $core->tpl->setVar('MOD', $module);
        $core->tpl->end();
    }
    access_delcache();
    echo '</div>' . "\n";
}

function build_tree($id_tree, $comment_array, $space = 0, $now_numb = 0)
{
    if (isset($comment_array[$id_tree])) {
        foreach ($comment_array[$id_tree] as $comment) {
            $now_numb--;
            build_comment($comment, $space, $now_numb);
            $new_numb = build_tree($comment['id'], $comment_array, ($space + 3), $now_numb);
        }
        return $new_numb > 0 ? $new_numb : $now_numb;
    }
}

function build_comment($comment, $space = '', $commNumber = 0): void
{
    global $core, $user, $adminUid, $page, $lang;
    $yrAdmin = false;
    $date = formatDate($comment['date'], true);
    if ($adminUid > 0 && $core->auth->user_id == $adminUid) $yrAdmin = true;
    echo '<div id="commentBox_' . $comment['id'] . '">' . "\n";
    $core->tpl->loadFile('comments/comments.view');
    $core->tpl->setVar('ID', $comment['id']);
    $core->tpl->setVar('NAME', ($comment['uid'] != 0) ? $comment['nick'] : $comment['gname']);
    $core->tpl->setVar('NID', $comment['post_id']);
    $core->tpl->setVar('AVATAR', avatar($comment['uid']));
    $core->tpl->setVar('BODY', '<div id="comment_' . $comment['id'] . '">' . stripslashes($core->bbDecode(html2bb(parseBB($comment['text'])))) . '</div>' . ($comment['signature'] ? str_replace('[sig]', stripslashes($core->bbDecode(html2bb(parseBB($comment['signature'])))), $user['commentSignature']) : ''));
    $core->tpl->setVar('UID', $comment['uid']);
    $core->tpl->setVar('URL', $comment['gurl']);
    $core->tpl->setVar('E-MAIL', $comment['gemail']);
    $core->tpl->setVar('NUMBER', $commNumber);
    $core->tpl->setVar('U_COMM', $comment['user_comments']);
    $core->tpl->setVar('SPACE', ((int)$space * 10));
    $core->tpl->setVar('SPACE_BG', ((int)$space * 10 - 15));
    $core->tpl->setVar('U_NEWS', $comment['user_news']);
    $core->tpl->setVar('DATE', $date);
    $core->tpl->sources = preg_replace_callback("#\\[moder\\](.*?)\\[/moder\\]#is", function ($matches) use ($core, $comment, $yrAdmin) {
        if ($core->auth->isAdmin or ($core->auth->isUser && $core->auth->user_id == $comment['uid']) or $yrAdmin) return $matches[1];
    }, $core->tpl->sources);
    $replace = array(
        "#\\[edit\\](.*?)\\[/edit\\]#is" => '<a href="javascript:void(0);" onclick="commentEdit(\'' . $comment['id'] . '\', \'comment_' . $comment['id'] . '\');" title="\\1">\\1</a>',
        "#\\[delete\\](.*?)\\[/delete\\]#is" => '<a href="javascript:void(0);" onclick="commentDelete(\'' . $comment['id'] . '\', \'commentBox_' . $comment['id'] . '\', \'' . $comment['module'] . '\', \'' . $comment['post_id'] . '\', \'' . $page . '\');" title="\\1">\\1</a>',
        "#\\[writeGuest\\](.*?)\\[/writeGuest\\]#is" => ($comment['uid'] == 0 ? '\\1' : ''),
        "#\\[writeUser\\](.*?)\\[/writeUser\\]#is" => ($comment['uid'] > 0 ? '\\1' : ''),
        "#\\[reply\\](.*?)\\[/reply\\]#is" => (/*$comment['uid'] != $core->auth->user_id &&*/
        $user['commentTree'] == 1 ? '\\1' : ''),
        "#\\[space\\](.*?)\\[/space\\]#is" => ($space > 0 ? '\\1' : ''),
    );
    $core->tpl->sources = preg_replace(array_keys($replace), array_values($replace), $core->tpl->sources);
    $core->tpl->end('comments/comments.view');
    echo '</div>' . "\n";
}

function checkCommentGuest($content, $uid)
{
    if ($uid == 0) return stripslashes($content);
}

function deleteComments($id, $mod = false, $pid = false, $uid = false): void
{
    global $db, $core, $lang;
    $post = $core->row_data('comments', 'id = "' . $id . '"');
    $mod_com = $core->row_data($mod, 'id = "' . $post['post_id'] . '"');
    if ($mod && $mod <> 'profile' && $post['post_id'] == $pid && $mod_com['comments'] > 0) getOneClicks($pid, $mod, 'comments', '-');
    if ($uid) getOneClicks($uid, 'users', 'user_comments', '-');
    $db->query("INSERT INTO " . DB_PREFIX . "_logs VALUES (NULL,'" . time() . "', '" . filter($_SERVER['REMOTE_ADDR']) . "', '" . $core->auth->user_id . "', '" . sess_count() . "', '" . str_replace(array('[nick]', '[module]', '[post_id]'), array($core->auth->user_info['nick'], $post['module'], $post['post_id']), $lang['logs_delete_comments']) . "', '1')");
    $core->del_data('comments', 'id = "' . $id . '" OR parent = "' . $id . '"');
}

function sess_count()
{
    $_SESSION['count'] = isset($_SESSION['count']) ? $_SESSION['count'] + 1 : 0;
    return $_SESSION['count'];
}

function generate_pin(): string
{
    $pin = '';
    for ($i = 0; $i < 5; $i++) {
        try {
            $pin .= random_int(0, 9);
        } catch (Exception $e) {
        }
    }
    return $pin;
}

function load_counter(): void
{
    echo '<div id = "counter"></div >
      <script >
      var n = localStorage . getItem(\'on_load_counter\');
      if (n === null)
          n = 0;
      }
      n++;
      localStorage.setItem("on_load_counter", n);
      document.getElementById(\'counter\').innerHTML = n;
      </script>';
}

function sess_clear()
{
    if (!isset($_SESSION)) session_start();
    $conter = 0;
    if (isset($_SESSION)) {
        // сбросить все переменные сессии
        $_SESSION = array();
        // сбросить куки, к которой привязана сессия
        if (ini_get("session.use_cookies")) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000,
                $params["path"], $params["domain"],
                $params["secure"], $params["httponly"]
            );
        }
        // уничтожить сессию
        $conter = session_destroy();
    } else {
        return;
    }
    return $conter;
}

function internoetics_mb_strimwidthd($string, $start = 0, $width = 150, $trimmarker = '...')
{
    $len = strlen(trim($string));
    return (($len > 20)) ? mb_strimwidth($string, $start, $width, "'.$trimmarker.'") . $trimmarker : $string;
}

function ajaxPoll(): void
{
    global $url, $core;
    require ROOT . 'usr/plugins/poll.plugin.php';
    switch ($url[2]) {
        case 'results':
            show_poll('results', intval($url[3]));
            break;
        case 'back_vote':
            show_poll(false, intval($url[3]));
            break;
        case 'doVote':
            $votes = explode('|', $_REQUEST['checks']);
            $pid = intval(str_replace('poll_', '', $_REQUEST['pid']));
            $qid = intval(str_replace('|', '', $_REQUEST['checks']));
            $nums = 0;
            foreach ($votes as $id) {
                $id = intval($id);
                if (!empty($id)) {
                    $nums++;
                    $core->upd_data('poll_questions', 'vote = vote+1', 'id = "' . $id . '" AND pid = "' . $pid . '"');
                }
            }
            $core->upd_data('polls', 'votes = votes+' . $nums, 'id = "' . $pid . '"');
            $core->ins_data('poll_voting', 'id,uid,pid,ip,time,qid', 'NULL, "' . $core->auth->user_id . '", "' . $pid . '", "' . getenv('REMOTE_ADDR') . '", "' . time() . '", "' . $qid . '"');
            show_poll('voted', $pid);
            break;
    }
}

function add_point($mod, $id, $do = '+'): void
{
    global $core;
    if (!file_exists(ROOT . 'usr/modules/' . $mod . '/comments.php')) {
        if ($mod <> 'profile') getOneClicks($id, $mod, 'comments');
        if ($core->auth->isUser) getOneClicks($core->auth->user_id, 'users', 'user_comments');
    } else {
        include(ROOT . 'usr/modules/' . $mod . '/comments.php');
    }
}

function detect_mobile_device()
{
    if (stristr(@$_SERVER['HTTP_USER_AGENT'], 'windows') && !stristr(@$_SERVER['HTTP_USER_AGENT'], 'windows ce')) return false;
    if (preg_match('/up.browser|up. link |windows ce|iemobile|mini|mmp|symbian|midp|wap|phone|pocket|mobile|pda|psp/i', @$_SERVER['HTTP_USER_AGENT'])) return true;
    if (isset($_SERVER['HTTP_ACCEPT']) && (stristr($_SERVER['HTTP_ACCEPT'], 'text/vnd.wap.wml') || stristr($_SERVER['HTTP_ACCEPT'], 'application/vnd.wap.xhtml xml'))) return true;
    if (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE']) || isset($_SERVER['X-OperaMini-Features']) || isset($_SERVER['UA-pixels'])) return true;
    $a = array('acs-', 'alav', 'alca', 'amoi', 'audi', 'aste', 'avan', 'benq', 'bird', 'blac',
        'bla z', 'brew', 'cell', 'cldc', 'cmd-', 'dang', 'doco', 'eric', 'hipt', 'inno',
        'ipaq', 'java', 'jigs', 'kddi', 'keji', 'leno', 'lg-c', 'lg-d', 'lg-g', 'lge-',
        'maui', 'maxo', 'midp', 'mi ts', 'mmef', 'mobi', 'mot-', 'moto', 'mwbp', 'nec-',
        'newt', 'noki', 'opwv', 'palm', 'pana', 'pant', 'pdxg', 'phil', 'play', 'pluc',
        'port', 'prox', 'qtek', 'qwap', 'sage', 'sams', 's any', 'sch-', 'sec-', 'send',
        'seri', 'sgh-', 'shar', 'sie-', 'siem', 'smal', 'smar', 'sony ', 'sph-', 'symb',
        't-mo', 'teli', 'tim-', 'tosh', 'tsm-', 'upg1', 'upsi', 'vk-v', 'voda', ' w3c ',
        'wap-', 'wapa', 'wapi', 'wapp', 'wapr', 'webc', 'winw', 'winw', 'xda', 'xda-');
    if (isset($a[substr(@$_SERVER['HTTP_USER_AGENT'], 0, 4)])) return true;
}

function detect_device(): string
{
    return detect_mobile_device() ? 'с мобильного телефона' : 'с обычного компьютера';
}

/*
      * Отслеживаем ботов
      * $agent - $_SERVER['HTTP_USER_AGENT']
      * $ret_id - если true то функция вернёт ид бота
      * $id - если известен ид бота то скрипт вернёт его имя
      */
function SpiderDetect($ret_id = false, $id = null): false|int|string
{
    global $lang;
    $agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    if (empty($agent)) return false;
    $engines = [
        // Yandex
        'YandexBot', 'YandexAccessibilityBot', 'YandexMobileBot', 'YandexDirectDyn', 'YandexScreenshotBot',
        'YandexImages', 'YandexVideo', 'YandexVideoParser', 'YandexMedia', 'YandexBlogs', 'YandexFavicons',
        'YandexWebmaster', 'YandexPagechecker', 'YandexImageResizer', 'YandexAdNet', 'YandexDirect',
        'YaDirectFetcher', 'YandexCalendar', 'YandexSitelinks', 'YandexMetrika', 'YandexNews',
        'YandexNewslinks', 'YandexCatalog', 'YandexAntivirus', 'YandexMarket', 'YandexVertis',
        'YandexForDomain', 'YandexSpravBot', 'YandexSearchShop', 'YandexMedianaBot', 'YandexOntoDB',
        'YandexOntoDBAPI', 'YandexTurbo', 'YandexVerticals',
        // Google
        'Googlebot', 'Googlebot-Image', 'Mediapartners-Google', 'AdsBot-Google', 'APIs-Google',
        'AdsBot-Google-Mobile', 'AdsBot-Google-Mobile', 'Googlebot-News', 'Googlebot-Video',
        'AdsBot-Google-Mobile-Apps',
        // Other
        'Mail.RU_Bot', 'bingbot', 'Accoona', 'ia_archiver', 'Ask Jeeves', 'OmniExplorer_Bot', 'W3C_Validator',
        'WebAlta', 'YahooFeedSeeker', 'Yahoo!', 'Ezooms', 'Tourlentabot', 'MJ12bot', 'AhrefsBot',
        'SearchBot', 'SiteStatus', 'Nigma.ru', 'Baiduspider', 'Statsbot', 'SISTRIX', 'AcoonBot', 'findlinks',
        'proximic', 'OpenindexSpider', 'statdom.ru', 'Exabot', 'Spider', 'SeznamBot', 'oBot', 'C-T bot',
        'Updownerbot', 'Snoopy', 'heritrix', 'Yeti', 'DomainVader', 'DCPbot', 'PaperLiBot', 'StackRambler',
        'msnbot', 'msnbot-media', 'msnbot-news', 'Accoona', 'ia_archiver', 'Ask Jeeves', 'W3C_Validator', 'WebAlta',
        'YahooFeedSeeker', 'Yahoo!', 'Ezooms', 'SiteStatus', 'Nigma.ru', 'Baiduspider', 'SISTRIX', 'findlinks',
        'proximic', 'OpenindexSpider', 'statdom.ru', 'Spider', 'Snoopy', 'heritrix', 'Yeti',
        'DomainVader', 'StackRambler'
    ];
    foreach ($engines as $key => $engine) {
        if (stripos($agent, $engine) !== false) {
            if (!$ret_id) {
                return ($engine);
            } else {
                return ($key);
            }
        } /*
		else {
            return $lang['bot_undefined'];
        }*/
    }
    return (false);
}

/*
      * Инитилизация системы учётов реффера
      */
function init_reffer(): void
{
    global $core, $db, $engines;
    loadConfig('reffer');
    $reffer = isset($_SERVER['HTTP_REFERER']) ? filter($_SERVER['HTTP_REFERER']) : getenv("http_referer");
    $reqUri = isset($_SERVER['REQUEST_URI']) ? filter($_SERVER['REQUEST_URI'], 'reqUri') : '';
    $time = time();
    $engineName = '';
    $sQuery = '';
    $query = array();
    $refferDomen = getHost($reffer);
    $myDomen = getHost($_SERVER['HTTP_HOST']);
    if (trim($reffer) && $refferDomen != $myDomen) {
        $uri = parse_url($reffer);
        if (isset($uri['query'])) parse_str($uri['query'], $query);
        foreach ($engines as $engine => $info) {
            if (eregStrt($info['serv_url'], $refferDomen)) {
                $fromEngine = true;
                $engineName = $info['name'];
                if (isset($query[$info['get']])) $sQuery = utf_decode($query[$info['get']]);
            }
        }
        $type = isset($fromEngine) ? 2 : 1;
        $compressRef = @base64_encode($reffer);
        //@base64_decode(gzinflate('bla', 9))
        $exists = $core->row_data('reffers', 'url = "' . $compressRef . '"', false, 'COUNT(*) as count');
        if ($exists['count'] > 0) {
            $core->upd_data('reffers', 'url = "' . $db->safesql($compressRef) . '", search_query = "' . $db->safesql($sQuery) . '", time = "' . $time . '", ip = "' . getRealIpAddr() . '", count = count+1', 'url = "' . $db->safesql($compressRef) . '"');
        } else {
            $core->ins_data('reffers', 'url,referer,to_url,search_query,time,ip,count,host,type', '"' . $db->safesql($compressRef) . '", "' . $db->safesql($engineName) . '", "' . $db->safesql($reqUri) . '", "' . $db->safesql($sQuery) . '","' . $time . '","' . getRealIpAddr() . '",1, "' . $db->safesql($refferDomen) . '","' . $type . '"');
        }
    }
}

function setHeaders($url, $cookies, $reffer = false): void
{
    global $config;
    static $cookie;
    $reffer = !$reffer ? $config['url'] : $reffer;
    if (trim($cookies) != '' && get_loaded_extensions('curl')) {
        if (!isset($cookie)) {
            $cookie = '';
            $bufferCookie = array_unique(explode("\n", $cookies));
            foreach ($bufferCookie as $cook) {
                if (trim($cook) != '' && eregStrt('=', $cook)) $cookie .= $cook . '; ';
            }
        }
        $curl_handle = curl_init($url);
        curl_setopt($curl_handle, CURLOPT_COOKIE, $cookie);
        curl_setopt($curl_handle, CURLOPT_REFERER, $reffer);
        curl_setopt($curl_handle, CURLOPT_USERAGENT, randomUserAgent());
        curl_exec($curl_handle);
        curl_close($curl_handle);
    }
}

function randomUserAgent(): string
{
    $agents = array('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)', 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ru) Opera 8.01', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1', 'Mozilla/4.0 (compatible; MSIE 5.01; Windows 98)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.1.4322)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.50 [en]', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.10) Gecko/20050717 Firefox/1.0.6', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 3.0 (build 00614))', 'Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.7.10) Gecko/20050717 Firefox/1.0.6', 'Opera/6.01 (Windows 2000; U) [ru]', 'Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.7.7) Gecko/20050414 Firefox/1.0.3', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts-MyWay; MRA 4.2 (build 01102))', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; snprtz|dialno; HbTools 4.7.0)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MRA 4.0 (build 00768))', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; OptusIE55-31)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.1 (build 00961); .NET CLR 1.1.4322)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.1 (build 00975); .NET CLR 1.1.4322)', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.2 (build 01102))', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.6.1)', 'Mozilla/4.0 (compatible; MSIE 5.0; Windows 98)', 'Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows 2000) Opera 7.0 [en]', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)', 'Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.8a5) Gecko/20041122');
    return $agents[rand(0, count_($agents) - 1)];
}

function gencode($lenght): string
{
    $code = array();
    $symbols = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '2', '3', '4', '5', '6', '7', '8', '9');
    for ($i = 0; $i < $lenght; $i++) {
        $code[] = $symbols[rand(0, sizeof($symbols) - 1)];
    }
    return implode('', $code);
}

function captcha_image($button = true): array|string
{
    global $security, $config, $lang;
    $captcha = array();
    $widths = $security['captcha_width'] . 'px';
    $height = $security['captcha_height'] . 'px';
    if ($security['switch_cp'] != 0) {
        if ($security['recaptcha'] == 0 && $security['smart_captcha'] == 0) {
            if (!isset($_SESSION)) session_start();
            $captcha = '<style type="text/css">/* <![CDATA[ */.captcha{width: ' . $widths . '; height: ' . $height . '; background: url("captcha") top left no-repeat;}/* ]]> */</style><a href="javascript:reloadCaptcha();" title="' . $lang['captcha_refresh'] . '"><div class="captcha" id="captcha"></div></a>';
        } else {
            if ($security['recaptcha_google']) $captcha = '<div class="g-recaptcha" data-sitekey="' . $security['recaptcha_public'] . '" data-theme="light"></div><script src="https://www.google.com/recaptcha/api.js?hl="' . $config['lang'] . '"" async defer></script>';
            if ($security['smart_captcha']) $captcha = '<div id="captcha-container" class="smart-captcha" data-sitekey="' . $security['smart_captcha_public'] . '" data-hl="' . $config['lang'] . '"></div><script src="https://smartcaptcha.yandexcloud.net/captcha.js" defer></script>';
        }
    }
    return $captcha;
}

function captcha_check($post_name)
{
    global $core, $security;
    if ($security['switch_cp'] != 0) {
        if (isset($security['recaptcha_google']) && $security['recaptcha_google']) {
            $privatekey = $security['recaptcha_private'];
            $recaptcha = new recaptcha($privatekey);
            $pp = '';
            $pp = $_REQUEST['g-recaptcha-response'];
            $resp = $recaptcha->verify($pp, getRealIpAddr());
            if ($resp != null && $resp->isSuccess()) {
                return true;
            } else {
                $errors = $resp->getErrorCodes();
                return false;
            }
        } elseif ($security['smart_captcha']) {
            $ch = curl_init();
            $args = http_build_query([
                "secret" => $security['smart_captcha_private'],
                "token" => $post_name,
                "ip" => $_SERVER['REMOTE_ADDR'], // Нужно передать IP-адрес пользователя.
                // Способ получения IP-адреса пользователя зависит от вашего прокси.
            ]);
            curl_setopt($ch, CURLOPT_URL, "https://smartcaptcha.yandexcloud.net/validate?$args");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 1);
            $server_output = curl_exec($ch);
            $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            if ($httpcode !== 200) {
                echo "Allow access due to an error: code=$httpcode; message=$server_output\n";
                return true;
            }
            $resp = json_decode($server_output);
            return $resp->status === "ok";
        } else {
            if (!isset($_SESSION)) session_start();
            if ($core->auth->isUser) return true;
            if (isset($_REQUEST[$post_name])) {
                if (isset($_SESSION['securityCode'])) {
                    if ($_SESSION['securityCode'] == mb_strtolower($_POST[$post_name])) {
                        unset($_SESSION['securityCode']);
                        return true;
                    }
                } else {
                    echo 'session failed';
                }
            }
        }
    } else {
        return true;
    }
}

function parse_req($value): void
{
    global $log_conf;
    if (!is_array($value)) {
        if (preg_match("#UNION|OUTFILE|SELECT|ALTER|INSERT|DROP|TRUNCATE#i", base64_decode($value))) {
            if ($log_conf['queryError'] == 1) writeInLog('Попытка произвести SQL-Inj текст: ' . $value, 'sql');
            //fatal_error(_ERROR, _UNKNOWN_ERROR);
            die();
        }
    } else {
        foreach ($value as $val) {
            parse_req($val);
        }
    }
}

function loadConfig($file): void
{
    global $config, $core;
    $mainFile = ROOT . 'etc/' . $file . '.config.php';
    require_once($mainFile);
    if ($config['lang'] != $core->lang && file_exists(ROOT . 'etc/' . $core->lang . '.' . $file . '.config.php')) require ROOT . 'etc/' . $core->lang . '.' . $file . '.config.php';
}

function loadTag($file): string
{
    return ROOT . '/usr/modules/' . $file . '/templates_tag.php';
}

function Langblocks(): void
{
    global $core;
    if (file_exists(ROOT . 'langs/' . $core->lang . '/' . $core->lang . '.blocks.lng')) require_once(ROOT . 'langs/' . $core->lang . '/' . $core->lang . '.blocks.lng');
}

function loadLangBLOCK($block): void
{
    global $core;
    $mainFile = ROOT . 'langs/' . $core->lang . '/blocks/' . $core->lang . '.' . $block . '.lng';
    if (file_exists(ROOT . 'langs/' . $core->lang . '.tpl.lng')) include(ROOT . 'langs/' . $core->lang . '.tpl.lng');
    if (isset ($core->lang) && $core->lang != '') {
        if (file_exists($mainFile)) {
            require_once $mainFile;
        } else die("Language file not found");
    } else {
        require_once $mainFile;
    }
}

function loadLang($file): void
{
    global $core;
    $mainFile = ROOT . 'usr/langs/' . $core->lang . '.' . $file . '.php';
    if (file_exists($mainFile)) require_once($mainFile);
}

function loadConfigBLOCK($module): void
{
    global $config, $core;
    $mainFile = ROOT . 'etc/blocks/' . $module . '.config.php';
    if (file_exists($mainFile)) require_once($mainFile);
    if ($config['lang'] != $core->lang && file_exists(ROOT . 'etc/blocks/' . $core->lang . '.' . $module . '.config.php')) require ROOT . 'etc/blocks/' . $core->lang . '.' . $module . '.config.php';
}

function SpeedTest(): void
{
    $str = '';
    $block_size = 16 * 1024; // Байт
    $blocks = !empty($_GET['b']) ? (int)$_GET['b'] : 10; // Блоков
// Блок случайных символов 16 КБ
    for ($i = 0; $i < $block_size; $i++) {
        $str .= chr(rand(32, 255));
    }
    echo "<SCRIPT>var time1 = new Date();</SCRIPT><!--";
    for ($i = 0; $i < $blocks; $i++) {
        echo $str;
    }
    echo "--><SCRIPT>var time2 = new Date();
   var time = time2.getTime() - time1.getTime();
   var cps = Math.round({$blocks} * {$block_size} * 1000/time;)
   var bps = Math.round({$blocks} * {$block_size} * 8000/time;)
   var kbps = Math.round(100 * bps/1024) /100;
   var KBps = Math.round(100 * cps/1024) /100;
   document.write('Скорость: ' + kbps + ' кбит/сек, ' + KBps + ' КБ/сек');
</SCRIPT>";
}

function timerRun(): void
{
    echo ').textContent = (time/1000).toFixed(1);
             // запускаем вызов функции run через 50 мс
             timeoutId = window.setTimeout(run, 50);
         };
       // запускаем функцию run
       run();
     }
     // функция для остановки таймера по timeoutId
     function stop() {
         if (timeoutId) {
             // прекращаем работу таймера
             clearTimeout(timeoutId);
             // присваиваем переменной timeoutId значение null
             timeoutId = null;
         }
     }
</script>';
}

function loadUserAuth()
{
    if (!isset($_SESSION)) session_start();
    if (isset($_SESSION['user_auth'])) {
        $user_auth = $_SESSION['user_auth'];
        $return = $user_auth;
    } else {
        $return = false;
    }
    return $return;
}

function flags_smile($_name): string
{
    global $smiles, $lang;
    $flags = '';
    foreach ($smiles as $tag => $param) {
        if ($param['cat'] == 'flags') {
            if ($param['abridged'] == strtoupper($_name)) $flags = '<img src="' . $param['url'] . '" title="' . $param['title'] . '" class="img-responsive mw30 ib br4" border="0" alt=""/>';
        } else {
            $flags = '<img src="media/smiles/flags/UN.png" border="0" class="img-responsive mw30 ib br4"  title="' . $lang['undefined'] . '" alt="">';
        }
    }
    return $flags;
}

function flags_langs($id): string
{
    $lang_dirs = get_folder();
    $lang_change = '';
    foreach ($lang_dirs as $value) {
        if (isset($value['icon']) and $value['icon'] and $value['id'] == $id) $lang_change = '<img src="langs/' . $id . '/' . $value['icon'] . '" title="' . $value['name'] . '" class="img-responsive mw30 ib br4" border="0" alt=""/>';
    }
    return $lang_change;
}

function lang_change(): string
{
    $lang_dirs = get_folder();
    $lang_change = '<li>';
    foreach ($lang_dirs as $key => $value) {
        $lang_change .= '<a href="/administration/language/save_lang/' . $key . '" data-lang="' . $key . '\">';
        if (isset($value['icon']) and $value['icon']) $lang_change .= '<img src="langs/' . $key . '/' . $value['icon'] . '">';
        $lang_change .= $value['name'] . '</a>';
    }
    $lang_change .= '</li>';
    return $lang_change;
}

/*
      * Кодировщик
      * $status - назначение кодировать или раскодировать
      * кодировать decoder('c', $text)
      * раскодировать decoder('d', $text)
      * $text - текст для кодировки
      */
function decoder($status, $text)
{
    global $core;
    if (isset($text)) {
        if ($status == 'c') {
            $content = str_replace(array('\p', '\n', '\r', ' ', '', '<', '>', '[', ']', '£', '€', '¶', '§', '©', '®', '™', '°', '±', '¼', '½', '¾', '×', '÷', 'ƒ', 'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', 'ρ', 'ς', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', '←', '↑', '→', '↓', '↔', '♠', '♣', '♥', '♦', '"', '&', '…', '′', '″', '–', '—', '‘', '’', '‚', '“', '”', '„', '«', '»'), array('""', '""', '""', '&nbsp;', '&quot;', '&lsqb;', '&rsqb;', '&lt;', '&gt;', '&pound;', '&euro;', '&para;', '&sect;', '&copy;', '&reg;', '&trade;', '&deg;', '&plusmn;', '&frac14;', '&frac12;', '&frac34;', '&times;', '&divide;', '&fnof;', '&Alpha;', '&Beta;', '&Gamma;', '&Delta;', '&Epsilon;', '&Zeta;', '&Eta;', '&Theta;', '&Iota;', '&Kappa;', '&Lambda;', '&Mu;', '&Nu;', '&Xi;', '&Omicron;', '&Pi;', '&Rho;', '&Sigma;', '&Tau;', '&Upsilon;', '&Phi;', '&Chi;', '&Psi;', '&Omega;', '&alpha;', '&beta;', '&gamma;', '&delta;', '&epsilon;', '&zeta;', '&eta;', '&theta;', '&iota;', '&kappa;', '&lambda;', '&mu;', '&nu;', '&xi;', '&omicron;', '&pi;', '&rho;', '&sigmaf;', '&sigma;', '&tau;', '&upsilon;', '&phi;', '&chi;', '&psi;', '&omega;', '&larr;', '&uarr;', '&rarr;', '&darr;', '&harr;', '&spades;', '&clubs;', '&hearts;', '&diams;', '&quot;', '&amp;', '&hellip;', '&prime;', '&Prime;', '&ndash;', '&mdash;', '&lsquo;', '&rsquo;', '&sbquo;', '&ldquo;', '&rdquo;', '&bdquo;', '&laquo;', '&raquo;'), (stripslashes($core->bbDecode(html2bb(parseBB($text))))));
        } elseif ($status == 'd') {
            $content = str_replace(array('""', '""', '""', '&nbsp;', '&quot;', '&lsqb;', '&rsqb;', '&lt;', '&gt;', '&pound;', '&euro;', '&para;', '&sect;', '&copy;', '&reg;', '&trade;', '&deg;', '&plusmn;', '&frac14;', '&frac12;', '&frac34;', '&times;', '&divide;', '&fnof;', '&Alpha;', '&Beta;', '&Gamma;', '&Delta;', '&Epsilon;', '&Zeta;', '&Eta;', '&Theta;', '&Iota;', '&Kappa;', '&Lambda;', '&Mu;', '&Nu;', '&Xi;', '&Omicron;', '&Pi;', '&Rho;', '&Sigma;', '&Tau;', '&Upsilon;', '&Phi;', '&Chi;', '&Psi;', '&Omega;', '&alpha;', '&beta;', '&gamma;', '&delta;', '&epsilon;', '&zeta;', '&eta;', '&theta;', '&iota;', '&kappa;', '&lambda;', '&mu;', '&nu;', '&xi;', '&omicron;', '&pi;', '&rho;', '&sigmaf;', '&sigma;', '&tau;', '&upsilon;', '&phi;', '&chi;', '&psi;', '&omega;', '&larr;', '&uarr;', '&rarr;', '&darr;', '&harr;', '&spades;', '&clubs;', '&hearts;', '&diams;', '&quot;', '&amp;', '&hellip;', '&prime;', '&Prime;', '&ndash;', '&mdash;', '&lsquo;', '&rsquo;', '&sbquo;', '&ldquo;', '&rdquo;', '&bdquo;', '&laquo;', '&raquo;'), array('\p', '\n', '\r', ' ', '', '<', '>', '[', ']', '£', '€', '¶', '§', '©', '®', '™', '°', '±', '¼', '½', '¾', '×', '÷', 'ƒ', 'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', 'ρ', 'ς', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', '←', '↑', '→', '↓', '↔', '♠', '♣', '♥', '♦', '"', '&', '…', '′', '″', '–', '—', '‘', '’', '‚', '“', '”', '„', '«', '»'), (stripslashes($core->bbDecode(html2bb(parseBB($text))))));
        } else {
            $content = false;
        }
    } else {
        return;
    }
    return $content;
}

function tinymce_entity_fix($s): array|string
{
    $entity_from = array('&amp;', '&lt;', '&gt;', '&nbsp;', '&quot;');
    $entity_to = array('&amp;amp;', '&amp;lt;', '&amp;gt;', '&amp;nbsp;', '&amp;quot;');
    return str_replace($entity_from, $entity_to, $s);
}

/*
      * Выводим статус активности объекта
      * $dbname - имя базы данных
      * $id - id
      * $module - название модуля
      * $time - дополнительный параметр
      */
function status_icon($dbname, $id, $module = false, $time = false, $link = false, $num = false): string
{
    global $core, $url, $lang;
    $start_link = $link ? '<a href="' . $link . '">' : '';
    $end_link = $link ? '</a>' : '';
    $fa_2x = $link ? 'fa-2x' : '';
    $row = $module == 'users' ? $core->row_data('users', 'u.id = "' . $id . '"', false, 'u.*, g.name, (SELECT uid FROM ' . DB_PREFIX . '_online WHERE u.id=uid LIMIT 1) as online', 'as u LEFT JOIN ' . DB_PREFIX . '_groups as g on(u.group = g.id)') : $core->row_data($dbname, 'id = "' . $id . '"');
    $stat = $row['active'] ?? ($row['status'] ?? '');
    $urls = isset($url[1]) ? ($url[1] == 'support' ? $url[1] : '') : '';
    $urlm = isset($url[1]) ? ($url[1] == 'moderation' ? $url[1] : '') : '';
    if ($module == 'users' && $row['online']) {
        $status_icon = $start_link . '<span class="fa fa-check-circle text-success fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['online'] . '"></span>' . $end_link;
    } elseif ($module == 'users' && $row['group'] == 5) {
        $status_icon = $start_link . '<span class="fa fa-circle text-danger fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['users_bans'] . '"></span>' . $end_link;
    } elseif ($module == 'users' && $row['active'] != 1) {
        $status_icon = $start_link . '<span class="fa fa-clock-o text-warning fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['time_is_up'] . '"></span>' . $end_link;
    } elseif ($module == 'users' && !$row['online']) {
        $status_icon = $start_link . '<span class="fa fa-circle text-dark fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['offline'] . '"></span>' . $end_link;
    } elseif ($dbname == 'groups' && $time == 1) {
        $status_icon = $start_link . '<span class="fa fa-check-circle text-success fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['actively'] . '"></span>' . $end_link;
    } elseif ($stat == 1 && $module == 'feedback' || $stat == 1 && $module == 'complaint') {
        $status_icon = $start_link . '<span class="fa fa-envelope-open-o text-warning fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['read'] . '"></span>' . $end_link;
    } elseif ($stat == 1 && !$num && $module == 'distribution') {
        $status_icon = $start_link . '<span class="fa fa-share-square-o text-success fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['mail_sent_out'] . '"></span>' . $end_link;
    } elseif ($stat == 1 && $module == 'distribution') {
        $status_icon = $start_link . '<span class="fa fa-send text-success fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['mail_sent'] . '"></span>' . $end_link;
    } elseif ($stat == 1 && $module == 'distribution') {
        $status_icon = $start_link . '<span class="fa fa-send text-success fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['mail_sent'] . '"></span>' . $end_link;
    } elseif ($urls && $stat == 1 && $module == 'support') {
        $status_icon = $start_link . '<span class="fa fa-plus-circle text-success fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['response_received'] . '"></span>' . $end_link;
    } elseif ($stat == 3 && $module == 'feedback' || $stat == 3 && $module == 'complaint' || $stat == 1 && $module == 'support') {
        $status_icon = $start_link . '<span class="fa fa-plus-circle text-success fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['response_sent'] . '"></span>' . $end_link;
    } elseif ($stat == 1) {
        $status_icon = $start_link . '<span class="fa fa-check-circle text-success fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['actively'] . '"></span>' . $end_link;
    } elseif ($stat == 2 && $module == 'feedback' || $stat == 2 && $module == 'complaint') {
        $status_icon = $start_link . '<span class="fa fa-minus-circle text-danger fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['no_response'] . '"></span>' . $end_link;
    } elseif ($stat == 3 && $module == 'support' && $time == 1) {
        $status_icon = $start_link . '<span class="fa fa-minus-circle text-danger fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['deleted_no_response'] . '"></span>' . $end_link;
    } elseif ($stat == 2 && $module == 'news' || $stat == 2 && $module == 'content' || $stat == 2 && $module == 'comment' || $stat == 2 && $module == 'guestbook' || $stat == 2 && $urlm == 'moderation') {
        $status_icon = $start_link . '<span class="fa fa-circle text-warning fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['on_moderation'] . '"></span>' . $end_link;
    } elseif ($stat == 2 && $module = 'support') {
        $status_icon = $start_link . '<span class="fa fa-archive text-warning fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['support_archive1'] . '"></span>' . $end_link;
    } elseif ($stat == 2 && $module = 'pools') {
        $status_icon = $start_link . '<span class="fa fa-clock-o text-warning fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['time_is_up'] . '"></span>' . $end_link;
    } elseif ($stat == 3 && $module == 'news' || $stat == 3 && $module == 'support') {
        $status_icon = $start_link . '<span class="fa fa-times-circle text-info fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['deleted_users'] . '&emsp;' . formatDate($time, true) . '"></span>' . $end_link;
    } elseif ($stat == 3 && $module == 'guestbook') {
        $status_icon = $start_link . '<span class="fa fa-times-circle text-info fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['deleted_admin'] . '"></span>' . $end_link;
    } elseif ($stat == 3 && $module == 'banners') {
        $status_icon = $start_link . '<span class="fa fa-hand-pointer-o text-warning fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['clicks_is_max'] . '"></span>' . $end_link;
    } elseif ($stat == 3) {
        $status_icon = $start_link . '<span class="fa fa-hand-pointer-o text-warning fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['clicks_is_max'] . '"></span>' . $end_link;
    } elseif ($stat == 4) {
        $status_icon = $start_link . '<span class="fa fa-eye text-warning fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['views_is_max'] . '"></span>' . $end_link;
    } elseif ($dbname == 'groups' && $time == 0) {
        $status_icon = $start_link . '<span class="fa fa-circle text-danger fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['not_actively'] . '"></span>' . $end_link;
    } elseif ($stat == 0 && $module == 'feedback' || $stat == 0 && $module == 'complaint' || $stat == 0 && $module == 'support') {
        $status_icon = $start_link . '<span class="fa fa-envelope-o text-danger fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['not_read'] . '"></span>' . $end_link;
    } elseif ($stat == 0 && $module == 'distribution') {
        $status_icon = $start_link . '<span class="fa fa-envelope text-info fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['mail_postponed'] . '"></span>' . $end_link;
    } else {
        $status_icon = $start_link . '<span class="fa fa-circle text-danger fa-md ' . $fa_2x . '" data-toggle="tooltip" data-original-title="' . $lang['not_actively'] . '"></span>' . $end_link;
    }
    return $status_icon;
}

function ComplaintInit($uid): void
{
    global $core, $lang;
    require_once(ROOT . 'usr/plugins/modal_box/init.php');
    if (!$core->auth->isUser) {
        $content = '<div class="mbmest">' . $lang['complaints_error1'] . '</div>';
    } elseif (isset($_COOKIE['complaint-' . $uid]) && $uid == $core->auth->user_info['id']) {
        $content = '<div class="mbmest">' . $lang['complaints_error2'] . '</div>';
    } elseif (isset($_COOKIE['complaint-' . $uid])) {
        $content = '<div class="mbmest">' . $lang['complaints_error3'] . '</div>';
    } else {
        $content = '<form action="complaint/send" method="post"><table style="width=:100%; border: 0; border-spacing: 1px; border-collapse: separate;"><input type="hidden" name="nid" value="&emsp;&emsp;&emsp;' . $uid . '"><tr><td style="width:30%; vertical-align: top;">' . $lang['complaints_title'] . '</td><td><select style="width: 93%; height: 100%;" class="fiel prepend-icon" name="title"><option value="' . $lang['complaints_title1'] . '">' . $lang['complaints_title1'] . '</option><option value="' . $lang['complaints_title2'] . '">' . $lang['complaints_title2'] . '</option><option value="' . $lang['complaints_title3'] . '">' . $lang['complaints_title3'] . '</option><option value="' . $lang['complaints_title4'] . '">' . $lang['complaints_title4'] . '</option><option value="' . $lang['complaints_title5'] . '">' . $lang['complaints_title5'] . '</option></td></tr><td>&nbsp;</td><tr></tr><tr><td style="vertical-align: top;">' . $lang['complaints_text'] . '</td><td><textarea class="fiel prepend-icon" name="message" style="width: 93%; height: 100%;" rows="4"></textarea><br/><sup>' . $lang['complaints_text_info'] . '</sup></td></tr><tr><td>&nbsp;</td><td><input type="submit" name="submit"  value="' . $lang['complaints_send'] . '" class="form-button-tt"/></tr></table></form>';
    }
    modal_box($lang['complain_report'], '', $content, 'Complaint');
}

function add_book($uid = false): void
{
    global $core;
    if ($uid) {
        $core->tpl->sources = preg_replace_callback("#\\[add_bookmarks\\](.*?)\\[/add_bookmarks\\]#is", function ($matches) use ($uid) {
            if (!empty($uid)) return $matches[1];
        }, $core->tpl->sources);
    }
}

function del_book($uid = false): void
{
    global $core;
    if ($uid) {
        $core->tpl->sources = preg_replace_callback("#\\[del_bookmarks\\](.*?)\\[/del_bookmarks\\]#is", function ($matches) use ($uid) {
            if (!empty($uid)) return $matches[1];
        }, $core->tpl->sources);
    }
}

function BookmarksInit($id, $mod, $title): void
{
    global $core, $news_conf, $content_conf, $lang;
    if ($mod == 'news') {
        $in = $news_conf['bookmarks'];
    } elseif ($mod == 'content') {
        $in = $content_conf['bookmarks'];
    } else {
        $in = '';
    }
    if ($in == 1) {
        $uid = $core->auth->user_id;
        $bookmark = $core->row_data('bookmarks', 'nid = "' . $id . '/' . $core->auth->user_id . '" and module = "' . $mod . '"');
        if (isset($bookmark['id'])) {
            if (isset($bookmark['nid']) || $bookmark['nid'] == $id . '/' . $core->auth->user_id && $bookmark['title'] == $title && $core->auth->user_info['id'] == $bookmark['uid'] && $bookmark['module'] == $mod || $core->auth->isUser && $core->auth->user_info['id'] == $bookmark['uid'] && $bookmark['module'] == $mod) {
                $core->tpl->setVar('add_bookmarks', '');
                add_book($uid);
                $core->tpl->setVar('del_bookmarks', '<a href="' . $mod . '/del_bookmarks/' . $bookmark['id'] . '">' . $lang['out_bookmarks'] . '</a>');
                del_book($uid);
            }
        } else {
            $core->tpl->setVar('add_bookmarks', '<a href="' . $mod . '/add_bookmarks/' . $id . '/' . $core->auth->user_id . '">' . $lang['in_bookmarks'] . '</a>');
            add_book($uid);
            $core->tpl->setVar('del_bookmarks', '');
            del_book($uid);
        }
    } else {
        $core->tpl->setVar('add_bookmarks', '');
        add_book(false);
        $core->tpl->setVar('del_bookmarks', '');
        del_book(false);
        $core->tpl->info($lang['off_bookmarks']);
    }
}

function bookmarksSubscribe($id, $mod, $do): void
{
    global $core, $db, $news_conf, $content_conf, $lang;
    $id = isset($id) ? intval($id) : '';
    $mod = isset($mod) ? filter($mod, 'module') : '';
    $do = isset($do) ? intval($do) : '';
    $info = '';
    $rows = '';
    if ($mod == 'news') {
        $limit = $news_conf['numbookmarks'];
    } elseif ($mod == 'content') {
        $limit = $content_conf['numbookmarks'];
    } else {
        $limit = '50';
    }
    $where = 'id = "' . $id . '"';
    $select = 'n.*, c.*';
    $as = 'as n LEFT JOIN ' . DB_PREFIX . '_langs as c on(c.postId=n.id and c.module="' . $mod . '")';
    $order = '';
    $query = $core->select_data($mod, $where, $order, $select, $as);
    $altname = $mod == 'news' ? 'altname' : 'translate';
    $mod_config = $mod == 'news' ? $news_conf : $content_conf;
    $info_mod_add = $mod == 'news' ? 'news_add_bookmarks' : 'static_add_bookmarks';
    $info_mod_del = $mod == 'news' ? 'news_delete_bookmarks' : 'static_delete_bookmarks';
    $title_mod = $mod == 'news' ? 'title' : 'keywords';
    if ($do == 1) {
        list($bookmarkslist) = $core->fetch_data('bookmarks', 'uid = "' . $core->auth->user_id . '"');
        $bookmark = $core->row_data('bookmarks', 'uid = "' . $core->auth->user_id . '" and module = "' . $mod . '"', 'id DESC LIMIT ' . $limit);
        if ($db->numRows($query) > 0) {
            while ($rows = $db->getRow($query)) {
                $link = $rows['cat'] !== ',0,' ? $mod . '/' . $core->getCat($mod, $rows['cat'], 'development') . '/' : $mod . '/';
                if (isset($bookmark['id']) && $bookmark['title'] == $rows[$title_mod] && $bookmark['nid'] == $rows['id'] . '/' . $core->auth->user_id && $core->auth->user_info['id'] == $bookmark['uid']) {
                    $info .= $lang['this_tab_already_exists'];
                } else {
                    if ($mod_config['numbookmarks'] !== $bookmarkslist) {
                        $core->ins_data('bookmarks', 'id,nid,uid,url,title,module,date', 'NULL, "' . $rows['id'] . '/' . $core->auth->user_id . '","' . $core->auth->user_id . '", "' . $link . $rows[$altname] . '.html' . '", "' . $rows['title'] . '", "' . $mod . '","' . time() . '"');
                        $info .= $lang[$info_mod_add];
                    } else {
                        $info .= str_replace(array('[numbookmarks]'), array($mod_config['numbookmarks']), $lang['error_add_limit_bookmarks']);
                    }
                }
            }
        }
    } else {
        $bookmark = $core->row_data('bookmarks', 'id = "' . $id . '" and uid = "' . $core->auth->user_id . '"');
        $rows = $core->row_data($mod, $where, $order, $select, $as);
        $title = isset($rows['id']) && $bookmark['title'] == $rows['title'] && $bookmark['uid'] == $core->auth->user_id ? $rows['title'] : '';
        if (isset($rows['id']) && $bookmark['title'] == $title && $bookmark['uid'] == $core->auth->user_id) {
            $info .= $lang['error_delete_bookmarks'];
        } else {
            $core->del_data('bookmarks', 'id = "' . $bookmark['id'] . '" and module = "' . $mod . '"');
            $info .= $lang[$info_mod_del];
        }
    }
    $core->tpl->info($info);
}

function social_list(): string
{
    loadConfig('social');
    global $config, $social, $lang;
    $s_list = '';
    if ($social['vk_is'] == '1') $s_list .= '<a href="' . $config['url'] . '/auth.php?url=vk" title="' . $lang['vk'] . '" rel="nofollow" class="right-panel-soc1"><img src="media/social/Vk.png" alt="' . $lang['vk'] . '" width="32" height="32"><ul></ul></a>';
    if ($social['ok_is'] == '1') $s_list .= '<a href="' . $config['url'] . '/auth.php?url=odnoklassniki" title="' . $lang['ok'] . '"><img src="media/social/Odnoklassniki.png" alt="' . $lang['ok'] . '" width="32" height="32"></a>';
    if ($social['fb_is'] == '1') $s_list .= '<a href="' . $config['url'] . '/auth.php?url=facebook" title="' . $lang['facebook'] . '"><img src="media/social/Facebook.png" alt="' . $lang['facebook'] . '" width="32" height="32"></a>';
    if ($social['mm_is'] == '1') $s_list .= '<a href="' . $config['url'] . '/auth.php?url=mailru" title="' . $lang['mailru'] . '"><img src="media/social/Mailru.png" alt="' . $lang['mailru'] . '" width="32" height="32"></a>';
    if ($social['gg_is'] == '1') $s_list .= '<a href="' . $config['url'] . '/auth.php?url=google" title="' . $lang['google'] . '"><img src="media/social/Google.png" alt="' . $lang['google'] . '" width="32" height="32"></a>';
    if ($social['ya_is'] == '1') $s_list .= '<a href="' . $config['url'] . '/auth.php?url=yandex" title="' . $lang['yandex'] . '"><img src="media/social/Yandex.png" alt="' . $lang['yandex'] . '" width="32" height="32"></a>';
    return $s_list;
}

function social_list_admin()
{
    loadConfig('social');
    global $config, $social, $lang;
    $s_list = '';
    if ($social['vk_is'] == '1') $s_list .= '<div class="col-sm-4"><a href="' . $config['url'] . '/auth.php?url=vk" class="button btn-social vk span-left mr5 btn-block">' . faSpan('fa-vk', 'fa1/lg', $lang['vk']) . '</a></div>';
    if ($social['fb_is'] == '1') $s_list .= '<div class="col-sm-4"><a href="' . $config['url'] . '/auth.php?url=facebook" class="button btn-social facebook span-left mr5 btn-block">' . faSpan('fa-facebook', 'fa1/lg', $lang['facebook']) . '</a></div>';
    if ($social['gg_is'] == '1') $s_list .= '<div class="col-sm-4"><a href="' . $config['url'] . '/auth.php?url=google" class="button btn-social googleplus span-left btn-block">' . faSpan('fa-google-plus', 'fa1/lg', $lang['google']) . '</a></div>';
    if ($social['ya_is'] == '1') $s_list .= '<div class="col-sm-4"><a href="' . $config['url'] . '/auth.php?url=yandex" class="button btn-social yandex span-left mr5 btn-block">' . faSpan('fa-yahoo', 'fa1/lg', $lang['yandex']) . '</a></div>';
    if ($social['ok_is'] == '1') $s_list .= '<div class="col-sm-4"><a href="' . $config['url'] . '/auth.php?url=odnoklassniki" class="button btn-social ok span-left mr5 btn-block">' . faSpan('fa-odnoklassniki', 'fa1/lg', $lang['ok']) . '</a></div>';
    if ($social['mm_is'] == '1') $s_list .= '<div class="col-sm-4"><a href="' . $config['url'] . '/auth.php?url=mailru" class="button btn-social mail span-left mr5 btn-block">' . faSpan('fa-envelope-o', 'fa1/lg', $lang['mailru']) . '</a></div>';
    return $s_list;
}

function filter($text, $type = false)
{
    global $core, $security;
    require_once(ROOT . 'etc/security.config.php');
    $allowArr = explode(',', $security['allowHTML']);
    $allowHTML = '<' . implode('>,<', $allowArr) . '>';
    $stopWords = explode(',', $security['stopWords']);
    foreach ($stopWords as $word) {
        $wordReplace[$word] = $security['stopReplace'];
    }
    $text = str_replace(array('||men||', '||and||', '||bol||'), array('<', '&', '>'), $text);
    $text = str_replace(array_keys($wordReplace), array_values($wordReplace), $text);
    switch ($type) {
        case 'title':
            $text = htmlspecialchars(strval(htmlspecialchars_decode($text)), ENT_QUOTES);
            break;
        case 'int':
            $text = intval($text);
            break;
        case 'str':
            $text = strval($text);
            break;
        case 'mail':
            $text = preg_match("/^[A-Z0-9_.-]+@([A-Z0-9][A-Z0-9-]+.)+[A-Z]{2,6}$/iu", $text) ? mb_strtolower($text) : '';
            break;
        case 'nick':
        case 'url':
            $text = if_sets("'[^A-ZА-Яa-zа-я0-9_ -.,\[\]\)\(-\@!?\$&*~]'ius", $text, "");
            break;
        case 'html':
            $text = preg_replace(array_keys($core->deniedHTML), array_values($core->deniedHTML), strval($text));
            break;
        case 'module':
        case 'a':
        case 'alphanum':
            $text = if_sets("'[^A-ZА-Яa-zа-я0-9_ -.,\[\]]'ius", $text, "");
            break;
        case 'no_html':
            $text = htmlspecialchars(strip_tags(urldecode(strval($text))));
            break;
        case 'provider':
            if (!($text == 'vk' || $text = 'yandex' || $text = 'mailru' || $text = 'google' || $text = 'facebook' || $text = 'odnoklassniki')) $text = '';
            break;
        case 'dir':
            $text = if_sets("'([^a-z0-9_/-]|[/]*$)'iu", $text, "");
            $text = if_sets("'[/]{2,}'", $text, "/");
            break;
        case 'ip':
            if (!preg_match("'[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'", $text)) $text = null;
            break;
        case 'reqUri':
            $text = eregStrt('index.php', $text) ? filter($text) : 'index.php';
            break;
        case 'forBB':
            $text = str_replace("\n", '<br/>', $text);
            break;
        case 'email':
            $text = filter_var($text, FILTER_VALIDATE_EMAIL);
            break;
        default:
            $text = htmlspecialchars(strval($text));
            break;
    }
    if ($type != 'template') $text = if_sets("/{%([^%]*)%}/i", $text, "&#123;%\\1%}");
    return $text;
}

/*
      * Ограничение групп для шаблонов
      * $group - группы для которых закрыть доступ через ,
      * $content - то что прячем
      */
function noGroup($matches): false|string
{
    global $core;
    $group = $matches[1];
    $content = $matches[2];
    $gr_array = explode(',', $group);
    return in_array($core->auth->group, $gr_array) ? false : stripslashes($content);
}

/*
      * Ограничение групп для шаблонов
      * $group - группы для которым показывать ,
      * $content - то что прячем
      */
function Group($matches): false|string
{
    global $core;
    $group = $matches[1];
    $content = $matches[2];
    $gr_array = explode(',', $group);
    return !in_array($core->auth->group, $gr_array) ? false : stripslashes($content);
}

/*
      * Условия для шаблонов и не только;)
      * $content - то что проверям
      * $data - то что выводим
      */
function if_set($content, $data): string
{
    return empty($content) ? '' : stripslashes($data);
}

function if_sets($rule, $data, $flag): array|string|null
{
    $GLOBALS["if_sets_flag"] = $flag;
    return preg_replace_callback($rule, function ($matches) use ($flag) {
        if (!empty($flag)) return $matches[1];
    }, trim((string)$data));
}

function checkUser($matches)
{
    global $core;
    if ($core->auth->isUser) return stripslashes($matches[1]);
}

/**
 * @param $matches
 * @return string|void
 */
function checkUprof($matches)
{
    global $db, $core, $url;
    if (isset($url[1]) && isset($core->auth->user_info['nick']) && $core->auth->user_info['nick'] !== $url[1]) {
        $wher = is_numeric($url[1]) ? 'id' : 'nick';
        $rows = $core->row_data('users', 'u.' . $wher . ' = "' . $db->safesql($url[1]) . '" AND u.active=1', false, 'u.*, g.name as gname, g.user as isUser, g.moderator as isModer, g.admin as isAdmin, g.showAttach, g.showHide, g.loadAttach, g.addPost, g.addComment, g.allowRating, g.maxWidth, g.maxPms, g.control, g.color, g.icon', 'as u LEFT JOIN ' . DB_PREFIX . '_groups as g ON(u.group = g.id)');
        $nick = is_array($rows) ? $rows['nick'] : '';
    } else {
        if ($core->auth->isUser) {
            $nick = $core->auth->user_info['nick'];
            $rows = $core->auth->user_info;
        }
    }
    return $_SERVER['QUERY_STRING'] == 'url=profile/' . $nick ? '' : stripslashes($matches[1]);
}

function checkUnprof($matches): string
{
    global $db, $core, $url;
    $not_res = array('register', 'forgot_pass', 'login', 'activate');
    if (isset($url[1]) && $core->auth->user_info['nick'] !== $url[1] && !in_array($url[1], $not_res)) {
        $wher = is_numeric($url[1]) ? 'id' : 'nick';
        $rows = $core->row_data('users', 'u.' . $wher . ' = "' . $db->safesql($url[1]) . '" AND u.active=1', false, 'u.*, g.name as gname, g.user as isUser, g.moderator as isModer, g.admin as isAdmin, g.showAttach, g.showHide, g.loadAttach, g.addPost, g.addComment, g.allowRating, g.maxWidth, g.maxPms, g.control, g.color, g.icon', 'as u LEFT JOIN ' . DB_PREFIX . '_groups as g ON(u.group = g.id)');
        $nick = $rows['nick'];
    } else {
        if ($core->auth->isUser) {
            $nick = $core->auth->user_info['nick'];
            $rows = $core->auth->user_info;
        }
    }
    return $_SERVER['QUERY_STRING'] != 'url=profile/' . $nick ? '' : stripslashes($matches[1]);
}

function checkOutpro($matches): string
{
    return $_SERVER['QUERY_STRING'] == 'url=profile' || $_SERVER['QUERY_STRING'] == 'url=profile/register' || $_SERVER['QUERY_STRING'] == 'url=profile/password' || $_SERVER['QUERY_STRING'] == 'url=profile/login' || $_SERVER['QUERY_STRING'] == 'url=profile/register_social' || $_SERVER['QUERY_STRING'] == 'url=profile/login_social' || $_SERVER['QUERY_STRING'] == 'url=profile/edit' || $_SERVER['QUERY_STRING'] == 'url=profile/friends_list' || $_SERVER['QUERY_STRING'] == 'url=pm' || $_SERVER['QUERY_STRING'] == 'url=pm/write' || $_SERVER['QUERY_STRING'] == 'url=pm/list' || $_SERVER['QUERY_STRING'] == 'url=pm/main' || $_SERVER['QUERY_STRING'] == 'url=pm/view' || $_SERVER['QUERY_STRING'] == 'url=pm/sent_ok' ? '' : stripslashes($matches[1]);
}

function checkInpro($matches): string
{
    return $_SERVER['QUERY_STRING'] == 'url=profile' || $_SERVER['QUERY_STRING'] == 'url=profile/register' || $_SERVER['QUERY_STRING'] == 'url=profile/password' || $_SERVER['QUERY_STRING'] == 'url=profile/login' || $_SERVER['QUERY_STRING'] == 'url=profile/register_social' || $_SERVER['QUERY_STRING'] == 'url=profile/login_social' || $_SERVER['QUERY_STRING'] == 'url=profile/edit' || $_SERVER['QUERY_STRING'] == 'url=profile/friends_list' || $_SERVER['QUERY_STRING'] == 'url=pm' || $_SERVER['QUERY_STRING'] == 'url=pm/write' || $_SERVER['QUERY_STRING'] == 'url=pm/list' || $_SERVER['QUERY_STRING'] == 'url=pm/main' || $_SERVER['QUERY_STRING'] == 'url=pm/view' || $_SERVER['QUERY_STRING'] == 'url=pm/sent_ok' ? stripslashes($matches[1]) : '';
}

function is_404($url): bool
{
    $handle = curl_init($url);
    curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); /* Get the HTML or whatever is linked in $url. */
    $response = curl_exec($handle); /* Check for 404 (file not found). */
    $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
    curl_close($handle); /* If the document has loaded successfully without any redirection or error */
    return !($httpCode >= 200 && $httpCode < 300);
}

function checkAdmin($matches)
{
    global $core;
    if ($core->auth->isAdmin) return stripslashes($matches[1]);
}

function get_url_status($url, $status_link = false, $timeout = 10): void
{
    global $lang;
    $ch = curl_init($url);
    // set cURL options
    $opts = array(CURLOPT_RETURNTRANSFER => true, // do not output to browser
        CURLOPT_URL => $url,            // set URL
        CURLOPT_NOBODY => true,         // do a HEAD request only
        CURLOPT_TIMEOUT => $timeout);   // set timeout
    curl_setopt_array($ch, $opts);
    curl_exec($ch); // do it!
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); // find HTTP status
    curl_close($ch); // close handle
    //example checking
    $n = $status_link ? '' : 'n';
    $numArray = [100, 101, 102, 103, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 421, 422, 423, 424, 425, 426, 428, 429, 431, 449, 451, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 520, 521, 522, 523, 524, 525, 526];
    if (in_array($status, $numArray)) $status_links = $lang['i' . $n . '_' . $status];
    echo $status_links ?? colorSpan('red', $lang['error']);
}

function toggle($text): string
{
    return 'data-toggle="tooltip" data-original-title="' . $text . '"';
}

function colorSpan($color, $text): string
{
    return '<span style="color: ' . $color . '"; ">' . $text . '</span>';
}

function faSpan($icon, $lg = false, $text = false, $i = false, $toggle = false): string
{
    $lgs = ($lg || ($lg == 'fa/lg')) ? ' fa-lg' : (($lg == 'fa1/lg') ? ' fa-lg ' : '');
    $texts = $text == 'right' ? '' : ($text ? $text : '');
    $position = $text == 'right' ? ' position-right' : ' position-left';
    $position = $text ? $position : '';
    $is = $i ? '<i class="fa fa-bars position-left">' : '';
    $isn = $i ? '</i>' : '';
    $fa = ($lg == 'fa' || $lg == 'fa/lg') ? 'fa ' : (($lg == 'fa1' || $lg == 'fa1/lg') ? 'fa1 ' : 'fa ');
    $toggle = $toggle ? 'data-toggle="tooltip" data-original-title="' . $toggle . '"' : 'aria-hidden="true"';
    return $is . '<span class="' . $fa . $icon . $lgs . $position . '" ' . $toggle . '></span>' . $texts . $isn;
}

function faI($icon, $lg = false, $text = false, $fa = false, $toggle = false, $style = false, $dop = false): string
{
    $lgs = $lg ? ' fa-lg' : '';
    $texts = $text == 'right' ? '' : ($text ? $text : '');
    $position = $text == 'right' ? ' position-right' : ' position-left';
    $position = $text ? $position : '';
    $fa = $fa ? 'fa1 ' : 'fa ';
    $toggle = $toggle ? 'data-toggle="tooltip" data-original-title="' . $toggle . '"' : 'aria-hidden="true"';
    $dop = $dop ? $dop : '';
    $style = $style ? 'style="' . $style . '"' : '';
    return '<i class="' . $fa . $icon . $lgs . $position . '" ' . $dop . '&nbsp;' . $toggle . '&nbsp;' . $style . '>&nbsp;' . $texts . '</i>';
}

function checkGuest($matches)
{
    global $core;
    if (!$core->auth->isUser) return stripslashes($matches[1]);
}

function checkCaptcha($matches)
{
    global $security;
    if ($security['switch_cp'] == 1) return stripslashes($matches[1]);
}

function checkSocial($matches)
{
    global $social;
    if ($social['switch'] == 1) return stripslashes($matches[1]);
}

function checkAuth($matches)
{
    loadConfigBLOCK('auth');
    global $auth_conf;
    if ($auth_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkBoard($matches)
{
    loadConfigBLOCK('board');
    global $board_conf;
    if ($board_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkBookmarks($matches)
{
    loadConfigBLOCK('bookmarks');
    global $bookmarks_conf;
    if ($bookmarks_conf['on'] == 1) return stripslashes($matches[1]);
}

function getBrowser(): array
{
    $u_agent = $_SERVER['HTTP_USER_AGENT'];
    $bname = 'Unknown';
    $platform = 'Unknown';
    //First get the platform?
    if (preg_match('/linux/i', $u_agent)) {
        $platform = 'linux';
    } elseif (preg_match('/macintosh|mac os x/i', $u_agent)) {
        $platform = 'mac';
    } elseif (preg_match('/windows|win32/i', $u_agent)) {
        $platform = 'windows';
    }
    // Next get the name of the useragent yes seperately and for good reason
    if (preg_match('/MSIE/i', $u_agent) && !preg_match('/Opera/i', $u_agent)) {
        $bname = 'Internet Explorer';
        $ub = "MSIE";
    } elseif (preg_match('/Firefox/i', $u_agent)) {
        $bname = 'Mozilla Firefox';
        $ub = "Firefox";
    } elseif (preg_match('/YaBrowser/i', $u_agent)) {
        $bname = 'Yandex';
        $ub = "YaBrowser";
    } elseif (preg_match('/Chrome/i', $u_agent)) {
        $bname = 'Google Chrome';
        $ub = "Chrome";
    } elseif (preg_match('/Safari/i', $u_agent)) {
        $bname = 'Apple Safari';
        $ub = "Safari";
    } elseif (preg_match('/Opera/i', $u_agent)) {
        $bname = 'Opera';
        $ub = "Opera";
    } elseif (preg_match('/Netscape/i', $u_agent)) {
        $bname = 'Netscape';
        $ub = "Netscape";
    }
    // finally get the correct version number
    $known = array('Version', $ub, 'other');
    $pattern = '#(?<browser>' . join('|', $known) . ')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
    if (!preg_match_all($pattern, $u_agent, $matches))  // we have no matching number just continue
        // see how many we have
        $i = count_($matches['browser']);
    $version = isset($i) && $i != 1 ? (strripos($u_agent, "Version") < strripos($u_agent, $ub) ? $matches['version'][0] : $matches['version'][1]) : $matches['version'][0];
    // check if we have a number
    if ($version == null || $version == "") $version = "?";
    return array(
        'userAgent' => $u_agent,
        'name' => $bname,
        'version' => $version,
        'platform' => $platform,
        'pattern' => $pattern
    );
}

function checkCalendar($matches)
{
    loadConfigBLOCK('calendar');
    global $calendar_conf;
    if ($calendar_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkCats($matches)
{
    loadConfigBLOCK('cats');
    global $cats_conf;
    if ($cats_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkFriends($matches)
{
    loadConfigBLOCK('friends');
    global $friends_conf;
    if ($friends_conf['on'] == 1) return stripslashes($matches[1]);
}


function checkGuestbook($matches)
{
    loadConfigBLOCK('guest');
    global $guest_conf;
    if ($guest_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkLastcom($matches)
{
    loadConfigBLOCK('lastcom');
    global $lastcom_conf;
    if ($lastcom_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkOnline($matches)
{
    loadConfigBLOCK('online');
    global $online_conf;
    if ($online_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkOnlinfriends($matches)
{
    loadConfigBLOCK('onlinfriends');
    global $onlinfriends_conf;
    if ($onlinfriends_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkPoll($matches)
{
    loadConfigBLOCK('poll');
    global $poll_conf;
    if ($poll_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkQuestion($matches)
{
    loadConfigBLOCK('question');
    global $question_conf;
    if ($question_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkSearch($matches)
{
    loadConfigBLOCK('search');
    global $search_conf;
    if ($search_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkRSS($matches)
{
    loadConfigBLOCK('rss');
    global $core, $rss_conf;
    list($rss) = $core->fetch_data('feed', 'active = 1');
    if ($rss > 0 || $rss_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkStatistics($matches)
{
    loadConfigBLOCK('statistics');
    global $statistics_conf;
    if ($statistics_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkSystem($matches)
{
    loadConfigBLOCK('system');
    global $system_conf;
    if ($system_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkTags($matches)
{
    loadConfigBLOCK('tags');
    global $tags_conf;
    if ($tags_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkThemes($matches)
{
    loadConfigBLOCK('themes');
    global $themes_conf;
    if ($themes_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkTopnews($matches)
{
    loadConfigBLOCK('topnews');
    global $topnews_conf;
    if ($topnews_conf['on'] == 1) return stripslashes($matches[1]);
}

function checkReCaptcha($matches)
{
    global $security;
    $is = $matches[1];
    $content = $matches[2];
    if ($is > 0) {
        if ($security['recaptcha'] == 1) return stripslashes($content);
    } else {
        if ($security['recaptcha'] == 0) return stripslashes($content);
    }
}

/*
      * Генерация ссылок для страничной навы
      * $link - ссылка модуля
      * $content - то что выводим
      * $type - номер страницы
      */
function pageLink($link, $content, $type, $onClick, $title): string
{
    return '<a href = "' . str_replace('{page}', 'page/' . $type, $link) . '" title = "' . $title . '" ' . (isset($onClick) ? str_replace('{num}', $type, $onClick) : '') . '><b>' . $content . '</b></a>';
}

/*
      * Форматинг ссылки для новости
      * $title - имя ссылки
      * $format - адресс сылки
      */
function format_link($title, $format): string
{
    return "<a href=\"" . $format . "\" title=\"{%TITLE%}\">" . stripslashes($title) . "</a>";
}

function truncate_words($text, $limit): string
{
    $text = mb_substr($text, 0, $limit);
    if (mb_substr($text, mb_strlen($text) - 1, 1) && mb_strlen($text) == $limit) {
        $textret = mb_substr($text, 0, mb_strlen($text) - mb_strlen(strrchr($text, ' ')));
        if (!empty($textret)) return $textret;
    }
    if (strlen($text) > $limit) $text = mb_substr($text, 0, $limit);
    return $text;
}

function short($count, $text): string
{
    $text = strip_tags($text);
    $text_f = $text;
    if (strlen($text) > $count) {
        $text = truncate_words($text, $count);
        if ($text_f != $text) $text = $text . '...';
    }
    return $text;
}

/*
      * Показывать только на главной или везде кроме главной? :)
      * $is - true или false отображать ТОЛЬКО на главной или КРОМЕ главной)
      * $content - контент
      */
function indexShow($matches)
{
    global $url;
    $is = intval($matches[1]);
    $content = $matches[2];
    if ($is > 0) {
        if (defined('INDEX_NOW')) return stripslashes($content);
    } else {
        if (!defined('INDEX_NOW')) return stripslashes($content);
    }
}

function getMounth($time): string
{
    if (date('M', $time) == 'Jan') $month = '.01';
    if (date('M', $time) == 'Feb') $month = '.02';
    if (date('M', $time) == 'Mar') $month = '.03';
    if (date('M', $time) == 'Apr') $month = '.04';
    if (date('M', $time) == 'May') $month = '.05';
    if (date('M', $time) == 'Jun') $month = '.06';
    if (date('M', $time) == 'Jul') $month = '.07';
    if (date('M', $time) == 'Aug') $month = '.08';
    if (date('M', $time) == 'Sep') $month = '.09';
    if (date('M', $time) == 'Oct') $month = '.10';
    if (date('M', $time) == 'Nov') $month = '.11';
    if (date('M', $time) == 'Dec') $month = '.12';
    return $month;
}

function getWeek($time)
{
    $wday = '';
    if (date('D', $time) == 'Wed') $wday = JText::_('SREDA');
    if (date('D', $time) == 'Mon') $wday = JText::_('PON');
    if (date('D', $time) == 'Sun') $wday = JText::_('BOS');
    if (date('D', $time) == 'Tue') $wday = JText::_('VTOR');
    if (date('D', $time) == 'Fri') $wday = JText::_('PYAT');
    if (date('D', $time) == 'Sat') $wday = JText::_('SUBB');
    if (date('D', $time) == 'Thu') $wday = JText::_('CHET');
    return $wday;
}

function readBlog($nick)
{
    global $db, $user, $core, $lang;
    if ($user['readBlog'] == 1) {
        $query = $core->select_data('blogs', 'readers LIKE "%,' . $db->safesql($nick) . ',%"', false, 'title, altname');
        if ($db->numRows($query) > 0) {
            $blogs = '';
            while ($blog = $db->getRow($query)) {
                $blogs .= '<span class="_bloglist"><a href = "blog/view/' . $blog['altname'] . '" title = "' . $lang['carma_action'] . '">' . $blog['title'] . '</a></span>';
            }
            return $blogs;
        }
    }
}

function getUserGuests($uid): string
{
    global $db, $user, $core, $lang;
    $guests = '';
    if ($user['userGuests'] == 1) {
        $gq = $core->select_data('users', 'g . id = "' . $uid . '"', 'g . time DESC', 'u . id as uuid, u . nick, u . last_visit, g .*', 'as u LEFT JOIN ' . DB_PREFIX . '_user_visitors as g on(u . id = g . visitor)');
        if ($db->numRows($gq) > 0) {
            $guests .= '<span class="_userfriends">';
            while ($frows = $db->getRow($gq)) {
                $guests .= '<a href = "profile/' . $frows['nick'] . '" title = "' . $lang['guest_page'] . '">' . $frows['nick'] . '</a>, ';
            }
            $guests .= '</span>';
        }
    }
    return $guests;
}

function TimeZoneList($userInfo): string
{
    global $lang;
    $langs = array(null, $lang['Pacific/Kwajalein'], $lang['Pacific/Samoa'], $lang['US/Hawaii'], $lang['US/Alaska'], $lang['Canada/Pacific'], $lang['Canada/Mountain'], $lang['Canada/Central'], $lang['Canada/Eastern'], $lang['Canada/Atlantic'], $lang['Canada/Newfoundland'], $lang['Brazil/East'], $lang['Atlantic/Bermuda'], $lang['Atlantic/Azores'], $lang['Europe/London'], $lang['Europe/Paris'], $lang['Europe/Kaliningrad'], $lang['Europe/Moscow'], $lang['Asia/Tehran'], $lang['Asia/Baku'], $lang['Asia/Kabul'], $lang['Asia/Karachi'], $lang['Asia/Calcutta'], $lang['Asia/Almaty'], $lang['Asia/Bangkok'], $lang['Asia/Hong_Kong'], $lang['Asia/Yakutsk'], $lang['Australia/Darwin'], $lang['Asia/Vladivostok'], $lang['Asia/Magadan'], $lang['Asia/Kamchatka']);
    $timezones = '<option value = ""> --</option>';
    for ($i = 1; $i < 31; $i++) {
        $timezones .= '<option value = "' . $langs[$i] . '"' . ($userInfo == $langs[$i] ? ' selected' : '') . '>' . $langs[$i] . '</option>';
    }
    return $timezones ?: '';
}

function Twofactor($userInfo): string
{
    global $lang;
    $twofactor = '';
    $langs = array($lang['twofactor_off'], $lang['twofactor_email_pin'], $lang['twofactor_GA_pin']);
    $twofactors = $userInfo ? explode(' . ', $userInfo) : explode(' . ', '0.0.0');
    for ($i = 0; $i < 3; $i++) {
        $twofactor .= '<option value = "' . $i . '"' . ($twofactors[0] == $i ? ' selected' : '') . '>' . $langs[$i] . '</option>';
    }
    return $twofactor ?: '';
}

function Gender($userInfo): string
{
    global $lang;
    $langs = array(null, $lang['female'], $lang['male']);
    $genders = $userInfo ? explode(' . ', $userInfo) : explode(' . ', '0.0.0');
    $gender = '<option value = ""> --</option>';
    for ($i = 1; $i < 3; $i++) {
        $gender .= '<option value = "' . $i . '"' . ($genders[0] == $i ? ' selected' : '') . '>' . $langs[$i] . '</option>';
    }
    return $gender ?: '';
}

function Gender_stat($userInfo)
{
    global $lang;
    return ($userInfo ? ($userInfo == 1) ? $lang['female'] : $lang['male'] : $lang['unspecified']) ?: '';
}

function Groups($userInfo): string
{
    global $core, $db;
    $gInfo = '';
    $_groups = array();
    $query = $core->select_data('groups', false, 'admin DESC,moderator DESC,user DESC,guest DESC,banned DESC');
    while ($rows = $db->getRow($query)) {
        $_groups[$rows['special']][] = $rows;
    }
    foreach ($_groups[0] as $r) {
        $selected = ($r['id'] == $userInfo) ? "selected" : "";
        $gInfo .= '<option value="' . $r['id'] . '"' . $selected . '>' . Glang($r['name']) . '</option>';
    }
    return $gInfo ?: '';
}

function Gexgroup($userInfo): string
{
    global $core, $db;
    $gInfo = '';
    $_groups = array();
    $query = $core->select_data('groups', false, 'admin DESC,moderator DESC,user DESC,guest DESC,banned DESC');
    while ($rows = $db->getRow($query)) {
        $_groups[$rows['special']][] = $rows;
    }
    $_groups[1] = $_groups[1] ?? false;
    if (is_array($_groups[1]) || is_object($_groups[1])) {
        foreach ($_groups[1] as $g) {
            $selected2 = ($g['id'] == $userInfo) ? "selected" : "";
            $gInfo .= '<option value="' . $g['id'] . '"' . $selected2 . '>' . Glang($g['name']) . '</option>';
        }
    }
    return $gInfo ?: '';
}


function Bday_visibility($userInfo): string
{
    global $lang;
    $langs = array($lang['not_show_date_birth'], $lang['show_date_birth'], $lang['show_date_birth_d_m']);
    $visibility = $userInfo ? explode(' . ', $userInfo) : explode(' . ', '0.0.0');
    $bday_visibility = '';
    for ($i = 0; $i < 3; $i++) {
        $bday_visibility .= '<option value = "' . $i . '"' . ($visibility[0] == $i ? ' selected' : '') . '>' . $langs[$i] . '</option>';
    }
    return $bday_visibility ?: '';
}

function Bday($userInfo): string
{
    $birthday = $userInfo ? explode(' . ', $userInfo) : explode(' . ', '0.0.0');
    $day = '<option value = ""> --</option>';
    for ($i = 1; $i < 32; $i++) {
        $day .= '<option value = "' . ($i < 10 ? '0' . $i : $i) . '"' . ($birthday[0] == $i ? ' selected' : '') . '>' . $i . '</option>';
    }
    return $day ?: '';
}

function Bmonth($userInfo): string
{
    global $lang;
    $langs = array(null, $lang['januarys'], $lang['februarys'], $lang['marchs'], $lang['aprils'], $lang['mays'], $lang['junes'], $lang['julys'], $lang['augusts'], $lang['septembers'], $lang['octobers'], $lang['novembers'], $lang['decembers']);
    $birthday = $userInfo ? explode(' . ', $userInfo) : explode(' . ', '0.0.0');
    $month = '<option value = "">--</option>';
    for ($i = 1; $i < 13; $i++) {
        $month .= '<option value = "' . $i . '"' . ($birthday[0] == $i ? ' selected' : '') . '>' . $langs[$i] . '</option>';
    }
    return $month ?: '';
}

function Byear($userInfo): string
{
    $i = 0;
    $birthday = $userInfo ? explode(' . ', $userInfo) : explode(' . ', '0.0.0');
    $year = '<option value = ""> ---</option>';
    for ($i = 2024; $i > 1935; $i--) {
        $year .= '<option value = "' . $i . '"' . ($birthday[0] == $i ? ' selected' : '') . '>' . $i . '</option>';
    }
    return $year ?: '';
}

function select_numbs($numb, $name, $nmin = '1', $nmax = '10'): string
{
    $numbs = '<select id = "' . $name . '" name = "' . $name . '" class="form-control">
              <option value = "0">0</option>';
    for ($i = $nmin; $i < $nmax; $i++) {
        $numbs .= '<option value = "' . $i . '"' . ($numb == $i ? ' selected' : '') . '>' . $i . '</option>';
    }
    $numbs .= '</select>';
    return $numbs;
}

function con_month($month)
{
    global $lang;
    $langs = array(null, $lang['januarys'], $lang['februarys'], $lang['marchs'], $lang['aprils'], $lang['mays'], $lang['junes'], $lang['julys'], $lang['augusts'], $lang['septembers'], $lang['octobers'], $lang['novembers'], $lang['decembers']);
    foreach ($langs as $key => $value) {
        if ($key == intval($month)) $month = $value;
    }
    return $month ?: '';
}

function carmaInit($uid, $uname): void
{
    global $core, $lang;
    require_once(ROOT . 'usr/plugins/modal_box/init.php');
    if (!$core->auth->isUser) {
        $content = '<div class="mbmest">' . $lang['carma_edit_for_reg'] . '</div>';
    } elseif ($uid == $core->auth->user_info['id']) {
        $content = '<div class="mbmest">' . $lang['carma_not_for_change'] . '</div>';
    } elseif (isset($_COOKIE['carma - ' . $uid])) {
        $content = '<div class="mbmest">' . $lang['carma_already_change'] . '</div>';
    } else {
        $content = '<table style="width=:100%; border: 0; border-spacing: 1px; border-collapse: separate;"><tr><td style = "width:30%; vertical-align: top;">' . $lang['carma_action'] . '</td><td><select class="date_selection" id = "carmaDo" style ="width:90%;"><option value = "p">' . $lang['carma_raise_reputation'] . '</option><option value = "m">' . $lang['carma_omit_reputation'] . '</option><option value = "n">' . $lang['carma_neutral'] . '</option></select></td></tr><tr><td><br/></td></tr><tr><td style="vertical-align: top;">' . $lang['carma_pm_user'] . '</td><td><textarea id = "carmaText" name = "textarea" style ="width:90%;" rows = "4"></textarea><br /><sup>' . $lang['carma_max_characters'] . '</sup></td></tr><tr><td>&nbsp;</td><td><input type = "button" value = "' . $lang['send'] . '" class="form-button-tt" onclick = "addCarma(\'' . $uid . '\', \'carma\')" /></td></tr></table>';
    }
    modal_box('<div style = "text-align: center;">' . $lang['carma_edit_user'] . '</div>', $lang['carma_select_action'] . ' "<b>' . $uname . '</b>"', $content, 'carma');
    $core->tpl->headerIncludes[] = '<script>function carmaHistory(){
    modal_box(\'carmaHistory\'); AJAXEngine.showedLoadBar = \'\'; AJAXEngine.sendRequest(\'ajax.php?do=carmaHistory&uid=' . $uid . '\', \'carmaHistory\'); }</script>';
    modal_box($lang['carma_history_user'], $lang['carma_view_history_user'] . ' "<b>' . $uname . '</b>"', '<div id="carmaHistory"><div class="mbmest">' . $lang['carma_upload_info_history_user'] . '</div></div>', 'carmaHistory');
}

function weekday($capital = false): void
{
    //День недели цифрой за нужную дату:
    $day = date('w', mktime(0, 0, 0, 9, 1, 2010));
    //Массив дней недели:
    $week = $capital ? ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'] : ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'];
    //День недели словом:
    echo $week[$day];
}

/*
      * Показывать контент только в определённых моудлях
      * $modules - модули в которых показывать через ,(запятую)
      * $content - контент
      */
function modulesShow($matches)
{
    global $url;
    $modulesArray = explode(',', $matches[1]);
    $tag = $matches[2];
    $content = $matches[3];
    if (in_array($url[0], $modulesArray)) {
        if ($tag == 1) return stripslashes($content);
    } else {
        if ($tag == 0) return stripslashes($content);
    }
}

function categoryShow($matches)
{
    global $core, $url;
    $categoryArray = explode(',', $matches[1]);
    $tag = $matches[2];
    $content = $matches[3];
    if ($url[0] == 'news' || $url[0] == 'content') {
        $row = $core->row_data('categories', 'altname="' . $url[1] . '"');
        $id_now = $row['id'];
        if (in_array($id_now, $categoryArray)) {
            if ($tag == 1) return stripslashes($content);
        } else {
            if ($tag == 0) return stripslashes($content);
        }
    }
}

function newsShow()
{
    global $core, $url, $matches;
    $newsArray = explode(',', $matches[1]);
    $tag = $matches[2];
    $content = $matches[3];
    if ($url[0] == 'news') {
        $altname = eregStrt('.html', $url[1]) ? $url[1] : $url[2];
        $altname = str_replace(".html", "", $altname);
        $row = $core->row_data('news', 'altname="' . $altname . '"');
        $id_now = $row['id'];
        if (in_array($id_now, $newsArray)) {
            if ($tag == 1) return stripslashes($content);
        } else {
            if ($tag == 0) return stripslashes($content);
        }
    }
}

function contentShow($matches)
{
    global $core, $url;
    $newsArray = explode(',', $matches[1]);
    $tag = $matches[2];
    $content = $matches[3];
    if ($url[0] == 'content') {
        $altname = eregStrt('.html', $url[1]) ? $url[1] : $url[2];
        $altname = str_replace(".html", "", $altname);
        $row = $core->row_data('content', 'translate="' . $altname . '"');
        $id_now = $row['id'];
        if (in_array($id_now, $newsArray)) {
            if ($tag == 1) return stripslashes($content);
        } else {
            if ($tag == 0) return stripslashes($content);
        }
    }
}

function addnewsShow($matches)
{
    global $url;
    $is = intval($matches[1]);
    $content = $matches[2];
    if ($is > 0) {
        if (($url[1] == 'addPost') || ($url[1] == 'savePost')) return stripslashes($content);
    } else {
        if (($url[1] != 'addPost') && ($url[1] != 'savePost')) return stripslashes($content);
    }
}

function fullnewsShow($matches)
{
    global $url;
    $is = intval($matches[1]);
    $content = $matches[2];
    if ($is > 0) {
        if (eregStrt('.html', $url[1]) || eregStrt('.html', $url[2])) return stripslashes($content);
    } else {
        if (!(eregStrt('.html', $url[1]) || eregStrt('.html', $url[2]))) return stripslashes($content);
    }
}

function errorLocation($cat_one, $url_link, $actual_link): void
{
    global $url;
    $altname = eregStrt('.html', $url[1]) ? $url[1] : '';
    $altname = str_replace(".html", "", $altname);
    if (isset($url[1]) && $url[1] == $cat_one || $altname) {
        if ($url_link == $actual_link || $altname) $location = true;
    } else {
        $location = false;
        @header("HTTP/1.0 404 Not Found");
        location('404.php');
    }
}

function buildCustom($matches)
{
    $custom = false;
    $category = filter($matches[1], 'a');
    $template = filter($matches[2], 'a');
    $aviable = filter($matches[3], 'a');
    $limit = intval($matches[4]);
    $module = filter($matches[5], 'module');
    $order = filter($matches[6], 'a');
    $short = filter($matches[7], 'a');
    $notin = false;
    if (isset($matches[7])) $notin = $matches[7];
    if (!empty($category) && !empty($template) && !empty($aviable) && ($limit > 0) && !empty($module) && file_exists(ROOT . 'usr/modules/' . $module . '/custom.php')) {
        if ($aviable == 'all' || (modulesShow($aviable, 1, 'on') == 'on')) {
            require(ROOT . 'usr/modules/' . $module . '/custom.php');
            return $custom;
        }
    }
}

function _getCustomImg($html): array|string
{
    preg_match_all('#<img[^>]+src=[\'"]([^\s>]*)[\'"][^>]*>#i', $html, $images, PREG_SET_ORDER);
    return in_array($html, $images) ? $images[1] : '';
}

function Uploads_files($path, $input_name): void
{
    $path = ROOT . $path;
// Разрешенные расширения файлов.
    $allow = array();
// Запрещенные расширения файлов.
    $deny = array(
        'phtml', 'php', 'php3', 'php4', 'php5', 'php6', 'php7', 'php8', 'phps', 'cgi', 'pl', 'asp',
        'aspx', 'shtml', 'shtm', 'htaccess', 'htpasswd', 'ini', 'log', 'sh', 'js', 'html',
        'htm', 'css', 'sql', 'spl', 'scgi', 'fcgi'
    );
// Директория куда будут загружаться файлы.
    if (isset($_FILES[$input_name])) {
        // Проверим директорию для загрузки.
        if (!is_dir($path)) mkdir($path, 0777, true);
        // Преобразуем массив $_FILES в удобный вид для перебора в foreach.
        $files = array();
        $diff = count_($_FILES[$input_name]) - count_($_FILES[$input_name], COUNT_RECURSIVE);
        if ($diff == 0) {
            $files = array($_FILES[$input_name]);
        } else {
            foreach ($_FILES[$input_name] as $k => $l) {
                foreach ($l as $i => $v) {
                    $files[$i][$k] = $v;
                }
            }
        }
        foreach ($files as $file) {
            // Проверим на ошибки загрузки.
            if (!empty($file['error']) || empty($file['tmp_name'])) {
                $alert = match (@$file['error']) {
                    1, 2 => colorSpan('red', 'Превышен размер загружаемого файла.'),
                    3 => colorSpan('red', 'Файл был получен только частично.'),
                    4 => colorSpan('red', 'Файл не был загружен.'),
                    6 => colorSpan('red', 'Файл не загружен - отсутствует временная директория.'),
                    7 => colorSpan('red', 'Не удалось записать файл на диск.'),
                    8 => colorSpan('red', 'PHP-расширение остановило загрузку файла.'),
                    9 => colorSpan('red', 'Файл не был загружен - директория не существует.'),
                    10 => colorSpan('red', 'Превышен максимально допустимый размер файла.'),
                    11 => colorSpan('red', 'Данный тип файла запрещен.'),
                    12 => colorSpan('red', 'Ошибка при копировании файла.'),
                    default => colorSpan('red', 'Файл не был загружен - неизвестная ошибка.'),
                };
            } elseif ($file['tmp_name'] == 'none' || !is_uploaded_file($file['tmp_name'])) {
                $alert = colorSpan('red', 'Не удалось загрузить файл.');
            } else {
                // Оставляем в имени файла только буквы, цифры и некоторые символы.
                $pattern = "[^a-zа-яё0-9,~!@#%^-_\$\?\(\)\{\}\[\]\.]";
                $name = mb_eregi_replace($pattern, '-', $file['name']);
                $name = mb_ereg_replace('[-]+', '-', $name);
                // Т.к. есть проблема с кириллицей в названиях файлов (файлы становятся недоступны).
                // Сделаем их транслит:
                $converter = array(
                    'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e',
                    'ё' => 'e', 'ж' => 'zh', 'з' => 'z', 'и' => 'i', 'й' => 'y', 'к' => 'k',
                    'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r',
                    'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c',
                    'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sch', 'ь' => '', 'ы' => 'y', 'ъ' => '',
                    'э' => 'e', 'ю' => 'yu', 'я' => 'ya',
                    'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E',
                    'Ё' => 'E', 'Ж' => 'Zh', 'З' => 'Z', 'И' => 'I', 'Й' => 'Y', 'К' => 'K',
                    'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O', 'П' => 'P', 'Р' => 'R',
                    'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C',
                    'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sch', 'Ь' => '', 'Ы' => 'Y', 'Ъ' => '',
                    'Э' => 'E', 'Ю' => 'Yu', 'Я' => 'Ya',
                );
                $name = strtr($name, $converter);
                $parts = pathinfo($name);
                if (empty($name) || empty($parts['extension'])) {
                    $alert = colorSpan('red', 'Недопустимое тип файла');
                } elseif (!empty($allow) && !in_array(strtolower($parts['extension']), $allow)) {
                    $alert = colorSpan('red', 'Недопустимый тип файла');
                } elseif (!empty($deny) && in_array(strtolower($parts['extension']), $deny)) {
                    $alert = colorSpan('red', 'Недопустимый тип файла');
                } else {
                    // Чтобы не затереть файл с таким же названием, добавим префикс.
                    $i = 0;
                    $prefix = '';
                    while (is_file($path . $parts['filename'] . $prefix . '.' . $parts['extension'])) {
                        $prefix = '(' . ++$i . ')';
                    }
                    $name = $parts['filename'] . $prefix . '.' . $parts['extension'];
                    // Перемещаем файл в директорию.
                    $alert = move_uploaded_file($file['tmp_name'], $path . $name) ? colorSpan('green', 'Файл «' . $name . '» успешно загружен.') : colorSpan('red', 'Не удалось загрузить файл.');
                }
            }
            // Выводим сообщение о результате загрузки.
            echo $alert;
        }
    }
}

function chooseModuleMenu($type = '', $mode = '')
{
    global $url;
    $typeArray = explode(',', $type);
    $modeArray = explode(',', $mode);
    $ccount = 1;
    if (!empty($url[1])) {
        if ($url[1] == 'module') $ccount = 2;
        if (in_array($url[$ccount], $modeArray)) {
            $ccount = 3;
            if (($type == '') && (empty($url[3]))) {
                return 'class="active"';
            } elseif (!empty($url[3])) {
                if (in_array($url[$ccount], $typeArray)) return 'class="active"';
            }
        }
    }
}

function activeModule($matches)
{
    global $core;
    $name = $matches[1];
    $content = $matches[2];
    if ($core->checkModule($name) == '1') return stripslashes($content);
}

function clearText($text): array|string|null
{
    $strip = "<strong>,<em>,<span style=\"text-decoration: underline;\">,<b>,<li>,<ul>,<ol>,<p>,<img>";
    $text = strip_tags($text, $strip);
    preg_match_all("#<([A-z]+)\s(.*?)[/]{0,1}>#", $text, $result);
    foreach ($result[0] as $key => $value) {
        $tag = $result[1][$key];
        $attr = $result[2][$key];
        preg_match('#src="[A-z0-9_\.\/-]*"#', $attr, $src);
        preg_match('#width="[0-9]+"#', $attr, $width);
        preg_match('#height="[0-9]+"#', $attr, $height);
        preg_match('#style="[A-z-]+:[\s]{0,1}[A-z0-9-]+[;]{0,1}"#', $attr, $style);
        $width = (empty($width[0])) ? '' : $width[0] . ' ';
        $height = (empty($height)) ? '' : $height[0] . ' ';
        $style = (empty($style[0])) ? '' : $style[0] . ' ';
        $src = (empty($src[0])) ? '' : $src[0] . ' ';
        $img = '<' . $tag . '&nbsp;' . $src . $width . $height . $style . (($tag == 'img') ? '/' : '') . '>';
        $text = str_replace($value, $img, $text);
        $text = preg_replace("#<([A-z]+)\s.*?>#", "<\\1>", $text);
    }
    return $text;
}

/*
function clearTEXT($text)
{
    $search = array("'ё'", "'<script[^>]*?>.*?</script>'si", "'<[\/\!]*?[^<>]*?>'si", "'([\r\n])[\s]+'", "'&(quot|#34);'i", "'&(amp|#38);'i", "'&(lt|#60);'i", "'&(gt|#62);'i", "'&(nbsp|#160);'i", "'&(iexcl|#161);'i", "'&(cent|#162);'i", "'&(pound|#163);'i", "'&(copy|#169);'i", "'&#(\d+);'e");
    $replace = array("е", " ", " ", "\\1 ", "\" ", " ", " ", " ", " ", chr(161), chr(162), chr(163), chr(169), "chr(\\1)");
    // $text = preg_replace_callback($search, $replace, $text);
    //$text = ereg_replace("( +)", " ", $text);
    $text = strip_tags($text);
    $del_symbols = array(",", ".", ";", ":", "\"", "#", "\$", "%", "^", "!", "@", "`", "~", "*", "-", "=", "+", "\\", "|", "/", ">", "<", "(", ")", "&", "?", "¹", "\t", "\r", "\n", "{", "}", "[", "]", "'", "“", "”", "•");
    $text = str_replace($del_symbols, array(" "), $text);
    $text = mb_ereg_replace('[ ]+', ' ', $text);
    $text = trim($text);
    $text = htmlspecialchars($text, ENT_QUOTES);
    return $text;
}*/
function clear_js($txt)
{
    if (!$txt) return;
    $find = array('/data:/i', '/about:/i', '/vbscript:/i', '/onclick/i', '/onload/i', '/onunload/i', '/onabort/i', '/onerror/i', '/onblur/i', '/onchange/i', '/onfocus/i', '/onreset/i', '/onsubmit/i', '/ondblclick/i', '/onkeydown/i', '/onkeypress/i', '/onkeyup/i', '/onmousedown/i', '/onmouseup/i', '/onmouseover/i', '/onmouseout/i', '/onselect/i', '/javascript/i', '/onmouseenter/i', '/onwheel/i', '/onshow/i', '/onafterprint/i', '/onbeforeprint/i', '/onbeforeunload/i', '/onhashchange/i', '/onmessage/i', '/ononline/i', '/onoffline/i', '/onpagehide/i', '/onpageshow/i', '/onpopstate/i', '/onresize/i', '/onstorage/i', '/oncontextmenu/i', '/oninvalid/i', '/oninput/i', '/onsearch/i', '/ondrag/i', '/ondragend/i', '/ondragenter/i', '/ondragleave/i', '/ondragover/i', '/ondragstart/i', '/ondrop/i', '/onmousemove/i', '/onmousewheel/i', '/onscroll/i', '/oncopy/i', '/oncut/i', '/onpaste/i', '/oncanplay/i', '/oncanplaythrough/i', '/oncuechange/i', '/ondurationchange/i', '/onemptied/i', '/onended/i', '/onloadeddata/i', '/onloadedmetadata/i', '/onloadstart/i', '/onpause/i', '/onprogress/i', '/onratechange/i', '/onseeked/i', '/onseeking/i', '/onstalled/i', '/onsuspend/i', '/ontimeupdate/i', '/onvolumechange/i', '/onwaiting/i', '/ontoggle/i');
    $replace = array("d&#1072;ta:", "&#1072;bout:", "vbscript<b></b>:", "&#111;nclick", "&#111;nload", "&#111;nunload", "&#111;nabort", "&#111;nerror", "&#111;nblur", "&#111;nchange", "&#111;nfocus", "&#111;nreset", "&#111;nsubmit", "&#111;ndblclick", "&#111;nkeydown", "&#111;nkeypress", "&#111;nkeyup", "&#111;nmousedown", "&#111;nmouseup", "&#111;nmouseover", "&#111;nmouseout", "&#111;nselect", "j&#1072;vascript", '&#111;nmouseenter', '&#111;nwheel', '&#111;nshow', '&#111;nafterprint', '&#111;nbeforeprint', '&#111;nbeforeunload', '&#111;nhashchange', '&#111;nmessage', '&#111;nonline', '&#111;noffline', '&#111;npagehide', '&#111;npageshow', '&#111;npopstate', '&#111;nresize', '&#111;nstorage', '&#111;ncontextmenu', '&#111;ninvalid', '&#111;ninput', '&#111;nsearch', '&#111;ndrag', '&#111;ndragend', '&#111;ndragenter', '&#111;ndragleave', '&#111;ndragover', '&#111;ndragstart', '&#111;ndrop', '&#111;nmousemove', '&#111;nmousewheel', '&#111;nscroll', '&#111;ncopy', '&#111;ncut', '&#111;npaste', '&#111;ncanplay', '&#111;ncanplaythrough', '&#111;ncuechange', '&#111;ndurationchange', '&#111;nemptied', '&#111;nended', '&#111;nloadeddata', '&#111;nloadedmetadata', '&#111;nloadstart', '&#111;npause', '&#111;nprogress', '&#111;nratechange', '&#111;nseeked', '&#111;nseeking', '&#111;nstalled', '&#111;nsuspend', '&#111;ntimeupdate', '&#111;nvolumechange', '&#111;nwaiting', '&#111;ntoggle');
    $txt = preg_replace($find, $replace, $txt);
    $txt = preg_replace("#<iframe#i", "&lt;iframe", $txt);
    $txt = preg_replace("#<script#i", "&lt;script", $txt);
    $txt = str_replace("<?", "&lt;?", $txt);
    return str_replace("?>", "?&gt;", $txt);
}

function clicks_views($db, $id, $max_views, $views, $max_clicks, $clicks)
{
    global $core;
    $active = '';
    if ($max_views && $views >= $max_views) {
        $active = 4;
    } elseif ($max_clicks && $clicks >= $max_clicks) {
        $active = 3;
    } elseif ($max_clicks || $max_views) {
        $active = 1;
    } else {
        return $active;
    }
    return $core->upd_data($db, 'active = ' . $active, 'id = "' . $id . '"');
}

function start_end($db, $id, $startdate, $enddate, $active)
{
    global $core;
    if ($startdate > time() || $startdate > time() && $enddate < time() && $active) {
        $active = 2;
    } elseif ($startdate < time() && !$enddate && $active || $startdate < time() && $enddate > time() && $active) {
        $active = 1;
    } else {
        $active = 0;
    }
    return $core->upd_data($db, 'active = ' . $active, 'id = "' . $id . '"');
}

function getOneClicks($id, $module, $one, $add = '+'): void
{
    global $core;
    $bid = $module == 'banners_ips' ? 'bid' : 'id';
    $core->upd_data($module, $one . '=' . $one . $add . '1', $bid . ' = "' . $id . '"');
}

function ifFields($xfields, $id, $content): string
{
    $fields = int_Serialize('uns', $xfields);
    return empty($xfields) ? '' : (!empty($fields[$id][1]) ? stripslashes($content) : '');
}

function mailSMTP($email, $mail_text, $title, $message): void
{
    global $config;
    if (!empty($email)) {
        require_once ROOT . '/boot/mail.class.php';
        $mailSMTP = new jmy_mail($config, $mail_text, $title);
        $mailSMTP->send($email, $title, $message);
    }
}

/*
 * Распаковка архива
 *
 * @param string $source - Путь к файлу архива
 * @param string $dest - куда извлекать
 *
 * @return bool|ZipArchive
 */
function createZipFromDir($dir, $zip_file): ZipArchive|bool
{
    $zip = new ZipArchive;
    if (true !== $zip->open($zip_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) return false;
    zipDir($dir, $zip);
    return $zip;
}

function unzip_file($file_path, $dest)
{
    global $lang;
    $zip = new ZipArchive;
    if (!is_dir($dest)) return $lang['no_folder'];
    // открываем архив
    if (true === $zip->open($file_path)) {
        $zip->extractTo($dest);
        $zip->close();
        return true;
    } else
        return $lang['error_unpack'];
}

function zipDir($dir, $zip, $relative_path = DIRECTORY_SEPARATOR): void
{
    $dir = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
    if ($handle = opendir($dir)) {
        while (false !== ($file = readdir($handle))) {
            if ($file === '.' || $file === '..') continue;
            if (is_file($dir . $file)) {
                $zip->addFile($dir . $file, $file);
            } elseif (is_dir($dir . $file)) {
                zipDir($dir . $file, $zip, $relative_path . $file);
            }
        }
    }
    closedir($handle);
}

/*
 *  Проверка наличия и фильтр :)
 *  $name = Имя для проверки
 *  $filter_type = Как фильтровать
 *  $chose == 'i'=> intval($name)
 *  $chose == 'f'=> filter($name, $filter_type)
 *  $type == 'is'=> isset($name)
 *  $type == 'nis'=> !isset($name)
 *  $type == 'em'=> empty($name)
 *  $type == 'nem'=> !empty($name)
 *  $content - контент
 *  $lang_text - текст ошибки
 *
 *  check_type($text, 'is') => isset($id/$text) ? intval($id)/filter($text, 'html') : '';
 *  check_type($text, 'nis') => !isset($id/$text) ? intval($id)/filter($text, 'html') : '';
 *  check_type($text, 'em') => empty($id/$text) ? intval($id)/filter($text, 'html') : '';
 *  check_type($text, 'nem') => !empty($id/$text) ? intval($id)/filter($text, 'html') : '';
 *
 * Допонительный текст ошибки
 *
 *  check_type($text, 'is', false, 'html', 'text') => isset($id/$text) ? intval($id)/filter($text, 'html') : $lang_text;
 *  check_type($text, 'nis', false, 'html', 'text') => !isset($id/$text) ? intval($id)/filter($text, 'html') : $lang_text;
 *  check_type($text, 'em', false, 'html', 'text') => empty($id/$text) ? intval($id)/filter($text, 'html') : $lang_text;
 *  check_type($text, 'nem', false, 'html', 'text') => !empty($id/$text) ? intval($id)/filter($text, 'html') : $lang_text;
 *
 *  Массив
 *
 *  check_type($array, 'ar', $rows_array) => array($array) ? $rows_array : '';
 *  check_type($array, 'is_ar', $rows_array) => is_array($rows) ? $rows_array : '';
 *  check_type($array, 'nis_ar', $rows_array) => !is_array($rows) ? $rows_array : '';
 *  check_type($array, 'in_ar', $rows_array) => in_array($rows_array, $array) ? $rows_array : '';
 *  check_type($array, 'nin_ar', $rows_array) => !in_array($rows_array, $array) ? $rows_array : '';
*/
function check_type($name, $type, $array = false, $filter_type = 'html', $lang_text = false)
{
    $types = array('is' => 'isset', 'nis' => '!isset', 'em' => 'empty', 'nem' => '!empty', 'ar' => 'array', 'is_ar' => 'is_array', 'nis_ar' => '!is_array', 'in_ar' => 'in_array', 'nin_ar' => '!in_array', '.' => $type);
    $result = is_numeric($name) ? $name : mb_strtolower(trim(strip_tags($name)), 'UTF-8');
    $res = str_replace(array_keys($types), array_values($types), $result);
    $lang_text = $lang_text ?? '';
    $chose = is_numeric($name) ? ($name > 0 ? intval($name) : NULL) : filter($name, $filter_type);
    $content = $res . ($name) ? $chose : $lang_text;
    if ($array) {
        if ($type == 'ar' || $type == 'is_ar' || $type == 'nis_ar') {
            $content = $res . ($chose) ? $chose : $lang_text;
        } elseif ($type == 'in_ar' || $type == 'nin_ar') {
            $content = $res . ($chose . ',' . $name) ? $chose : $lang_text;
        } else {
            $content = $name;
        }
    }
    return $content;
}

function count_($array): int
{
    return is_array($array) ? count($array) : 0;
}

parse_req($_REQUEST);
$_SERVER["REQUEST_URI"] = filter($_SERVER["REQUEST_URI"], 'reqUri');
$_SERVER['REMOTE_ADDR'] = filter($_SERVER['REMOTE_ADDR'], 'ip');